gdi32: Add a helper function that implements PutImage on a bitmap.

This commit is contained in:
Alexandre Julliard 2012-05-29 14:29:40 +02:00
parent cf85fb14ab
commit 7c4c233d12
4 changed files with 68 additions and 72 deletions

View File

@ -210,7 +210,6 @@ HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
bmpobj->dib.dsBm = bm;
bmpobj->dib.dsBm.bmBits = NULL;
bmpobj->funcs = &dib_driver;
if (!(hbitmap = alloc_gdi_handle( &bmpobj->header, OBJ_BITMAP, &bitmap_funcs )))
{
@ -393,14 +392,14 @@ LONG WINAPI SetBitmapBits(
info->bmiHeader.biWidth = 0;
info->bmiHeader.biHeight = 0;
info->bmiHeader.biSizeImage = 0;
err = bmp->funcs->pPutImage( NULL, hbitmap, 0, info, NULL, NULL, NULL, SRCCOPY );
err = put_image_into_bitmap( bmp, 0, info, NULL, NULL, NULL );
if (!err || err == ERROR_BAD_FORMAT)
{
info->bmiHeader.biWidth = bmp->dib.dsBm.bmWidth;
info->bmiHeader.biHeight = -dst.height;
info->bmiHeader.biSizeImage = dst.height * dst_stride;
err = bmp->funcs->pPutImage( NULL, hbitmap, clip, info, &src_bits, &src, &dst, SRCCOPY );
err = put_image_into_bitmap( bmp, clip, info, &src_bits, &src, &dst );
}
if (err) count = 0;

View File

@ -733,11 +733,11 @@ INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
copy_bitmapinfo( dst_info, src_info );
err = bitmap->funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
err = put_image_into_bitmap( bitmap, clip, dst_info, &src_bits, &src, &dst );
if (err == ERROR_BAD_FORMAT)
{
err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE );
if (!err) err = bitmap->funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
if (!err) err = put_image_into_bitmap( bitmap, clip, dst_info, &src_bits, &src, &dst );
}
if(err) result = 0;
@ -1492,8 +1492,6 @@ HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
bmp->dib.dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
bmp->dib.dsBmih = info->bmiHeader;
bmp->funcs = &dib_driver;
if (info->bmiHeader.biBitCount <= 8) /* build the color table */
{
if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))

View File

@ -466,7 +466,7 @@ static int get_overlap( const dib_info *dst, const RECT *dst_rect,
return ret;
}
static DWORD copy_rect( dib_info *dst, const RECT *dst_rect, const dib_info *src, const RECT *src_rect,
static void copy_rect( dib_info *dst, const RECT *dst_rect, const dib_info *src, const RECT *src_rect,
const struct clipped_rects *clipped_rects, INT rop2 )
{
POINT origin;
@ -495,7 +495,7 @@ static DWORD copy_rect( dib_info *dst, const RECT *dst_rect, const dib_info *src
dst->funcs->solid_rects( dst, count, rects, and, xor );
/* fall through */
case R2_NOP:
return ERROR_SUCCESS;
return;
}
overlap = get_overlap( dst, dst_rect, src, src_rect );
@ -550,7 +550,6 @@ static DWORD copy_rect( dib_info *dst, const RECT *dst_rect, const dib_info *src
dst->funcs->copy_rect( dst, &rects[i], src, &origin, rop2, overlap );
}
}
return ERROR_SUCCESS;
}
static DWORD blend_rect( dib_info *dst, const RECT *dst_rect, const dib_info *src, const RECT *src_rect,
@ -875,6 +874,9 @@ static BOOL matching_color_info( const dib_info *dib, const BITMAPINFO *info )
{
const RGBQUAD *color_table = info->bmiColors;
if (info->bmiHeader.biPlanes != 1) return FALSE;
if (info->bmiHeader.biBitCount != dib->bit_count) return FALSE;
switch (info->bmiHeader.biBitCount)
{
case 1:
@ -919,6 +921,33 @@ static BOOL matching_color_info( const dib_info *dib, const BITMAPINFO *info )
return FALSE;
}
DWORD put_image_into_bitmap( BITMAPOBJ *bmp, HRGN clip, BITMAPINFO *info,
const struct gdi_image_bits *bits, struct bitblt_coords *src,
struct bitblt_coords *dst )
{
struct clipped_rects clipped_rects;
dib_info dib, src_dib;
if (!init_dib_info_from_bitmapobj( &dib, bmp )) return ERROR_OUTOFMEMORY;
if (!matching_color_info( &dib, info )) goto update_format;
if (!bits) return ERROR_SUCCESS;
if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
init_dib_info_from_bitmapinfo( &src_dib, info, bits->ptr );
src_dib.bits.is_copy = bits->is_copy;
if (get_clipped_rects( &dib, &dst->visrect, clip, &clipped_rects ))
copy_rect( &dib, &dst->visrect, &src_dib, &src->visrect, &clipped_rects, R2_COPYPEN );
return ERROR_SUCCESS;
update_format:
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = dib.bit_count;
set_color_info( &dib, info );
return ERROR_BAD_FORMAT;
}
static inline BOOL rop_uses_pat(DWORD rop)
{
return ((rop >> 4) & 0x0f0000) != (rop & 0x0f0000);
@ -931,53 +960,31 @@ DWORD dibdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info
const struct gdi_image_bits *bits, struct bitblt_coords *src,
struct bitblt_coords *dst, DWORD rop )
{
dib_info *dib = NULL, stand_alone;
struct clipped_rects clipped_rects;
DWORD ret;
DWORD ret = ERROR_SUCCESS;
dib_info src_dib;
HRGN tmp_rgn = 0;
dibdrv_physdev *pdev = NULL;
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
TRACE( "%p %p %p\n", dev, hbitmap, info );
if (hbitmap)
{
DWORD ret;
BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
if (!bmp) return ERROR_INVALID_HANDLE;
if (!init_dib_info_from_bitmapobj( &stand_alone, bmp ))
{
ret = ERROR_OUTOFMEMORY;
goto done;
}
dib = &stand_alone;
rop = SRCCOPY;
}
else
{
pdev = get_dibdrv_pdev( dev );
dib = &pdev->dib;
ret = put_image_into_bitmap( bmp, clip, info, bits, src, dst );
GDI_ReleaseObj( hbitmap );
return ret;
}
if (info->bmiHeader.biPlanes != 1) goto update_format;
if (info->bmiHeader.biBitCount != dib->bit_count) goto update_format;
if (!matching_color_info( dib, info )) goto update_format;
if (!bits)
{
ret = ERROR_SUCCESS;
goto done;
}
if ((src->width != dst->width) || (src->height != dst->height))
{
ret = ERROR_TRANSFORM_NOT_SUPPORTED;
goto done;
}
if (!matching_color_info( &pdev->dib, info )) goto update_format;
if (!bits) return ERROR_SUCCESS;
if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
init_dib_info_from_bitmapinfo( &src_dib, info, bits->ptr );
src_dib.bits.is_copy = bits->is_copy;
if (!hbitmap)
{
if (clip && pdev->clip)
{
tmp_rgn = CreateRectRgn( 0, 0, 0, 0 );
@ -986,35 +993,25 @@ DWORD dibdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info
}
else if (!clip) clip = pdev->clip;
add_clipped_bounds( pdev, &dst->visrect, clip );
}
if (!get_clipped_rects( dib, &dst->visrect, clip, &clipped_rects ))
if (get_clipped_rects( &pdev->dib, &dst->visrect, clip, &clipped_rects ))
{
ret = ERROR_SUCCESS;
goto done;
}
if (!rop_uses_pat( rop ))
{
int rop2 = ((rop >> 16) & 0xf) + 1;
ret = copy_rect( dib, &dst->visrect, &src_dib, &src->visrect, &clipped_rects, rop2 );
copy_rect( &pdev->dib, &dst->visrect, &src_dib, &src->visrect, &clipped_rects, rop2 );
}
else
{
ret = execute_rop( pdev, &dst->visrect, &src_dib, &src->visrect, &clipped_rects, rop );
}
goto done;
if (tmp_rgn) DeleteObject( tmp_rgn );
return ret;
update_format:
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = dib->bit_count;
set_color_info( dib, info );
ret = ERROR_BAD_FORMAT;
done:
if (tmp_rgn) DeleteObject( tmp_rgn );
if (hbitmap) GDI_ReleaseObj( hbitmap );
return ret;
info->bmiHeader.biBitCount = pdev->dib.bit_count;
set_color_info( &pdev->dib, info );
return ERROR_BAD_FORMAT;
}
/***********************************************************************

View File

@ -186,7 +186,6 @@ typedef struct tagBITMAPOBJ
DIBSECTION dib;
SIZE size; /* For SetBitmapDimension() */
RGBQUAD *color_table; /* DIB color table if <= 8bpp (always 1 << bpp in size) */
const struct gdi_dc_funcs *funcs; /* DC function table */
} BITMAPOBJ;
static inline BOOL is_bitmapobj_dib( const BITMAPOBJ *bmp )
@ -271,6 +270,9 @@ extern BOOL render_aa_text_bitmapinfo( HDC hdc, BITMAPINFO *info, struct gdi_ima
UINT aa_flags, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;
extern DWORD get_image_from_bitmap( BITMAPOBJ *bmp, BITMAPINFO *info,
struct gdi_image_bits *bits, struct bitblt_coords *src ) DECLSPEC_HIDDEN;
extern DWORD put_image_into_bitmap( BITMAPOBJ *bmp, HRGN clip, BITMAPINFO *info,
const struct gdi_image_bits *bits, struct bitblt_coords *src,
struct bitblt_coords *dst ) DECLSPEC_HIDDEN;
/* driver.c */
extern const struct gdi_dc_funcs null_driver DECLSPEC_HIDDEN;