From dd39da49e5de78e25fa237ca29ff5b13a3dfbe56 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Tue, 12 Jul 2011 16:10:50 +0100 Subject: [PATCH] gdi32: Use a local copy of the bitmap info structure to further simplify GetDIBits. --- dlls/gdi32/dib.c | 190 ++++++++++++++++++++++++++++------------------- 1 file changed, 114 insertions(+), 76 deletions(-) diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index 5103919ff29..e0073f16630 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -63,6 +63,7 @@ #include #include #include +#include #include "windef.h" #include "winbase.h" @@ -443,6 +444,59 @@ static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff}; static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f}; static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f}; + +/************************************************************************ + * copy_color_info + * + * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO. + */ +static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse) +{ + unsigned int colors = src->bmiHeader.biBitCount > 8 ? 0 : 1 << src->bmiHeader.biBitCount; + RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize); + + assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ); + + if (src->bmiHeader.biClrUsed) colors = src->bmiHeader.biClrUsed; + + if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst; + if (coloruse == DIB_PAL_COLORS) + memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) ); + else + { + unsigned int i; + for (i = 0; i < colors; i++) + { + core->bmciColors[i].rgbtRed = src_colors[i].rgbRed; + core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen; + core->bmciColors[i].rgbtBlue = src_colors[i].rgbBlue; + } + } + } + else + { + dst->bmiHeader.biClrUsed = src->bmiHeader.biClrUsed; + dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage; + + if (src->bmiHeader.biCompression == BI_BITFIELDS) + /* bitfields are always at bmiColors even in larger structures */ + memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) ); + else if (colors) + { + void *colorptr = (char *)dst + dst->bmiHeader.biSize; + unsigned int size; + + if (coloruse == DIB_PAL_COLORS) + size = colors * sizeof(WORD); + else + size = colors * sizeof(RGBQUAD); + memcpy( colorptr, src_colors, size ); + } + } +} + /****************************************************************************** * GetDIBits [GDI32.@] * @@ -470,9 +524,8 @@ INT WINAPI GetDIBits( LONG height; WORD planes, bpp; DWORD compr, size; - void* colorPtr; - RGBQUAD quad_buf[256]; - RGBQUAD* rgbQuads = quad_buf; + char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf; if (!info) return 0; @@ -495,14 +548,9 @@ INT WINAPI GetDIBits( return 0; } - colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize; - if(!core_header) rgbQuads = colorPtr; - /* Transfer color info */ - - switch (bpp) + if (bpp == 0) /* query bitmap info only */ { - case 0: /* query bitmap info only */ if (core_header) { BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info; @@ -549,34 +597,46 @@ INT WINAPI GetDIBits( } lines = abs(bmp->bitmap.bmHeight); goto done; + } + + /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our + own copy and transfer the colour info back at the end */ + + dst_info->bmiHeader.biSize = sizeof(dst_info->bmiHeader); + dst_info->bmiHeader.biWidth = width; + dst_info->bmiHeader.biHeight = height; + dst_info->bmiHeader.biPlanes = planes; + dst_info->bmiHeader.biBitCount = bpp; + dst_info->bmiHeader.biCompression = compr; + dst_info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp ); + dst_info->bmiHeader.biXPelsPerMeter = 0; + dst_info->bmiHeader.biYPelsPerMeter = 0; + dst_info->bmiHeader.biClrUsed = 0; + dst_info->bmiHeader.biClrImportant = 0; + + switch (bpp) + { case 1: case 4: case 8: { unsigned int colors = 1 << bpp; - if (!core_header) info->bmiHeader.biClrUsed = 0; - if (coloruse == DIB_PAL_COLORS) { - WORD *index = colorPtr; + WORD *index = (WORD*)dst_info->bmiColors; for (i = 0; i < colors; i++, index++) *index = i; - - break; } - /* If the bitmap object already has a dib section at the + /* If the bitmap object is a dib section at the same color depth then get the color map from it */ - - if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) + else if (bmp->dib && bpp == bmp->dib->dsBm.bmBitsPixel) { colors = min( colors, bmp->nb_colors ); - - if (!core_header && colors != 1 << bpp) info->bmiHeader.biClrUsed = colors; - - memcpy(rgbQuads, bmp->color_table, colors * sizeof(RGBQUAD)); + if (colors != 1 << bpp) dst_info->bmiHeader.biClrUsed = colors; + memcpy( dst_info->bmiColors, bmp->color_table, colors * sizeof(RGBQUAD) ); } /* For color DDBs in native depth (mono DDBs always have a black/white palette): @@ -589,16 +649,16 @@ INT WINAPI GetDIBits( memset( palEntry, 0, sizeof(palEntry) ); if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry )) { - release_dc_ptr( dc ); - GDI_ReleaseObj( hbitmap ); - return 0; + lines = 0; + goto done; } + for (i = 0; i < colors; i++) { - rgbQuads[i].rgbRed = palEntry[i].peRed; - rgbQuads[i].rgbGreen = palEntry[i].peGreen; - rgbQuads[i].rgbBlue = palEntry[i].peBlue; - rgbQuads[i].rgbReserved = 0; + dst_info->bmiColors[i].rgbRed = palEntry[i].peRed; + dst_info->bmiColors[i].rgbGreen = palEntry[i].peGreen; + dst_info->bmiColors[i].rgbBlue = palEntry[i].peBlue; + dst_info->bmiColors[i].rgbReserved = 0; } } else @@ -606,76 +666,64 @@ INT WINAPI GetDIBits( switch (bpp) { case 1: - rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0; - rgbQuads[0].rgbReserved = 0; - rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff; - rgbQuads[1].rgbReserved = 0; + dst_info->bmiColors[0].rgbRed = dst_info->bmiColors[0].rgbGreen = dst_info->bmiColors[0].rgbBlue = 0; + dst_info->bmiColors[0].rgbReserved = 0; + dst_info->bmiColors[1].rgbRed = dst_info->bmiColors[1].rgbGreen = dst_info->bmiColors[1].rgbBlue = 0xff; + dst_info->bmiColors[1].rgbReserved = 0; break; case 4: /* The EGA palette is the first and last 8 colours of the default palette with the innermost pair swapped */ - memcpy(rgbQuads, DefLogPaletteQuads, 7 * sizeof(RGBQUAD)); - memcpy(rgbQuads + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD)); - memcpy(rgbQuads + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD)); - memcpy(rgbQuads + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD)); + memcpy(dst_info->bmiColors, DefLogPaletteQuads, 7 * sizeof(RGBQUAD)); + memcpy(dst_info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD)); + memcpy(dst_info->bmiColors + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD)); + memcpy(dst_info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD)); break; case 8: - memcpy(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD)); - memcpy(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD)); + memcpy(dst_info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD)); + memcpy(dst_info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD)); for (i = 10; i < 246; i++) { - rgbQuads[i].rgbRed = (i & 0x07) << 5; - rgbQuads[i].rgbGreen = (i & 0x38) << 2; - rgbQuads[i].rgbBlue = i & 0xc0; - rgbQuads[i].rgbReserved = 0; + dst_info->bmiColors[i].rgbRed = (i & 0x07) << 5; + dst_info->bmiColors[i].rgbGreen = (i & 0x38) << 2; + dst_info->bmiColors[i].rgbBlue = i & 0xc0; + dst_info->bmiColors[i].rgbReserved = 0; } } } - - if(core_header) - { - RGBTRIPLE *triple = (RGBTRIPLE *)colorPtr; - for (i = 0; i < colors; i++) - { - triple[i].rgbtRed = rgbQuads[i].rgbRed; - triple[i].rgbtGreen = rgbQuads[i].rgbGreen; - triple[i].rgbtBlue = rgbQuads[i].rgbBlue; - } - } - break; } case 15: - if (info->bmiHeader.biCompression == BI_BITFIELDS) - memcpy( info->bmiColors, bit_fields_555, sizeof(bit_fields_555) ); + if (dst_info->bmiHeader.biCompression == BI_BITFIELDS) + memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) ); break; case 16: - if (info->bmiHeader.biCompression == BI_BITFIELDS) + if (dst_info->bmiHeader.biCompression == BI_BITFIELDS) { if (bmp->dib) { if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp) - memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) ); + memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) ); else - memcpy( info->bmiColors, bit_fields_555, sizeof(bit_fields_555) ); + memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) ); } else - memcpy( info->bmiColors, bit_fields_565, sizeof(bit_fields_565) ); + memcpy( dst_info->bmiColors, bit_fields_565, sizeof(bit_fields_565) ); } break; case 24: case 32: - if (info->bmiHeader.biCompression == BI_BITFIELDS) + if (dst_info->bmiHeader.biCompression == BI_BITFIELDS) { if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp) - memcpy( info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) ); + memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) ); else - memcpy( info->bmiColors, bit_fields_888, sizeof(bit_fields_888) ); + memcpy( dst_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) ); } break; } @@ -894,7 +942,7 @@ INT WINAPI GetDIBits( break; default: /* ? bit DIB */ - FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount); + FIXME("Unsupported DIB depth %d\n", dst_info->bmiHeader.biBitCount); break; } } @@ -904,22 +952,12 @@ INT WINAPI GetDIBits( PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetDIBits ); if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0; else lines = physdev->funcs->pGetDIBits( physdev, hbitmap, startscan, - lines, bits, info, coloruse ); + lines, bits, dst_info, coloruse ); } } else lines = abs(height); - /* The knowledge base article Q81498 ("DIBs and Their Uses") states that - if bits == NULL and bpp != 0, only biSizeImage and the color table are - filled in. */ - if (!core_header) - { - /* FIXME: biSizeImage should be calculated according to the selected - compression algorithm if biCompression != BI_RGB */ - info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp ); - TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage); - } - TRACE("biWidth = %d, biHeight = %d\n", width, height); + copy_color_info( info, dst_info, coloruse ); done: release_dc_ptr( dc );