Signed-off-by: Shawn M. Chapla schapla@codeweavers.com --- dlls/gdiplus/tests/metafile.c | 97 +++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+)
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index 8179e1a5fd..f0b31b4f9c 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3174,6 +3174,102 @@ static void test_unknownfontdecode(void) GdipDisposeImage((GpImage*)metafile); }
+static const emfplus_record fillregion_records[] = { + { EMR_HEADER }, + { EmfPlusRecordTypeHeader }, + { EmfPlusRecordTypeObject, ObjectTypeRegion << 8, 1 }, + { EmfPlusRecordTypeFillRegion, 0x8000, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1, 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeRegion << 8) | 2, 1 }, + { EmfPlusRecordTypeFillRegion, 2, 1 }, + { EmfPlusRecordTypeEndOfFile }, + { EMR_EOF }, + { 0 } +}; + +static void test_fillregion(void) +{ + static const GpPointF dst_points[3] = {{0.0, 0.0}, {100.0, 0.0}, {0.0, 100.0}}; + static const GpRectF frame = {0.0, 0.0, 100.0, 100.0}; + static const GpRectF solidrect = {20.0, 20.0, 20.0, 20.0}; + static const GpRectF hatchrect = {50.0, 50.0, 20.0, 20.0}; + + GpStatus stat; + GpMetafile *metafile; + GpGraphics *graphics; + GpBitmap *bitmap; + GpBrush *solidbrush, *hatchbrush; + GpRegion *solidregion, *hatchregion; + ARGB color; + HDC hdc; + + hdc = CreateCompatibleDC(0); + stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, + L"winetest", &metafile); + expect(Ok, stat); + DeleteDC(hdc); + hdc = NULL; + + stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics); + expect(Ok, stat); + + stat = GdipCreateRegionRect(&solidrect, &solidregion); + expect(Ok, stat); + + stat = GdipCreateSolidFill(0xffaabbcc, (GpSolidFill**)&solidbrush); + expect(Ok, stat); + + stat = GdipFillRegion(graphics, solidbrush, solidregion); + expect(Ok, stat); + + stat = GdipCreateRegionRect(&hatchrect, &hatchregion); + expect(Ok, stat); + + stat = GdipCreateHatchBrush(HatchStyleHorizontal, 0xffff0000, 0xff0000ff, + (GpHatch**)&hatchbrush); + expect(Ok, stat); + + stat = GdipFillRegion(graphics, hatchbrush, hatchregion); + expect(Ok, stat); + + stat = GdipDeleteGraphics(graphics); + graphics = NULL; + expect(Ok, stat); + + check_metafile(metafile, fillregion_records, "regionfill metafile", dst_points, + &frame, UnitPixel); + sync_metafile(&metafile, "regionfill.emf"); + + stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap); + expect(Ok, stat); + + stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); + expect(Ok, stat); + + play_metafile(metafile, graphics, fillregion_records, "regionfill playback", + dst_points, &frame, UnitPixel); + + stat = GdipBitmapGetPixel(bitmap, 25, 25, &color); + expect(Ok, stat); + todo_wine expect(0xffaabbcc, color); + + stat = GdipBitmapGetPixel(bitmap, 56, 56, &color); + expect(Ok, stat); + todo_wine expect(0xffff0000, color); + + stat = GdipBitmapGetPixel(bitmap, 57, 57, &color); + expect(Ok, stat); + todo_wine expect(0xff0000ff, color); + + GdipDeleteRegion(solidregion); + GdipDeleteRegion(hatchregion); + GdipDeleteBrush(solidbrush); + GdipDeleteBrush(hatchbrush); + GdipDeleteGraphics(graphics); + GdipDisposeImage((GpImage*)bitmap); + GdipDisposeImage((GpImage*)metafile); +} + START_TEST(metafile) { struct GdiplusStartupInput gdiplusStartupInput; @@ -3225,6 +3321,7 @@ START_TEST(metafile) test_restoredc(); test_drawdriverstring(); test_unknownfontdecode(); + test_fillregion();
GdiplusShutdown(gdiplusToken); }
Signed-off-by: Shawn M. Chapla schapla@codeweavers.com --- dlls/gdiplus/metafile.c | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index d6bcbb5c12..ed4e8a8be4 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -563,6 +563,16 @@ typedef struct EmfPlusDrawDriverString BYTE VariableData[1]; } EmfPlusDrawDriverString;
+typedef struct EmfPlusFillRegion +{ + EmfPlusRecordHeader Header; + union + { + DWORD BrushId; + EmfPlusARGB Color; + } data; +} EmfPlusFillRegion; + static void metafile_free_object_table_entry(GpMetafile *metafile, BYTE id) { struct emfplus_object *object = &metafile->objtable[id]; @@ -3438,6 +3448,42 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
return stat; } + case EmfPlusRecordTypeFillRegion: + { + EmfPlusFillRegion * const fill = (EmfPlusFillRegion*)header; + GpSolidFill *solidfill = NULL; + GpBrush *brush; + BYTE region = flags & 0xff; + + if (dataSize != sizeof(EmfPlusFillRegion) - sizeof(EmfPlusRecordHeader)) + return InvalidParameter; + + if (region >= EmfPlusObjectTableSize || + real_metafile->objtable[region].type != ObjectTypeRegion) + return InvalidParameter; + + if (flags & 0x8000) + { + stat = GdipCreateSolidFill(fill->data.Color, &solidfill); + if (stat != Ok) + return stat; + brush = (GpBrush*)solidfill; + } + else + { + if (fill->data.BrushId >= EmfPlusObjectTableSize || + real_metafile->objtable[fill->data.BrushId].type != ObjectTypeBrush) + return InvalidParameter; + + brush = real_metafile->objtable[fill->data.BrushId].u.brush; + } + + stat = GdipFillRegion(real_metafile->playback_graphics, brush, + real_metafile->objtable[region].u.region); + GdipDeleteBrush((GpBrush*)solidfill); + + return stat; + } default: FIXME("Not implemented for record type %x\n", recordType); return NotImplemented;
Signed-off-by: Esme Povirk esme@codeweavers.com
Signed-off-by: Shawn M. Chapla schapla@codeweavers.com --- dlls/gdiplus/gdiplus_private.h | 2 ++ dlls/gdiplus/graphics.c | 13 ++++++--- dlls/gdiplus/metafile.c | 48 ++++++++++++++++++++++++++++++++++ dlls/gdiplus/tests/metafile.c | 16 ++++++------ 4 files changed, 67 insertions(+), 12 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 1b2de4e8f4..aac5509afa 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -107,6 +107,8 @@ extern GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath * extern GpStatus METAFILE_DrawDriverString(GpMetafile *metafile, GDIPCONST UINT16 *text, INT length, GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush, GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_FillRegion(GpMetafile* metafile, GpBrush* brush, + GpRegion* region) DECLSPEC_HIDDEN; extern void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1, diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 1307bdc1ef..f0da41c6cb 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -4700,11 +4700,16 @@ GpStatus WINGDIPAPI GdipFillRegion(GpGraphics* graphics, GpBrush* brush, if(graphics->busy) return ObjectBusy;
- if (!graphics->image && !graphics->alpha_hdc) - stat = GDI32_GdipFillRegion(graphics, brush, region); + if (graphics->image && graphics->image->type == ImageTypeMetafile) + stat = METAFILE_FillRegion((GpMetafile*)graphics->image, brush, region); + else + { + if (!graphics->image && !graphics->alpha_hdc) + stat = GDI32_GdipFillRegion(graphics, brush, region);
- if (stat == NotImplemented) - stat = SOFTWARE_GdipFillRegion(graphics, brush, region); + if (stat == NotImplemented) + stat = SOFTWARE_GdipFillRegion(graphics, brush, region); + }
if (stat == NotImplemented) { diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index ed4e8a8be4..1d7c0fe306 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -4854,3 +4854,51 @@ GpStatus METAFILE_DrawDriverString(GpMetafile *metafile, GDIPCONST UINT16 *text,
return Ok; } + +GpStatus METAFILE_FillRegion(GpMetafile* metafile, GpBrush* brush, GpRegion* region) +{ + GpStatus stat; + DWORD brush_id; + DWORD region_id; + EmfPlusFillRegion *fill_region_record; + BOOL inline_color; + + if (metafile->metafile_type != MetafileTypeEmfPlusOnly && + metafile->metafile_type != MetafileTypeEmfPlusDual) + { + FIXME("metafile type not supported: %i\n", metafile->metafile_type); + return NotImplemented; + } + + inline_color = (brush->bt == BrushTypeSolidColor); + if (!inline_color) + { + stat = METAFILE_AddBrushObject(metafile, brush, &brush_id); + if (stat != Ok) + return stat; + } + + stat = METAFILE_AddRegionObject(metafile, region, ®ion_id); + if (stat != Ok) + return stat; + + stat = METAFILE_AllocateRecord(metafile, sizeof(EmfPlusFillRegion), + (void**)&fill_region_record); + if (stat != Ok) + return stat; + + fill_region_record->Header.Type = EmfPlusRecordTypeFillRegion; + fill_region_record->Header.Flags = region_id; + + if (inline_color) + { + fill_region_record->Header.Flags |= 0x8000; + fill_region_record->data.Color = ((GpSolidFill*)brush)->color; + } + else + fill_region_record->data.BrushId = brush_id; + + METAFILE_WriteRecords(metafile); + + return Ok; +} diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index f0b31b4f9c..ddb58504c9 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3177,11 +3177,11 @@ static void test_unknownfontdecode(void) static const emfplus_record fillregion_records[] = { { EMR_HEADER }, { EmfPlusRecordTypeHeader }, - { EmfPlusRecordTypeObject, ObjectTypeRegion << 8, 1 }, - { EmfPlusRecordTypeFillRegion, 0x8000, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1, 1 }, - { EmfPlusRecordTypeObject, (ObjectTypeRegion << 8) | 2, 1 }, - { EmfPlusRecordTypeFillRegion, 2, 1 }, + { EmfPlusRecordTypeObject, ObjectTypeRegion << 8 }, + { EmfPlusRecordTypeFillRegion, 0x8000 }, + { EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 1 }, + { EmfPlusRecordTypeObject, (ObjectTypeRegion << 8) | 2 }, + { EmfPlusRecordTypeFillRegion, 2 }, { EmfPlusRecordTypeEndOfFile }, { EMR_EOF }, { 0 } @@ -3251,15 +3251,15 @@ static void test_fillregion(void)
stat = GdipBitmapGetPixel(bitmap, 25, 25, &color); expect(Ok, stat); - todo_wine expect(0xffaabbcc, color); + expect(0xffaabbcc, color);
stat = GdipBitmapGetPixel(bitmap, 56, 56, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color); + expect(0xffff0000, color);
stat = GdipBitmapGetPixel(bitmap, 57, 57, &color); expect(Ok, stat); - todo_wine expect(0xff0000ff, color); + expect(0xff0000ff, color);
GdipDeleteRegion(solidregion); GdipDeleteRegion(hatchregion);
We should probably get rid of that FIXME in GdipFillRegion. All brush types are implemented now, and anything not implemented will have a FIXME elsewhere.
On Wed, Jul 22, 2020 at 11:48:43AM -0500, Esme Povirk (they/them) wrote:
We should probably get rid of that FIXME in GdipFillRegion. All brush types are implemented now, and anything not implemented will have a FIXME elsewhere.
METAFILE_AddBrushObject still only supports BrushTypeSolidColor and BrushTypeHatchFill currently, although like you said there are FIXMEs for this elsewhere.
I could add another patch to remove this FIXME (or just do it in this patch, if you prefer).
Signed-off-by: Esme Povirk esme@codeweavers.com