Module: wine Branch: master Commit: 6f275874f359dce37c38936ed78800c611121697 URL: http://source.winehq.org/git/wine.git/?a=commit;h=6f275874f359dce37c38936ed7...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Sep 6 13:27:03 2011 +0200
gdi32: Add a SetDIBitsToDevice implementation in the null driver using PutImage.
---
dlls/gdi32/dib.c | 101 +++++++++++++++++++++++++++++++++++++++++++++ dlls/gdi32/driver.c | 7 --- dlls/gdi32/gdi_private.h | 3 + dlls/gdi32/tests/bitmap.c | 5 ++ 4 files changed, 109 insertions(+), 7 deletions(-)
diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index 927a74f..c1de074 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -610,6 +610,107 @@ done: }
+INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy, + INT x_src, INT y_src, UINT startscan, UINT lines, + const void *bits, BITMAPINFO *src_info, UINT coloruse ) +{ + DC *dc = get_nulldrv_dc( dev ); + char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer; + struct bitblt_coords src, dst; + struct gdi_image_bits src_bits; + DWORD err; + UINT height; + BOOL top_down; + POINT pt; + RECT rect; + + top_down = (src_info->bmiHeader.biHeight < 0); + height = abs( src_info->bmiHeader.biHeight ); + + src_bits.ptr = (void *)bits; + src_bits.is_copy = FALSE; + src_bits.free = NULL; + + if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0; + + if (!lines || (startscan >= height)) return 0; + if (!top_down && lines > height - startscan) lines = height - startscan; + + /* map src to top-down coordinates with startscan as origin */ + src.x = x_src; + src.y = startscan + lines - (y_src + cy); + src.width = cx; + src.height = cy; + if (src.y > 0) + { + if (!top_down) + { + /* get rid of unnecessary lines */ + if (src.y >= lines) return 0; + lines -= src.y; + src.y = 0; + } + else if (src.y >= lines) return lines; + } + src_info->bmiHeader.biHeight = top_down ? -lines : lines; + + src.visrect.left = src.x; + src.visrect.top = src.y; + src.visrect.right = src.x + cx; + src.visrect.bottom = src.y + cy; + rect.left = 0; + rect.top = 0; + rect.right = src_info->bmiHeader.biWidth; + rect.bottom = abs( src_info->bmiHeader.biHeight ); + if (!intersect_rect( &src.visrect, &src.visrect, &rect )) return 0; + + pt.x = x_dst; + pt.y = y_dst; + LPtoDP( dev->hdc, &pt, 1 ); + dst.x = pt.x; + dst.y = pt.y; + dst.width = cx; + dst.height = cy; + if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1; + + dst.visrect.left = dst.x; + dst.visrect.top = dst.y; + dst.visrect.right = dst.x + cx; + dst.visrect.bottom = dst.y + cy; + if (get_clip_box( dc, &rect )) intersect_rect( &dst.visrect, &dst.visrect, &rect ); + + offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y ); + intersect_rect( &rect, &src.visrect, &dst.visrect ); + src.visrect = dst.visrect = rect; + offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y ); + if (is_rect_empty( &dst.visrect )) return lines; + + dev = GET_DC_PHYSDEV( dc, pPutImage ); + memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )); + err = dev->funcs->pPutImage( dev, 0, 0, dst_info, &src_bits, &src, &dst, SRCCOPY ); + if (err == ERROR_BAD_FORMAT) + { + void *ptr; + + dst_info->bmiHeader.biWidth = src.visrect.right - src.visrect.left; + ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info )); + if (ptr) + { + err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr ); + if (src_bits.free) src_bits.free( &src_bits ); + src_bits.ptr = ptr; + src_bits.is_copy = TRUE; + src_bits.free = free_heap_bits; + if (!err) err = dev->funcs->pPutImage( dev, 0, 0, dst_info, &src_bits, &src, &dst, SRCCOPY ); + } + else err = ERROR_OUTOFMEMORY; + } + if (err) lines = 0; + if (src_bits.free) src_bits.free( &src_bits ); + return lines; +} + /*********************************************************************** * SetDIBitsToDevice (GDI32.@) */ diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index 6233525..5beb04d 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -502,13 +502,6 @@ static UINT nulldrv_SetDIBColorTable( PHYSDEV dev, UINT pos, UINT count, const R return 0; }
-static INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD width, DWORD height, - INT x_src, INT y_src, UINT start, UINT lines, - const void *bits, BITMAPINFO *info, UINT coloruse ) -{ - return 0; -} - static void nulldrv_SetDeviceClipping( PHYSDEV dev, HRGN vis_rgn, HRGN clip_rgn ) { } diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 82dbc36..c4ed75a 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -499,6 +499,9 @@ extern INT nulldrv_SaveDC( PHYSDEV dev ) DECLSPEC_HIDDEN; extern BOOL nulldrv_ScaleViewportExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size ) DECLSPEC_HIDDEN; extern BOOL nulldrv_ScaleWindowExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size ) DECLSPEC_HIDDEN; extern BOOL nulldrv_SelectClipPath( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD width, DWORD height, + INT x_src, INT y_src, UINT start, UINT lines, + const void *bits, BITMAPINFO *info, UINT coloruse ) DECLSPEC_HIDDEN; extern INT nulldrv_SetMapMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; extern BOOL nulldrv_SetViewportExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size ) DECLSPEC_HIDDEN; extern BOOL nulldrv_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index 6a80232..a2dbfd9 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -4265,6 +4265,11 @@ static void test_SetDIBitsToDevice(void) for (i = 0; i < 64; i++) ok( dib_bits[i] == 0xaaaaaaaa, "%d: got %08x\n", i, dib_bits[i] ); memset( dib_bits, 0xaa, 64 * 4 );
+ ret = SetDIBitsToDevice( hdc, 0, 2, 8, 4, 0, -1, 3, 12, data, info, DIB_RGB_COLORS ); + ok( ret == 0, "got %d\n", ret ); + for (i = 0; i < 64; i++) ok( dib_bits[i] == 0xaaaaaaaa, "%d: got %08x\n", i, dib_bits[i] ); + memset( dib_bits, 0xaa, 64 * 4 ); + SetMapMode( hdc, MM_ANISOTROPIC ); SetWindowExtEx( hdc, 3, 3, NULL ); ret = SetDIBitsToDevice( hdc, 2, 2, 2, 2, 1, 2, 1, 5, data, info, DIB_RGB_COLORS );