diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index 0650e08272e..6ef0d946dd9 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -90,6 +90,9 @@ typedef struct dibdrv_physdev DWORD brush_color, brush_and, brush_xor; dib_info brush_dib; void *brush_and_bits, *brush_xor_bits; + const BITMAPINFO *brush_pattern_info; + void *brush_pattern_bits; + UINT brush_pattern_usage; BOOL (* brush_rects)(struct dibdrv_physdev *pdev, dib_info *dib, int num, const RECT *rects, HRGN clip); /* background */ diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index 3418dc86d0d..cf714b5f68e 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -1246,6 +1246,30 @@ static BOOL create_hatch_brush_bits(dibdrv_physdev *pdev) return ret; } +static void select_pattern_brush( dibdrv_physdev *pdev, dib_info *pattern ) +{ + RECT rect; + + free_pattern_brush( pdev ); + copy_dib_color_info(&pdev->brush_dib, &pdev->dib); + + pdev->brush_dib.height = pattern->height; + pdev->brush_dib.width = pattern->width; + pdev->brush_dib.stride = get_dib_stride( pdev->brush_dib.width, pdev->brush_dib.bit_count ); + + pdev->brush_dib.bits.param = NULL; + pdev->brush_dib.bits.ptr = HeapAlloc( GetProcessHeap(), 0, + pdev->brush_dib.height * pdev->brush_dib.stride ); + pdev->brush_dib.bits.is_copy = TRUE; + pdev->brush_dib.bits.free = free_heap_bits; + + rect.left = rect.top = 0; + rect.right = pattern->width; + rect.bottom = pattern->height; + + pdev->brush_dib.funcs->convert_to(&pdev->brush_dib, pattern, &rect); +} + /********************************************************************** * pattern_brush * @@ -1263,6 +1287,16 @@ static BOOL pattern_brush(dibdrv_physdev *pdev, dib_info *dib, int num, const RE switch(pdev->brush_style) { case BS_DIBPATTERN: + if (pdev->brush_pattern_usage == DIB_PAL_COLORS) + { + dib_info pattern; + HPALETTE pal = GetCurrentObject( pdev->dev.hdc, OBJ_PAL ); + if (!init_dib_info_from_brush( &pattern, pdev->brush_pattern_info, + pdev->brush_pattern_bits, DIB_PAL_COLORS, pal )) + return FALSE; + select_pattern_brush( pdev, &pattern ); + free_dib_info( &pattern ); + } if(!create_pattern_brush_bits(pdev)) return FALSE; break; @@ -1317,6 +1351,11 @@ static BOOL pattern_brush(dibdrv_physdev *pdev, dib_info *dib, int num, const RE } } release_wine_region( region ); + + /* we need to recompute the bits each time for DIB_PAL_COLORS */ + if (pdev->brush_style == BS_DIBPATTERN && pdev->brush_pattern_usage == DIB_PAL_COLORS) + free_pattern_brush_bits( pdev ); + return TRUE; } @@ -1347,9 +1386,7 @@ HBRUSH dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, HBITMAP bitmap, if (bitmap || info) /* pattern brush */ { - dib_info orig_dib; - HPALETTE pal = (usage == DIB_PAL_COLORS) ? GetCurrentObject(dev->hdc, OBJ_PAL) : NULL; - RECT rect; + dib_info pattern; BOOL ret; if (!info) @@ -1357,37 +1394,30 @@ HBRUSH dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, HBITMAP bitmap, BITMAPOBJ *bmp = GDI_GetObjPtr( bitmap, OBJ_BITMAP ); if (!bmp) return 0; - ret = init_dib_info_from_bitmapobj( &orig_dib, bmp, 0 ); + ret = init_dib_info_from_bitmapobj( &pattern, bmp, 0 ); GDI_ReleaseObj( bitmap ); + if (!ret) return 0; + select_pattern_brush( pdev, &pattern ); + free_dib_info( &pattern ); + } + else if (usage != DIB_PAL_COLORS) + { + if (!init_dib_info_from_brush( &pattern, info, bits, DIB_RGB_COLORS, 0 )) return 0; + select_pattern_brush( pdev, &pattern ); + free_dib_info( &pattern ); + } + else + { + /* brush is actually selected only when it's used */ + free_pattern_brush( pdev ); } - else ret = init_dib_info_from_brush( &orig_dib, info, bits, usage, pal ); - if (!ret) return 0; - - if (usage == DIB_PAL_COLORS) FIXME( "DIB_PAL_COLORS brush not handled correctly\n"); - - free_pattern_brush( pdev ); - copy_dib_color_info(&pdev->brush_dib, &pdev->dib); - - pdev->brush_dib.height = orig_dib.height; - pdev->brush_dib.width = orig_dib.width; - pdev->brush_dib.stride = get_dib_stride( pdev->brush_dib.width, pdev->brush_dib.bit_count ); - - pdev->brush_dib.bits.param = NULL; - pdev->brush_dib.bits.ptr = HeapAlloc( GetProcessHeap(), 0, - pdev->brush_dib.height * pdev->brush_dib.stride ); - pdev->brush_dib.bits.is_copy = TRUE; - pdev->brush_dib.bits.free = free_heap_bits; - - rect.left = rect.top = 0; - rect.right = orig_dib.width; - rect.bottom = orig_dib.height; - - pdev->brush_dib.funcs->convert_to(&pdev->brush_dib, &orig_dib, &rect); pdev->brush_rects = pattern_brush; pdev->brush_style = BS_DIBPATTERN; + pdev->brush_pattern_info = info; + pdev->brush_pattern_bits = bits; + pdev->brush_pattern_usage = usage; pdev->defer &= ~DEFER_BRUSH; - free_dib_info(&orig_dib); return next->funcs->pSelectBrush( next, hbrush, bitmap, info, bits, usage ); } diff --git a/dlls/gdi32/tests/brush.c b/dlls/gdi32/tests/brush.c index f0ef2dfc31c..c6c76785e8f 100644 --- a/dlls/gdi32/tests/brush.c +++ b/dlls/gdi32/tests/brush.c @@ -288,7 +288,7 @@ static void test_palette_brush(void) pal->palPalEntry[255 - i].peGreen << 8 | pal->palPalEntry[255 - i].peBlue); if (expect) - todo_wine ok( dib_bits[i] == expect, "wrong bits %x/%x at %u,%u\n", dib_bits[i], expect, i % 16, i / 16 ); + ok( dib_bits[i] == expect, "wrong bits %x/%x at %u,%u\n", dib_bits[i], expect, i % 16, i / 16 ); else ok( dib_bits[i] == expect, "wrong bits %x/%x at %u,%u\n", dib_bits[i], expect, i % 16, i / 16 ); }