From: Damjan Jovanovic Subject: [PATCH] gdi32: fix PatBlt() drawing with negative width/height Message-Id: Date: Sat, 14 Nov 2020 11:56:57 +0200 In a (x, y, w, h) rectangle passed to PatBlt(), a negative w results in the rectangle drawn being (x+w, y, -w, h), and negative h results in (x, y+h, w, -h). Wine instead does (x+w+1, y, -w, h) and (x, y+h+1, w, -h), so the rectangle drawn is shifted 1 pixel row too far down and/or 1 pixel column too far right. This patch recalculates the rectangle dimensions correctly. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=27584 Signed-off-by: Damjan Jovanovic --- dlls/gdi32/bitblt.c | 11 +++++++++++ dlls/gdi32/tests/bitmap.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c index d2cc746c3fe..445ce1ab1f2 100644 --- a/dlls/gdi32/bitblt.c +++ b/dlls/gdi32/bitblt.c @@ -539,6 +539,17 @@ BOOL WINAPI PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop update_dc( dc ); + if (width < 0) + { + left += width; + width = -width; + } + if (height < 0) + { + top += height; + height = -height; + } + dst.log_x = left; dst.log_y = top; dst.log_width = width; diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index fe3482671b2..a3969cf25d6 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -3074,6 +3074,41 @@ static void test_BitBlt(void) DeleteDC(hdcScreen); } +static void test_PatBlt(void) +{ + HDC hdc; + HBITMAP hbmp, holdbmp; + HBRUSH holdbrush; + RECT r; + const DWORD b = 0; + const DWORD w = 0xffffff; + + hdc = CreateCompatibleDC(0); + ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc); + hbmp = CreateBitmap(3, 3, 1, 1, NULL); + ok(hbmp != NULL, "CreateBitmap returned %p\n", hbmp); + holdbmp = SelectObject(hdc, hbmp); + holdbrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH)); + SetRect(&r, 0, 0, 3, 3); + + FillRect(hdc, &r, GetStockObject(WHITE_BRUSH)); + PatBlt(hdc, 0, 0, 2, 1, PATCOPY); + ok(GetPixel(hdc, 0, 0) == b && GetPixel(hdc, 1, 0) == b && GetPixel(hdc, 2, 0) == w, "row 0 wrong\n"); + ok(GetPixel(hdc, 0, 1) == w && GetPixel(hdc, 1, 1) == w && GetPixel(hdc, 2, 1) == w, "row 1 wrong\n"); + ok(GetPixel(hdc, 0, 2) == w && GetPixel(hdc, 1, 2) == w && GetPixel(hdc, 2, 2) == w, "row 2 wrong\n"); + + FillRect(hdc, &r, GetStockObject(WHITE_BRUSH)); + PatBlt(hdc, 2, 2, -2, -1, PATCOPY); + ok(GetPixel(hdc, 0, 0) == w && GetPixel(hdc, 1, 0) == w && GetPixel(hdc, 2, 0) == w, "row 0 wrong\n"); + ok(GetPixel(hdc, 0, 1) == b && GetPixel(hdc, 1, 1) == b && GetPixel(hdc, 2, 1) == w, "row 1 wrong\n"); + ok(GetPixel(hdc, 0, 2) == w && GetPixel(hdc, 1, 2) == w && GetPixel(hdc, 2, 2) == w, "row 2 wrong\n"); + + SelectObject(hdc, holdbrush); + SelectObject(hdc, holdbmp); + DeleteObject(hbmp); + DeleteDC(hdc); +} + static void check_StretchBlt_pixel(HDC hdcDst, HDC hdcSrc, UINT32 *dstBuffer, UINT32 *srcBuffer, DWORD dwRop, UINT32 expected, int line) { @@ -5962,6 +5997,7 @@ START_TEST(bitmap) test_select_object(); test_CreateBitmap(); test_BitBlt(); + test_PatBlt(); test_StretchBlt(); test_StretchDIBits(); test_GdiAlphaBlend();