From 66399f6f726fdd69d6b5ab4f2f19a34fa5331205 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Fri, 17 Jun 2011 12:45:36 +0100 Subject: [PATCH] gdi32: Add support for hatched brushes. --- dlls/gdi32/dibdrv/dibdrv.h | 1 + dlls/gdi32/dibdrv/objects.c | 111 +++++++++++++++++- dlls/gdi32/dibdrv/primitives.c | 255 +++++++++++++++++++++++++++++++++++++++-- dlls/gdi32/gdi_private.h | 13 +++ 4 files changed, 369 insertions(+), 11 deletions(-) diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index eb8f2045e8d..2e0cadf25b4 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -43,6 +43,7 @@ typedef struct primitive_funcs void (* pattern_rects)(const dib_info *dib, int num, const RECT *rc, const POINT *orign, const dib_info *brush, void *and_bits, void *xor_bits); DWORD (* colorref_to_pixel)(const dib_info *dib, COLORREF color); BOOL (* convert_to)(dib_info *dst, const dib_info *src, const RECT *src_rect); + BOOL (* create_rop_masks)(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits); } primitive_funcs; extern const primitive_funcs funcs_8888 DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index 2e9ece1a59b..69faaeba015 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -161,6 +161,28 @@ static inline void get_pen_bkgnd_masks(const dibdrv_physdev *pdev, DWORD *and, D } } +static inline void get_brush_bkgnd_masks(const dibdrv_physdev *pdev, DWORD *and, DWORD *xor) +{ + if(GetBkMode(pdev->dev.hdc) == TRANSPARENT) + { + *and = pdev->bkgnd_and; + *xor = pdev->bkgnd_xor; + } + else + { + DWORD color = pdev->bkgnd_color; + + if(pdev->dib.bit_count == 1) + { + if(pdev->brush_colorref == GetBkColor(pdev->dev.hdc)) + color = pdev->brush_color; + else + color = ~pdev->brush_color; + } + calc_and_xor_masks( pdev->brush_rop, color, and, xor ); + } +} + static inline void order_end_points(int *s, int *e) { if(*s > *e) @@ -1083,6 +1105,63 @@ static BOOL create_pattern_brush_bits(dibdrv_physdev *pdev) return TRUE; } +static const DWORD hatches[6][8] = +{ + { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }, /* HS_HORIZONTAL */ + { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, /* HS_VERTICAL */ + { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, /* HS_FDIAGONAL */ + { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, /* HS_BDIAGONAL */ + { 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08 }, /* HS_CROSS */ + { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 } /* HS_DIAGCROSS */ +}; + +static BOOL create_hatch_brush_bits(dibdrv_physdev *pdev) +{ + dib_info hatch; + rop_mask fg_mask, bg_mask; + rop_mask_bits mask_bits; + DWORD size; + BOOL ret; + + assert(pdev->brush_and_bits == NULL); + assert(pdev->brush_xor_bits == NULL); + + /* Just initialise brush_dib with the color / sizing info. We don't + need the bits as we'll calculate the rop masks straight from + the hatch patterns. */ + + copy_dib_color_info(&pdev->brush_dib, &pdev->dib); + pdev->brush_dib.width = 8; + pdev->brush_dib.height = 8; + pdev->brush_dib.stride = ((pdev->brush_dib.width * pdev->brush_dib.bit_count + 31) >> 3) & ~3; + + size = pdev->brush_dib.height * pdev->brush_dib.stride; + + mask_bits.and = pdev->brush_and_bits = HeapAlloc(GetProcessHeap(), 0, size); + mask_bits.xor = pdev->brush_xor_bits = HeapAlloc(GetProcessHeap(), 0, size); + + if(!mask_bits.and || !mask_bits.xor) + { + ERR("Failed to create pattern brush bits\n"); + free_pattern_brush_bits( pdev ); + return FALSE; + } + + hatch.bit_count = 1; + hatch.height = hatch.width = 8; + hatch.stride = 4; + hatch.bits = (void *) hatches[pdev->brush_hatch]; + + fg_mask.and = pdev->brush_and; + fg_mask.xor = pdev->brush_xor; + get_brush_bkgnd_masks( pdev, &bg_mask.and, &bg_mask.xor ); + + ret = pdev->brush_dib.funcs->create_rop_masks( &pdev->brush_dib, &hatch, &fg_mask, &bg_mask, &mask_bits ); + if(!ret) free_pattern_brush_bits( pdev ); + + return ret; +} + /********************************************************************** * pattern_brush * @@ -1096,8 +1175,24 @@ static BOOL pattern_brush(dibdrv_physdev *pdev, int num, RECT *rects) POINT origin; if(pdev->brush_and_bits == NULL) - if(!create_pattern_brush_bits(pdev)) + { + switch(pdev->brush_style) + { + case BS_DIBPATTERN: + if(!create_pattern_brush_bits(pdev)) + return FALSE; + break; + + case BS_HATCHED: + if(!create_hatch_brush_bits(pdev)) + return FALSE; + break; + + default: + ERR("Unexpected brush style %d\n", pdev->brush_style); return FALSE; + } + } GetBrushOrgEx(pdev->dev.hdc, &origin); @@ -1142,7 +1237,7 @@ static BOOL null_brush(dibdrv_physdev *pdev, int num, RECT *rects) void update_brush_rop( dibdrv_physdev *pdev, INT rop ) { pdev->brush_rop = rop; - if(pdev->brush_style == BS_SOLID) + if(pdev->brush_style == BS_SOLID || pdev->brush_style == BS_HATCHED) calc_and_xor_masks(rop, pdev->brush_color, &pdev->brush_and, &pdev->brush_xor); free_pattern_brush_bits( pdev ); } @@ -1206,6 +1301,18 @@ HBRUSH CDECL dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush ) break; } + case BS_HATCHED: + { + if(logbrush.lbHatch > HS_DIAGCROSS) return 0; + pdev->brush_hatch = logbrush.lbHatch; + pdev->brush_colorref = logbrush.lbColor; + pdev->brush_color = get_fg_color( pdev, pdev->brush_colorref ); + calc_and_xor_masks(GetROP2(dev->hdc), pdev->brush_color, &pdev->brush_and, &pdev->brush_xor); + pdev->brush_rects = pattern_brush; + pdev->defer &= ~DEFER_BRUSH; + break; + } + default: break; } diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c index c6751db8b17..68eb4ae568d 100644 --- a/dlls/gdi32/dibdrv/primitives.c +++ b/dlls/gdi32/dibdrv/primitives.c @@ -2194,12 +2194,241 @@ static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_ return FALSE; } +static BOOL create_rop_masks_32(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits) +{ + BYTE *hatch_start = hatch->bits, *hatch_ptr; + DWORD mask_start = 0, mask_offset; + DWORD *and_bits = bits->and, *xor_bits = bits->xor; + int x, y; + + for(y = 0; y < hatch->height; y++) + { + hatch_ptr = hatch_start; + mask_offset = mask_start; + for(x = 0; x < hatch->width; x++) + { + if(*hatch_ptr & pixel_masks_1[x % 8]) + { + and_bits[mask_offset] = fg->and; + xor_bits[mask_offset] = fg->xor; + } + else + { + and_bits[mask_offset] = bg->and; + xor_bits[mask_offset] = bg->xor; + } + if(x % 8 == 7) hatch_ptr++; + mask_offset++; + } + hatch_start += hatch->stride; + mask_start += dib->stride / 4; + } + + return TRUE; +} + +static BOOL create_rop_masks_24(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits) +{ + BYTE *hatch_start = hatch->bits, *hatch_ptr; + DWORD mask_start = 0, mask_offset; + BYTE *and_bits = bits->and, *xor_bits = bits->xor; + int x, y; + + for(y = 0; y < hatch->height; y++) + { + hatch_ptr = hatch_start; + mask_offset = mask_start; + for(x = 0; x < hatch->width; x++) + { + if(*hatch_ptr & pixel_masks_1[x % 8]) + { + and_bits[mask_offset] = fg->and & 0xff; + xor_bits[mask_offset++] = fg->xor & 0xff; + and_bits[mask_offset] = (fg->and >> 8) & 0xff; + xor_bits[mask_offset++] = (fg->xor >> 8) & 0xff; + and_bits[mask_offset] = (fg->and >> 16) & 0xff; + xor_bits[mask_offset++] = (fg->xor >> 16) & 0xff; + } + else + { + and_bits[mask_offset] = bg->and & 0xff; + xor_bits[mask_offset++] = bg->xor & 0xff; + and_bits[mask_offset] = (bg->and >> 8) & 0xff; + xor_bits[mask_offset++] = (bg->xor >> 8) & 0xff; + and_bits[mask_offset] = (bg->and >> 16) & 0xff; + xor_bits[mask_offset++] = (bg->xor >> 16) & 0xff; + } + if(x % 8 == 7) hatch_ptr++; + } + hatch_start += hatch->stride; + mask_start += dib->stride; + } + + return TRUE; +} + +static BOOL create_rop_masks_16(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits) +{ + BYTE *hatch_start = hatch->bits, *hatch_ptr; + DWORD mask_start = 0, mask_offset; + WORD *and_bits = bits->and, *xor_bits = bits->xor; + int x, y; + + for(y = 0; y < hatch->height; y++) + { + hatch_ptr = hatch_start; + mask_offset = mask_start; + for(x = 0; x < hatch->width; x++) + { + if(*hatch_ptr & pixel_masks_1[x % 8]) + { + and_bits[mask_offset] = fg->and; + xor_bits[mask_offset] = fg->xor; + } + else + { + and_bits[mask_offset] = bg->and; + xor_bits[mask_offset] = bg->xor; + } + if(x % 8 == 7) hatch_ptr++; + mask_offset++; + } + hatch_start += hatch->stride; + mask_start += dib->stride / 2; + } + + return TRUE; +} + +static BOOL create_rop_masks_8(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits) +{ + BYTE *hatch_start = hatch->bits, *hatch_ptr; + DWORD mask_start = 0, mask_offset; + BYTE *and_bits = bits->and, *xor_bits = bits->xor; + int x, y; + + for(y = 0; y < hatch->height; y++) + { + hatch_ptr = hatch_start; + mask_offset = mask_start; + for(x = 0; x < hatch->width; x++) + { + if(*hatch_ptr & pixel_masks_1[x % 8]) + { + and_bits[mask_offset] = fg->and; + xor_bits[mask_offset] = fg->xor; + } + else + { + and_bits[mask_offset] = bg->and; + xor_bits[mask_offset] = bg->xor; + } + if(x % 8 == 7) hatch_ptr++; + mask_offset++; + } + hatch_start += hatch->stride; + mask_start += dib->stride; + } + + return TRUE; +} + +static BOOL create_rop_masks_4(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits) +{ + BYTE *hatch_start = hatch->bits, *hatch_ptr; + DWORD mask_start = 0, mask_offset; + BYTE *and_bits = bits->and, *xor_bits = bits->xor; + const rop_mask *rop_mask; + int x, y; + + for(y = 0; y < hatch->height; y++) + { + hatch_ptr = hatch_start; + mask_offset = mask_start; + for(x = 0; x < hatch->width; x++) + { + if(*hatch_ptr & pixel_masks_1[x % 8]) + rop_mask = fg; + else + rop_mask = bg; + + if(x & 1) + { + and_bits[mask_offset] = (rop_mask->and & 0x0f) | (and_bits[mask_offset] & 0xf0); + xor_bits[mask_offset] = (rop_mask->xor & 0x0f) | (xor_bits[mask_offset] & 0xf0); + mask_offset++; + } + else + { + and_bits[mask_offset] = (rop_mask->and << 4) & 0xf0; + xor_bits[mask_offset] = (rop_mask->xor << 4) & 0xf0; + } + + if(x % 8 == 7) hatch_ptr++; + } + hatch_start += hatch->stride; + mask_start += dib->stride; + } + + return TRUE; +} + +static BOOL create_rop_masks_1(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits) +{ + BYTE *hatch_start = hatch->bits, *hatch_ptr; + DWORD mask_start = 0, mask_offset; + BYTE *and_bits = bits->and, *xor_bits = bits->xor; + rop_mask rop_mask; + int x, y, bit_pos; + + for(y = 0; y < hatch->height; y++) + { + hatch_ptr = hatch_start; + mask_offset = mask_start; + for(x = 0, bit_pos = 0; x < hatch->width; x++) + { + if(*hatch_ptr & pixel_masks_1[x % 8]) + { + rop_mask.and = (fg->and & 1) ? 0xff : 0; + rop_mask.xor = (fg->xor & 1) ? 0xff : 0; + } + else + { + rop_mask.and = (bg->and & 1) ? 0xff : 0; + rop_mask.xor = (bg->xor & 1) ? 0xff : 0; + } + + if(bit_pos == 0) and_bits[mask_offset] = xor_bits[mask_offset] = 0; + + and_bits[mask_offset] = (rop_mask.and & pixel_masks_1[bit_pos]) | (and_bits[mask_offset] & ~pixel_masks_1[bit_pos]); + xor_bits[mask_offset] = (rop_mask.xor & pixel_masks_1[bit_pos]) | (xor_bits[mask_offset] & ~pixel_masks_1[bit_pos]); + + if(++bit_pos == 8) + { + mask_offset++; + hatch_ptr++; + bit_pos = 0; + } + } + hatch_start += hatch->stride; + mask_start += dib->stride; + } + + return TRUE; +} + +static BOOL create_rop_masks_null(const dib_info *dib, const dib_info *hatch, const rop_mask *fg, const rop_mask *bg, rop_mask_bits *bits) +{ + return FALSE; +} + const primitive_funcs funcs_8888 = { solid_rects_32, pattern_rects_32, colorref_to_pixel_888, - convert_to_8888 + convert_to_8888, + create_rop_masks_32 }; const primitive_funcs funcs_32 = @@ -2207,7 +2436,8 @@ const primitive_funcs funcs_32 = solid_rects_32, pattern_rects_32, colorref_to_pixel_masks, - convert_to_32 + convert_to_32, + create_rop_masks_32 }; const primitive_funcs funcs_24 = @@ -2215,7 +2445,8 @@ const primitive_funcs funcs_24 = solid_rects_24, pattern_rects_24, colorref_to_pixel_888, - convert_to_24 + convert_to_24, + create_rop_masks_24 }; const primitive_funcs funcs_555 = @@ -2223,7 +2454,8 @@ const primitive_funcs funcs_555 = solid_rects_16, pattern_rects_16, colorref_to_pixel_555, - convert_to_555 + convert_to_555, + create_rop_masks_16 }; const primitive_funcs funcs_16 = @@ -2231,7 +2463,8 @@ const primitive_funcs funcs_16 = solid_rects_16, pattern_rects_16, colorref_to_pixel_masks, - convert_to_16 + convert_to_16, + create_rop_masks_16 }; const primitive_funcs funcs_8 = @@ -2239,7 +2472,8 @@ const primitive_funcs funcs_8 = solid_rects_8, pattern_rects_8, colorref_to_pixel_colortable, - convert_to_8 + convert_to_8, + create_rop_masks_8 }; const primitive_funcs funcs_4 = @@ -2247,7 +2481,8 @@ const primitive_funcs funcs_4 = solid_rects_4, pattern_rects_4, colorref_to_pixel_colortable, - convert_to_4 + convert_to_4, + create_rop_masks_4 }; const primitive_funcs funcs_1 = @@ -2255,7 +2490,8 @@ const primitive_funcs funcs_1 = solid_rects_1, pattern_rects_1, colorref_to_pixel_colortable, - convert_to_1 + convert_to_1, + create_rop_masks_1 }; const primitive_funcs funcs_null = @@ -2263,5 +2499,6 @@ const primitive_funcs funcs_null = solid_rects_null, pattern_rects_null, colorref_to_pixel_null, - convert_to_null + convert_to_null, + create_rop_masks_null }; diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 7d1240b1197..cc3592fb48a 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -109,6 +109,18 @@ typedef struct BOOL mark; } dash_pos; +typedef struct +{ + DWORD and; + DWORD xor; +} rop_mask; + +typedef struct +{ + void *and; + void *xor; +} rop_mask_bits; + typedef struct dibdrv_physdev { struct gdi_physdev dev; @@ -126,6 +138,7 @@ typedef struct dibdrv_physdev /* brush */ UINT brush_style; + UINT brush_hatch; INT brush_rop; /* PatBlt, for example, can override the DC's rop2 */ COLORREF brush_colorref; DWORD brush_color, brush_and, brush_xor; -- 2.11.4.GIT