[PATCH] gdi32: fix PatBlt() drawing with negative width/height
Damjan Jovanovic
damjan.jov at gmail.com
Sat Nov 14 03:56:57 CST 2020
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 <damjan.jov at gmail.com>
---
dlls/gdi32/bitblt.c | 11 +++++++++++
dlls/gdi32/tests/bitmap.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
-------------- next part --------------
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();
More information about the wine-devel
mailing list