From 81b7555da8bfa48ec494bfb57827fc8e8ab3a1aa Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 18 Mar 2021 15:18:01 +0300 Subject: [PATCH] gdiplus/metafile: Implement FillEllipse() recording. Signed-off-by: Nikolay Sivov Signed-off-by: Esme Povirk Signed-off-by: Alexandre Julliard --- dlls/gdiplus/gdiplus_private.h | 1 + dlls/gdiplus/graphics.c | 11 +++++++ dlls/gdiplus/metafile.c | 46 +++++++++++++++++++++++++++ dlls/gdiplus/tests/metafile.c | 58 ++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+) diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 0b6dfb69b07..9b608035909 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -111,6 +111,7 @@ extern GpStatus METAFILE_FillRegion(GpMetafile* metafile, GpBrush* brush, GpRegion* region) DECLSPEC_HIDDEN; extern void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN; extern GpStatus METAFILE_DrawEllipse(GpMetafile *metafile, GpPen *pen, GpRectF *rect) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_FillEllipse(GpMetafile *metafile, GpBrush *brush, GpRectF *rect) DECLSPEC_HIDDEN; extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1, REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN; diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index b2d0e6bf59b..97dfc4a75f2 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -4258,6 +4258,17 @@ GpStatus WINGDIPAPI GdipFillEllipse(GpGraphics *graphics, GpBrush *brush, REAL x if(graphics->busy) return ObjectBusy; + if (graphics->image && graphics->image->type == ImageTypeMetafile) + { + GpRectF rect; + + rect.X = x; + rect.Y = y; + rect.Width = width; + rect.Height = height; + return METAFILE_FillEllipse((GpMetafile *)graphics->image, brush, &rect); + } + stat = GdipCreatePath(FillModeAlternate, &path); if (stat == Ok) diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 3e7853ecd50..c285dc58f40 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -4850,6 +4850,52 @@ GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) return Ok; } +GpStatus METAFILE_FillEllipse(GpMetafile *metafile, GpBrush *brush, GpRectF *rect) +{ + EmfPlusFillEllipse *record; + DWORD brush_id = -1; + BOOL inline_color; + GpStatus stat; + + if (metafile->metafile_type == MetafileTypeEmf) + { + FIXME("stub!\n"); + return NotImplemented; + } + + inline_color = brush->bt == BrushTypeSolidColor; + if (!inline_color) + { + stat = METAFILE_AddBrushObject(metafile, brush, &brush_id); + if (stat != Ok) return stat; + } + + stat = METAFILE_AllocateRecord(metafile, sizeof(EmfPlusFillEllipse), (void **)&record); + if (stat != Ok) return stat; + record->Header.Type = EmfPlusRecordTypeFillEllipse; + if (inline_color) + { + record->Header.Flags = 0x8000; + record->BrushId = ((GpSolidFill *)brush)->color; + } + else + record->BrushId = brush_id; + + if (is_integer_rect(rect)) + { + record->Header.Flags |= 0x4000; + record->RectData.rect.X = (SHORT)rect->X; + record->RectData.rect.Y = (SHORT)rect->Y; + record->RectData.rect.Width = (SHORT)rect->Width; + record->RectData.rect.Height = (SHORT)rect->Height; + } + else + memcpy(&record->RectData.rectF, rect, sizeof(*rect)); + + METAFILE_WriteRecords(metafile); + return Ok; +} + static GpStatus METAFILE_AddFontObject(GpMetafile *metafile, GDIPCONST GpFont *font, DWORD *id) { EmfPlusObject *object_record; diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index fede802b675..410e9a6ab8c 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3593,6 +3593,63 @@ static void test_drawellipse(void) expect(Ok, stat); } +static const emfplus_record fill_ellipse_records[] = +{ + { EMR_HEADER }, + { EmfPlusRecordTypeHeader }, + { EmfPlusRecordTypeFillEllipse, 0xc000 }, + { EMR_SAVEDC, 0, 1 }, + { EMR_SETICMMODE, 0, 1 }, + { EMR_BITBLT, 0, 1 }, + { EMR_RESTOREDC, 0, 1 }, + { EmfPlusRecordTypeEndOfFile }, + { EMR_EOF }, + { 0 } +}; + +static void test_fillellipse(void) +{ + static const GpRectF frame = { 0.0f, 0.0f, 100.0f, 100.0f }; + + GpMetafile *metafile; + GpGraphics *graphics; + GpSolidFill *brush; + HENHMETAFILE hemf; + GpStatus stat; + HDC hdc; + + hdc = CreateCompatibleDC(0); + stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile); + expect(Ok, stat); + DeleteDC(hdc); + + stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics); + expect(Ok, stat); + + stat = GdipCreateSolidFill(0xffaabbcc, &brush); + expect(Ok, stat); + + stat = GdipFillEllipse(graphics, (GpBrush *)brush, 0.0f, 0.0f, 10.0f, 20.0f); + expect(Ok, stat); + + stat = GdipDeleteBrush((GpBrush*)brush); + expect(Ok, stat); + + stat = GdipDeleteGraphics(graphics); + expect(Ok, stat); + sync_metafile(&metafile, "fill_ellipse.emf"); + + stat = GdipGetHemfFromMetafile(metafile, &hemf); + expect(Ok, stat); + + check_emfplus(hemf, fill_ellipse_records, "fill ellipse"); + + DeleteEnhMetaFile(hemf); + + stat = GdipDisposeImage((GpImage*)metafile); + expect(Ok, stat); +} + START_TEST(metafile) { struct GdiplusStartupInput gdiplusStartupInput; @@ -3648,6 +3705,7 @@ START_TEST(metafile) test_lineargradient(); test_printer_dc(); test_drawellipse(); + test_fillellipse(); GdiplusShutdown(gdiplusToken); }