Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45273
-- v11: gdiplus: add support for LineCapArrowAnchor.
From: Bartosz Kosiorek gang65@poczta.onet.pl
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45273 --- dlls/gdiplus/graphicspath.c | 53 +++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 23 deletions(-)
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index fdb7dd24906..9194f6d42aa 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -1876,7 +1876,7 @@ static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF * }
static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, - REAL pen_width, GpLineCap cap, int add_first_points, + REAL pen_width, GpLineCap cap, GpCustomLineCap* custom_cap, int add_first_points, int add_last_point, path_list_node_t **last_point) { switch (cap) @@ -1889,6 +1889,7 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, add_bevel_point(endpoint, nextpoint, pen_width, 0, last_point); break; case LineCapSquare: + case LineCapCustom: { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; @@ -1897,20 +1898,25 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, REAL bevel_dx, bevel_dy; REAL extend_dx, extend_dy;
- extend_dx = -distance * segment_dx / segment_length; - extend_dy = -distance * segment_dy / segment_length; + extend_dx = distance * segment_dx / segment_length; + extend_dy = distance * segment_dy / segment_length;
- bevel_dx = -distance * segment_dy / segment_length; - bevel_dy = distance * segment_dx / segment_length; + bevel_dx = -extend_dy; + bevel_dy = extend_dx; + + if (cap == LineCapCustom) + { + extend_dx = -2.0 * custom_cap->inset * extend_dx; + extend_dy = -2.0 * custom_cap->inset * extend_dy; + }
if (add_first_points) - *last_point = add_path_list_node(*last_point, endpoint->X + extend_dx + bevel_dx, - endpoint->Y + extend_dy + bevel_dy, PathPointTypeLine); + *last_point = add_path_list_node(*last_point, endpoint->X - extend_dx + bevel_dx, + endpoint->Y - extend_dy + bevel_dy, PathPointTypeLine);
if (add_last_point) - *last_point = add_path_list_node(*last_point, endpoint->X + extend_dx - bevel_dx, - endpoint->Y + extend_dy - bevel_dy, PathPointTypeLine); - + *last_point = add_path_list_node(*last_point, endpoint->X - extend_dx - bevel_dx, + endpoint->Y - extend_dy - bevel_dy, PathPointTypeLine); break; } case LineCapRound: @@ -1983,8 +1989,8 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, }
static void widen_open_figure(const GpPointF *points, int start, int end, - GpPen *pen, REAL pen_width, GpLineCap start_cap, - GpLineCap end_cap, path_list_node_t **last_point); + GpPen *pen, REAL pen_width, GpLineCap start_cap, GpCustomLineCap* custom_start, + GpLineCap end_cap, GpCustomLineCap* custom_end, path_list_node_t **last_point);
static void widen_closed_figure(const GpPointF *points, int start, int end, GpPen *pen, REAL pen_width, path_list_node_t **last_point); @@ -2145,7 +2151,7 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, if ((custom->pathdata.Types[custom->pathdata.Count - 1] & PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath) widen_closed_figure(tmp_points, 0, custom->pathdata.Count - 1, pen, pen_width, last_point); else - widen_open_figure(tmp_points, 0, custom->pathdata.Count - 1, pen, pen_width, custom->strokeEndCap, custom->strokeStartCap, last_point); + widen_open_figure(tmp_points, 0, custom->pathdata.Count - 1, pen, pen_width, custom->strokeEndCap, NULL, custom->strokeStartCap, NULL, last_point); } else { @@ -2167,8 +2173,8 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, }
static void widen_open_figure(const GpPointF *points, int start, int end, - GpPen *pen, REAL pen_width, GpLineCap start_cap, - GpLineCap end_cap, path_list_node_t **last_point) + GpPen *pen, REAL pen_width, GpLineCap start_cap, GpCustomLineCap* custom_start, + GpLineCap end_cap, GpCustomLineCap* custom_end, path_list_node_t **last_point) { int i; path_list_node_t *prev_point; @@ -2179,21 +2185,21 @@ static void widen_open_figure(const GpPointF *points, int start, int end, prev_point = *last_point;
widen_cap(&points[start], &points[start+1], - pen_width, start_cap, FALSE, TRUE, last_point); + pen_width, start_cap, custom_start, FALSE, TRUE, last_point);
for (i=start+1; i<end; i++) widen_joint(&points[i-1], &points[i], &points[i+1], pen, pen_width, last_point);
widen_cap(&points[end], &points[end-1], - pen_width, end_cap, TRUE, TRUE, last_point); + pen_width, end_cap, custom_end, TRUE, TRUE, last_point);
for (i=end-1; i>start; i--) widen_joint(&points[i+1], &points[i], &points[i-1], pen, pen_width, last_point);
widen_cap(&points[start], &points[start+1], - pen_width, start_cap, TRUE, FALSE, last_point); + pen_width, start_cap, custom_start, TRUE, FALSE, last_point);
prev_point->next->type = PathPointTypeStart; (*last_point)->type |= PathPointTypeCloseSubpath; @@ -2337,8 +2343,8 @@ static void widen_dashed_figure(GpPath *path, int start, int end, int closed, tmp_points[num_tmp_points].Y = path->pathdata.Points[i].Y + segment_dy * segment_pos / segment_length;
widen_open_figure(tmp_points, 0, num_tmp_points, pen, pen_width, - draw_start_cap ? pen->startcap : LineCapFlat, - LineCapFlat, last_point); + draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart, + LineCapFlat, NULL, last_point); draw_start_cap = 0; num_tmp_points = 0; } @@ -2371,8 +2377,8 @@ static void widen_dashed_figure(GpPath *path, int start, int end, int closed, { /* last dash overflows last segment */ widen_open_figure(tmp_points, 0, num_tmp_points-1, pen, pen_width, - draw_start_cap ? pen->startcap : LineCapFlat, - closed ? LineCapFlat : pen->endcap, last_point); + draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart, + closed ? LineCapFlat : pen->endcap, pen->customend, last_point); }
heap_free(dash_pattern_scaled); @@ -2446,7 +2452,8 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix, if (pen->dash != DashStyleSolid) widen_dashed_figure(flat_path, subpath_start, i, 0, pen, pen_width, &last_point); else - widen_open_figure(flat_path->pathdata.Points, subpath_start, i, pen, pen_width, pen->startcap, pen->endcap, &last_point); + widen_open_figure(flat_path->pathdata.Points, subpath_start, i, pen, pen_width, + pen->startcap, pen->customstart, pen->endcap, pen->customend, &last_point); } }
From: Bartosz Kosiorek gang65@poczta.onet.pl
--- dlls/gdiplus/graphicspath.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 9194f6d42aa..10ffa85d6e3 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -2128,13 +2128,13 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, 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 */ - posx = endpoint->X - pen_width * segment_dx / segment_length; - posy = endpoint->Y - pen_width * segment_dy / segment_length; - sina = -pen_width * custom->scale * segment_dx / segment_length; cosa = pen_width * custom->scale * segment_dy / segment_length;
+ /* Coordination where cap needs to be drawn */ + posx = endpoint->X + sina; + posy = endpoint->Y - cosa; + if (!custom->fill) { tmp_points = heap_alloc_zero(custom->pathdata.Count * sizeof(GpPoint));
From: Bartosz Kosiorek gang65@poczta.onet.pl
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42809 --- dlls/gdiplus/graphicspath.c | 32 +++++++++++++++++++++++++------ dlls/gdiplus/tests/graphicspath.c | 7 +++---- 2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 10ffa85d6e3..2e30300e348 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -33,6 +33,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
+#define SQRT3 1.73205080757 + typedef struct path_list_node_t path_list_node_t; struct path_list_node_t { GpPointF pt; @@ -1890,6 +1892,7 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, break; case LineCapSquare: case LineCapCustom: + case LineCapArrowAnchor: { REAL segment_dy = nextpoint->Y-endpoint->Y; REAL segment_dx = nextpoint->X-endpoint->X; @@ -1909,6 +1912,11 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, extend_dx = -2.0 * custom_cap->inset * extend_dx; extend_dy = -2.0 * custom_cap->inset * extend_dy; } + else if (cap == LineCapArrowAnchor) + { + extend_dx = -3.0 * extend_dx; + extend_dy = -3.0 * extend_dy; + }
if (add_first_points) *last_point = add_path_list_node(*last_point, endpoint->X - extend_dx + bevel_dx, @@ -2105,6 +2113,24 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint, endpoint->Y + perp_dy, PathPointTypeLine); break; } + case LineCapArrowAnchor: + { + 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 = pen_width * segment_dx / segment_length; + REAL par_dy = pen_width * segment_dy / segment_length; + REAL perp_dx = -par_dy; + REAL perp_dy = par_dx; + + *last_point = add_path_list_node(*last_point, endpoint->X, + endpoint->Y, PathPointTypeStart); + *last_point = add_path_list_node(*last_point, endpoint->X + SQRT3 * par_dx - perp_dx, + endpoint->Y + SQRT3 * par_dy - perp_dy, PathPointTypeLine); + *last_point = add_path_list_node(*last_point, endpoint->X + SQRT3 * par_dx + perp_dx, + endpoint->Y + SQRT3 * par_dy + perp_dy, PathPointTypeLine); + break; + } case LineCapCustom: { REAL segment_dy = nextpoint->Y - endpoint->Y; @@ -2416,12 +2442,6 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
last_point = points;
- if (pen->endcap > LineCapDiamondAnchor && pen->endcap != LineCapCustom) - FIXME("unimplemented end cap %x\n", pen->endcap); - - if (pen->startcap > LineCapDiamondAnchor && pen->startcap != LineCapCustom) - FIXME("unimplemented start cap %x\n", pen->startcap); - if (pen->dashcap != DashCapFlat) FIXME("unimplemented dash cap %d\n", pen->dashcap);
diff --git a/dlls/gdiplus/tests/graphicspath.c b/dlls/gdiplus/tests/graphicspath.c index ab1e7cb2fda..5082f0671d2 100644 --- a/dlls/gdiplus/tests/graphicspath.c +++ b/dlls/gdiplus/tests/graphicspath.c @@ -114,7 +114,7 @@ static void _ok_path_fudge(GpPath* path, const path_test_t *expected, INT expect stringify_point_type(types[idx], name);
todo_wine_if (expected[eidx].todo || numskip) - ok_(__FILE__,line)(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx, + ok_(__FILE__,line)(match, "Expected #%d: %s (%.6f,%.6f) but got %s (%.6f,%.6f)\n", eidx, ename, expected[eidx].X, expected[eidx].Y, name, points[idx].X, points[idx].Y);
@@ -1655,7 +1655,6 @@ static void test_widen_cap(void) const path_test_t *expected; INT expected_size; BOOL dashed; - BOOL todo_size; } caps[] = { @@ -1676,7 +1675,7 @@ static void test_widen_cap(void) { LineCapDiamondAnchor, 10.0, widenline_capdiamondanchor_path, ARRAY_SIZE(widenline_capdiamondanchor_path) }, { LineCapArrowAnchor, 10.0, widenline_caparrowanchor_path, - ARRAY_SIZE(widenline_caparrowanchor_path), FALSE, TRUE }, + ARRAY_SIZE(widenline_caparrowanchor_path) }, { LineCapSquareAnchor, 0.0, widenline_capsquareanchor_thin_path, ARRAY_SIZE(widenline_capsquareanchor_thin_path) }, { LineCapSquareAnchor, 10.0, widenline_capsquareanchor_dashed_path, @@ -1729,7 +1728,7 @@ static void test_widen_cap(void) } }
- ok_path_fudge(path, caps[i].expected, caps[i].expected_size, caps[i].todo_size, 0.000005); + ok_path_fudge(path, caps[i].expected, caps[i].expected_size, FALSE, 0.000005);
GdipDeletePen(pen); }
@madewokherd What additionally needs to be made to approve this Merge Request?
This merge request was approved by Esme Povirk.
Nothing, I just wasn't at work yesterday so I haven't reviewed it.