gdi32: Implement SelectBrush for DIB pattern brushes.
This commit is contained in:
parent
5ac51cd24f
commit
3c70a26e4b
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue