Module: wine Branch: master Commit: 107849916fff56e0322bec7901ed5a10d205b345 URL: http://source.winehq.org/git/wine.git/?a=commit;h=107849916fff56e0322bec7901...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Aug 3 11:12:05 2011 +0200
gdi32: Reimplement SetBitmapBits using the PutImage driver entry point.
---
dlls/gdi32/bitmap.c | 93 ++++++++++++++++++++++++++++++++++---------------- 1 files changed, 63 insertions(+), 30 deletions(-)
diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c index bce5183..f0c5764 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -518,8 +518,13 @@ LONG WINAPI SetBitmapBits( LONG count, /* [in] Number of bytes in bitmap array */ LPCVOID bits) /* [in] Address of array with bitmap bits */ { + char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *info = (BITMAPINFO *)buffer; BITMAPOBJ *bmp; - LONG height, ret; + DWORD err; + int i, src_stride, dst_stride; + struct bitblt_coords src, dst; + struct gdi_image_bits src_bits;
if (!bits) return 0;
@@ -531,43 +536,71 @@ LONG WINAPI SetBitmapBits( count = -count; }
- if (bmp->dib) /* simply copy the bits into the DIB */ - { - DIBSECTION *dib = bmp->dib; - char *dest = dib->dsBm.bmBits; - LONG max = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight; - if (count > max) count = max; - ret = count; + if (bmp->dib) src_stride = get_bitmap_stride( bmp->dib->dsBmih.biWidth, bmp->dib->dsBmih.biBitCount ); + else src_stride = get_bitmap_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel ); + + dst_stride = get_dib_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel ); + + src.visrect.left = src.x = 0; + src.visrect.top = src.y = 0; + src.visrect.right = src.width = bmp->bitmap.bmWidth; + src.visrect.bottom = src.height = min( count / src_stride, bmp->bitmap.bmHeight ); + dst = src; + + /* Only set entire lines */ + count = src.height * src_stride;
- if (bmp->dib->dsBmih.biHeight >= 0) /* not top-down, need to flip contents vertically */ + TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n", + hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight, + bmp->bitmap.bmBitsPixel, src.height ); + + if (src_stride == dst_stride) + { + src_bits.ptr = (void *)bits; + src_bits.is_copy = FALSE; + src_bits.free = NULL; + } + else + { + if (!(src_bits.ptr = HeapAlloc( GetProcessHeap(), 0, dst.height * dst_stride ))) { - dest += dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight; - while (count > 0) - { - dest -= dib->dsBm.bmWidthBytes; - memcpy( dest, bits, min( count, dib->dsBm.bmWidthBytes ) ); - bits = (const char *)bits + dib->dsBm.bmWidthBytes; - count -= dib->dsBm.bmWidthBytes; - } + GDI_ReleaseObj( hbitmap ); + return 0; } - else memcpy( dest, bits, count ); - - GDI_ReleaseObj( hbitmap ); - return ret; + src_bits.is_copy = TRUE; + src_bits.free = free_heap_bits; + for (i = 0; i < dst.height; i++) + memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, src_stride ); }
- /* Only get entire lines */ - height = count / bmp->bitmap.bmWidthBytes; - if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight; - count = height * bmp->bitmap.bmWidthBytes; + /* query the color info */ + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel; + info->bmiHeader.biCompression = BI_RGB; + info->bmiHeader.biXPelsPerMeter = 0; + info->bmiHeader.biYPelsPerMeter = 0; + info->bmiHeader.biClrUsed = 0; + info->bmiHeader.biClrImportant = 0; + info->bmiHeader.biWidth = 0; + info->bmiHeader.biHeight = 0; + info->bmiHeader.biSizeImage = 0; + err = bmp->funcs->pPutImage( NULL, hbitmap, 0, info, NULL, NULL, NULL, SRCCOPY );
- TRACE("(%p, %d, %p) %dx%d %d colors fetched height: %d\n", - hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight, - 1 << bmp->bitmap.bmBitsPixel, height ); + if (!err || err == ERROR_BAD_FORMAT) + { + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel; + info->bmiHeader.biWidth = bmp->bitmap.bmWidth; + info->bmiHeader.biHeight = -dst.height; + info->bmiHeader.biSizeImage = dst.height * dst_stride; + err = bmp->funcs->pPutImage( NULL, hbitmap, 0, info, &src_bits, &src, &dst, SRCCOPY ); + } + if (err) count = 0;
- ret = bmp->funcs->pSetBitmapBits( hbitmap, bits, count ); + if (src_bits.free) src_bits.free( &src_bits ); GDI_ReleaseObj( hbitmap ); - return ret; + return count; }
/**********************************************************************