Module: wine Branch: master Commit: f2e3d996093420e2ff477c3d13902ec60be1c615 URL: http://source.winehq.org/git/wine.git/?a=commit;h=f2e3d996093420e2ff477c3d13...
Author: Vincent Povirk vincent@codeweavers.com Date: Wed Feb 24 16:59:50 2010 -0600
gdiplus: Implement GdipImageRotateFlip.
---
dlls/gdiplus/image.c | 141 +++++++++++++++++++++++++++++++++++++++++++- dlls/gdiplus/tests/image.c | 38 ++++++------ 2 files changed, 158 insertions(+), 21 deletions(-)
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 8736b23..0a73dcf 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -1831,6 +1831,37 @@ GpStatus WINGDIPAPI GdipEmfToWmfBits(HENHMETAFILE hemf, UINT cbData16, return NotImplemented; }
+/* Internal utility function: Replace the image data of dst with that of src, + * and free src. */ +static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette) +{ + GdipFree(dst->bitmapbits); + DeleteDC(dst->hdc); + DeleteObject(dst->hbitmap); + + if (clobber_palette) + { + GdipFree(dst->image.palette_entries); + dst->image.palette_flags = src->image.palette_flags; + dst->image.palette_count = src->image.palette_count; + dst->image.palette_entries = src->image.palette_entries; + } + else + GdipFree(src->image.palette_entries); + + dst->image.xres = src->image.xres; + dst->image.yres = src->image.yres; + dst->width = src->width; + dst->height = src->height; + dst->format = src->format; + dst->hbitmap = src->hbitmap; + dst->hdc = src->hdc; + dst->bits = src->bits; + dst->stride = src->stride; + + GdipFree(src); +} + GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) { TRACE("%p\n", image); @@ -3438,6 +3469,112 @@ GpStatus WINGDIPAPI GdipGetImageThumbnail(GpImage *image, UINT width, UINT heigh */ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type) { - FIXME("(%p %u) stub\n", image, type); - return NotImplemented; + GpBitmap *new_bitmap; + GpBitmap *bitmap; + int bpp, bytesperpixel; + int rotate_90, flip_x, flip_y; + int src_x_offset, src_y_offset; + LPBYTE src_origin; + UINT x, y, width, height; + BitmapData src_lock, dst_lock; + GpStatus stat; + + TRACE("(%p, %u)\n", image, type); + + rotate_90 = type&1; + flip_x = (type&6) == 2 || (type&6) == 4; + flip_y = (type&3) == 1 || (type&3) == 2; + + if (image->type != ImageTypeBitmap) + { + FIXME("Not implemented for type %i\n", image->type); + return NotImplemented; + } + + bitmap = (GpBitmap*)image; + bpp = PIXELFORMATBPP(bitmap->format); + + if (bpp < 8) + { + FIXME("Not implemented for %i bit images\n", bpp); + return NotImplemented; + } + + if (rotate_90) + { + width = bitmap->height; + height = bitmap->width; + } + else + { + width = bitmap->width; + height = bitmap->height; + } + + bytesperpixel = bpp/8; + + stat = GdipCreateBitmapFromScan0(width, height, 0, bitmap->format, NULL, &new_bitmap); + + if (stat != Ok) + return stat; + + stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format, &src_lock); + + if (stat == Ok) + { + stat = GdipBitmapLockBits(new_bitmap, NULL, ImageLockModeWrite, bitmap->format, &dst_lock); + + if (stat == Ok) + { + LPBYTE src_row, src_pixel; + LPBYTE dst_row, dst_pixel; + + src_origin = src_lock.Scan0; + if (flip_x) src_origin += bytesperpixel * (bitmap->width - 1); + if (flip_y) src_origin += src_lock.Stride * (bitmap->height - 1); + + if (rotate_90) + { + if (flip_y) src_x_offset = -src_lock.Stride; + else src_x_offset = src_lock.Stride; + if (flip_x) src_y_offset = -bytesperpixel; + else src_y_offset = bytesperpixel; + } + else + { + if (flip_x) src_x_offset = -bytesperpixel; + else src_x_offset = bytesperpixel; + if (flip_y) src_y_offset = -src_lock.Stride; + else src_y_offset = src_lock.Stride; + } + + src_row = src_origin; + dst_row = dst_lock.Scan0; + for (y=0; y<height; y++) + { + src_pixel = src_row; + dst_pixel = dst_row; + for (x=0; x<width; x++) + { + /* FIXME: This could probably be faster without memcpy. */ + memcpy(dst_pixel, src_pixel, bytesperpixel); + dst_pixel += bytesperpixel; + src_pixel += src_x_offset; + } + src_row += src_y_offset; + dst_row += dst_lock.Stride; + } + + GdipBitmapUnlockBits(new_bitmap, &dst_lock); + } + + GdipBitmapUnlockBits(bitmap, &src_lock); + } + + if (stat == Ok) + move_bitmap(bitmap, new_bitmap, FALSE); + else + GdipDisposeImage((GpImage*)new_bitmap); + + return stat; } diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 262f9a2..0ca22e5 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -1719,30 +1719,30 @@ static void test_rotateflip(void) expect(Ok, stat);
stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone); - todo_wine expect(Ok, stat); + expect(Ok, stat);
stat = GdipGetImageWidth(bitmap, &width); expect(Ok, stat); stat = GdipGetImageHeight(bitmap, &height); expect(Ok, stat); - todo_wine expect(2, width); - todo_wine expect(3, height); + expect(2, width); + expect(3, height);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color); expect(Ok, stat); - todo_wine expect(0xff00ffff, color); + expect(0xff00ffff, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color); - todo_wine expect(Ok, stat); - todo_wine expect(0xffffff00, color); + expect(Ok, stat); + expect(0xffffff00, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color); - todo_wine expect(Ok, stat); - todo_wine expect(0xff0000ff, color); + expect(Ok, stat); + expect(0xff0000ff, color);
expect(0, bits[0]); expect(0, bits[1]); @@ -1755,7 +1755,7 @@ static void test_rotateflip(void) expect(Ok, stat);
stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX); - todo_wine expect(Ok, stat); + expect(Ok, stat);
stat = GdipGetImageWidth(bitmap, &width); expect(Ok, stat); @@ -1766,19 +1766,19 @@ static void test_rotateflip(void)
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color); expect(Ok, stat); - todo_wine expect(0xff0000ff, color); + expect(0xff0000ff, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color); expect(Ok, stat); - todo_wine expect(0xffffff00, color); + expect(0xffffff00, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color); expect(Ok, stat); - todo_wine expect(0xff00ffff, color); + expect(0xff00ffff, color);
expect(0, bits[0]); expect(0, bits[1]); @@ -1791,7 +1791,7 @@ static void test_rotateflip(void) expect(Ok, stat);
stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY); - todo_wine expect(Ok, stat); + expect(Ok, stat);
stat = GdipGetImageWidth(bitmap, &width); expect(Ok, stat); @@ -1802,19 +1802,19 @@ static void test_rotateflip(void)
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color); expect(Ok, stat); - todo_wine expect(0xff00ffff, color); + expect(0xff00ffff, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color); expect(Ok, stat); - todo_wine expect(0xffffff00, color); + expect(0xffffff00, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color);
stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color); expect(Ok, stat); - todo_wine expect(0xff0000ff, color); + expect(0xff0000ff, color);
expect(0, bits[0]); expect(0, bits[1]);