[PATCH 0/3] MR11727: gdiplus/metafile: Fix emf+ image rendering
The documentation says that the upper-left, upper-right, and lower-left corners should be passed in. However, the code was incorrectly passing the lower-right corner instead of the lower-left, resulting in skewed rendering. https://learn.microsoft.com/en-us/windows/win32/api/gdiplusgraphics/nf-gdipl... Before: {width=141 height=145} After: {width=132 height=137} -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11727
From: Tobiasz Laskowski <tlaskowski@codeweavers.com> --- dlls/gdiplus/tests/metafile.c | 63 +++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index b0315acbf98..6504d773ea8 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -2725,25 +2725,33 @@ static BOOL CALLBACK play_drawimage_proc(EmfPlusRecordType recordType, UINT flag return TRUE; } -static void check_play_drawimage(DrawImageBaseRecord* record) { +static GpBitmap* check_play_drawimage(DrawImageBaseRecord* record) { static const GpRectF frame = { 0.0f, 0.0f, 100.0f, 100.0f }; GpMetafile* metafile; GpGraphics* graphics; GpBitmap* bitmap; play_draw_image_ctx ctx; GpStatus stat; + ARGB color = 0; HDC hdc; hdc = CreateCompatibleDC(0); - stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile); + + stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap); expect(Ok, stat); - stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics); + stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); + expect(Ok, stat); + stat = GdipGraphicsClear(graphics, 0xffff0000); + expect(Ok, stat); + stat = GdipDeleteGraphics(graphics); expect(Ok, stat); - stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap); + stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile); expect(Ok, stat); + stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics); + expect(Ok, stat); stat = GdipDrawImage(graphics, (GpImage*)bitmap, 0.0f, 0.0f); expect(Ok, stat); @@ -2752,7 +2760,9 @@ static void check_play_drawimage(DrawImageBaseRecord* record) { stat = GdipDeleteGraphics(graphics); expect(Ok, stat); - stat = GdipCreateFromHDC(hdc, &graphics); + stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap); + expect(Ok, stat); + stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); expect(Ok, stat); ctx.metafile = metafile; @@ -2764,13 +2774,36 @@ static void check_play_drawimage(DrawImageBaseRecord* record) { expect(Ok, stat); expect(TRUE, ctx.executed); + stat = GdipBitmapGetPixel(bitmap, 0, 0, &color); + expect(Ok, stat); + expect(0xffff0000, color); + + stat = GdipBitmapGetPixel(bitmap, 99, 0, &color); + expect(Ok, stat); + expect(0xffff0000, color); + + stat = GdipBitmapGetPixel(bitmap, 99, 99, &color); + expect(Ok, stat); + expect(0xffff0000, color); + + stat = GdipBitmapGetPixel(bitmap, 100, 100, &color); + expect(InvalidParameter, stat); + + stat = GdipBitmapGetPixel(bitmap, -1, -1, &color); + expect(InvalidParameter, stat); + GdipDeleteGraphics(graphics); GdipDisposeImage((GpImage*)metafile); DeleteDC(hdc); + + return bitmap; } static void test_drawimage_record(void) { DrawImageRecord record; + GpStatus stat; + ARGB color = 0; + GpBitmap* bitmap; record.Header.Type = EmfPlusRecordTypeDrawImage; record.Header.Flags = 0; @@ -2788,11 +2821,21 @@ static void test_drawimage_record(void) { record.rectF.Width = 100.0f; record.rectF.Height = 100.0f; - check_play_drawimage((DrawImageBaseRecord*)&record); + bitmap = check_play_drawimage((DrawImageBaseRecord*)&record); + + stat = GdipBitmapGetPixel(bitmap, 0, 99, &color); + expect(Ok, stat); + todo_wine + expect(0xffff0000, color); + + GdipDisposeImage((GpImage*)bitmap); } static void test_drawimagepoints_record(void) { DrawImagePointsRecord record; + GpStatus stat; + ARGB color = 0; + GpBitmap* bitmap; record.Header.Type = EmfPlusRecordTypeDrawImagePoints; record.Header.Flags = 0; @@ -2814,7 +2857,13 @@ static void test_drawimagepoints_record(void) { record.pointsF[2].X = 0.0f; record.pointsF[2].Y = 100.0f; - check_play_drawimage((DrawImageBaseRecord*)&record); + bitmap = check_play_drawimage((DrawImageBaseRecord*)&record); + + stat = GdipBitmapGetPixel(bitmap, 0, 99, &color); + expect(Ok, stat); + expect(0xffff0000, color); + + GdipDisposeImage((GpImage*)bitmap); } static const emfplus_record properties_records[] = { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11727
From: Tobiasz Laskowski <tlaskowski@codeweavers.com> The documentation says that the upper-left, upper-right, and lower-left corners should be passed in. However, the code was incorrectly passing the lower-right corner instead of the lower-left, resulting in skewed rendering. https://learn.microsoft.com/en-us/windows/win32/api/gdiplusgraphics/nf-gdipl... --- dlls/gdiplus/metafile.c | 8 ++++---- dlls/gdiplus/tests/metafile.c | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index b9323559582..ad3533acb4e 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -3240,8 +3240,8 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile, points[0].Y = draw->RectData.rect.Y; points[1].X = points[0].X + draw->RectData.rect.Width; points[1].Y = points[0].Y; - points[2].X = points[1].X; - points[2].Y = points[1].Y + draw->RectData.rect.Height; + points[2].X = points[0].X; + points[2].Y = points[0].Y + draw->RectData.rect.Height; } else { @@ -3249,8 +3249,8 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile, points[0].Y = draw->RectData.rectF.Y; points[1].X = points[0].X + draw->RectData.rectF.Width; points[1].Y = points[0].Y; - points[2].X = points[1].X; - points[2].Y = points[1].Y + draw->RectData.rectF.Height; + points[2].X = points[0].X; + points[2].Y = points[0].Y + draw->RectData.rectF.Height; } return GdipDrawImagePointsRect(real_metafile->playback_graphics, real_metafile->objtable[image].u.image, diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index 6504d773ea8..4a47551c777 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -2825,7 +2825,6 @@ static void test_drawimage_record(void) { stat = GdipBitmapGetPixel(bitmap, 0, 99, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); GdipDisposeImage((GpImage*)bitmap); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11727
From: Tobiasz Laskowski <tlaskowski@codeweavers.com> Now both the DrawImage and DrawImagePoints cases have the correct pixel in the bottom left corner, we can place this check in the common function. --- dlls/gdiplus/tests/metafile.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index 4a47551c777..5dc2dd25bdc 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -2725,7 +2725,7 @@ static BOOL CALLBACK play_drawimage_proc(EmfPlusRecordType recordType, UINT flag return TRUE; } -static GpBitmap* check_play_drawimage(DrawImageBaseRecord* record) { +static void check_play_drawimage(DrawImageBaseRecord* record) { static const GpRectF frame = { 0.0f, 0.0f, 100.0f, 100.0f }; GpMetafile* metafile; GpGraphics* graphics; @@ -2778,6 +2778,10 @@ static GpBitmap* check_play_drawimage(DrawImageBaseRecord* record) { expect(Ok, stat); expect(0xffff0000, color); + stat = GdipBitmapGetPixel(bitmap, 0, 99, &color); + expect(Ok, stat); + expect(0xffff0000, color); + stat = GdipBitmapGetPixel(bitmap, 99, 0, &color); expect(Ok, stat); expect(0xffff0000, color); @@ -2793,17 +2797,13 @@ static GpBitmap* check_play_drawimage(DrawImageBaseRecord* record) { expect(InvalidParameter, stat); GdipDeleteGraphics(graphics); + GdipDisposeImage((GpImage*)bitmap); GdipDisposeImage((GpImage*)metafile); DeleteDC(hdc); - - return bitmap; } static void test_drawimage_record(void) { DrawImageRecord record; - GpStatus stat; - ARGB color = 0; - GpBitmap* bitmap; record.Header.Type = EmfPlusRecordTypeDrawImage; record.Header.Flags = 0; @@ -2821,20 +2821,11 @@ static void test_drawimage_record(void) { record.rectF.Width = 100.0f; record.rectF.Height = 100.0f; - bitmap = check_play_drawimage((DrawImageBaseRecord*)&record); - - stat = GdipBitmapGetPixel(bitmap, 0, 99, &color); - expect(Ok, stat); - expect(0xffff0000, color); - - GdipDisposeImage((GpImage*)bitmap); + check_play_drawimage((DrawImageBaseRecord*)&record); } static void test_drawimagepoints_record(void) { DrawImagePointsRecord record; - GpStatus stat; - ARGB color = 0; - GpBitmap* bitmap; record.Header.Type = EmfPlusRecordTypeDrawImagePoints; record.Header.Flags = 0; @@ -2856,13 +2847,7 @@ static void test_drawimagepoints_record(void) { record.pointsF[2].X = 0.0f; record.pointsF[2].Y = 100.0f; - bitmap = check_play_drawimage((DrawImageBaseRecord*)&record); - - stat = GdipBitmapGetPixel(bitmap, 0, 99, &color); - expect(Ok, stat); - expect(0xffff0000, color); - - GdipDisposeImage((GpImage*)bitmap); + check_play_drawimage((DrawImageBaseRecord*)&record); } static const emfplus_record properties_records[] = { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11727
This merge request was approved by Esme Povirk. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11727
participants (3)
-
Esme Povirk (@madewokherd) -
Tobi Laskowski (@tobil) -
Tobiasz Laskowski