Module: wine Branch: master Commit: fea3a7447aba49b2f7f6c5e53b581b60b96539f8 URL: https://gitlab.winehq.org/wine/wine/-/commit/fea3a7447aba49b2f7f6c5e53b581b6...
Author: Zhiyi Zhang zzhang@codeweavers.com Date: Wed May 3 22:36:13 2023 +0800
gdiplus: Support playing back pen custom start line cap.
---
dlls/gdiplus/metafile.c | 124 +++++++++++++++++++++++++++++++++++++++++- dlls/gdiplus/tests/metafile.c | 1 - 2 files changed, 123 insertions(+), 2 deletions(-)
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 92c818afbac..9d209e81983 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -2340,6 +2340,122 @@ static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_si return status; }
+static GpStatus metafile_deserialize_custom_line_cap(const BYTE *record_data, UINT data_size, GpCustomLineCap **cap) +{ + EmfPlusCustomStartCapData *custom_cap_data = (EmfPlusCustomStartCapData *)record_data; + EmfPlusCustomLineCap *line_cap; + GpStatus status; + UINT offset; + + *cap = NULL; + + if (data_size < FIELD_OFFSET(EmfPlusCustomStartCapData, data)) + return InvalidParameter; + if (data_size < FIELD_OFFSET(EmfPlusCustomStartCapData, data) + custom_cap_data->CustomStartCapSize) + return InvalidParameter; + offset = FIELD_OFFSET(EmfPlusCustomStartCapData, data); + line_cap = (EmfPlusCustomLineCap *)(record_data + offset); + + if (data_size < offset + FIELD_OFFSET(EmfPlusCustomLineCap, CustomLineCapData)) + return InvalidParameter; + offset += FIELD_OFFSET(EmfPlusCustomLineCap, CustomLineCapData); + + if (line_cap->Type == CustomLineCapTypeAdjustableArrow) + { + EmfPlusCustomLineCapArrowData *arrow_data; + GpAdjustableArrowCap *arrow_cap; + + arrow_data = (EmfPlusCustomLineCapArrowData *)(record_data + offset); + + if (data_size < offset + sizeof(EmfPlusCustomLineCapArrowData)) + return InvalidParameter; + + if ((status = GdipCreateAdjustableArrowCap(arrow_data->Height, arrow_data->Width, + arrow_data->FillState, &arrow_cap))) + return status; + + if ((status = GdipSetAdjustableArrowCapMiddleInset(arrow_cap, arrow_data->MiddleInset))) + goto arrow_cap_failed; + if ((status = GdipSetCustomLineCapStrokeCaps((GpCustomLineCap *)arrow_cap, arrow_data->LineStartCap, arrow_data->LineEndCap))) + goto arrow_cap_failed; + if ((status = GdipSetCustomLineCapStrokeJoin((GpCustomLineCap *)arrow_cap, arrow_data->LineJoin))) + goto arrow_cap_failed; + if ((status = GdipSetCustomLineCapWidthScale((GpCustomLineCap *)arrow_cap, arrow_data->WidthScale))) + goto arrow_cap_failed; + + *cap = (GpCustomLineCap *)arrow_cap; + return Ok; + + arrow_cap_failed: + GdipDeleteCustomLineCap((GpCustomLineCap *)arrow_cap); + return status; + } + else + { + GpPath *path, *fill_path = NULL, *stroke_path = NULL; + EmfPlusCustomLineCapData *line_cap_data; + GpCustomLineCap *line_cap = NULL; + GpStatus status; + + line_cap_data = (EmfPlusCustomLineCapData *)(record_data + offset); + + if (data_size < offset + FIELD_OFFSET(EmfPlusCustomLineCapData, OptionalData)) + return InvalidParameter; + offset += FIELD_OFFSET(EmfPlusCustomLineCapData, OptionalData); + + if (line_cap_data->CustomLineCapDataFlags == CustomLineCapDataFillPath) + { + EmfPlusCustomLineCapDataFillPath *fill_path = (EmfPlusCustomLineCapDataFillPath *)(record_data + offset); + + if (data_size < offset + FIELD_OFFSET(EmfPlusCustomLineCapDataFillPath, FillPath)) + return InvalidParameter; + if (data_size < offset + fill_path->FillPathLength) + return InvalidParameter; + + offset += FIELD_OFFSET(EmfPlusCustomLineCapDataFillPath, FillPath); + } + else + { + EmfPlusCustomLineCapDataLinePath *line_path = (EmfPlusCustomLineCapDataLinePath *)(record_data + offset); + + if (data_size < offset + FIELD_OFFSET(EmfPlusCustomLineCapDataLinePath, LinePath)) + return InvalidParameter; + if (data_size < offset + line_path->LinePathLength) + return InvalidParameter; + + offset += FIELD_OFFSET(EmfPlusCustomLineCapDataLinePath, LinePath); + } + + if ((status = metafile_deserialize_path(record_data + offset, data_size - offset, &path))) + return status; + + if (line_cap_data->CustomLineCapDataFlags == CustomLineCapDataFillPath) + fill_path = path; + else + stroke_path = path; + + if ((status = GdipCreateCustomLineCap(fill_path, stroke_path, line_cap_data->BaseCap, + line_cap_data->BaseInset, &line_cap))) + goto default_cap_failed; + if ((status = GdipSetCustomLineCapStrokeCaps(line_cap, line_cap_data->StrokeStartCap, line_cap_data->StrokeEndCap))) + goto default_cap_failed; + if ((status = GdipSetCustomLineCapStrokeJoin(line_cap, line_cap_data->StrokeJoin))) + goto default_cap_failed; + if ((status = GdipSetCustomLineCapWidthScale(line_cap, line_cap_data->WidthScale))) + goto default_cap_failed; + + GdipDeletePath(path); + *cap = line_cap; + return Ok; + + default_cap_failed: + if (line_cap) + GdipDeleteCustomLineCap(line_cap); + GdipDeletePath(path); + return status; + } +} + static GpStatus metafile_get_pen_brush_data_offset(EmfPlusPen *data, UINT data_size, DWORD *ret) { EmfPlusPenData *pendata = (EmfPlusPenData *)data->data; @@ -2446,6 +2562,7 @@ static GpStatus METAFILE_PlaybackObject(GpMetafile *metafile, UINT flags, UINT d { EmfPlusPen *data = (EmfPlusPen *)record_data; EmfPlusPenData *pendata = (EmfPlusPenData *)data->data; + GpCustomLineCap *custom_line_cap; GpBrush *brush; DWORD offset; GpPen *pen; @@ -2542,7 +2659,12 @@ static GpStatus METAFILE_PlaybackObject(GpMetafile *metafile, UINT flags, UINT d if (pendata->PenDataFlags & PenDataCustomStartCap) { EmfPlusCustomStartCapData *startcap = (EmfPlusCustomStartCapData *)((BYTE *)pendata + offset); - FIXME("PenDataCustomStartCap is not supported.\n"); + if ((status = metafile_deserialize_custom_line_cap((BYTE *)startcap, data_size, &custom_line_cap)) != Ok) + goto penfailed; + status = GdipSetPenCustomStartCap(pen, custom_line_cap); + GdipDeleteCustomLineCap(custom_line_cap); + if (status != Ok) + goto penfailed; offset += FIELD_OFFSET(EmfPlusCustomStartCapData, data) + startcap->CustomStartCapSize; }
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index ceca8e4a9bb..4e4277d4d1f 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3983,7 +3983,6 @@ static void test_pen(void)
stat = GdipBitmapGetPixel(bitmap, 10, 10, &color); expect(Ok, stat); - todo_wine expect(0xffff0000, color);
stat = GdipBitmapGetPixel(bitmap, 40, 90, &color);