From c54b667e25a8cff0919de9b22fa3265068ab4eb2 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 8 Mar 2017 21:29:51 +0100 Subject: [PATCH] gdi32: Add support for DIBINDEX colors in 1-bpp blits. Signed-off-by: Alexandre Julliard --- dlls/gdi32/bitblt.c | 19 +++++++++++-------- dlls/gdi32/dibdrv/bitblt.c | 2 +- dlls/gdi32/dibdrv/primitives.c | 27 +++++++++++++++------------ dlls/gdi32/gdi_private.h | 2 +- dlls/gdi32/tests/dib.c | 6 ++---- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c index a17d248ff14..3d8c128fd70 100644 --- a/dlls/gdi32/bitblt.c +++ b/dlls/gdi32/bitblt.c @@ -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 ))) { diff --git a/dlls/gdi32/dibdrv/bitblt.c b/dlls/gdi32/dibdrv/bitblt.c index d865ffb4ce1..79cd629980c 100644 --- a/dlls/gdi32/dibdrv/bitblt.c +++ b/dlls/gdi32/dibdrv/bitblt.c @@ -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; diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c index a47e31c89c6..e740ef87cd8 100644 --- a/dlls/gdi32/dibdrv/primitives.c +++ b/dlls/gdi32/dibdrv/primitives.c @@ -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; } diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index ab3c9bb1416..1eba2909683 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -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; diff --git a/dlls/gdi32/tests/dib.c b/dlls/gdi32/tests/dib.c index 999913f7511..188001e5606 100644 --- a/dlls/gdi32/tests/dib.c +++ b/dlls/gdi32/tests/dib.c @@ -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 );