Module: wine Branch: oldstable Commit: b4e12ea07f033e64a3e236d5f0f796a9e7e40c14 URL: https://source.winehq.org/git/wine.git/?a=commit;h=b4e12ea07f033e64a3e236d5f...
Author: Damjan Jovanovic damjan.jov@gmail.com Date: Fri Dec 13 05:17:54 2019 +0200
gdiplus: GdipGraphicsClear() should overwrite pixels, not alpha blend.
All sample code in the Python Pyglet library suffers from terrible text corruption, caused by the inability to erase the background between rendering sequential font glyphs, resulting in leftovers from previous letters mixing with the image of new letters.
This is because it attempts to erase the background by calling GdipGraphicsClear() with ARGB color 0x00000000 (completely transparent black), and in our gdiplus alpha blending that into the background has no effect. It should be using CompositeModeSourceCopy to overwrite the background with that brush instead.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=30506 Signed-off-by: Damjan Jovanovic damjan.jov@gmail.com Signed-off-by: Vincent Povirk vincent@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org (cherry picked from commit 3c8784bf9c1a897de021587437c5ec4f648c84a1) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
dlls/gdiplus/graphics.c | 4 ++++ dlls/gdiplus/tests/image.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+)
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 3216a3ea43..9ba0b15c77 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -4942,6 +4942,7 @@ GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics *graphics, ARGB color) GpSolidFill *brush; GpStatus stat; GpRectF wnd_rect; + CompositingMode prev_comp_mode;
TRACE("(%p, %x)\n", graphics, color);
@@ -4962,8 +4963,11 @@ GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics *graphics, ARGB color) return stat; }
+ GdipGetCompositingMode(graphics, &prev_comp_mode); + GdipSetCompositingMode(graphics, CompositingModeSourceCopy); GdipFillRectangle(graphics, (GpBrush*)brush, wnd_rect.X, wnd_rect.Y, wnd_rect.Width, wnd_rect.Height); + GdipSetCompositingMode(graphics, prev_comp_mode);
GdipDeleteBrush((GpBrush*)brush);
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 5aec1c283a..414ef19253 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -5484,6 +5484,48 @@ todo_wine GdipDisposeImage((GpImage *)bitmap); }
+static void test_graphics_clear(void) +{ + BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 }; + BYTE cleared[8] = { 0,0,0,0, 0,0,0,0 }; + BYTE *bits; + GpBitmap *bitmap; + GpGraphics *graphics; + BitmapData data; + GpStatus status; + int match; + + status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap); + expect(Ok, status); + + status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); + expect(Ok, status); + + status = GdipGraphicsClear(graphics, 0x00000000); + expect(Ok, status); + + status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppARGB, &data); + expect(Ok, status); + ok(data.Width == 2, "expected 2, got %d\n", data.Width); + ok(data.Height == 1, "expected 1, got %d\n", data.Height); + ok(data.Stride == 8, "expected 8, got %d\n", data.Stride); + ok(data.PixelFormat == PixelFormat32bppARGB, "expected PixelFormat32bppARGB, got %d\n", data.PixelFormat); + match = !memcmp(data.Scan0, cleared, sizeof(cleared)); + ok(match, "bits don't match\n"); + if (!match) + { + bits = data.Scan0; + trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB, + bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]); + } + status = GdipBitmapUnlockBits(bitmap, &data); + expect(Ok, status); + + status = GdipDeleteGraphics(graphics); + expect(Ok, status); + GdipDisposeImage((GpImage *)bitmap); +} + START_TEST(image) { HMODULE mod = GetModuleHandleA("gdiplus.dll"); @@ -5559,6 +5601,7 @@ START_TEST(image) test_histogram(); test_imageabort(); test_GdipLoadImageFromStream(); + test_graphics_clear();
GdiplusShutdown(gdiplusToken); }