Vincent Povirk : gdiplus: Copy only the area requested when (un) locking bitmaps.

Alexandre Julliard julliard at winehq.org
Fri Feb 25 11:19:44 CST 2011


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Thu Feb 24 16:32:54 2011 -0600

gdiplus: Copy only the area requested when (un)locking bitmaps.

---

 dlls/gdiplus/gdiplus_private.h |    1 +
 dlls/gdiplus/image.c           |   37 +++++++++++++++++++++++++++++--------
 dlls/gdiplus/tests/image.c     |    4 ++++
 3 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index bdfb204..42e28fa 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -280,6 +280,7 @@ struct GpBitmap{
     BYTE *bits; /* actual image bits if this is a DIB */
     INT stride; /* stride of bits if this is a DIB */
     BYTE *own_bits; /* image bits that need to be freed with this object */
+    INT lockx, locky; /* X and Y coordinates of the rect when a bitmap is locked for writing. */
 };
 
 struct GpCachedBitmap{
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index 2139e97..070ea3d 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -990,8 +990,8 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
         }
     }
 
-    abs_height = bitmap->height;
-    stride = (bitmap->width * bitspp + 7) / 8;
+    abs_height = act_rect.Height;
+    stride = (act_rect.Width * bitspp + 7) / 8;
     stride = (stride + 3) & ~3;
 
     buff = GdipAlloc(stride * abs_height);
@@ -1000,9 +1000,19 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
 
     if (flags & ImageLockModeRead)
     {
-        stat = convert_pixels(bitmap->width, bitmap->height,
+        static int fixme=0;
+
+        if (!fixme && (PIXELFORMATBPP(bitmap->format) * act_rect.X) % 8 != 0)
+        {
+            FIXME("Cannot copy rows that don't start at a whole byte.\n");
+            fixme = 1;
+        }
+
+        stat = convert_pixels(act_rect.Width, act_rect.Height,
             stride, buff, format,
-            bitmap->stride, bitmap->bits, bitmap->format, bitmap->image.palette_entries);
+            bitmap->stride,
+            bitmap->bits + bitmap->stride * act_rect.Y + PIXELFORMATBPP(bitmap->format) * act_rect.X / 8,
+            bitmap->format, bitmap->image.palette_entries);
 
         if (stat != Ok)
         {
@@ -1016,11 +1026,13 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
     lockeddata->PixelFormat = format;
     lockeddata->Reserved = flags;
     lockeddata->Stride = stride;
-    lockeddata->Scan0  = buff + (bitspp / 8) * act_rect.X + stride * act_rect.Y;
+    lockeddata->Scan0  = buff;
 
     bitmap->lockmode = flags;
     bitmap->numlocks++;
     bitmap->bitmapbits = buff;
+    bitmap->lockx = act_rect.X;
+    bitmap->locky = act_rect.Y;
 
     return Ok;
 }
@@ -1042,6 +1054,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
     BitmapData* lockeddata)
 {
     GpStatus stat;
+    static int fixme=0;
 
     TRACE("(%p,%p)\n", bitmap, lockeddata);
 
@@ -1071,9 +1084,17 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
         return Ok;
     }
 
-    stat = convert_pixels(bitmap->width, bitmap->height,
-        bitmap->stride, bitmap->bits, bitmap->format,
-        lockeddata->Stride, bitmap->bitmapbits, lockeddata->PixelFormat, NULL);
+    if (!fixme && (PIXELFORMATBPP(bitmap->format) * bitmap->lockx) % 8 != 0)
+    {
+        FIXME("Cannot copy rows that don't start at a whole byte.\n");
+        fixme = 1;
+    }
+
+    stat = convert_pixels(lockeddata->Width, lockeddata->Height,
+        bitmap->stride,
+        bitmap->bits + bitmap->stride * bitmap->locky + PIXELFORMATBPP(bitmap->format) * bitmap->lockx / 8,
+        bitmap->format,
+        lockeddata->Stride, lockeddata->Scan0, lockeddata->PixelFormat, NULL);
 
     if (stat != Ok)
     {
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
index 82d7588..005969b 100644
--- a/dlls/gdiplus/tests/image.c
+++ b/dlls/gdiplus/tests/image.c
@@ -687,6 +687,10 @@ static void test_LockBits(void)
     expect(Ok, stat);
     expect(0xff563412, color);
 
+    stat = GdipBitmapGetPixel(bm, 2, 8, &color);
+    expect(Ok, stat);
+    expect(0xffc30000, color);
+
     stat = GdipDisposeImage((GpImage*)bm);
     expect(Ok, stat);
     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);




More information about the wine-cvs mailing list