From: Bartosz Kosiorek gang65@poczta.onet.pl
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45273 --- dlls/gdiplus/customlinecap.c | 2 +- dlls/gdiplus/gdiplus_private.h | 4 ++-- dlls/gdiplus/graphicspath.c | 35 +++++++++++++++++++++++++++++-- dlls/gdiplus/tests/graphicspath.c | 13 ++++++++++++ 4 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/dlls/gdiplus/customlinecap.c b/dlls/gdiplus/customlinecap.c index c05aecae29a..3943150d875 100644 --- a/dlls/gdiplus/customlinecap.c +++ b/dlls/gdiplus/customlinecap.c @@ -305,7 +305,7 @@ static void arrowcap_update_path(GpAdjustableArrowCap *cap) points[2].X = cap->width / 2.0; points[2].Y = -cap->height; points[3].X = 0.0; - points[3].Y = -cap->height - cap->middle_inset; + points[3].Y = -cap->height + cap->middle_inset; } else { diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 77b35659946..51b83b3242a 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -352,8 +352,8 @@ struct GpCustomLineCap{ GpPathData pathdata; BOOL fill; /* TRUE for fill, FALSE for stroke */ GpLineCap basecap; /* cap used together with customLineCap */ - REAL inset; /* how much to adjust the end of the line */ - GpLineJoin join; + REAL inset; /* distance between line and cap */ + GpLineJoin join; /* joins used for drawing custom cap*/ REAL scale; };
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 5ddd96778db..1758306ef58 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -2091,6 +2091,37 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, endpoint->Y + perp_dy, PathPointTypeLine); break; } + case LineCapCustom: + { + REAL segment_dy = nextpoint->Y - endpoint->Y; + REAL segment_dx = nextpoint->X - endpoint->X; + REAL segment_length = sqrtf(segment_dy * segment_dy + segment_dx * segment_dx); + REAL par_dx, par_dy; + REAL perp_dx, perp_dy; + REAL sina, cosa; + + if(!custom) + break; + + TRACE("GpCustomLineCap fill: %d basecap: %d inset: %f join: %d scale: %f pen_width:%f\n", custom->fill, custom->basecap, custom->inset, custom->join, custom->scale, pen_width); + // Coordination where cap needs to be drawn + par_dx = -pen_width * segment_dx / segment_length; + par_dy = -pen_width * segment_dy / segment_length; + + sina = -pen_width * custom->scale * segment_dx / segment_length; + cosa = pen_width * custom->scale * segment_dy / segment_length; + + for (INT i = 0; i < custom->pathdata.Count; i++) + { + // rotation of CustomCap according to line + perp_dx = custom->pathdata.Points[i].X * cosa + (custom->pathdata.Points[i].Y - custom->inset) * sina; + perp_dy = custom->pathdata.Points[i].X * sina - (custom->pathdata.Points[i].Y - custom->inset) * cosa; + *last_point = add_path_list_node(*last_point, endpoint->X + par_dx + perp_dx, + endpoint->Y + par_dy + perp_dy, custom->pathdata.Types[i]); + } + // FIXME: The line should be shorter, and it should ends up when Arrow/Cap is started draw + break; + } }
(*last_point)->type |= PathPointTypeCloseSubpath; @@ -2341,10 +2372,10 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
last_point = points;
- if (pen->endcap > LineCapDiamondAnchor) + if (pen->endcap > LineCapDiamondAnchor && pen->endcap != LineCapCustom) FIXME("unimplemented end cap %x\n", pen->endcap);
- if (pen->startcap > LineCapDiamondAnchor) + if (pen->startcap > LineCapDiamondAnchor && pen->startcap != LineCapCustom) FIXME("unimplemented start cap %x\n", pen->startcap);
if (pen->dashcap != DashCapFlat) diff --git a/dlls/gdiplus/tests/graphicspath.c b/dlls/gdiplus/tests/graphicspath.c index 07e6dd166ad..213fecef2ca 100644 --- a/dlls/gdiplus/tests/graphicspath.c +++ b/dlls/gdiplus/tests/graphicspath.c @@ -1682,9 +1682,12 @@ static void test_widen_cap(void) { LineCapSquareAnchor, 10.0, widenline_capsquareanchor_dashed_path, ARRAY_SIZE(widenline_capsquareanchor_dashed_path), TRUE }, }; + + GpAdjustableArrowCap *arrowcap; GpStatus status; GpPath *path; GpPen *pen; + int i;
status = GdipCreatePath(FillModeAlternate, &path); @@ -1749,6 +1752,16 @@ static void test_widen_cap(void) expect(Ok, status); ok_path_fudge(path, widenline_capsquareanchor_multifigure_path, ARRAY_SIZE(widenline_capsquareanchor_multifigure_path), FALSE, 0.000005); + + status = GdipCreateAdjustableArrowCap(4.0, 4.0, TRUE, &arrowcap); + ok(status == Ok, "Failed to create adjustable cap, %d\n", status); + status = GdipSetAdjustableArrowCapMiddleInset(arrowcap, 1.0); + ok(status == Ok, "Failed to set middle inset inadjustable cap, %d\n", status); + status = GdipSetPenCustomEndCap(pen, arrowcap); + ok(status == Ok, "Failed to create custom end cap, %d\n", status); + status = GdipWidenPath(path, pen, NULL, FlatnessDefault); + expect(Ok, status); + GdipDeletePen(pen);
GdipDeletePath(path);