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