Module: wine Branch: master Commit: 3c70a26e4b8b2814b44ef6e284a750a369404a3a URL: http://source.winehq.org/git/wine.git/?a=commit;h=3c70a26e4b8b2814b44ef6e284...
Author: Huw Davies huw@codeweavers.com Date: Thu May 12 12:05:37 2011 +0100
gdi32: Implement SelectBrush for DIB pattern brushes.
---
dlls/gdi32/dibdrv/dc.c | 102 ++++++++++++++++++++++++++++++++++++++++++- dlls/gdi32/dibdrv/dibdrv.h | 5 ++ dlls/gdi32/dibdrv/objects.c | 49 ++++++++++++++++++++ dlls/gdi32/gdi_private.h | 2 + 4 files changed, 157 insertions(+), 1 deletions(-)
diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index a9a53ad..7a11bec 100644 --- a/dlls/gdi32/dibdrv/dc.c +++ b/dlls/gdi32/dibdrv/dc.c @@ -108,6 +108,29 @@ static BOOL init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD return TRUE; }
+BOOL init_dib_info_from_packed(dib_info *dib, const BITMAPINFOHEADER *bi, WORD usage) +{ + DWORD *masks = NULL; + RGBQUAD *color_table = NULL; + BYTE *ptr = (BYTE*)bi + bi->biSize; + int num_colors = bi->biClrUsed; + + if(bi->biCompression == BI_BITFIELDS) + { + masks = (DWORD *)ptr; + ptr += 3 * sizeof(DWORD); + } + + if(!num_colors && bi->biBitCount <= 8) num_colors = 1 << bi->biBitCount; + if(num_colors) color_table = (RGBQUAD*)ptr; + if(usage == DIB_PAL_COLORS) + ptr += num_colors * sizeof(WORD); + else + ptr += num_colors * sizeof(*color_table); + + return init_dib_info(dib, bi, masks, ptr); +} + static void clear_dib_info(dib_info *dib) { dib->bits = NULL; @@ -118,7 +141,7 @@ static void clear_dib_info(dib_info *dib) * * Free the resources associated with a dib and optionally the bits */ -static void free_dib_info(dib_info *dib, BOOL free_bits) +void free_dib_info(dib_info *dib, BOOL free_bits) { if(free_bits) { @@ -127,6 +150,80 @@ static void free_dib_info(dib_info *dib, BOOL free_bits) } }
+void copy_dib_color_info(dib_info *dst, const dib_info *src) +{ + dst->bit_count = src->bit_count; + dst->red_mask = src->red_mask; + dst->green_mask = src->green_mask; + dst->blue_mask = src->blue_mask; + dst->red_len = src->red_len; + dst->green_len = src->green_len; + dst->blue_len = src->blue_len; + dst->red_shift = src->red_shift; + dst->green_shift = src->green_shift; + dst->blue_shift = src->blue_shift; + dst->funcs = src->funcs; +} + +static BOOL dib_formats_match(const dib_info *d1, const dib_info *d2) +{ + if(d1->bit_count != d2->bit_count) return FALSE; + + switch(d1->bit_count) + { + case 24: return TRUE; + + case 32: + case 16: + return (d1->red_mask == d2->red_mask) && (d1->green_mask == d2->green_mask) && + (d1->blue_mask == d2->blue_mask); + + default: + ERR("Unexpected depth %d\n", d1->bit_count); + return FALSE; + } +} + +/************************************************************** + * convert_dib + * + * Converts src into the format specified in dst. + * + * FIXME: At the moment this always creates a top-down dib, + * do we want to give the option of bottom-up? + */ +BOOL convert_dib(dib_info *dst, const dib_info *src) +{ + INT y; + + dst->height = src->height; + dst->width = src->width; + dst->stride = ((dst->width * dst->bit_count + 31) >> 3) & ~3; + dst->bits = NULL; + + if(dib_formats_match(src, dst)) + { + dst->bits = HeapAlloc(GetProcessHeap(), 0, dst->height * dst->stride); + + if(src->stride > 0) + memcpy(dst->bits, src->bits, dst->height * dst->stride); + else + { + BYTE *src_bits = src->bits; + BYTE *dst_bits = dst->bits; + for(y = 0; y < dst->height; y++) + { + memcpy(dst_bits, src_bits, dst->stride); + dst_bits += dst->stride; + src_bits += src->stride; + } + } + return TRUE; + } + FIXME("Format conversion not implemented\n"); + return FALSE; +} + /*********************************************************************** * dibdrv_DeleteDC */ @@ -135,6 +232,7 @@ static BOOL CDECL dibdrv_DeleteDC( PHYSDEV dev ) dibdrv_physdev *pdev = get_dibdrv_pdev(dev); TRACE("(%p)\n", dev); DeleteObject(pdev->clip); + free_pattern_brush(pdev); free_dib_info(&pdev->dib, FALSE); return 0; } @@ -156,6 +254,8 @@ static HBITMAP CDECL dibdrv_SelectBitmap( PHYSDEV dev, HBITMAP bitmap ) pdev->defer = 0;
clear_dib_info(&pdev->dib); + clear_dib_info(&pdev->brush_dib); + pdev->brush_and_bits = pdev->brush_xor_bits = NULL;
if(!init_dib_info(&pdev->dib, &bmp->dib->dsBmih, bmp->dib->dsBitfields, bmp->dib->dsBm.bmBits)) pdev->defer |= DEFER_FORMAT; diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index 7327fca..1982866 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -48,6 +48,11 @@ extern const primitive_funcs funcs_null DECLSPEC_HIDDEN; extern void calc_and_xor_masks(INT rop, DWORD color, DWORD *and, DWORD *xor) DECLSPEC_HIDDEN; extern void update_brush_rop( dibdrv_physdev *pdev, INT rop ) DECLSPEC_HIDDEN; extern void reset_dash_origin(dibdrv_physdev *pdev) DECLSPEC_HIDDEN; +extern BOOL init_dib_info_from_packed(dib_info *dib, const BITMAPINFOHEADER *bi, WORD usage) DECLSPEC_HIDDEN; +extern void free_dib_info(dib_info *dib, BOOL free_bits) DECLSPEC_HIDDEN; +extern void free_pattern_brush(dibdrv_physdev *pdev) DECLSPEC_HIDDEN; +extern void copy_dib_color_info(dib_info *dst, const dib_info *src) DECLSPEC_HIDDEN; +extern BOOL convert_dib(dib_info *dst, const dib_info *src) DECLSPEC_HIDDEN;
static inline BOOL defer_pen(dibdrv_physdev *pdev) { diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index 52aab44..dde7a96 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -956,11 +956,37 @@ static BOOL solid_brush(dibdrv_physdev *pdev, int num, RECT *rects) return TRUE; }
+/********************************************************************** + * pattern_brush + * + * Fill a number of rectangles with the pattern brush + * FIXME: Should we insist l < r && t < b? Currently we assume this. + */ +static BOOL pattern_brush(dibdrv_physdev *pdev, int num, RECT *rects) +{ + return FALSE; +} + +static void free_pattern_brush_bits( dibdrv_physdev *pdev ) +{ + HeapFree(GetProcessHeap(), 0, pdev->brush_and_bits); + HeapFree(GetProcessHeap(), 0, pdev->brush_xor_bits); + pdev->brush_and_bits = NULL; + pdev->brush_xor_bits = NULL; +} + +void free_pattern_brush( dibdrv_physdev *pdev ) +{ + free_pattern_brush_bits( pdev ); + free_dib_info( &pdev->brush_dib, TRUE ); +} + void update_brush_rop( dibdrv_physdev *pdev, INT rop ) { pdev->brush_rop = rop; if(pdev->brush_style == BS_SOLID) calc_and_xor_masks(rop, pdev->brush_color, &pdev->brush_and, &pdev->brush_xor); + free_pattern_brush_bits( pdev ); }
/*********************************************************************** @@ -983,6 +1009,8 @@ HBRUSH CDECL dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
pdev->defer |= DEFER_BRUSH;
+ free_pattern_brush( pdev ); + switch(logbrush.lbStyle) { case BS_SOLID: @@ -991,6 +1019,27 @@ HBRUSH CDECL dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush ) pdev->brush_rects = solid_brush; pdev->defer &= ~DEFER_BRUSH; break; + + case BS_DIBPATTERN: + { + BITMAPINFOHEADER *bi = GlobalLock((HGLOBAL)logbrush.lbHatch); + dib_info orig_dib; + + if(!bi) return NULL; + if(init_dib_info_from_packed(&orig_dib, bi, LOWORD(logbrush.lbColor))) + { + copy_dib_color_info(&pdev->brush_dib, &pdev->dib); + if(convert_dib(&pdev->brush_dib, &orig_dib)) + { + pdev->brush_rects = pattern_brush; + pdev->defer &= ~DEFER_BRUSH; + } + free_dib_info(&orig_dib, FALSE); + } + GlobalUnlock((HGLOBAL)logbrush.lbHatch); + break; + } + default: break; } diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 9cb528c..0f59f48 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -124,6 +124,8 @@ typedef struct dibdrv_physdev UINT brush_style; INT brush_rop; /* PatBlt, for example, can override the DC's rop2 */ DWORD brush_color, brush_and, brush_xor; + dib_info brush_dib; + void *brush_and_bits, *brush_xor_bits; BOOL (* brush_rects)(struct dibdrv_physdev *pdev, int num, RECT *rects);
/* background */