Commit 7c4c233d authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent cf85fb14
...@@ -210,7 +210,6 @@ HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp ) ...@@ -210,7 +210,6 @@ HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
bmpobj->dib.dsBm = bm; bmpobj->dib.dsBm = bm;
bmpobj->dib.dsBm.bmBits = NULL; bmpobj->dib.dsBm.bmBits = NULL;
bmpobj->funcs = &dib_driver;
if (!(hbitmap = alloc_gdi_handle( &bmpobj->header, OBJ_BITMAP, &bitmap_funcs ))) if (!(hbitmap = alloc_gdi_handle( &bmpobj->header, OBJ_BITMAP, &bitmap_funcs )))
{ {
...@@ -393,14 +392,14 @@ LONG WINAPI SetBitmapBits( ...@@ -393,14 +392,14 @@ LONG WINAPI SetBitmapBits(
info->bmiHeader.biWidth = 0; info->bmiHeader.biWidth = 0;
info->bmiHeader.biHeight = 0; info->bmiHeader.biHeight = 0;
info->bmiHeader.biSizeImage = 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) if (!err || err == ERROR_BAD_FORMAT)
{ {
info->bmiHeader.biWidth = bmp->dib.dsBm.bmWidth; info->bmiHeader.biWidth = bmp->dib.dsBm.bmWidth;
info->bmiHeader.biHeight = -dst.height; info->bmiHeader.biHeight = -dst.height;
info->bmiHeader.biSizeImage = dst.height * dst_stride; 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; if (err) count = 0;
......
...@@ -733,11 +733,11 @@ INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan, ...@@ -733,11 +733,11 @@ INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
copy_bitmapinfo( dst_info, src_info ); 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) if (err == ERROR_BAD_FORMAT)
{ {
err = convert_bits( src_info, &src, dst_info, &src_bits, FALSE ); 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; if(err) result = 0;
...@@ -1492,8 +1492,6 @@ HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage, ...@@ -1492,8 +1492,6 @@ HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
bmp->dib.dsBm.bmBitsPixel = info->bmiHeader.biBitCount; bmp->dib.dsBm.bmBitsPixel = info->bmiHeader.biBitCount;
bmp->dib.dsBmih = info->bmiHeader; bmp->dib.dsBmih = info->bmiHeader;
bmp->funcs = &dib_driver;
if (info->bmiHeader.biBitCount <= 8) /* build the color table */ if (info->bmiHeader.biBitCount <= 8) /* build the color table */
{ {
if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc )) if (usage == DIB_PAL_COLORS && !fill_color_table_from_pal_colors( info, hdc ))
......
...@@ -466,7 +466,7 @@ static int get_overlap( const dib_info *dst, const RECT *dst_rect, ...@@ -466,7 +466,7 @@ static int get_overlap( const dib_info *dst, const RECT *dst_rect,
return ret; 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 ) const struct clipped_rects *clipped_rects, INT rop2 )
{ {
POINT origin; POINT origin;
...@@ -495,7 +495,7 @@ static DWORD copy_rect( dib_info *dst, const RECT *dst_rect, const dib_info *src ...@@ -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 ); dst->funcs->solid_rects( dst, count, rects, and, xor );
/* fall through */ /* fall through */
case R2_NOP: case R2_NOP:
return ERROR_SUCCESS; return;
} }
overlap = get_overlap( dst, dst_rect, src, src_rect ); 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 ...@@ -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 ); 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, 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 ) ...@@ -875,6 +874,9 @@ static BOOL matching_color_info( const dib_info *dib, const BITMAPINFO *info )
{ {
const RGBQUAD *color_table = info->bmiColors; 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) switch (info->bmiHeader.biBitCount)
{ {
case 1: case 1:
...@@ -919,6 +921,33 @@ static BOOL matching_color_info( const dib_info *dib, const BITMAPINFO *info ) ...@@ -919,6 +921,33 @@ static BOOL matching_color_info( const dib_info *dib, const BITMAPINFO *info )
return FALSE; 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) static inline BOOL rop_uses_pat(DWORD rop)
{ {
return ((rop >> 4) & 0x0f0000) != (rop & 0x0f0000); return ((rop >> 4) & 0x0f0000) != (rop & 0x0f0000);
...@@ -931,90 +960,58 @@ DWORD dibdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info ...@@ -931,90 +960,58 @@ DWORD dibdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info
const struct gdi_image_bits *bits, struct bitblt_coords *src, const struct gdi_image_bits *bits, struct bitblt_coords *src,
struct bitblt_coords *dst, DWORD rop ) struct bitblt_coords *dst, DWORD rop )
{ {
dib_info *dib = NULL, stand_alone;
struct clipped_rects clipped_rects; struct clipped_rects clipped_rects;
DWORD ret; DWORD ret = ERROR_SUCCESS;
dib_info src_dib; dib_info src_dib;
HRGN tmp_rgn = 0; HRGN tmp_rgn = 0;
dibdrv_physdev *pdev = NULL; dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
TRACE( "%p %p %p\n", dev, hbitmap, info ); TRACE( "%p %p %p\n", dev, hbitmap, info );
if (hbitmap) if (hbitmap)
{ {
DWORD ret;
BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ); BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
if (!bmp) return ERROR_INVALID_HANDLE; if (!bmp) return ERROR_INVALID_HANDLE;
if (!init_dib_info_from_bitmapobj( &stand_alone, bmp )) ret = put_image_into_bitmap( bmp, clip, info, bits, src, dst );
{ GDI_ReleaseObj( hbitmap );
ret = ERROR_OUTOFMEMORY; return ret;
goto done;
}
dib = &stand_alone;
rop = SRCCOPY;
}
else
{
pdev = get_dibdrv_pdev( dev );
dib = &pdev->dib;
} }
if (info->bmiHeader.biPlanes != 1) goto update_format; if (!matching_color_info( &pdev->dib, info )) goto update_format;
if (info->bmiHeader.biBitCount != dib->bit_count) goto update_format; if (!bits) return ERROR_SUCCESS;
if (!matching_color_info( dib, info )) goto update_format; if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
if (!bits)
{
ret = ERROR_SUCCESS;
goto done;
}
if ((src->width != dst->width) || (src->height != dst->height))
{
ret = ERROR_TRANSFORM_NOT_SUPPORTED;
goto done;
}
init_dib_info_from_bitmapinfo( &src_dib, info, bits->ptr ); init_dib_info_from_bitmapinfo( &src_dib, info, bits->ptr );
src_dib.bits.is_copy = bits->is_copy; src_dib.bits.is_copy = bits->is_copy;
if (!hbitmap) if (clip && pdev->clip)
{
if (clip && pdev->clip)
{
tmp_rgn = CreateRectRgn( 0, 0, 0, 0 );
CombineRgn( tmp_rgn, clip, pdev->clip, RGN_AND );
clip = tmp_rgn;
}
else if (!clip) clip = pdev->clip;
add_clipped_bounds( pdev, &dst->visrect, clip );
}
if (!get_clipped_rects( dib, &dst->visrect, clip, &clipped_rects ))
{ {
ret = ERROR_SUCCESS; tmp_rgn = CreateRectRgn( 0, 0, 0, 0 );
goto done; CombineRgn( tmp_rgn, clip, pdev->clip, RGN_AND );
clip = tmp_rgn;
} }
else if (!clip) clip = pdev->clip;
add_clipped_bounds( pdev, &dst->visrect, clip );
if (!rop_uses_pat( rop )) if (get_clipped_rects( &pdev->dib, &dst->visrect, clip, &clipped_rects ))
{
int rop2 = ((rop >> 16) & 0xf) + 1;
ret = copy_rect( dib, &dst->visrect, &src_dib, &src->visrect, &clipped_rects, rop2 );
}
else
{ {
ret = execute_rop( pdev, &dst->visrect, &src_dib, &src->visrect, &clipped_rects, rop ); if (!rop_uses_pat( rop ))
{
int rop2 = ((rop >> 16) & 0xf) + 1;
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: update_format:
info->bmiHeader.biPlanes = 1; info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = dib->bit_count; info->bmiHeader.biBitCount = pdev->dib.bit_count;
set_color_info( dib, info ); set_color_info( &pdev->dib, info );
ret = ERROR_BAD_FORMAT; return ERROR_BAD_FORMAT;
done:
if (tmp_rgn) DeleteObject( tmp_rgn );
if (hbitmap) GDI_ReleaseObj( hbitmap );
return ret;
} }
/*********************************************************************** /***********************************************************************
......
...@@ -186,7 +186,6 @@ typedef struct tagBITMAPOBJ ...@@ -186,7 +186,6 @@ typedef struct tagBITMAPOBJ
DIBSECTION dib; DIBSECTION dib;
SIZE size; /* For SetBitmapDimension() */ SIZE size; /* For SetBitmapDimension() */
RGBQUAD *color_table; /* DIB color table if <= 8bpp (always 1 << bpp in size) */ RGBQUAD *color_table; /* DIB color table if <= 8bpp (always 1 << bpp in size) */
const struct gdi_dc_funcs *funcs; /* DC function table */
} BITMAPOBJ; } BITMAPOBJ;
static inline BOOL is_bitmapobj_dib( const BITMAPOBJ *bmp ) 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 ...@@ -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; UINT aa_flags, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;
extern DWORD get_image_from_bitmap( BITMAPOBJ *bmp, BITMAPINFO *info, extern DWORD get_image_from_bitmap( BITMAPOBJ *bmp, BITMAPINFO *info,
struct gdi_image_bits *bits, struct bitblt_coords *src ) DECLSPEC_HIDDEN; 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 */ /* driver.c */
extern const struct gdi_dc_funcs null_driver DECLSPEC_HIDDEN; extern const struct gdi_dc_funcs null_driver DECLSPEC_HIDDEN;
......
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