gdi32: If possible use the GetImage driver entry to fill the colour table for GetDIBits.
This commit is contained in:
parent
d947f6ef08
commit
b94616864d
163
dlls/gdi32/dib.c
163
dlls/gdi32/dib.c
|
@ -881,14 +881,16 @@ INT WINAPI GetDIBits(
|
||||||
{
|
{
|
||||||
DC * dc;
|
DC * dc;
|
||||||
BITMAPOBJ * bmp;
|
BITMAPOBJ * bmp;
|
||||||
int i, ret = 0;
|
int i, dst_to_src_offset, ret = 0;
|
||||||
LONG width;
|
DWORD err;
|
||||||
LONG height;
|
|
||||||
WORD bpp;
|
|
||||||
char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
|
char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
|
||||||
BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
|
BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
|
||||||
unsigned int colors = 0;
|
char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
|
||||||
|
BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
|
||||||
const struct gdi_dc_funcs *funcs;
|
const struct gdi_dc_funcs *funcs;
|
||||||
|
struct gdi_image_bits src_bits;
|
||||||
|
struct bitblt_coords src, dst;
|
||||||
|
BOOL empty_rect = FALSE;
|
||||||
|
|
||||||
/* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
|
/* 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 */
|
own copy and transfer the colour info back at the end */
|
||||||
|
@ -911,90 +913,12 @@ INT WINAPI GetDIBits(
|
||||||
funcs = bmp->funcs;
|
funcs = bmp->funcs;
|
||||||
if (bmp->dib) funcs = dc->dibdrv.dev.funcs;
|
if (bmp->dib) funcs = dc->dibdrv.dev.funcs;
|
||||||
|
|
||||||
width = dst_info->bmiHeader.biWidth;
|
if (dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
|
||||||
height = dst_info->bmiHeader.biHeight;
|
|
||||||
bpp = dst_info->bmiHeader.biBitCount;
|
|
||||||
if (bpp == 0) /* query bitmap info only */
|
|
||||||
{
|
{
|
||||||
ret = fill_query_info( info, bmp );
|
ret = fill_query_info( info, bmp );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (bpp)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
case 4:
|
|
||||||
case 8:
|
|
||||||
{
|
|
||||||
colors = 1 << bpp;
|
|
||||||
|
|
||||||
/* If the bitmap object is a dib section at the
|
|
||||||
same color depth then get the color map from it */
|
|
||||||
if (bmp->dib && bpp == bmp->dib->dsBm.bmBitsPixel && coloruse == DIB_RGB_COLORS)
|
|
||||||
{
|
|
||||||
colors = min( colors, bmp->nb_colors );
|
|
||||||
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):
|
|
||||||
Generate the color map from the selected palette. In the DIB_PAL_COLORS
|
|
||||||
case we'll fix up the indices after the format conversion. */
|
|
||||||
else if ( (bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) || coloruse == DIB_PAL_COLORS )
|
|
||||||
{
|
|
||||||
if (!fill_color_table_from_palette( dst_info, dc ))
|
|
||||||
{
|
|
||||||
lines = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fill_default_color_table( dst_info );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 15:
|
|
||||||
if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
|
|
||||||
memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 16:
|
|
||||||
if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
|
|
||||||
{
|
|
||||||
if (bmp->dib)
|
|
||||||
{
|
|
||||||
if (bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
|
|
||||||
memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
|
|
||||||
else
|
|
||||||
memcpy( dst_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
memcpy( dst_info->bmiColors, bit_fields_565, sizeof(bit_fields_565) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 24:
|
|
||||||
case 32:
|
|
||||||
if (dst_info->bmiHeader.biCompression == BI_BITFIELDS)
|
|
||||||
{
|
|
||||||
if (bmp->dib && bmp->dib->dsBmih.biCompression == BI_BITFIELDS && bmp->dib->dsBmih.biBitCount == bpp)
|
|
||||||
memcpy( dst_info->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD) );
|
|
||||||
else
|
|
||||||
memcpy( dst_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bits && lines)
|
|
||||||
{
|
|
||||||
char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
|
|
||||||
BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
|
|
||||||
struct gdi_image_bits src_bits;
|
|
||||||
struct bitblt_coords src, dst;
|
|
||||||
DWORD err;
|
|
||||||
int dst_to_src_offset;
|
|
||||||
BOOL empty_rect;
|
|
||||||
|
|
||||||
src.visrect.left = 0;
|
src.visrect.left = 0;
|
||||||
src.visrect.top = 0;
|
src.visrect.top = 0;
|
||||||
src.visrect.right = bmp->bitmap.bmWidth;
|
src.visrect.right = bmp->bitmap.bmWidth;
|
||||||
|
@ -1005,12 +929,11 @@ INT WINAPI GetDIBits(
|
||||||
dst.visrect.right = dst_info->bmiHeader.biWidth;
|
dst.visrect.right = dst_info->bmiHeader.biWidth;
|
||||||
dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
|
dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
|
||||||
|
|
||||||
if (startscan >= dst.visrect.bottom)
|
if (lines == 0 || startscan >= dst.visrect.bottom)
|
||||||
{
|
bits = NULL;
|
||||||
ret = 1; /* yes, this is strange */
|
|
||||||
goto empty_image;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (bits)
|
||||||
|
{
|
||||||
if (dst_info->bmiHeader.biHeight > 0)
|
if (dst_info->bmiHeader.biHeight > 0)
|
||||||
{
|
{
|
||||||
dst_to_src_offset = -startscan;
|
dst_to_src_offset = -startscan;
|
||||||
|
@ -1038,7 +961,7 @@ INT WINAPI GetDIBits(
|
||||||
if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
|
if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
|
||||||
{
|
{
|
||||||
int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
|
int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
|
||||||
int pad_bytes = pad_lines * get_dib_stride( width, bpp );
|
int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
|
||||||
memset( bits, 0, pad_bytes );
|
memset( bits, 0, pad_bytes );
|
||||||
bits = (char *)bits + pad_bytes;
|
bits = (char *)bits + pad_bytes;
|
||||||
}
|
}
|
||||||
|
@ -1047,33 +970,71 @@ INT WINAPI GetDIBits(
|
||||||
{
|
{
|
||||||
if (dst.visrect.bottom < lines)
|
if (dst.visrect.bottom < lines)
|
||||||
{
|
{
|
||||||
int pad_lines = lines - dst.visrect.bottom, stride = get_dib_stride( width, bpp );
|
int pad_lines = lines - dst.visrect.bottom;
|
||||||
|
int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
|
||||||
int pad_bytes = pad_lines * stride;
|
int pad_bytes = pad_lines * stride;
|
||||||
memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
|
memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty_rect) goto empty_image;
|
if (empty_rect) bits = NULL;
|
||||||
|
|
||||||
src.x = src.visrect.left;
|
src.x = src.visrect.left;
|
||||||
src.y = src.visrect.top;
|
src.y = src.visrect.top;
|
||||||
src.width = src.visrect.right - src.visrect.left;
|
src.width = src.visrect.right - src.visrect.left;
|
||||||
src.height = src.visrect.bottom - src.visrect.top;
|
src.height = src.visrect.bottom - src.visrect.top;
|
||||||
|
|
||||||
err = funcs->pGetImage( NULL, hbitmap, src_info, &src_bits, &src );
|
lines = src.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
|
||||||
|
|
||||||
if (err) goto done;
|
if (err) goto done;
|
||||||
|
|
||||||
ret = src.height;
|
/* fill out the src colour table, if it needs one */
|
||||||
|
|
||||||
if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
|
if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
|
||||||
{
|
{
|
||||||
if (bmp->dib)
|
|
||||||
memcpy( src_info->bmiColors, bmp->color_table, bmp->nb_colors * sizeof(RGBQUAD) );
|
|
||||||
else
|
|
||||||
fill_default_color_table( src_info );
|
fill_default_color_table( src_info );
|
||||||
|
src_info->bmiHeader.biClrUsed = 1 << src_info->bmiHeader.biBitCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if the src and dst are the same depth, copy the colour info across */
|
||||||
|
if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
|
||||||
|
{
|
||||||
|
switch (src_info->bmiHeader.biBitCount)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
if (src_info->bmiHeader.biCompression == BI_RGB)
|
||||||
|
{
|
||||||
|
src_info->bmiHeader.biCompression = BI_BITFIELDS;
|
||||||
|
memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
if (src_info->bmiHeader.biCompression == BI_RGB)
|
||||||
|
{
|
||||||
|
src_info->bmiHeader.biCompression = BI_BITFIELDS;
|
||||||
|
memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
|
||||||
|
copy_color_info( dst_info, src_info, coloruse );
|
||||||
|
}
|
||||||
|
else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
|
||||||
|
{
|
||||||
|
if( coloruse == DIB_PAL_COLORS )
|
||||||
|
{
|
||||||
|
if (!fill_color_table_from_palette( dst_info, dc )) goto done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fill_default_color_table( dst_info );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits)
|
||||||
|
{
|
||||||
if(dst_info->bmiHeader.biHeight > 0)
|
if(dst_info->bmiHeader.biHeight > 0)
|
||||||
dst_info->bmiHeader.biHeight = src.height;
|
dst_info->bmiHeader.biHeight = src.height;
|
||||||
else
|
else
|
||||||
|
@ -1081,13 +1042,15 @@ INT WINAPI GetDIBits(
|
||||||
|
|
||||||
convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
|
convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
|
||||||
if (src_bits.free) src_bits.free( &src_bits );
|
if (src_bits.free) src_bits.free( &src_bits );
|
||||||
|
ret = lines;
|
||||||
}
|
}
|
||||||
else ret = abs( height );
|
else
|
||||||
|
ret = empty_rect ? FALSE : TRUE;
|
||||||
|
|
||||||
empty_image:
|
|
||||||
if (coloruse == DIB_PAL_COLORS)
|
if (coloruse == DIB_PAL_COLORS)
|
||||||
{
|
{
|
||||||
WORD *index = (WORD *)dst_info->bmiColors;
|
WORD *index = (WORD *)dst_info->bmiColors;
|
||||||
|
int colors = get_dib_num_of_colors( dst_info );
|
||||||
for (i = 0; i < colors; i++, index++)
|
for (i = 0; i < colors; i++, index++)
|
||||||
*index = i;
|
*index = i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1255,21 +1255,18 @@ static void test_GetDIBits_selected_DIB(UINT bpp)
|
||||||
/* Test various combinations of lines = 0 and bits2 = NULL */
|
/* Test various combinations of lines = 0 and bits2 = NULL */
|
||||||
memset( info2->bmiColors, 0xcc, 256 * sizeof(RGBQUAD) );
|
memset( info2->bmiColors, 0xcc, 256 * sizeof(RGBQUAD) );
|
||||||
res = GetDIBits( dc, dib, 0, 0, bits2, info2, DIB_RGB_COLORS );
|
res = GetDIBits( dc, dib, 0, 0, bits2, info2, DIB_RGB_COLORS );
|
||||||
todo_wine
|
|
||||||
ok( res == 1, "got %d (bpp %d)\n", res, bpp );
|
ok( res == 1, "got %d (bpp %d)\n", res, bpp );
|
||||||
ok( !memcmp( info->bmiColors, info2->bmiColors, (1 << bpp) * sizeof(RGBQUAD) ),
|
ok( !memcmp( info->bmiColors, info2->bmiColors, (1 << bpp) * sizeof(RGBQUAD) ),
|
||||||
"color table mismatch (bpp %d)\n", bpp );
|
"color table mismatch (bpp %d)\n", bpp );
|
||||||
|
|
||||||
memset( info2->bmiColors, 0xcc, 256 * sizeof(RGBQUAD) );
|
memset( info2->bmiColors, 0xcc, 256 * sizeof(RGBQUAD) );
|
||||||
res = GetDIBits( dc, dib, 0, 0, NULL, info2, DIB_RGB_COLORS );
|
res = GetDIBits( dc, dib, 0, 0, NULL, info2, DIB_RGB_COLORS );
|
||||||
todo_wine
|
|
||||||
ok( res == 1, "got %d (bpp %d)\n", res, bpp );
|
ok( res == 1, "got %d (bpp %d)\n", res, bpp );
|
||||||
ok( !memcmp( info->bmiColors, info2->bmiColors, (1 << bpp) * sizeof(RGBQUAD) ),
|
ok( !memcmp( info->bmiColors, info2->bmiColors, (1 << bpp) * sizeof(RGBQUAD) ),
|
||||||
"color table mismatch (bpp %d)\n", bpp );
|
"color table mismatch (bpp %d)\n", bpp );
|
||||||
|
|
||||||
memset( info2->bmiColors, 0xcc, 256 * sizeof(RGBQUAD) );
|
memset( info2->bmiColors, 0xcc, 256 * sizeof(RGBQUAD) );
|
||||||
res = GetDIBits( dc, dib, 0, info->bmiHeader.biHeight, NULL, info2, DIB_RGB_COLORS );
|
res = GetDIBits( dc, dib, 0, info->bmiHeader.biHeight, NULL, info2, DIB_RGB_COLORS );
|
||||||
todo_wine
|
|
||||||
ok( res == 1, "got %d (bpp %d)\n", res, bpp );
|
ok( res == 1, "got %d (bpp %d)\n", res, bpp );
|
||||||
ok( !memcmp( info->bmiColors, info2->bmiColors, (1 << bpp) * sizeof(RGBQUAD) ),
|
ok( !memcmp( info->bmiColors, info2->bmiColors, (1 << bpp) * sizeof(RGBQUAD) ),
|
||||||
"color table mismatch (bpp %d)\n", bpp );
|
"color table mismatch (bpp %d)\n", bpp );
|
||||||
|
@ -1386,7 +1383,6 @@ static void test_GetDIBits_selected_DDB(BOOL monochrome)
|
||||||
|
|
||||||
/* Get the palette indices */
|
/* Get the palette indices */
|
||||||
res = GetDIBits(dc, ddb, 0, 0, NULL, info2, DIB_PAL_COLORS);
|
res = GetDIBits(dc, ddb, 0, 0, NULL, info2, DIB_PAL_COLORS);
|
||||||
todo_wine
|
|
||||||
ok( res == 1, "got %d (bpp %d)\n", res, bpp );
|
ok( res == 1, "got %d (bpp %d)\n", res, bpp );
|
||||||
|
|
||||||
for (i = 0; i < (1 << info->bmiHeader.biBitCount); i++)
|
for (i = 0; i < (1 << info->bmiHeader.biBitCount); i++)
|
||||||
|
|
Loading…
Reference in New Issue