Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45273
-- v3: 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 | 30 ++++++++++++++++++++++++------ dlls/gdiplus/tests/graphicspath.c | 20 +++++++++++++++++++- 2 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 10ffa85d6e3..9dd1e7783da 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -1890,6 +1890,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 +1910,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 +2111,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 + 1.734 * par_dx - perp_dx, + endpoint->Y + 1.734 * par_dy - perp_dy, PathPointTypeLine); + *last_point = add_path_list_node(*last_point, endpoint->X + 1.734 * par_dx + perp_dx, + endpoint->Y + 1.734 * par_dy + perp_dy, PathPointTypeLine); + break; + } case LineCapCustom: { REAL segment_dy = nextpoint->Y - endpoint->Y; @@ -2416,12 +2440,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..2265db9a6d7 100644 --- a/dlls/gdiplus/tests/graphicspath.c +++ b/dlls/gdiplus/tests/graphicspath.c @@ -1576,6 +1576,24 @@ static path_test_t widenline_capdiamondanchor_path[] = { {50.0, 0.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/ };
+/* + + this helper structure and function modeled after gdi path.c test +typedef struct +{ + REAL X, Y; + BYTE type; + + /* How many extra entries before this one only on wine + * but not on native? + int wine_only_entries_preceding; + + /* 0 - This entry matches on wine. + * 1 - This entry corresponds to a single entry on wine that does not match the native entry. + * 2 - This entry is currently skipped on wine but present on native. * + int todo; +} path_test_t; +*/ static path_test_t widenline_caparrowanchor_path[] = { {15.0, 5.0, PathPointTypeStart, 0, 1}, /*0*/ {40.0, 5.0, PathPointTypeLine, 0, 1}, /*1*/ @@ -1676,7 +1694,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), FALSE }, { LineCapSquareAnchor, 0.0, widenline_capsquareanchor_thin_path, ARRAY_SIZE(widenline_capsquareanchor_thin_path) }, { LineCapSquareAnchor, 10.0, widenline_capsquareanchor_dashed_path,
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=126812
Your paranoid android.
=== debian11 (32 bit report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11 (32 bit ar:MA report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11 (32 bit de report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11 (32 bit fr report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11 (32 bit he:IL report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11 (32 bit hi:IN report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11 (32 bit ja:JP report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11 (32 bit zh:CN report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11b (32 bit WoW report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)
=== debian11b (64 bit WoW report) ===
gdiplus: graphicspath.c:1750: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (22.3,0.0) graphicspath.c:1750: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) graphicspath.c:1750: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (32.7,20.0) graphicspath.c:1750: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0)