Huw Davies : gdi32: Implement SelectBrush for DIB pattern brushes.
Alexandre Julliard
julliard at winehq.org
Thu May 12 13:57:51 CDT 2011
Module: wine
Branch: master
Commit: 3c70a26e4b8b2814b44ef6e284a750a369404a3a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=3c70a26e4b8b2814b44ef6e284a750a369404a3a
Author: Huw Davies <huw at 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 */
More information about the wine-cvs
mailing list