Commit 3c70a26e authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

gdi32: Implement SelectBrush for DIB pattern brushes.

parent 5ac51cd2
......@@ -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;
......
......@@ -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)
{
......
......@@ -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;
}
......
......@@ -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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment