gdi32: Add support for DIBINDEX colors in 1-bpp blits.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-03-08 21:29:51 +01:00
parent 89d31e42fc
commit c54b667e25
5 changed files with 30 additions and 26 deletions

View File

@ -221,7 +221,7 @@ static DWORD blend_bits( const BITMAPINFO *src_info, const struct gdi_image_bits
return blend_bitmapinfo( src_info, src_bits->ptr, src, dst_info, dst_bits->ptr, dst, blend );
}
static RGBQUAD get_dc_rgb_color( DC *dc, COLORREF color )
static RGBQUAD get_dc_rgb_color( DC *dc, int color_table_size, COLORREF color )
{
RGBQUAD ret = { 0, 0, 0, 0 };
@ -238,8 +238,11 @@ static RGBQUAD get_dc_rgb_color( DC *dc, COLORREF color )
}
if (color >> 16 == 0x10ff) /* DIBINDEX */
{
/* FIXME: need to propagate the index into the conversion functions */
WARN( "monochrome blit uses DIBINDEX %x\n", color );
if (color_table_size)
{
if (LOWORD(color) >= color_table_size) color = 0x10ff0000; /* fallback to index 0 */
*(DWORD *)&ret = color;
}
return ret;
}
ret.rgbRed = GetRValue( color );
@ -249,10 +252,10 @@ static RGBQUAD get_dc_rgb_color( DC *dc, COLORREF color )
}
/* helper to retrieve either both colors or only the background color for monochrome blits */
void get_mono_dc_colors( DC *dc, BITMAPINFO *info, int count )
void get_mono_dc_colors( DC *dc, int color_table_size, BITMAPINFO *info, int count )
{
info->bmiColors[count - 1] = get_dc_rgb_color( dc, dc->backgroundColor );
if (count > 1) info->bmiColors[0] = get_dc_rgb_color( dc, dc->textColor );
info->bmiColors[count - 1] = get_dc_rgb_color( dc, color_table_size, dc->backgroundColor );
if (count > 1) info->bmiColors[0] = get_dc_rgb_color( dc, color_table_size, dc->textColor );
info->bmiHeader.biClrUsed = count;
}
@ -284,12 +287,12 @@ BOOL nulldrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
/* 1-bpp source without a color table uses the destination DC colors */
if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
get_mono_dc_colors( dc_dst, src_info, 2 );
get_mono_dc_colors( dc_dst, dst_info->bmiHeader.biClrUsed, src_info, 2 );
/* 1-bpp destination without a color table requires a fake 1-entry table
* that contains only the background color */
if (dst_info->bmiHeader.biBitCount == 1 && !dst_colors)
get_mono_dc_colors( dc_src, dst_info, 1 );
get_mono_dc_colors( dc_src, src_info->bmiHeader.biClrUsed, dst_info, 1 );
if (!(err = convert_bits( src_info, src, dst_info, &bits )))
{

View File

@ -1001,7 +1001,7 @@ DWORD dibdrv_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
/* For mask_rect, 1-bpp source without a color table uses the destination DC colors */
if (info->bmiHeader.biBitCount == 1 && pdev->dib.bit_count != 1 && !info->bmiHeader.biClrUsed)
get_mono_dc_colors( dc, info, 2 );
get_mono_dc_colors( dc, pdev->dib.color_table_size, info, 2 );
init_dib_info_from_bitmapinfo( &src_dib, info, bits->ptr );
src_dib.bits.is_copy = bits->is_copy;

View File

@ -108,6 +108,9 @@ static const BYTE pixel_masks_4[2] = {0xf0, 0x0f};
static const BYTE pixel_masks_1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
static const BYTE edge_masks_1[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
#define FILTER_DIBINDEX(rgbquad,other_val) \
(HIWORD( *(DWORD *)(&rgbquad) ) == 0x10ff ? LOWORD( *(DWORD *)(&rgbquad) ) : (other_val))
#define ROPS_WITHOUT_COPY( _d, _s ) \
case R2_BLACK: LOOP( (_d) = 0 ) break; \
case R2_NOTMERGEPEN: LOOP( (_d) = ~((_d) | (_s)) ) break; \
@ -3757,7 +3760,7 @@ static void convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rec
int i;
for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
for(y = src_rect->top; y < src_rect->bottom; y++)
{
@ -4144,7 +4147,7 @@ static void convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rec
int i;
for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
dst_colors[i] = rgbquad_to_pixel_colortable(dst, color_table[i]);
dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
for(y = src_rect->top; y < src_rect->bottom; y++)
{
@ -4188,7 +4191,7 @@ static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
case 32:
{
DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
DWORD bg_pixel = rgbquad_to_pixel_masks(src, bg_entry);
DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry));
if(src->funcs == &funcs_8888)
{
@ -4289,7 +4292,7 @@ static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
case 24:
{
BYTE *src_start = get_pixel_ptr_24(src, src_rect->left, src_rect->top), *src_pixel;
DWORD bg_pixel = RGB( bg_entry.rgbRed, bg_entry.rgbGreen, bg_entry.rgbBlue );
DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, RGB(bg_entry.rgbRed, bg_entry.rgbGreen, bg_entry.rgbBlue));
for(y = src_rect->top; y < src_rect->bottom; y++)
{
@ -4323,7 +4326,7 @@ static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
case 16:
{
WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
DWORD bg_pixel = rgbquad_to_pixel_masks(src, bg_entry);
DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_masks(src, bg_entry));
if(src->funcs == &funcs_555)
{
@ -4463,7 +4466,7 @@ static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
{
const RGBQUAD *color_table = get_dib_color_table( src );
BYTE *src_start = get_pixel_ptr_8(src, src_rect->left, src_rect->top), *src_pixel;
DWORD bg_pixel = rgbquad_to_pixel_colortable( src, bg_entry );
DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
for(y = src_rect->top; y < src_rect->bottom; y++)
{
@ -4500,7 +4503,7 @@ static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
{
const RGBQUAD *color_table = get_dib_color_table( src );
BYTE *src_start = get_pixel_ptr_4(src, src_rect->left, src_rect->top), *src_pixel;
DWORD bg_pixel = rgbquad_to_pixel_colortable( src, bg_entry );
DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
for(y = src_rect->top; y < src_rect->bottom; y++)
{
@ -4543,7 +4546,7 @@ static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
{
const RGBQUAD *color_table = get_dib_color_table( src );
BYTE *src_start = get_pixel_ptr_1(src, src_rect->left, src_rect->top);
DWORD bg_pixel = rgbquad_to_pixel_colortable(src, bg_entry);
DWORD bg_pixel = FILTER_DIBINDEX(bg_entry, rgbquad_to_pixel_colortable(src, bg_entry));
for(y = src_rect->top; y < src_rect->bottom; y++)
{
@ -4553,8 +4556,8 @@ static void convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
{
src_val = (src_start[pos / 8] & pixel_masks_1[pos % 8]) ? 1 : 0;
rgb = color_table[src_val];
dst_val = rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
dst_val = FILTER_DIBINDEX(rgb, rgb_to_pixel_mono(dst, dither, x, y, src_val, bg_pixel,
rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
if(bit_pos == 0) *dst_pixel = 0;
*dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
@ -5866,7 +5869,7 @@ static void mask_rect_8( const dib_info *dst, const RECT *rc,
get_rop_codes( rop2, &codes );
for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
dst_colors[i] = rgbquad_to_pixel_colortable( dst, color_table[i] );
dst_colors[i] = FILTER_DIBINDEX(color_table[i], rgbquad_to_pixel_colortable(dst, color_table[i]));
/* Special case starting and finishing in same byte, neither on byte boundary */
if ((origin->x & 7) && (origin_end & 7) && (origin->x & ~7) == (origin_end & ~7))
@ -6005,7 +6008,7 @@ static void mask_rect_4( const dib_info *dst, const RECT *rc,
for (i = 0; i < sizeof(dst_colors) / sizeof(dst_colors[0]); i++)
{
dst_colors[i] = rgbquad_to_pixel_colortable( dst, color_table[i] );
dst_colors[i] = FILTER_DIBINDEX(color_table[i],rgbquad_to_pixel_colortable(dst, color_table[i]));
/* Set high nibble to match so we don't need to shift it later. */
dst_colors[i] |= dst_colors[i] << 4;
}

View File

@ -200,7 +200,7 @@ extern BOOL intersect_vis_rectangles( struct bitblt_coords *dst, struct bitblt_c
extern DWORD stretch_bits( const BITMAPINFO *src_info, struct bitblt_coords *src,
BITMAPINFO *dst_info, struct bitblt_coords *dst,
struct gdi_image_bits *bits, int mode ) DECLSPEC_HIDDEN;
extern void get_mono_dc_colors( DC *dc, BITMAPINFO *info, int count ) DECLSPEC_HIDDEN;
extern void get_mono_dc_colors( DC *dc, int color_table_size, BITMAPINFO *info, int count ) DECLSPEC_HIDDEN;
/* brush.c */
extern BOOL store_brush_pattern( LOGBRUSH *brush, struct brush_pattern *pattern ) DECLSPEC_HIDDEN;

View File

@ -2477,8 +2477,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
}
SetTextColor( hdc, old_text );
SetBkColor( hdc, old_bkgnd );
compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 1-bpp ddb SRCCOPY", 0,
bmi->bmiHeader.biBitCount <= 8 /* todo: DIBINDEX for indexed formats */ );
compare_hash(hdc, bmi, bits, "BitBlt src 1-bpp ddb SRCCOPY" );
DeleteObject( bmp );
@ -2536,8 +2535,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ );
SetTextColor( hdc, old_text );
SetBkColor( hdc, old_bkgnd );
compare_hash_broken_todo(hdc, bmi, bits, "BitBlt dst 1-bpp ddb", 0,
bmi->bmiHeader.biBitCount <= 8 /* todo: DIBINDEX for indexed formats */ );
compare_hash(hdc, bmi, bits, "BitBlt dst 1-bpp ddb");
DeleteDC( src_dc );
DeleteObject( bmp );