From: "Changhui Liu" Subject: [PATCH 3/3] gdiplus: fix SOFTWARE_GdipFillRegion when window origin point changed Message-Id: Date: Tue, 23 Dec 2014 13:26:57 +0800 ------------------ Regards.






------------------
Regards.
 
From 65e84b8dd349ee9c84de241a9d8cf50dc8387aae Mon Sep 17 00:00:00 2001 From: Changhui Liu Date: Mon, 22 Dec 2014 16:53:37 +0800 Subject: gdiplus: fix SOFTWARE_GdipFillRegion when window origin point changed To: wine-patches Reply-To: wine-devel --- dlls/gdiplus/graphics.c | 13 +++ dlls/gdiplus/tests/graphics.c | 246 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 259 insertions(+) diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index ce4a3ab..0845e41 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -4011,9 +4011,22 @@ static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush, &gp_bound_rect, gp_bound_rect.Width); if (stat == Ok) + { + /*Because the ExtSelectClipRgn in alpha_blend_pixels_hrgn use gdi32 device coordinate + So check if need perform a conversion */ + if (graphics->hdc) + { + POINT pt = {0, 0}; + LPtoDP(graphics->hdc, &pt, 1); + if (pt.x!=0 || pt.y!=0) + { + OffsetRgn (hregion, pt.x, pt.y); + } + } stat = alpha_blend_pixels_hrgn(graphics, gp_bound_rect.X, gp_bound_rect.Y, (BYTE*)pixel_data, gp_bound_rect.Width, gp_bound_rect.Height, gp_bound_rect.Width * 4, hregion); + } GdipFree(pixel_data); } diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c index 6406f27..cb6a27d 100644 --- a/dlls/gdiplus/tests/graphics.c +++ b/dlls/gdiplus/tests/graphics.c @@ -5692,6 +5692,248 @@ static void test_GdipFillRectanglesOnMemoryDCSolidBrush(void) ReleaseDC(hwnd, dc); } +static void test_GdipFillRectanglesOnMemoryDCTextureBrush(void) +{ + ARGB color[6] = {0,0,0,0,0,0}; + POINT pt = {0,0}; + RECT rect = {100, 100, 180, 180}; + UINT width = rect.right - rect.left; + UINT height = rect.bottom - rect.top; + GpStatus status = 0; + union + { + GpBitmap *bitmap; + GpImage *image; + } src_img; + GpTexture *brush = NULL; + GpGraphics *graphics = NULL; + HDC dc = GetDC( hwnd); + HDC hdc = CreateCompatibleDC(dc); + HBITMAP bmp = CreateCompatibleBitmap(dc, width, height); + HGDIOBJ old = SelectObject(hdc, bmp); + + UINT x = 0; + UINT y = 0; + UINT src_img_width = width/2; + UINT src_img_height = height/2; + BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4); + DWORD *pixel = (DWORD *)src_img_data; + ok(pixel != NULL, "Expected src_img_data is valid\n"); + + /*Change the window origin is the key test point*/ + SetWindowOrgEx(hdc, rect.left, rect.top, &pt); + + /*build a blue solid image!*/ + for(y = 0; y < src_img_height; ++y) + { + for(x = 0; x < src_img_width; ++x) + { + pixel[x] = BLUE_COLOR; + } + + pixel += src_img_width; + } + + status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4, + PixelFormat32bppARGB, src_img_data, &src_img.bitmap); + expect(Ok, status); + + status = GdipCreateTexture(src_img.image, 0, &brush); + expect(Ok, status); + + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + + status = GdipSetClipRectI(graphics, rect.left+width/2, rect.top+height/2, + width, height, CombineModeReplace); + expect(Ok, status); + + status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, rect.right, rect.bottom); + expect(Ok, status); + + GdipDisposeImage(src_img.image); + GdipDeleteBrush((GpBrush*)brush); + GdipDeleteGraphics(graphics); + GdipFree(src_img_data); + + pixel = GetBitmapPixelBuffer(hdc, bmp, width, height); + if (pixel) + { + color[0] = GetBitmapPixel(width/2, height/2); + color[1] = GetBitmapPixel(width/2+1, height/2); + color[2] = GetBitmapPixel(width/2, height/2+1); + color[3] = GetBitmapPixel(width/2-1, height/2-1); + color[4] = GetBitmapPixel(width/2-1, height-1); + color[5] = GetBitmapPixel(width-1, height/2-1); + } + ok(IsBlue(color[0]) && IsBlue(color[1]) && IsBlue(color[2]) && + color[3] == 0 && color[4] == 0 && color[5] == 0, + "Expected GdipFillRectangleI take effect!\n" ); + ReleaseBitmapPixelBuffer(pixel); + + SelectObject(hdc, old); + DeleteObject(bmp); + DeleteDC(hdc); + ReleaseDC(hwnd, dc); +} + +static void test_GdipFillRectanglesOnBitmapTextureBrush(void) +{ + ARGB color[6] = {0,0,0,0,0,0}; + UINT x = 0; + UINT y = 0; + RECT rect = {100, 100, 180, 180}; + UINT width = rect.right - rect.left; + UINT height = rect.bottom - rect.top; + UINT src_img_width = width/2; + UINT src_img_height = height/2; + + GpStatus status = 0; + union + { + GpBitmap *bitmap; + GpImage *image; + } src_img; + union + { + GpBitmap *bitmap; + GpImage *image; + } dst_img; + + GpTexture *brush = NULL; + GpGraphics *graphics = NULL; + BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4); + DWORD *pixel = (DWORD *)src_img_data; + ok(pixel != NULL, "Expected src_img_data is valid\n"); + + status = GdipCreateBitmapFromScan0(width, height, width*4, + PixelFormat32bppARGB, NULL, &dst_img.bitmap); + expect(Ok, status); + + /*build a blue solid image!*/ + for(y = 0; y < src_img_height; ++y) + { + for(x = 0; x < src_img_width; ++x) + { + pixel[x] = BLUE_COLOR; + } + + pixel += src_img_width; + } + + status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4, + PixelFormat32bppARGB, src_img_data, &src_img.bitmap); + expect(Ok, status); + + status = GdipCreateTexture(src_img.image, 0, &brush); + expect(Ok, status); + + status = GdipGetImageGraphicsContext(dst_img.image, &graphics); + expect(Ok, status); + + status = GdipSetClipRectI(graphics, 0, 0, width, height, CombineModeReplace); + expect(Ok, status); + + status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, width/2, height/2); + expect(Ok, status); + + GdipDeleteBrush((GpBrush*)brush); + GdipDeleteGraphics(graphics); + + GdipBitmapGetPixel(dst_img.bitmap, 0, 0, &color[0]); + GdipBitmapGetPixel(dst_img.bitmap, 0, 1, &color[1]); + GdipBitmapGetPixel(dst_img.bitmap, 1, 0, &color[2]); + GdipBitmapGetPixel(dst_img.bitmap, width/2, 0, &color[3]); + GdipBitmapGetPixel(dst_img.bitmap, width/2, height/2, &color[4]); + GdipBitmapGetPixel(dst_img.bitmap, 0, height/2, &color[5]); + + ok(IsBlue(color[0]) && IsBlue(color[1]) && IsBlue(color[2]) && + color[3] == 0 && color[4] == 0 && color[5] == 0, + "Expected GdipFillRectangleI take effect!\n" ); + + GdipDisposeImage(src_img.image); + GdipDisposeImage(dst_img.image); + GdipFree(src_img_data); +} + +static void test_GdipDrawImagePointsRectOnMemoryDC(void) +{ + ARGB color[6] = {0,0,0,0,0,0}; + POINT pt = {0,0}; + RECT rect = {100, 100, 180, 180}; + UINT width = rect.right - rect.left; + UINT height = rect.bottom - rect.top; + GpStatus status = 0; + union + { + GpBitmap *bitmap; + GpImage *image; + } src_img; + GpGraphics *graphics = NULL; + HDC dc = GetDC( hwnd); + HDC hdc = CreateCompatibleDC(dc); + HBITMAP bmp = CreateCompatibleBitmap(dc, width, height); + HGDIOBJ old = SelectObject(hdc, bmp); + + UINT x = 0; + UINT y = 0; + UINT src_img_width = width/2; + UINT src_img_height = height/2; + BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4); + DWORD *pixel = (DWORD *)src_img_data; + ok(pixel != NULL, "Expected src_img_data is valid\n"); + + /*Change the window origin is the key test point*/ + SetWindowOrgEx(hdc, rect.left, rect.top, &pt); + + /*build a blue solid image!*/ + for(y = 0; y < src_img_height; ++y) + { + for(x = 0; x < src_img_width; ++x) + { + pixel[x] = BLUE_COLOR; + } + + pixel += src_img_width; + } + + status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4, + PixelFormat32bppARGB, src_img_data, &src_img.bitmap); + expect(Ok, status); + + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + + status = GdipDrawImageRectRectI(graphics, src_img.image, + rect.left+width/2, rect.top+height/2, width/2, height/2, + 0, 0, src_img_width, src_img_height, UnitPixel, NULL, NULL, NULL); + expect(Ok, status); + + GdipDisposeImage(src_img.image); + GdipDeleteGraphics(graphics); + GdipFree(src_img_data); + + pixel = GetBitmapPixelBuffer(hdc, bmp, width, height); + if (pixel) + { + color[0] = GetBitmapPixel(width/2, height/2); + color[1] = GetBitmapPixel(width/2+1, height/2); + color[2] = GetBitmapPixel(width/2, height/2+1); + color[3] = GetBitmapPixel(width/2-1, height/2-1); + color[4] = GetBitmapPixel(width/2-1, height-1); + color[5] = GetBitmapPixel(width-1, height/2-1); + } + ok(IsBlue(color[0]) && IsBlue(color[1]) && IsBlue(color[2]) && + color[3] == 0 && color[4] == 0 && color[5] == 0, + "Expected GdipDrawImageRectRectI take effect!\n" ); + ReleaseBitmapPixelBuffer(pixel); + + SelectObject(hdc, old); + DeleteObject(bmp); + DeleteDC(hdc); + ReleaseDC(hwnd, dc); +} + START_TEST(graphics) { struct GdiplusStartupInput gdiplusStartupInput; @@ -5765,6 +6007,10 @@ START_TEST(graphics) test_GdipFillRectangles(); test_GdipGetVisibleClipBounds_memoryDC(); test_GdipFillRectanglesOnMemoryDCSolidBrush(); + test_GdipFillRectanglesOnMemoryDCTextureBrush(); + test_GdipFillRectanglesOnBitmapTextureBrush(); + test_GdipDrawImagePointsRectOnMemoryDC(); + GdiplusShutdown(gdiplusToken); DestroyWindow( hwnd ); } -- 1.9.1