Fix Cafe Stella (SteamID: 1829980) Flowchart crashes once there are 2 things on it.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/gdiplus/tests/metafile.c | 126 ++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+)
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index aa844a62ff9..48da5c648ef 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3874,6 +3874,131 @@ static void test_setclippath(void) expect(Ok, stat); }
+static const emfplus_record pen_dc_records[] = +{ + { EMR_HEADER }, + { EmfPlusRecordTypeHeader }, + { EmfPlusRecordTypeObject, ObjectTypePen << 8 }, + { EmfPlusRecordTypeObject, (ObjectTypePath << 8) | 1 }, + { EmfPlusRecordTypeDrawPath, 1 }, + { EMR_SAVEDC, 0, 1 }, + { EMR_SETICMMODE, 0, 1 }, + { EMR_BITBLT, 0, 1 }, + { EMR_RESTOREDC, 0, 1 }, + { EmfPlusRecordTypeEndOfFile }, + { EMR_EOF }, + { 0 } +}; + +static const emfplus_record pen_bitmap_records[] = +{ + { EMR_HEADER }, + { EmfPlusRecordTypeHeader }, + { EmfPlusRecordTypeObject, ObjectTypePen << 8 }, + { EmfPlusRecordTypeObject, (ObjectTypePath << 8) | 1 }, + { EmfPlusRecordTypeDrawPath, 1 }, + { EmfPlusRecordTypeEndOfFile }, + { EMR_EOF }, + { 0 } +}; + +static void test_pen(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}; + GpMetafile *metafile, *clone_metafile; + GpPath *draw_path, *line_cap_path; + GpCustomLineCap *custom_line_cap; + GpGraphics *graphics; + HENHMETAFILE hemf; + COLORREF color; + GpStatus stat; + GpPen *pen; + HWND hwnd; + BOOL ret; + HDC hdc; + + /* Record */ + 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, &draw_path); + expect(Ok, stat); + stat = GdipAddPathLine(draw_path, 25, 25, 25, 75); + expect(Ok, stat); + + stat = GdipCreatePen1((ARGB)0xffff0000, 1.0f, UnitPixel, &pen); + expect(Ok, stat); + stat = GdipCreatePath(FillModeAlternate, &line_cap_path); + expect(Ok, stat); + stat = GdipAddPathRectangle(line_cap_path, 5.0, 5.0, 10.0, 10.0); + expect(Ok, stat); + stat = GdipCreateCustomLineCap(NULL, line_cap_path, LineCapCustom, 0.0, &custom_line_cap); + expect(Ok, stat); + stat = GdipSetPenCustomStartCap(pen, custom_line_cap); + expect(Ok, stat); + stat = GdipSetPenCustomEndCap(pen, custom_line_cap); + expect(Ok, stat); + stat = GdipDeleteCustomLineCap(custom_line_cap); + expect(Ok, stat); + stat = GdipDeletePath(line_cap_path); + expect(Ok, stat); + + stat = GdipDrawPath(graphics, pen, draw_path); + expect(Ok, stat); + + stat = GdipDeletePen(pen); + expect(Ok, stat); + stat = GdipDeletePath(draw_path); + expect(Ok, stat); + stat = GdipDeleteGraphics(graphics); + expect(Ok, stat); + + GdipCloneImage((GpImage *)metafile, (GpImage **)&clone_metafile); + sync_metafile(&metafile, "pen.emf"); + + stat = GdipGetHemfFromMetafile(metafile, &hemf); + expect(Ok, stat); + + check_emfplus(hemf, pen_dc_records, "pen record"); + + ret = DeleteEnhMetaFile(hemf); + ok(ret != 0, "Failed to delete enhmetafile.\n"); + stat = GdipDisposeImage((GpImage *)metafile); + expect(Ok, stat); + + /* Play back */ + /* Create graphics from a window DC for this test because bitmap DC uses + * SOFTWARE_GdipDrawPath(), which doesn't support drawing line caps */ + hwnd = CreateWindowA("static", NULL, WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, 0); + hdc = GetDC(0); + stat = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, stat); + + play_metafile(clone_metafile, graphics, pen_bitmap_records, "pen playback", dst_points, &frame, UnitPixel); + + color = GetPixel(hdc, 10, 10); + todo_wine + expect(RGB(0xff, 0, 0), color); + + color = GetPixel(hdc, 40, 90); + todo_wine + flaky /* Win10 + */ + expect(RGB(0xff, 0, 0), color); + + stat = GdipDisposeImage((GpImage *)clone_metafile); + expect(Ok, stat); + stat = GdipDeleteGraphics(graphics); + expect(Ok, stat); + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); +} + START_TEST(metafile) { struct GdiplusStartupInput gdiplusStartupInput; @@ -3934,6 +4059,7 @@ START_TEST(metafile) test_offsetclip(); test_resetclip(); test_setclippath(); + test_pen();
GdiplusShutdown(gdiplusToken); }
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/gdiplus/metafile.c | 230 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 215 insertions(+), 15 deletions(-)
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 90ef39e34d6..da1b3241105 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -46,6 +46,12 @@ HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
typedef ARGB EmfPlusARGB;
+typedef struct EmfPlusPointF +{ + float X; + float Y; +} EmfPlusPointF; + typedef struct EmfPlusRecordHeader { WORD Type; @@ -177,6 +183,12 @@ enum PenDataFlags PenDataCustomEndCap = 0x1000 };
+enum CustomLineCapData +{ + CustomLineCapDataFillPath = 0x1, + CustomLineCapDataLinePath = 0x2, +}; + typedef struct EmfPlusTransformMatrix { REAL TransformMatrix[6]; @@ -287,14 +299,20 @@ typedef struct EmfPlusBrush } BrushData; } EmfPlusBrush;
-typedef struct EmfPlusPen -{ - DWORD Version; - DWORD Type; - /* EmfPlusPenData */ - /* EmfPlusBrush */ - BYTE data[1]; -} EmfPlusPen; +typedef struct EmfPlusCustomLineCapArrowData +{ + REAL Width; + REAL Height; + REAL MiddleInset; + BOOL FillState; + DWORD LineStartCap; + DWORD LineEndCap; + DWORD LineJoin; + REAL LineMiterLimit; + REAL WidthScale; + EmfPlusPointF FillHotSpot; + EmfPlusPointF LineHotSpot; +} EmfPlusCustomLineCapArrowData;
typedef struct EmfPlusPath { @@ -307,6 +325,55 @@ typedef struct EmfPlusPath BYTE data[1]; } EmfPlusPath;
+typedef struct EmfPlusCustomLineCapDataFillPath +{ + INT FillPathLength; + /* EmfPlusPath */ + BYTE FillPath[1]; +} EmfPlusCustomLineCapDataFillPath; + +typedef struct EmfPlusCustomLineCapDataLinePath +{ + INT LinePathLength; + /* EmfPlusPath */ + BYTE LinePath[1]; +} EmfPlusCustomLineCapDataLinePath; + +typedef struct EmfPlusCustomLineCapData +{ + DWORD CustomLineCapDataFlags; + DWORD BaseCap; + REAL BaseInset; + DWORD StrokeStartCap; + DWORD StrokeEndCap; + DWORD StrokeJoin; + REAL StrokeMiterLimit; + REAL WidthScale; + EmfPlusPointF FillHotSpot; + EmfPlusPointF LineHotSpot; + /* EmfPlusCustomLineCapDataFillPath */ + /* EmfPlusCustomLineCapDataLinePath */ + BYTE OptionalData[1]; +} EmfPlusCustomLineCapData; + +typedef struct EmfPlusCustomLineCap +{ + DWORD Version; + DWORD Type; + /* EmfPlusCustomLineCapArrowData */ + /* EmfPlusCustomLineCapData */ + BYTE CustomLineCapData[1]; +} EmfPlusCustomLineCap; + +typedef struct EmfPlusPen +{ + DWORD Version; + DWORD Type; + /* EmfPlusPenData */ + /* EmfPlusBrush */ + BYTE data[1]; +} EmfPlusPen; + typedef struct EmfPlusRegionNodePath { DWORD RegionNodePathLength; @@ -416,12 +483,6 @@ typedef struct EmfPlusPoint short Y; } EmfPlusPoint;
-typedef struct EmfPlusPointF -{ - float X; - float Y; -} EmfPlusPointF; - typedef struct EmfPlusDrawImage { EmfPlusRecordHeader Header; @@ -1055,6 +1116,134 @@ static void METAFILE_FillBrushData(GDIPCONST GpBrush *brush, EmfPlusBrush *data) } }
+static void METAFILE_PrepareCustomLineCapData(GDIPCONST GpCustomLineCap *cap, DWORD *ret_cap_size, + DWORD *ret_cap_data_size, DWORD *ret_path_size) +{ + DWORD cap_size, path_size = 0; + + /* EmfPlusCustomStartCapData */ + cap_size = FIELD_OFFSET(EmfPlusCustomStartCapData, data); + /* -> EmfPlusCustomLineCap */ + cap_size += FIELD_OFFSET(EmfPlusCustomLineCap, CustomLineCapData); + /* -> EmfPlusCustomLineCapArrowData */ + if (cap->type == CustomLineCapTypeAdjustableArrow) + cap_size += sizeof(EmfPlusCustomLineCapArrowData); + /* -> EmfPlusCustomLineCapData */ + else + { + /* -> EmfPlusCustomLineCapOptionalData */ + cap_size += FIELD_OFFSET(EmfPlusCustomLineCapData, OptionalData); + if (cap->fill) + /* -> EmfPlusCustomLineCapDataFillPath */ + cap_size += FIELD_OFFSET(EmfPlusCustomLineCapDataFillPath, FillPath); + else + /* -> EmfPlusCustomLineCapDataLinePath */ + cap_size += FIELD_OFFSET(EmfPlusCustomLineCapDataLinePath, LinePath); + + /* -> EmfPlusPath in EmfPlusCustomLineCapDataFillPath and EmfPlusCustomLineCapDataLinePath */ + path_size = FIELD_OFFSET(EmfPlusPath, data); + path_size += sizeof(PointF) * cap->pathdata.Count; + path_size += sizeof(BYTE) * cap->pathdata.Count; + path_size = (path_size + 3) & ~3; + + cap_size += path_size; + } + + *ret_cap_size = cap_size; + *ret_cap_data_size = cap_size - FIELD_OFFSET(EmfPlusCustomStartCapData, data); + *ret_path_size = path_size; +} + +static void METAFILE_FillCustomLineCapData(GDIPCONST GpCustomLineCap *cap, BYTE *ptr, + REAL line_miter_limit, DWORD data_size, DWORD path_size) +{ + EmfPlusCustomStartCapData *cap_data; + EmfPlusCustomLineCap *line_cap; + DWORD i, j; + + cap_data = (EmfPlusCustomStartCapData *)ptr; + cap_data->CustomStartCapSize = data_size; + i = FIELD_OFFSET(EmfPlusCustomStartCapData, data); + + line_cap = (EmfPlusCustomLineCap *)(ptr + i); + line_cap->Version = VERSION_MAGIC2; + line_cap->Type = cap->type; + i += FIELD_OFFSET(EmfPlusCustomLineCap, CustomLineCapData); + + if (cap->type == CustomLineCapTypeAdjustableArrow) + { + EmfPlusCustomLineCapArrowData *arrow_data; + GpAdjustableArrowCap *arrow_cap; + + arrow_data = (EmfPlusCustomLineCapArrowData *)(ptr + i); + arrow_cap = (GpAdjustableArrowCap *)cap; + arrow_data->Width = arrow_cap->width; + arrow_data->Height = arrow_cap->height; + arrow_data->MiddleInset = arrow_cap->middle_inset; + arrow_data->FillState = arrow_cap->cap.fill; + arrow_data->LineStartCap = arrow_cap->cap.strokeStartCap; + arrow_data->LineEndCap = arrow_cap->cap.strokeEndCap; + arrow_data->LineJoin = arrow_cap->cap.join; + arrow_data->LineMiterLimit = line_miter_limit; + arrow_data->WidthScale = arrow_cap->cap.scale; + arrow_data->FillHotSpot.X = 0; + arrow_data->FillHotSpot.Y = 0; + arrow_data->LineHotSpot.X = 0; + arrow_data->LineHotSpot.Y = 0; + } + else + { + EmfPlusCustomLineCapData *line_cap_data = (EmfPlusCustomLineCapData *)(ptr + i); + EmfPlusPath *path; + + if (cap->fill) + line_cap_data->CustomLineCapDataFlags = CustomLineCapDataFillPath; + else + line_cap_data->CustomLineCapDataFlags = CustomLineCapDataLinePath; + line_cap_data->BaseCap = cap->basecap; + line_cap_data->BaseInset = cap->inset; + line_cap_data->StrokeStartCap = cap->strokeStartCap; + line_cap_data->StrokeEndCap = cap->strokeEndCap; + line_cap_data->StrokeJoin = cap->join; + line_cap_data->StrokeMiterLimit = line_miter_limit; + line_cap_data->WidthScale = cap->scale; + line_cap_data->FillHotSpot.X = 0; + line_cap_data->FillHotSpot.Y = 0; + line_cap_data->LineHotSpot.X = 0; + line_cap_data->LineHotSpot.Y = 0; + i += FIELD_OFFSET(EmfPlusCustomLineCapData, OptionalData); + + if (cap->fill) + { + EmfPlusCustomLineCapDataFillPath *fill_path = (EmfPlusCustomLineCapDataFillPath *)(ptr + i); + fill_path->FillPathLength = path_size; + i += FIELD_OFFSET(EmfPlusCustomLineCapDataFillPath, FillPath); + } + else + { + EmfPlusCustomLineCapDataLinePath *line_path = (EmfPlusCustomLineCapDataLinePath *)(ptr + i); + line_path->LinePathLength = path_size; + i += FIELD_OFFSET(EmfPlusCustomLineCapDataLinePath, LinePath); + } + + path = (EmfPlusPath *)(ptr + i); + path->Version = VERSION_MAGIC2; + path->PathPointCount = cap->pathdata.Count; + path->PathPointFlags = 0; + i += FIELD_OFFSET(EmfPlusPath, data); + for (j = 0; j < cap->pathdata.Count; ++j) + { + *(PointF *)(ptr + i) = cap->pathdata.Points[j]; + i += sizeof(PointF); + } + for (j = 0; j < cap->pathdata.Count; ++j) + { + *(BYTE *)(ptr + i) = cap->pathdata.Types[j]; + i += sizeof(BYTE); + } + } +} + static GpStatus METAFILE_AddBrushObject(GpMetafile *metafile, GDIPCONST GpBrush *brush, DWORD *id) { EmfPlusObject *object_record; @@ -4562,6 +4751,7 @@ static GpStatus METAFILE_AddPathObject(GpMetafile *metafile, GpPath *path, DWORD
static GpStatus METAFILE_AddPenObject(GpMetafile *metafile, GpPen *pen, DWORD *id) { + DWORD custom_start_cap_size = 0, custom_start_cap_data_size = 0, custom_start_cap_path_size = 0; DWORD i, data_flags, pen_data_size, brush_size; EmfPlusObject *object_record; EmfPlusPenData *pen_data; @@ -4626,7 +4816,10 @@ static GpStatus METAFILE_AddPenObject(GpMetafile *metafile, GpPen *pen, DWORD *i /* TODO: Add support for PenDataCompoundLine */ if (pen->customstart) { - FIXME("ignoring custom start cup\n"); + data_flags |= PenDataCustomStartCap; + METAFILE_PrepareCustomLineCapData(pen->customstart, &custom_start_cap_size, + &custom_start_cap_data_size, &custom_start_cap_path_size); + pen_data_size += custom_start_cap_size; } if (pen->customend) { @@ -4719,6 +4912,13 @@ static GpStatus METAFILE_AddPenObject(GpMetafile *metafile, GpPen *pen, DWORD *i *(REAL*)(pen_data->OptionalData + i) = pen->align; i += sizeof(DWORD); } + if (data_flags & PenDataCustomStartCap) + { + METAFILE_FillCustomLineCapData(pen->customstart, pen_data->OptionalData + i, + pen->miterlimit, custom_start_cap_data_size, + custom_start_cap_path_size); + i += custom_start_cap_size; + }
METAFILE_FillBrushData(pen->brush, (EmfPlusBrush*)(object_record->ObjectData.pen.data + pen_data_size));
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/gdiplus/metafile.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index da1b3241105..e51b44e0f0a 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -4752,6 +4752,7 @@ static GpStatus METAFILE_AddPathObject(GpMetafile *metafile, GpPath *path, DWORD static GpStatus METAFILE_AddPenObject(GpMetafile *metafile, GpPen *pen, DWORD *id) { DWORD custom_start_cap_size = 0, custom_start_cap_data_size = 0, custom_start_cap_path_size = 0; + DWORD custom_end_cap_size = 0, custom_end_cap_data_size = 0, custom_end_cap_path_size = 0; DWORD i, data_flags, pen_data_size, brush_size; EmfPlusObject *object_record; EmfPlusPenData *pen_data; @@ -4823,7 +4824,10 @@ static GpStatus METAFILE_AddPenObject(GpMetafile *metafile, GpPen *pen, DWORD *i } if (pen->customend) { - FIXME("ignoring custom end cup\n"); + data_flags |= PenDataCustomEndCap; + METAFILE_PrepareCustomLineCapData(pen->customend, &custom_end_cap_size, + &custom_end_cap_data_size, &custom_end_cap_path_size); + pen_data_size += custom_end_cap_size; }
stat = METAFILE_PrepareBrushData(pen->brush, &brush_size); @@ -4919,6 +4923,13 @@ static GpStatus METAFILE_AddPenObject(GpMetafile *metafile, GpPen *pen, DWORD *i custom_start_cap_path_size); i += custom_start_cap_size; } + if (data_flags & PenDataCustomEndCap) + { + METAFILE_FillCustomLineCapData(pen->customend, pen_data->OptionalData + i, + pen->miterlimit, custom_end_cap_data_size, + custom_end_cap_path_size); + i += custom_end_cap_size; + }
METAFILE_FillBrushData(pen->brush, (EmfPlusBrush*)(object_record->ObjectData.pen.data + pen_data_size));
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/gdiplus/metafile.c | 113 +++++++++++++++++++++++++++++++++- dlls/gdiplus/tests/metafile.c | 1 - 2 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index e51b44e0f0a..0f91aba39c2 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -2347,6 +2347,111 @@ 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) + custom_cap_data->CustomStartCapSize) + return InvalidParameter; + + offset = FIELD_OFFSET(EmfPlusCustomStartCapData, data); + line_cap = (EmfPlusCustomLineCap *)(record_data + offset); + + offset += FIELD_OFFSET(EmfPlusCustomLineCap, CustomLineCapData); + if (line_cap->Type == CustomLineCapTypeAdjustableArrow) + { + EmfPlusCustomLineCapArrowData *arrow_data; + GpAdjustableArrowCap *arrow_cap; + + arrow_data = (EmfPlusCustomLineCapArrowData *)(record_data + offset); + + 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 + { + EmfPlusCustomLineCapData *line_cap_data; + GpCustomLineCap *line_cap; + EmfPlusPath *path; + + line_cap_data = (EmfPlusCustomLineCapData *)(record_data + offset); + offset += FIELD_OFFSET(EmfPlusCustomLineCapData, OptionalData); + if (line_cap_data->CustomLineCapDataFlags == CustomLineCapDataFillPath) + { + EmfPlusCustomLineCapDataFillPath *fill_path = (EmfPlusCustomLineCapDataFillPath *)(record_data + offset); + offset += FIELD_OFFSET(EmfPlusCustomLineCapDataFillPath, FillPath); + if (data_size < offset + fill_path->FillPathLength) + return InvalidParameter; + + path = (EmfPlusPath *)(record_data + offset); + } + else + { + EmfPlusCustomLineCapDataLinePath *line_path = (EmfPlusCustomLineCapDataLinePath *)(record_data + offset); + offset += FIELD_OFFSET(EmfPlusCustomLineCapDataLinePath, LinePath); + if (data_size < offset + line_path->LinePathLength) + return InvalidParameter; + + path = (EmfPlusPath *)(record_data + offset); + } + + line_cap = heap_alloc_zero(sizeof(GpCustomLineCap)); + if (!line_cap) + return OutOfMemory; + + line_cap->pathdata.Points = heap_alloc_zero(path->PathPointCount * sizeof(PointF)); + if (!line_cap->pathdata.Points) + { + heap_free(line_cap); + return OutOfMemory; + } + line_cap->pathdata.Types = heap_alloc_zero(path->PathPointCount * sizeof(BYTE)); + if (!line_cap->pathdata.Types) + { + heap_free(line_cap->pathdata.Points); + heap_free(line_cap); + return OutOfMemory; + } + + memcpy(line_cap->pathdata.Points, (BYTE *)path + FIELD_OFFSET(EmfPlusPath, data), path->PathPointCount * sizeof(PointF)); + memcpy(line_cap->pathdata.Types, (BYTE *)path + FIELD_OFFSET(EmfPlusPath, data) + path->PathPointCount * sizeof(PointF), + path->PathPointCount * sizeof(BYTE)); + line_cap->pathdata.Count = path->PathPointCount; + line_cap->type = CustomLineCapTypeDefault; + line_cap->fill = line_cap_data->CustomLineCapDataFlags == CustomLineCapDataFillPath; + line_cap->basecap = line_cap_data->BaseCap; + line_cap->inset = line_cap_data->BaseInset; + line_cap->strokeStartCap = line_cap_data->StrokeStartCap; + line_cap->strokeEndCap = line_cap_data->StrokeEndCap; + line_cap->join = line_cap_data->StrokeJoin; + line_cap->scale = line_cap_data->WidthScale; + *cap = line_cap; + return Ok; + } +} + static GpStatus metafile_get_pen_brush_data_offset(EmfPlusPen *data, UINT data_size, DWORD *ret) { EmfPlusPenData *pendata = (EmfPlusPenData *)data->data; @@ -2453,6 +2558,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; @@ -2549,7 +2655,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 48da5c648ef..909767edbee 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3983,7 +3983,6 @@ static void test_pen(void) play_metafile(clone_metafile, graphics, pen_bitmap_records, "pen playback", dst_points, &frame, UnitPixel);
color = GetPixel(hdc, 10, 10); - todo_wine expect(RGB(0xff, 0, 0), color);
color = GetPixel(hdc, 40, 90);
From: Zhiyi Zhang zzhang@codeweavers.com
Fix Cafe Stella (SteamID: 1829980) Flowchart crashes once there are 2 things on it. --- dlls/gdiplus/metafile.c | 7 ++++++- dlls/gdiplus/tests/metafile.c | 1 - 2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 0f91aba39c2..6e726e7f008 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -2667,7 +2667,12 @@ static GpStatus METAFILE_PlaybackObject(GpMetafile *metafile, UINT flags, UINT d if (pendata->PenDataFlags & PenDataCustomEndCap) { EmfPlusCustomEndCapData *endcap = (EmfPlusCustomEndCapData *)((BYTE *)pendata + offset); - FIXME("PenDataCustomEndCap is not supported.\n"); + if ((status = metafile_deserialize_custom_line_cap((BYTE *)endcap, data_size, &custom_line_cap)) != Ok) + goto penfailed; + status = GdipSetPenCustomEndCap(pen, custom_line_cap); + GdipDeleteCustomLineCap(custom_line_cap); + if (status != Ok) + goto penfailed; offset += FIELD_OFFSET(EmfPlusCustomEndCapData, data) + endcap->CustomEndCapSize; }
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index 909767edbee..ac10746f639 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -3986,7 +3986,6 @@ static void test_pen(void) expect(RGB(0xff, 0, 0), color);
color = GetPixel(hdc, 40, 90); - todo_wine flaky /* Win10 + */ expect(RGB(0xff, 0, 0), color);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=132895
Your paranoid android.
=== w11pro64_amd (64 bit report) ===
gdiplus: metafile.c:3986: Test failed: Expected 00000255, got 00000000