gdi32: Always store a copy of the bitmap bits for pattern brushes.
This commit is contained in:
parent
8a86f6c993
commit
a196ad8fc1
|
@ -55,88 +55,37 @@ static const struct gdi_obj_funcs brush_funcs =
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* fetch the contents of the brush bitmap and cache them in the brush pattern */
|
static BOOL copy_bitmap( struct brush_pattern *brush, HBITMAP bitmap )
|
||||||
void cache_pattern_bits( PHYSDEV physdev, struct brush_pattern *pattern )
|
|
||||||
{
|
{
|
||||||
|
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256])];
|
||||||
|
BITMAPINFO *info = (BITMAPINFO *)buffer;
|
||||||
struct gdi_image_bits bits;
|
struct gdi_image_bits bits;
|
||||||
struct bitblt_coords src;
|
struct bitblt_coords src;
|
||||||
BITMAPINFO *info;
|
BITMAPOBJ *bmp = GDI_GetObjPtr( bitmap, OBJ_BITMAP );
|
||||||
BITMAPOBJ *bmp;
|
|
||||||
|
|
||||||
if (pattern->info) return; /* already cached */
|
if (!bmp) return FALSE;
|
||||||
if (!(bmp = GDI_GetObjPtr( pattern->bitmap, OBJ_BITMAP ))) return;
|
|
||||||
|
|
||||||
/* we don't need to cache if we are selecting into the same type of DC */
|
|
||||||
if (physdev && bmp->funcs == physdev->funcs) goto done;
|
|
||||||
|
|
||||||
if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
|
|
||||||
|
|
||||||
src.visrect.left = src.x = 0;
|
src.visrect.left = src.x = 0;
|
||||||
src.visrect.top = src.y = 0;
|
src.visrect.top = src.y = 0;
|
||||||
src.visrect.right = src.width = bmp->dib.dsBm.bmWidth;
|
src.visrect.right = src.width = bmp->dib.dsBm.bmWidth;
|
||||||
src.visrect.bottom = src.height = bmp->dib.dsBm.bmHeight;
|
src.visrect.bottom = src.height = bmp->dib.dsBm.bmHeight;
|
||||||
if (bmp->funcs->pGetImage( NULL, pattern->bitmap, info, &bits, &src ))
|
if (bmp->funcs->pGetImage( NULL, bitmap, info, &bits, &src )) goto done;
|
||||||
|
|
||||||
|
brush->bits = bits;
|
||||||
|
if (!bits.free)
|
||||||
{
|
{
|
||||||
HeapFree( GetProcessHeap(), 0, info );
|
if (!(brush->bits.ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ))) goto done;
|
||||||
|
memcpy( brush->bits.ptr, bits.ptr, info->bmiHeader.biSizeImage );
|
||||||
|
brush->bits.free = free_heap_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(brush->info = HeapAlloc( GetProcessHeap(), 0, get_dib_info_size( info, DIB_RGB_COLORS ))))
|
||||||
|
{
|
||||||
|
if (brush->bits.free) brush->bits.free( &brush->bits );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
memcpy( brush->info, info, get_dib_info_size( info, DIB_RGB_COLORS ));
|
||||||
/* release the unneeded space */
|
brush->bits.is_copy = FALSE; /* the bits can't be modified */
|
||||||
HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, info,
|
|
||||||
get_dib_info_size( info, DIB_RGB_COLORS ));
|
|
||||||
pattern->info = info;
|
|
||||||
pattern->bits = bits;
|
|
||||||
pattern->usage = DIB_RGB_COLORS;
|
|
||||||
|
|
||||||
done:
|
|
||||||
GDI_ReleaseObj( pattern->bitmap );
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL copy_bitmap( struct brush_pattern *brush, HBITMAP bitmap )
|
|
||||||
{
|
|
||||||
BITMAPINFO *info;
|
|
||||||
BITMAPOBJ *bmp = GDI_GetObjPtr( bitmap, OBJ_BITMAP );
|
|
||||||
|
|
||||||
if (!bmp) return FALSE;
|
|
||||||
|
|
||||||
if (!is_bitmapobj_dib( bmp ))
|
|
||||||
{
|
|
||||||
if ((brush->bitmap = CreateBitmap( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmHeight,
|
|
||||||
bmp->dib.dsBm.bmPlanes, bmp->dib.dsBm.bmBitsPixel, NULL )))
|
|
||||||
{
|
|
||||||
if (bmp->funcs->pCopyBitmap( bitmap, brush->bitmap ))
|
|
||||||
{
|
|
||||||
BITMAPOBJ *copy = GDI_GetObjPtr( brush->bitmap, OBJ_BITMAP );
|
|
||||||
copy->funcs = bmp->funcs;
|
|
||||||
GDI_ReleaseObj( copy );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DeleteObject( brush->bitmap );
|
|
||||||
brush->bitmap = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GDI_ReleaseObj( bitmap );
|
|
||||||
return brush->bitmap != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
info = HeapAlloc( GetProcessHeap(), 0,
|
|
||||||
get_dib_info_size( (BITMAPINFO *)&bmp->dib.dsBmih, DIB_RGB_COLORS ));
|
|
||||||
if (!info) goto done;
|
|
||||||
info->bmiHeader = bmp->dib.dsBmih;
|
|
||||||
if (info->bmiHeader.biCompression == BI_BITFIELDS)
|
|
||||||
memcpy( &info->bmiHeader + 1, bmp->dib.dsBitfields, sizeof(bmp->dib.dsBitfields) );
|
|
||||||
else if (info->bmiHeader.biClrUsed)
|
|
||||||
memcpy( &info->bmiHeader + 1, bmp->color_table, info->bmiHeader.biClrUsed * sizeof(RGBQUAD) );
|
|
||||||
if (!(brush->bits.ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
|
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, info );
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
memcpy( brush->bits.ptr, bmp->dib.dsBm.bmBits, info->bmiHeader.biSizeImage );
|
|
||||||
brush->bits.is_copy = TRUE;
|
|
||||||
brush->bits.free = free_heap_bits;
|
|
||||||
brush->info = info;
|
|
||||||
brush->usage = DIB_RGB_COLORS;
|
brush->usage = DIB_RGB_COLORS;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -200,7 +149,6 @@ BOOL store_brush_pattern( LOGBRUSH *brush, struct brush_pattern *pattern )
|
||||||
void free_brush_pattern( struct brush_pattern *pattern )
|
void free_brush_pattern( struct brush_pattern *pattern )
|
||||||
{
|
{
|
||||||
if (pattern->bits.free) pattern->bits.free( &pattern->bits );
|
if (pattern->bits.free) pattern->bits.free( &pattern->bits );
|
||||||
if (pattern->bitmap) DeleteObject( pattern->bitmap );
|
|
||||||
HeapFree( GetProcessHeap(), 0, pattern->info );
|
HeapFree( GetProcessHeap(), 0, pattern->info );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,8 +159,6 @@ BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *
|
||||||
|
|
||||||
if (!(brush = GDI_GetObjPtr( handle, OBJ_BRUSH ))) return FALSE;
|
if (!(brush = GDI_GetObjPtr( handle, OBJ_BRUSH ))) return FALSE;
|
||||||
|
|
||||||
if (!brush->pattern.info) cache_pattern_bits( NULL, &brush->pattern );
|
|
||||||
|
|
||||||
if (brush->pattern.info)
|
if (brush->pattern.info)
|
||||||
{
|
{
|
||||||
memcpy( info, brush->pattern.info, get_dib_info_size( brush->pattern.info, brush->pattern.usage ));
|
memcpy( info, brush->pattern.info, get_dib_info_size( brush->pattern.info, brush->pattern.usage ));
|
||||||
|
@ -495,11 +441,7 @@ static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc )
|
||||||
PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectBrush );
|
PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectBrush );
|
||||||
struct brush_pattern *pattern = &brush->pattern;
|
struct brush_pattern *pattern = &brush->pattern;
|
||||||
|
|
||||||
if (!pattern->info)
|
if (!pattern->info) pattern = NULL;
|
||||||
{
|
|
||||||
if (pattern->bitmap) cache_pattern_bits( physdev, pattern );
|
|
||||||
else pattern = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GDI_inc_ref_count( handle );
|
GDI_inc_ref_count( handle );
|
||||||
GDI_ReleaseObj( handle );
|
GDI_ReleaseObj( handle );
|
||||||
|
|
|
@ -1873,17 +1873,7 @@ static BOOL select_pattern_brush( dibdrv_physdev *pdev, dib_brush *brush, BOOL *
|
||||||
if (pattern.bit_count == 1 && !pattern.color_table)
|
if (pattern.bit_count == 1 && !pattern.color_table)
|
||||||
dither = FALSE; /* monochrome DDB pattern brushes don't get dithered */
|
dither = FALSE; /* monochrome DDB pattern brushes don't get dithered */
|
||||||
|
|
||||||
if (!brush->pattern.info)
|
if (brush->pattern.info->bmiHeader.biClrUsed && brush->pattern.usage == DIB_PAL_COLORS)
|
||||||
{
|
|
||||||
BITMAPOBJ *bmp = GDI_GetObjPtr( brush->pattern.bitmap, OBJ_BITMAP );
|
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
if (!bmp) return FALSE;
|
|
||||||
ret = init_dib_info_from_bitmapobj( &pattern, bmp );
|
|
||||||
GDI_ReleaseObj( brush->pattern.bitmap );
|
|
||||||
if (!ret) return FALSE;
|
|
||||||
}
|
|
||||||
else if (brush->pattern.info->bmiHeader.biClrUsed && brush->pattern.usage == DIB_PAL_COLORS)
|
|
||||||
{
|
{
|
||||||
copy_bitmapinfo( info, brush->pattern.info );
|
copy_bitmapinfo( info, brush->pattern.info );
|
||||||
fill_color_table_from_pal_colors( info, pdev->dev.hdc );
|
fill_color_table_from_pal_colors( info, pdev->dev.hdc );
|
||||||
|
|
|
@ -221,7 +221,6 @@ extern DWORD stretch_bits( const BITMAPINFO *src_info, struct bitblt_coords *src
|
||||||
struct gdi_image_bits *bits, int mode ) DECLSPEC_HIDDEN;
|
struct gdi_image_bits *bits, int mode ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* brush.c */
|
/* brush.c */
|
||||||
extern void cache_pattern_bits( PHYSDEV physdev, struct brush_pattern *pattern ) DECLSPEC_HIDDEN;
|
|
||||||
extern BOOL store_brush_pattern( LOGBRUSH *brush, struct brush_pattern *pattern ) DECLSPEC_HIDDEN;
|
extern BOOL store_brush_pattern( LOGBRUSH *brush, struct brush_pattern *pattern ) DECLSPEC_HIDDEN;
|
||||||
extern void free_brush_pattern( struct brush_pattern *pattern ) DECLSPEC_HIDDEN;
|
extern void free_brush_pattern( struct brush_pattern *pattern ) DECLSPEC_HIDDEN;
|
||||||
extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage ) DECLSPEC_HIDDEN;
|
extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -243,11 +243,7 @@ static HGDIOBJ PEN_SelectObject( HGDIOBJ handle, HDC hdc )
|
||||||
break;
|
break;
|
||||||
case OBJ_EXTPEN:
|
case OBJ_EXTPEN:
|
||||||
pattern = &pen->pattern;
|
pattern = &pen->pattern;
|
||||||
if (!pattern->info)
|
if (!pattern->info) pattern = NULL;
|
||||||
{
|
|
||||||
if (pattern->bitmap) cache_pattern_bits( physdev, pattern );
|
|
||||||
else pattern = NULL;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GDI_ReleaseObj( handle );
|
GDI_ReleaseObj( handle );
|
||||||
|
|
Loading…
Reference in New Issue