[resend PATCH 2/3] gdiplus/metafile: Implement playback for EmfPlusRecordTypeFillClosedCurve
Nikolay Sivov <[email protected]> Tue, 7 Nov 2017 12:28:01 +0300
| Newsgroups | gmane.comp.emulators.wine.patches |
|---|---|
| Message-ID | <[email protected]> |
Signed-off-by: Nikolay Sivov <[email protected]> --- dlls/gdiplus/metafile.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 0bf152967c..683f3e5cca 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -500,6 +500,20 @@ typedef struct EmfPlusFillPath } data; } EmfPlusFillPath; +typedef struct EmfPlusFillClosedCurve +{ + EmfPlusRecordHeader Header; + DWORD BrushId; + float Tension; + DWORD Count; + union + { + EmfPlusPointR7 pointsR[1]; + EmfPlusPoint points[1]; + EmfPlusPointF pointsF[1]; + } PointData; +} EmfPlusFillClosedCurve; + typedef struct EmfPlusFillEllipse { EmfPlusRecordHeader Header; @@ -3064,6 +3078,86 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile, GdipDeleteBrush((GpBrush *)solidfill); return stat; } + case EmfPlusRecordTypeFillClosedCurve: + { + static const UINT fixed_part_size = FIELD_OFFSET(EmfPlusFillClosedCurve, PointData) - + sizeof(EmfPlusRecordHeader); + EmfPlusFillClosedCurve *fill = (EmfPlusFillClosedCurve *)header; + GpSolidFill *solidfill = NULL; + GpFillMode mode; + GpBrush *brush; + UINT size, i; + + if (dataSize <= fixed_part_size) + return InvalidParameter; + + if (fill->Count == 0) + return InvalidParameter; + + if (flags & 0x800) /* P */ + size = (fixed_part_size + sizeof(EmfPlusPointR7) * fill->Count + 3) & ~3; + else if (flags & 0x4000) /* C */ + size = fixed_part_size + sizeof(EmfPlusPoint) * fill->Count; + else + size = fixed_part_size + sizeof(EmfPlusPointF) * fill->Count; + + if (dataSize != size) + return InvalidParameter; + + mode = flags & 0x200 ? FillModeWinding : FillModeAlternate; /* W */ + + if (flags & 0x8000) /* S */ + { + stat = GdipCreateSolidFill(fill->BrushId, (GpSolidFill **)&solidfill); + if (stat != Ok) + return stat; + brush = (GpBrush *)solidfill; + } + else + { + if (fill->BrushId >= EmfPlusObjectTableSize || + real_metafile->objtable[fill->BrushId].type != ObjectTypeBrush) + return InvalidParameter; + + brush = real_metafile->objtable[fill->BrushId].u.brush; + } + + if (flags & (0x800 | 0x4000)) + { + GpPointF *points = GdipAlloc(fill->Count * sizeof(*points)); + if (points) + { + if (flags & 0x800) /* P */ + { + for (i = 1; i < fill->Count; i++) + { + points[i].X = points[i - 1].X + fill->PointData.pointsR[i].X; + points[i].Y = points[i - 1].Y + fill->PointData.pointsR[i].Y; + } + } + else + { + for (i = 0; i < fill->Count; i++) + { + points[i].X = fill->PointData.points[i].X; + points[i].Y = fill->PointData.points[i].Y; + } + } + + stat = GdipFillClosedCurve2(real_metafile->playback_graphics, brush, + points, fill->Count, fill->Tension, mode); + GdipFree(points); + } + else + stat = OutOfMemory; + } + else + stat = GdipFillClosedCurve2(real_metafile->playback_graphics, brush, + (const GpPointF *)fill->PointData.pointsF, fill->Count, fill->Tension, mode); + + GdipDeleteBrush((GpBrush *)solidfill); + return stat; + } case EmfPlusRecordTypeFillEllipse: { EmfPlusFillEllipse *fill = (EmfPlusFillEllipse *)header; -- 2.14.2