Module: wine Branch: master Commit: de37cedb70df9993eefcab48cd55421b128d1f32 URL: http://source.winehq.org/git/wine.git/?a=commit;h=de37cedb70df9993eefcab48cd...
Author: Piotr Caban piotr@codeweavers.com Date: Thu Jul 13 11:54:00 2017 +0200
gdiplus: Add partial support for GdipFillPath on metafiles.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Vincent Povirk vincent@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/gdiplus/gdiplus_private.h | 1 + dlls/gdiplus/graphics.c | 3 ++ dlls/gdiplus/metafile.c | 80 ++++++++++++++++++++++++++++++++++++++++++ dlls/gdiplus/tests/metafile.c | 68 +++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 8c23bbb..88109d7 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -112,6 +112,7 @@ extern GpStatus METAFILE_DrawImagePointsRect(GpMetafile* metafile, GpImage *imag DrawImageAbort callback, VOID *callbackData) DECLSPEC_HIDDEN; extern GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val) DECLSPEC_HIDDEN; extern GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) 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 68614f1..10d581d 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -4140,6 +4140,9 @@ GpStatus WINGDIPAPI GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *p if(graphics->busy) return ObjectBusy;
+ if (graphics->image && graphics->image->type == ImageTypeMetafile) + return METAFILE_FillPath((GpMetafile*)graphics->image, brush, path); + if (!graphics->image && !graphics->alpha_hdc) stat = GDI32_GdipFillPath(graphics, brush, path);
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 3d6214d..a1db09b 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -309,6 +309,7 @@ typedef struct EmfPlusObject EmfPlusRecordHeader Header; union { + EmfPlusBrush brush; EmfPlusPen pen; EmfPlusPath path; EmfPlusImage image; @@ -351,6 +352,16 @@ typedef struct EmfPlusDrawPath DWORD PenId; } EmfPlusDrawPath;
+typedef struct EmfPlusFillPath +{ + EmfPlusRecordHeader Header; + union + { + DWORD BrushId; + EmfPlusARGB Color; + } data; +} EmfPlusFillPath; + static DWORD METAFILE_AddObjectId(GpMetafile *metafile) { return (metafile->next_object_id++) % 64; @@ -2915,3 +2926,72 @@ GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) METAFILE_WriteRecords(metafile); return NotImplemented; } + +static GpStatus METAFILE_AddBrushObject(GpMetafile *metafile, GpBrush *brush, DWORD *id) +{ + EmfPlusObject *object_record; + GpStatus stat; + DWORD size; + + *id = -1; + if (metafile->metafile_type != MetafileTypeEmfPlusOnly && metafile->metafile_type != MetafileTypeEmfPlusDual) + return Ok; + + stat = METAFILE_PrepareBrushData(brush, &size); + if (stat != Ok) return stat; + + stat = METAFILE_AllocateRecord(metafile, + FIELD_OFFSET(EmfPlusObject, ObjectData) + size, (void**)&object_record); + if (stat != Ok) return stat; + + *id = METAFILE_AddObjectId(metafile); + object_record->Header.Type = EmfPlusRecordTypeObject; + object_record->Header.Flags = *id | ObjectTypeBrush << 8; + METAFILE_FillBrushData(brush, &object_record->ObjectData.brush); + return Ok; +} + +GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) +{ + EmfPlusFillPath *fill_path_record; + DWORD brush_id = -1, path_id; + 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_AddPathObject(metafile, path, &path_id); + if (stat != Ok) return stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusFillPath), (void**)&fill_path_record); + if (stat != Ok) return stat; + fill_path_record->Header.Type = EmfPlusRecordTypeFillPath; + if (inline_color) + { + fill_path_record->Header.Flags = 0x8000 | path_id; + fill_path_record->data.Color.Blue = ((GpSolidFill*)brush)->color & 0xff; + fill_path_record->data.Color.Green = (((GpSolidFill*)brush)->color >> 8) & 0xff; + fill_path_record->data.Color.Red = (((GpSolidFill*)brush)->color >> 16) & 0xff; + fill_path_record->data.Color.Alpha = ((GpSolidFill*)brush)->color >> 24; + } + else + { + fill_path_record->Header.Flags = path_id; + fill_path_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 fe14e29..feeaedb 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -2549,6 +2549,73 @@ static void test_drawpath(void) expect(Ok, stat); }
+static const emfplus_record fill_path_records[] = { + {0, EMR_HEADER}, + {0, EmfPlusRecordTypeHeader}, + {0, EmfPlusRecordTypeObject}, + {0, EmfPlusRecordTypeFillPath}, + {1, EMR_SAVEDC}, + {1, EMR_SETICMMODE}, + {1, EMR_BITBLT}, + {1, EMR_RESTOREDC}, + {0, EmfPlusRecordTypeEndOfFile}, + {0, EMR_EOF}, + {0} +}; + +static void test_fillpath(void) +{ + static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0}; + static const GpRectF frame = {0.0, 0.0, 100.0, 100.0}; + + GpMetafile *metafile; + GpGraphics *graphics; + GpSolidFill *brush; + HENHMETAFILE hemf; + GpStatus stat; + GpPath *path; + 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 = GdipCreatePath(FillModeAlternate, &path); + expect(Ok, stat); + stat = GdipAddPathLine(path, 5, 5, 30, 30); + expect(Ok, stat); + stat = GdipAddPathLine(path, 30, 30, 5, 30); + expect(Ok, stat); + + stat = GdipCreateSolidFill(0xffaabbcc, &brush); + expect(Ok, stat); + + stat = GdipFillPath(graphics, (GpBrush*)brush, path); + expect(Ok, stat); + + stat = GdipDeleteBrush((GpBrush*)brush); + expect(Ok, stat); + stat = GdipDeletePath(path); + expect(Ok, stat); + + stat = GdipDeleteGraphics(graphics); + expect(Ok, stat); + sync_metafile(&metafile, "fill_path.emf"); + + stat = GdipGetHemfFromMetafile(metafile, &hemf); + expect(Ok, stat); + + check_emfplus(hemf, fill_path_records, "fill path"); + DeleteEnhMetaFile(hemf); + + stat = GdipDisposeImage((GpImage*)metafile); + expect(Ok, stat); +} + START_TEST(metafile) { struct GdiplusStartupInput gdiplusStartupInput; @@ -2589,6 +2656,7 @@ START_TEST(metafile) test_drawimage(); test_properties(); test_drawpath(); + test_fillpath();
GdiplusShutdown(gdiplusToken); }