Vincent Povirk : gdiplus: Explicitly copy the bits from dib sections to new bitmaps.

Alexandre Julliard julliard at winehq.org
Mon Dec 14 09:51:17 CST 2009


Module: wine
Branch: master
Commit: 3424dac3863f57c5d9724a31744469b9fcd4bd89
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3424dac3863f57c5d9724a31744469b9fcd4bd89

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Sat Dec 12 17:13:39 2009 -0600

gdiplus: Explicitly copy the bits from dib sections to new bitmaps.

On Windows, GdipCreateBitmapFromHBITMAP creates a copy of the bitmap, not
a reference. Currently, we match this behavior, but this is only because
we cannot yet create bitmap objects that reference existing memory. If
GdipCreateBitmapFromScan0 were fixed to do this, FromHBITMAP would break.

Therefore, we always pass NULL to FromScan0 so that it allocates new memory
for the bitmap.

---

 dlls/gdiplus/image.c       |   35 ++++++++++++++++++++++++++---------
 dlls/gdiplus/tests/image.c |   13 ++++++++++++-
 2 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index f78b70a..aa03712 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -2659,7 +2659,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
     BITMAP bm;
     GpStatus retval;
     PixelFormat format;
-    BYTE* bits;
+    BitmapData lockeddata;
+    INT y;
 
     TRACE("%p %p %p\n", hbm, hpal, bitmap);
 
@@ -2700,16 +2701,32 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
             return InvalidParameter;
     }
 
-    if (bm.bmBits)
-        bits = (BYTE*)bm.bmBits + (bm.bmHeight - 1) * bm.bmWidthBytes;
-    else
+    retval = GdipCreateBitmapFromScan0(bm.bmWidth, bm.bmHeight, 0,
+        format, NULL, bitmap);
+
+    if (retval == Ok)
     {
-        FIXME("can only get image data from DIB sections\n");
-        bits = NULL;
-    }
+        retval = GdipBitmapLockBits(*bitmap, NULL, ImageLockModeWrite,
+            format, &lockeddata);
+        if (retval == Ok)
+        {
+            if (bm.bmBits)
+            {
+                for (y=0; y<bm.bmHeight; y++)
+                {
+                    memcpy((BYTE*)lockeddata.Scan0+lockeddata.Stride*y,
+                           (BYTE*)bm.bmBits+bm.bmWidthBytes*(bm.bmHeight-1-y),
+                           bm.bmWidthBytes);
+                }
+            }
+            else
+            {
+                FIXME("can only get image data from DIB sections\n");
+            }
 
-    retval = GdipCreateBitmapFromScan0(bm.bmWidth, bm.bmHeight, -bm.bmWidthBytes,
-        format, bits, bitmap);
+            GdipBitmapUnlockBits(*bitmap, &lockeddata);
+        }
+    }
 
     return retval;
 }
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
index 1ef2651..66c6410 100644
--- a/dlls/gdiplus/tests/image.c
+++ b/dlls/gdiplus/tests/image.c
@@ -465,6 +465,7 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
     const REAL HEIGHT2 = 20;
     HDC hdc;
     BITMAPINFO bmi;
+    BYTE *bits;
 
     stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
     expect(InvalidParameter, stat);
@@ -504,16 +505,26 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
     bmi.bmiHeader.biPlanes = 1;
     bmi.bmiHeader.biCompression = BI_RGB;
 
-    hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
+    hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
     ok(hbm != NULL, "CreateDIBSection failed\n");
 
+    bits[0] = 0;
+
     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
     expect(Ok, stat);
     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
     expectf(WIDTH1,  width);
     expectf(HEIGHT1, height);
     if (stat == Ok)
+    {
+        /* test whether writing to the bitmap affects the original */
+        stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
+        expect(Ok, stat);
+
+        expect(0, bits[0]);
+
         GdipDisposeImage((GpImage*)gpbm);
+    }
 
     LogPal = GdipAlloc(sizeof(LOGPALETTE));
     ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");




More information about the wine-cvs mailing list