Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45273
-- v2: gdiplus: add support for LineCapArrowAnchor. gdiplus: fix position of Custom Cap when Scale is different that 1. gdiplus: add support for Custom Line Indent.
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 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 10ffa85d6e3..93d5c8991a7 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 + 1.75 * par_dx + perp_dx, + endpoint->Y + 1.75 * par_dy + perp_dy, PathPointTypeStart); + *last_point = add_path_list_node(*last_point, endpoint->X, + endpoint->Y, PathPointTypeLine); + *last_point = add_path_list_node(*last_point, endpoint->X + 1.75 * par_dx - perp_dx, + endpoint->Y + 1.75 * 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);
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=126798
Your paranoid android.
=== debian11 (32 bit report) ===
gdiplus: graphicspath.c:1732: Test succeeded inside todo block: Path size 10 does not match expected size 10 graphicspath.c:1732: Test failed: Expected #4: PathPointTypeStart (5.0,10.0) but got PathPointTypeStart (22.5,20.0) graphicspath.c:1732: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (5.0,10.0) graphicspath.c:1732: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.5,0.0) graphicspath.c:1732: Test failed: Expected #7: PathPointTypeStart (50.0,10.0) but got PathPointTypeStart (32.5,0.0) graphicspath.c:1732: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (50.0,10.0) graphicspath.c:1732: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.5,20.0)
=== debian11 (32 bit zh:CN report) ===
gdiplus: graphicspath.c:1732: Test succeeded inside todo block: Path size 10 does not match expected size 10 graphicspath.c:1732: Test failed: Expected #4: PathPointTypeStart (5.0,10.0) but got PathPointTypeStart (22.5,20.0) graphicspath.c:1732: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (5.0,10.0) graphicspath.c:1732: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.5,0.0) graphicspath.c:1732: Test failed: Expected #7: PathPointTypeStart (50.0,10.0) but got PathPointTypeStart (32.5,0.0) graphicspath.c:1732: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (50.0,10.0) graphicspath.c:1732: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.5,20.0)
=== debian11b (64 bit WoW report) ===
gdiplus: graphicspath.c:1732: Test succeeded inside todo block: Path size 10 does not match expected size 10 graphicspath.c:1732: Test failed: Expected #4: PathPointTypeStart (5.0,10.0) but got PathPointTypeStart (22.5,20.0) graphicspath.c:1732: Test failed: Expected #5: PathPointTypeLine (22.3,0.0) but got PathPointTypeLine (5.0,10.0) graphicspath.c:1732: Test failed: Expected #6: PathPointTypeLine | PathPointTypeCloseSubpath (22.3,20.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (22.5,0.0) graphicspath.c:1732: Test failed: Expected #7: PathPointTypeStart (50.0,10.0) but got PathPointTypeStart (32.5,0.0) graphicspath.c:1732: Test failed: Expected #8: PathPointTypeLine (32.7,20.0) but got PathPointTypeLine (50.0,10.0) graphicspath.c:1732: Test failed: Expected #9: PathPointTypeLine | PathPointTypeCloseSubpath (32.7,0.0) but got PathPointTypeLine | PathPointTypeCloseSubpath (32.5,20.0)
On Fri Nov 25 22:05:34 2022 +0000, Bartosz Kosiorek wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/1539/diffs?diff_id=21075&start_sha=1d304b27ed4efae49d2b087790e5a87d17ebe23f#9d342cb9ef84c6aa095e339b5428909837d1092b_2347_2371)
Fixed. I have also added support for LineCapArrowAnchor in next commit.
LineCapArrowAnchor was tested with application: [gdiplusdisplayLineCapArrowAnchor.exe](/uploads/ad1cfc9374f8b65b0d751027390bc035/gdiplusdisplayLineCapArrowAnchor.exe)
Bartosz Kosiorek (@gang65) commented about dlls/gdiplus/graphicspath.c:
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 + 1.75 * par_dx + perp_dx,
Length of the arrow value (1.75) was taken experimentally (it is not documented), by coparison generated arrows with native and buildin gdiplus dll.