gdi32: Add support for hatched brushes.
This commit is contained in:
parent
68b15bc5ff
commit
66399f6f72
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue