Alexandre Julliard : gdi32: Reimplement SetBitmapBits using the PutImage driver entry point.
Alexandre Julliard
julliard at winehq.org
Wed Aug 3 12:48:10 CDT 2011
Module: wine
Branch: master
Commit: 107849916fff56e0322bec7901ed5a10d205b345
URL: http://source.winehq.org/git/wine.git/?a=commit;h=107849916fff56e0322bec7901ed5a10d205b345
Author: Alexandre Julliard <julliard at 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;
}
/**********************************************************************
More information about the wine-cvs
mailing list