This is an attempt to fix https://bugs.winehq.org/show_bug.cgi?id=51139
The first two patches just increase the coverage for stroking and StrokeContains, and proved helpful during development of the actual fix.
The third patch fixes a small issue in the segment comparision helper.
The fourth patch adds the test case triggering bug 51139. As the test causes a hang, the critical part is commented out instead of using the regular wine_todo.
The fifth patch is preparative refactoring, so the bugfix itself is more self-contained.
The sixth patch is the actual fix, and patch 7 reenables the critical test case parts.
The last patch is just some minor, final cleanup.
This patch series obsoletes the previous attempt: "d2d: Suppress last empty segment also for D2D1_FIGURE_END_OPEN", which avoided the infinite loop, but also caused several regressions.
Stefan Brüns (8): d2d1/tests: Test StrokeContains when last segment is bezier and closes the path d2d1/tests: Add test for single quadratic bezier segment d2d1/tests: Avoid out-of-bounds access when comparing segments d2d1/tests: Test coincident last/first vertex for both OPEN and CLOSED d2d1: Refactor outline generation as preparation for new TYPE_END vertex d2d1: Use special vertex TYPE_END when last/first coincede d2d1/tests: Reenable tests formerly causing infinite loop d2d1: remove extraneous checks for last vertex
dlls/d2d1/geometry.c | 215 +++++++++++++++-------------------------- dlls/d2d1/tests/d2d1.c | 171 ++++++++++++++++++++++++++++++-- 2 files changed, 244 insertions(+), 142 deletions(-)
Also check StrokeContains result on the last segment when the last vertex of a bezier curve coincedes with the first vertex of the figure and the figure is explicitly closed.
Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- dlls/d2d1/tests/d2d1.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 70c47795b4e..2d9bcfc892e 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -10253,8 +10253,14 @@ static void test_stroke_contains_point(BOOL d3d11) {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, { 90.5f, 485.3f}, 0.1f, 1.0f, TRUE, TRUE}, {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, { 91.5f, 485.3f}, 0.1f, 1.0f, TRUE, FALSE}, {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, { 89.0f, 485.3f}, 0.1f, 1.0f, TRUE, FALSE}, - - /* 20. A curve where the control points project beyond the endpoints + {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {167.0f, 729.8f}, 0.0f, 1.0f, TRUE, TRUE}, + {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {167.0f, 728.6f}, 0.0f, 1.0f, TRUE, FALSE}, + {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {167.0f, 731.0f}, 0.0f, 1.0f, TRUE, FALSE}, + {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {173.0f, 729.8f}, 0.0f, 1.0f, TRUE, TRUE}, + {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {173.0f, 728.6f}, 0.0f, 1.0f, TRUE, FALSE}, + {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {173.0f, 731.0f}, 0.0f, 1.0f, TRUE, FALSE}, + + /* 26. A curve where the control points project beyond the endpoints * onto the line through the endpoints. */ {{{{0.0f}}}, {306.97f, 791.67f}, 0.0f, 1.0f, FALSE, FALSE}, {{{{0.0f}}}, {307.27f, 791.67f}, 0.0f, 1.0f, FALSE, TRUE}, @@ -10271,7 +10277,7 @@ static void test_stroke_contains_point(BOOL d3d11) {{{{0.0f}}}, {392.73f, 791.67f}, 0.0f, 1.0f, FALSE, TRUE}, {{{{0.0f}}}, {393.03f, 791.67f}, 0.0f, 1.0f, FALSE, FALSE},
- /* 32. A curve where the endpoints coincide. */ + /* 38. A curve where the endpoints coincide. */ {{{{0.0f}}}, {570.23f, 799.77f}, 0.0f, 1.0f, FALSE, FALSE}, {{{{0.0f}}}, {570.53f, 799.77f}, 0.0f, 1.0f, FALSE, TRUE}, {{{{0.0f}}}, {571.73f, 799.77f}, 0.0f, 1.0f, FALSE, TRUE}, @@ -10287,7 +10293,7 @@ static void test_stroke_contains_point(BOOL d3d11) {{{{0.0f}}}, {629.47f, 799.77f}, 0.0f, 1.0f, FALSE, TRUE}, {{{{0.0f}}}, {629.77f, 799.77f}, 0.0f, 1.0f, FALSE, FALSE},
- /* 44. A curve with coinciding endpoints, as well as coinciding + /* 50. A curve with coinciding endpoints, as well as coinciding * control points. */ {{{{0.0f}}}, {825.00f, 800.00f}, 0.0f, 1.0f, FALSE, TRUE}, {{{{0.0f}}}, {861.00f, 824.00f}, 0.0f, 1.0f, FALSE, TRUE}, @@ -10296,7 +10302,7 @@ static void test_stroke_contains_point(BOOL d3d11) {{{{0.0f}}}, {864.00f, 824.00f}, 0.0f, 1.0f, FALSE, FALSE}, {{{{0.0f}}}, {864.00f, 826.00f}, 0.0f, 1.0f, FALSE, FALSE},
- /* 50. Shear transforms. */ + /* 56. Shear transforms. */ {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, { 837.2f, 600.0f}, 0.1f, 5.0f, TRUE, FALSE}, {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, { 837.5f, 600.0f}, 0.1f, 5.0f, TRUE, TRUE}, {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, {1186.3f, 791.7f}, 0.1f, 5.0f, TRUE, TRUE},
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=104977
Your paranoid android.
=== debian11 (32 bit Hebrew:Israel report) ===
d2d1: d2d1.c:6664: Test failed: d2d1.c:6269: Test marked todo: Figure does not match.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Extra test for outline generation code, path with only 2 vertices.
Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- dlls/d2d1/tests/d2d1.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 2d9bcfc892e..adb9c5a7959 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -6879,6 +6879,45 @@ static void test_draw_geometry(BOOL d3d11) "AiWaAiScAiKdAiGeAh+hAhyjAhmuAg3GxgEA"); ok(match, "Figure does not match.\n");
+ hr = ID2D1Factory_CreatePathGeometry(factory, &geometry); + ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr); + hr = ID2D1PathGeometry_Open(geometry, &sink); + ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr); + + set_point(&point, 20.0f, 80.0f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW); + quadratic_to(sink, 20.0f, 160.0f, 60.0f, 160.0f); + ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED); + + set_point(&point, 100.0f, 80.0f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW); + quadratic_to(sink, 100.0f, 160.0f, 140.0f, 160.0f); + ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN); + + hr = ID2D1GeometrySink_Close(sink); + ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr); + ID2D1GeometrySink_Release(sink); + + ID2D1RenderTarget_BeginDraw(rt); + ID2D1RenderTarget_Clear(rt, &color); + ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 10.0f, NULL); + hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL); + ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr); + ID2D1PathGeometry_Release(geometry); + + match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, + "3iUCngEEnAEGmgEImAEKlgEMlAEOkgEQkAESjgEUjAEWigEYiAEahgEchAEeggEggAEifiR9JXsn" + "eSl4KnYUAhZ0FQMWcxQFFnEVBhZwFAgWbxQJFm0VChZsFAwWaxQNFmoUDhZpFA8WaBQQFmcVEBZm" + "FREWZRUSFmUVEhZkFhIWZBYSFmQWEhZkFxEWZBgQFmQZDxZlGwwWZh0JFmciAxZpOWw2bzN0Lnsn" + "2mEA"); + ok(match, "Figure does not match.\n"); + + match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0, + "njIUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjQEUjAEUjAEUjQEUjAEUjAEVjAEUjAEVjAEUjQEUjAEV" + "jAEUjQEUjQEUjQEUjQEUjQEVjAEVjAEVjQEVjAEWjAEWjAEWjAEXiwEYigEZigEbiAEdhgEiggEv" + "di53KX4ihwEZ6GEA"); + ok(match, "Figure does not match.\n"); + ID2D1SolidColorBrush_Release(brush); ID2D1Factory_Release(factory); release_test_context(&ctx);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=104979
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w7u_adm (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w7u_el (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w8 (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w8adm (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w864 (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064v1507 (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064v1809 (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064 (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064_tsign (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w10pro64 (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w864 (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064v1507 (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064v1809 (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064 (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064_2qxl (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w1064_tsign (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w10pro64 (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w10pro64_ar (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w10pro64_he (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w10pro64_ja (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== w10pro64_zh_CN (64 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
=== debian11 (32 bit Hindi:India report) ===
d2d1: d2d1.c:6688: Test failed: d2d1.c:9259: Test marked todo: Test 0: Got unexpected dpi_x 6.00000000e+001, expected 0.00000000e+000.
=== debian11 (32 bit Chinese:China report) ===
d2d1: d2d1.c:6672: Test failed: d2d1.c:10048: Test marked todo: Test 4: Got unexpected output bounds {0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000}, expected {-2.00000000e+000, -3.00000000e+000, 1.00000000e+001, 3.90000000e+001}.
On Freitag, 7. Januar 2022 10:01:55 CET you wrote:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=104979
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
d2d1: d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match. d2d1.c:6913: Test failed: Figure does not match. d2d1.c:6919: Test failed: Figure does not match.
As the output on windows and wine are visually identical (see attached PNGs) and only differ by single pixels on the edge it should be sufficient to update the references and let it pass with some slack (max_diff = 24 resp 17).
Kind regards,
Stefan
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de wrote:
- match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0,
"3iUCngEEnAEGmgEImAEKlgEMlAEOkgEQkAESjgEUjAEWigEYiAEahgEchAEeggEggAEifiR9JXsn"
"eSl4KnYUAhZ0FQMWcxQFFnEVBhZwFAgWbxQJFm0VChZsFAwWaxQNFmoUDhZpFA8WaBQQFmcVEBZm"
"FREWZRUSFmUVEhZkFhIWZBYSFmQWEhZkFxEWZBgQFmQZDxZlGwwWZh0JFmciAxZpOWw2bzN0Lnsn"
"2mEA");
- ok(match, "Figure does not match.\n");
- match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0,
"njIUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjQEUjAEUjAEUjQEUjAEUjAEVjAEUjAEVjAEUjQEUjAEV"
"jAEUjQEUjQEUjQEUjQEUjQEVjAEVjAEVjQEVjAEWjAEWjAEWjAEXiwEYigEZigEbiAEdhgEiggEv"
"di53KX4ihwEZ6GEA");
- ok(match, "Figure does not match.\n");
Like the testbot, I'm getting some failures on Windows (Windows 7, AMD Radeon HD 6310):
d2d1.c:795: diff 19 > max_diff 0. d2d1.c:640: 3iUCngEEnAEGmgEImAEKlgEMlAEOkgEQkAESjgEUjAEWigEYiAEahgEchAEeggEggQEhfyN9JXsn d2d1.c:640: eih4KnYUAhZ1FAMWcxQFFnIUBhZwFQcWbxQJFm4UChZsFQsWaxUMFmoVDRZpFQ4WaBUPFmcVEBZm d2d1.c:640: FREWZhURFmUWERZkFhIWZBYSFmQXERZkFxEWZBgQFmQaDhZlGwwWZh0JFmghAxZpOWw2bzN0Lnwm d2d1.c:659: 2mEA d2d1.c:6913: Test failed: Figure does not match. d2d1.c:795: diff 26 > max_diff 0. d2d1.c:640: njIUjAEUjAEUjAEUjAEUjAEUjQEUjAEUjAEUjAEUjQEUjAEUjAEUjQEUjAEUjQEUjAEVjAEUjQEU d2d1.c:640: jAEVjAEVjAEVjAEVjAEVjAEVjAEVjQEVjAEWiwEWjAEWjAEXiwEXiwEYigEaiQEbiAEdhwEhggEz d2d1.c:659: ci53KX4iiAEY6GEA d2d1.c:6919: Test failed: Figure does not match. d2d1.c:795: diff 19 > max_diff 0. d2d1.c:640: 3iUCngEEnAEGmgEImAEKlgEMlAEOkgEQkAESjgEUjAEWigEYiAEahgEchAEeggEggQEhfyN9JXsn d2d1.c:640: eih4KnYUAhZ1FAMWcxQFFnIUBhZwFQcWbxQJFm4UChZsFQsWaxUMFmoVDRZpFQ4WaBUPFmcVEBZm d2d1.c:640: FREWZhURFmUWERZkFhIWZBYSFmQXERZkFxEWZBgQFmQaDhZlGwwWZh0JFmghAxZpOWw2bzN0Lnwm d2d1.c:659: 2mEA d2d1.c:6913: Test failed: Figure does not match. d2d1.c:795: diff 26 > max_diff 0. d2d1.c:640: njIUjAEUjAEUjAEUjAEUjAEUjQEUjAEUjAEUjAEUjQEUjAEUjAEUjQEUjAEUjQEUjAEVjAEUjQEU d2d1.c:640: jAEVjAEVjAEVjAEVjAEVjAEVjAEVjQEVjAEWiwEWjAEWjAEXiwEXiwEYigEaiQEbiAEdhwEhggEz d2d1.c:659: ci53KX4iiAEY6GEA d2d1.c:6919: Test failed: Figure does not match. 0ad4:d2d1: 10456 tests executed (0 marked as todo, 4 failures), 0 skipped.
Increasing the tolerance from 0 to 32 gets rid of the failures for me.
On Freitag, 7. Januar 2022 19:30:39 CET you wrote:
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de
wrote:
- match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0,
"3iUCngEEnAEGmgEImAEKlgEMlAEOkgEQkAESjgEUjAEWigEYiAEahgEchAEeggEggAEifiR9 JXsn" + "eSl4KnYUAhZ0FQMWcxQFFnEVBhZwFAgWbxQJFm0VChZsFAwWaxQNFmoUDhZpFA8WaBQQFmcV EBZm" + "FREWZRUSFmUVEhZkFhIWZBYSFmQWEhZkFxEWZBgQFmQZDxZlGwwWZh0JFmciAxZpOWw2bzN0 Lnsn" + "2mEA");
- ok(match, "Figure does not match.\n");
- match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0,
"njIUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjQEUjAEUjAEUjQEUjAEUjAEVjAEUjAEVjAEUjQEU jAEV" + "jAEUjQEUjQEUjQEUjQEUjQEVjAEVjAEVjQEVjAEWjAEWjAEWjAEXiwEYigEZigEbiAEdhgEi ggEv" + "di53KX4ihwEZ6GEA");
- ok(match, "Figure does not match.\n");
Like the testbot, I'm getting some failures on Windows (Windows 7, AMD Radeon HD 6310):
d2d1.c:795: diff 19 > max_diff 0. d2d1.c:640:
3iUCngEEnAEGmgEImAEKlgEMlAEOkgEQkAESjgEUjAEWigEYiAEahgEchAEeggEggQEhfyN9JXsn d2d1.c:640: eih4KnYUAhZ1FAMWcxQFFnIUBhZwFQcWbxQJFm4UChZsFQsWaxUMFmoVDRZpFQ4WaBUPFmcVEBZm d2d1.c:640: FREWZhURFmUWERZkFhIWZBYSFmQXERZkFxEWZBgQFmQaDhZlGwwWZh0JFmghAxZpOWw2bzN0Lnwm d2d1.c:659: 2mEA
I have updated the reference to the one returned from the Testbot on Win, and update the slack to 17 resp. 24. The difference between your result on Win 7 and the TB result is 4 (for the first figure), so this should have you covered.
See https://testbot.winehq.org/JobDetails.pl?Key=104999 for the updated reference.
Kind regards,
Stefan
In case real and expected segment count differ, don't compare the segment type/position for extra segments.
Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- dlls/d2d1/tests/d2d1.c | 44 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index adb9c5a7959..9e9ec1e9fd0 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -1248,6 +1248,7 @@ static void geometry_sink_check_(unsigned int line, const struct geometry_sink * const struct expected_geometry_figure *expected_figure; const struct geometry_figure *figure; unsigned int i, j; + unsigned int segment_count; BOOL match;
ok_(__FILE__, line)(sink->fill_mode == fill_mode, @@ -1276,7 +1277,10 @@ static void geometry_sink_check_(unsigned int line, const struct geometry_sink * "Got unexpected figure %u segment count %u, expected %u.\n", i, figure->segment_count, expected_figure->segment_count);
- for (j = 0; j < figure->segment_count; ++j) + segment_count = expected_figure->segment_count < figure->segment_count ? + expected_figure->segment_count : figure->segment_count; + + for (j = 0; j < segment_count; ++j) { expected_segment = &expected_figure->segments[j]; segment = &figure->segments[j]; @@ -1315,6 +1319,44 @@ static void geometry_sink_check_(unsigned int line, const struct geometry_sink * break; } } + + for (j = segment_count; j < expected_figure->segment_count; ++j) + { + segment = &expected_figure->segments[j]; + switch (segment->type) + { + case SEGMENT_LINE: + ok_(__FILE__, line)(FALSE, "Missing figure %u segment %u {%.8e, %.8e}.\n", + i, j, segment->u.line.x, segment->u.line.y); + break; + case SEGMENT_BEZIER: + ok_(__FILE__, line)(FALSE, "Missing figure %u segment %u " + "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}\n", + i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y, + segment->u.bezier.point2.x, segment->u.bezier.point2.y, + segment->u.bezier.point3.x, segment->u.bezier.point3.y); + break; + } + } + + for (j = segment_count; j < figure->segment_count; ++j) + { + segment = &figure->segments[j]; + switch (segment->type) + { + case SEGMENT_LINE: + ok_(__FILE__, line)(FALSE, "Got unexpected figure %u segment %u {%.8e, %.8e}.\n", + i, j, segment->u.line.x, segment->u.line.y); + break; + case SEGMENT_BEZIER: + ok_(__FILE__, line)(FALSE, "Got unexpected figure %u segment %u " + "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}\n", + i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y, + segment->u.bezier.point2.x, segment->u.bezier.point2.y, + segment->u.bezier.point3.x, segment->u.bezier.point3.y); + break; + } + } } }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=104981
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w7u_adm (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w7u_el (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w8 (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w8adm (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:795: Test failed: diff 17 > max_diff 0. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w864 (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064v1507 (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064v1809 (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064 (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064_tsign (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w10pro64 (32 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w864 (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064v1507 (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064v1809 (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064 (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064_2qxl (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w1064_tsign (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w10pro64 (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w10pro64_ar (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w10pro64_he (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w10pro64_ja (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== w10pro64_zh_CN (64 bit report) ===
d2d1: d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6955: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match. d2d1.c:6961: Test failed: Figure does not match.
=== debian11 (32 bit German report) ===
d2d1: d2d1.c:6714: Test failed: d2d1.c:6291: Test marked todo: Figure does not match.
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de wrote:
In case real and expected segment count differ, don't compare the segment type/position for extra segments.
Unless it's e.g. a huge help when debugging failures, I'm not sure we care; if the segment counts don't match the test is going to fail, one way or another.
On Freitag, 7. Januar 2022 18:10:05 CET you wrote:
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de
wrote:
In case real and expected segment count differ, don't compare the segment type/position for extra segments.
Unless it's e.g. a huge help when debugging failures, I'm not sure we care; if the segment counts don't match the test is going to fail, one way or another.
This is an invalid memory access (though read-only). This should never be done, even in tests.
Kind regards, Stefan
On Tue, 11 Jan 2022 at 08:55, Stefan Brüns stefan.bruens@rwth-aachen.de wrote:
On Freitag, 7. Januar 2022 18:10:05 CET you wrote:
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de
wrote:
In case real and expected segment count differ, don't compare the segment type/position for extra segments.
Unless it's e.g. a huge help when debugging failures, I'm not sure we care; if the segment counts don't match the test is going to fail, one way or another.
This is an invalid memory access (though read-only). This should never be done, even in tests.
That's not the position the Wine project has historically taken on this kind of thing, at least when it comes to the tests. The basic idea is that the test isn't supposed to fail, so when it does, we don't particularly care about any follow-up damage. (Provided that's limited to the test process.) I.e., think of ok() much like assert().
On Dienstag, 11. Januar 2022 16:47:14 CET you wrote:
On Tue, 11 Jan 2022 at 08:55, Stefan Brüns stefan.bruens@rwth-aachen.de
wrote:
On Freitag, 7. Januar 2022 18:10:05 CET you wrote:
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de
wrote:
In case real and expected segment count differ, don't compare the segment type/position for extra segments.
Unless it's e.g. a huge help when debugging failures, I'm not sure we care; if the segment counts don't match the test is going to fail, one way or another.
This is an invalid memory access (though read-only). This should never be done, even in tests.
That's not the position the Wine project has historically taken on this kind of thing, at least when it comes to the tests. The basic idea is that the test isn't supposed to fail, so when it does, we don't particularly care about any follow-up damage. (Provided that's limited to the test process.) I.e., think of ok() much like assert().
The follow-up damage is not only to the process, but most importantly to the person trying to debug the issue.
In case the segments do not match (which is the more likely case, as it is just random data for the extraneous segments), it print totally bogus coordinates. This is confusing at best, printing a totally wrong message ("mismatching segments") and random coordinates.
In case the segments do match (possible, as the allocated memory may reuse memory of an previous test, and coordinates of sequential tests are often similar), no coordinates are printed.
For someone very familiar with the code, this might be expected. For anybody else debugging becomes harder. I have wasted half an hour getting what was actually going on, and this change would have saved me the time.
Kind regards,
Stefan
On Tue, 11 Jan 2022 at 17:09, Stefan Brüns stefan.bruens@rwth-aachen.de wrote:
On Dienstag, 11. Januar 2022 16:47:14 CET you wrote:
On Tue, 11 Jan 2022 at 08:55, Stefan Brüns stefan.bruens@rwth-aachen.de
wrote:
On Freitag, 7. Januar 2022 18:10:05 CET you wrote:
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de
wrote:
In case real and expected segment count differ, don't compare the segment type/position for extra segments.
Unless it's e.g. a huge help when debugging failures, I'm not sure we care; if the segment counts don't match the test is going to fail, one way or another.
This is an invalid memory access (though read-only). This should never be done, even in tests.
That's not the position the Wine project has historically taken on this kind of thing, at least when it comes to the tests. The basic idea is that the test isn't supposed to fail, so when it does, we don't particularly care about any follow-up damage. (Provided that's limited to the test process.) I.e., think of ok() much like assert().
The follow-up damage is not only to the process, but most importantly to the person trying to debug the issue.
In case the segments do not match (which is the more likely case, as it is just random data for the extraneous segments), it print totally bogus coordinates. This is confusing at best, printing a totally wrong message ("mismatching segments") and random coordinates.
In case the segments do match (possible, as the allocated memory may reuse memory of an previous test, and coordinates of sequential tests are often similar), no coordinates are printed.
For someone very familiar with the code, this might be expected. For anybody else debugging becomes harder. I have wasted half an hour getting what was actually going on, and this change would have saved me the time.
Right, that kind of thing was what I was referring to with "Unless it's e.g. a huge help when debugging failures," earlier. In that case I think this is fine.
Henri
Provide two orientatations for both cases (END_OPEN/END_CLOSED) each.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51139 Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- dlls/d2d1/tests/d2d1.c | 82 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 9e9ec1e9fd0..27d78a01ff0 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -3083,6 +3083,23 @@ static void test_path_geometry(BOOL d3d11) /* Figure 28. */ {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}}, {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}}, + /* Figure 29. */ + {SEGMENT_LINE, {{{ 40.0f, 100.0f}}}}, + {SEGMENT_BEZIER, {{{4.00000000e+01f, 7.66666666e+01f}, + {3.33333333e+01f, 7.00000000e+01f}, + {2.00000000e+01f, 8.00000000e+01f}}}}, + {SEGMENT_LINE, {{{ 60.0f, 40.0f}}}}, + {SEGMENT_BEZIER, {{{8.33333333e+01f, 4.00000000e+01f}, + {9.00000000e+01f, 3.33333333e+01f}, + {8.00000000e+01f, 2.00000000e+01f}}}}, + {SEGMENT_LINE, {{{140.0f, 160.0f}}}}, + {SEGMENT_BEZIER, {{{1.16666666e+02f, 1.60000000e+02f}, + {1.10000000e+02f, 1.66666666e+02f}, + {1.20000000e+02f, 1.80000000e+02f}}}}, + {SEGMENT_LINE, {{{170.0f, 110.0f}}}}, + {SEGMENT_BEZIER, {{{1.70000000e+02f, 1.26666666e+02f}, + {1.73333333e+02f, 1.30000000e+02f}, + {1.80000000e+02f, 1.20000000e+02f}}}}, }; static const struct expected_geometry_figure expected_figures[] = { @@ -3126,6 +3143,11 @@ static void test_path_geometry(BOOL d3d11) {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 8, &expected_segments[164]}, /* 28 */ {D2D1_FIGURE_BEGIN_HOLLOW, D2D1_FIGURE_END_OPEN, { 40.0f, 20.0f}, 2, &expected_segments[172]}, + /* 29 */ + {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_OPEN, { 20.0f, 80.0f}, 2, &expected_segments[174]}, + {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_OPEN, { 80.0f, 20.0f}, 2, &expected_segments[176]}, + {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 120.0f, 180.0f}, 2, &expected_segments[178]}, + {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 180.0f, 120.0f}, 2, &expected_segments[180]}, };
if (!init_test_context(&ctx, d3d11)) @@ -3871,6 +3893,66 @@ static void test_path_geometry(BOOL d3d11)
ID2D1PathGeometry_Release(geometry);
+ hr = ID2D1Factory_CreatePathGeometry(factory, &geometry); + ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr); + hr = ID2D1PathGeometry_Open(geometry, &sink); + ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr); + +#if 0 + set_point(&point, 20.0f, 80.0f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED); + line_to(sink, 40.0f, 100.0f); + quadratic_to(sink, 40.0f, 65.0f, 20.0f, 80.0f); + ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN); + + set_point(&point, 80.0f, 20.0f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED); + line_to(sink, 60.0f, 40.0f); + quadratic_to(sink, 95.0f, 40.0f, 80.0f, 20.0f); + ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN); +#endif + + set_point(&point, 120.0f, 180.0f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED); + line_to(sink, 140.0f, 160.0f); + quadratic_to(sink, 105.0f, 160.0f, 120.0f, 180.0f); + ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED); + + set_point(&point, 180.0f, 120.0f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED); + line_to(sink, 170.0f, 110.0f); + quadratic_to(sink, 170.0f, 135.0f, 180.0f, 120.0f); + ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED); + + hr = ID2D1GeometrySink_Close(sink); + ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr); + ID2D1GeometrySink_Release(sink); + + set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); + hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); + ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr); +#if 0 + match = compare_rect(&rect, 20.0f, 20.0f, 180.0f, 180.0f, 0); +#else + match = compare_rect(&rect, 115.5f, 110.0f, 180.0f, 180.0f, 0); +#endif + ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", + rect.left, rect.top, rect.right, rect.bottom); + + geometry_sink_init(&simplify_sink); + hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES, + NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface); + ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr); + trace("SIMPLIFY done\n"); +#if 0 + geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[29], 1); +#else + geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 2, &expected_figures[31], 1); +#endif + geometry_sink_cleanup(&simplify_sink); + + ID2D1PathGeometry_Release(geometry); + ID2D1SolidColorBrush_Release(brush); ID2D1Factory_Release(factory); release_test_context(&ctx);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=104982
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w7u_adm (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w7u_el (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w8 (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w8adm (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w864 (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: d2d1.c:9242: Tests skipped: Failed to create REF d3d device, hr 0x80004002.
Report validation errors: d2d1:d2d1 is missing some skip messages
=== w1064v1507 (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w1064v1809 (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w1064 (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w1064_tsign (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w10pro64 (32 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w864 (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w1064v1507 (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w1064v1809 (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w1064 (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w1064_2qxl (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w1064_tsign (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w10pro64 (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w10pro64_ar (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w10pro64_he (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w10pro64_ja (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
=== w10pro64_zh_CN (64 bit report) ===
d2d1: d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3939: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7037: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match. d2d1.c:7043: Test failed: Figure does not match.
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de wrote:
Provide two orientatations for both cases (END_OPEN/END_CLOSED) each.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51139 Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de
dlls/d2d1/tests/d2d1.c | 82 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
Like the testbot, I'm getting some failures on Windows (Windows 7, AMD Radeon HD 6310):
d2d1.c:3897: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3904: SIMPLIFY done d2d1.c:3897: Test failed: Got unexpected rectangle {1.15500008e+002, 1.10000000e+002, 1.80000000e+002, 1.80000000e+002}. d2d1.c:3904: SIMPLIFY done 0ba8:d2d1: 10482 tests executed (0 marked as todo, 2 failures), 0 skipped.
Increasing the tolerance on the compare_rect() call from 0 to 1 gets rid of it for me.
- geometry_sink_init(&simplify_sink);
- hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
- ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
- trace("SIMPLIFY done\n");
That trace() looks like leftover debug code.
This is a preparative patch for the next change, behavior is essentially unchanged, though it may be slightly faster.
Rearrange code for outline segment and join generation so it will work for END_OPEN/END_CLOSED path, with coincident and disparate last/first vertex.
Each vertex is now fetched once, and pivoted on the next iteration. Also move invariants in front of the loop,
Path segments are drawn starting with the first segment, up to vertex_count - 2 (index of start vertex). Only in case of a END_CLOSED figure with non-coincident last/first vertex, also the last line segment is drawn.
Joins are added between all drawn segments, and only for END_CLOSED also the join at the first vertex is added.
Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- dlls/d2d1/geometry.c | 97 ++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 45 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index a7074899fda..41987771ed4 100644 --- a/dlls/d2d1/geometry.c +++ b/dlls/d2d1/geometry.c @@ -2597,43 +2597,69 @@ static BOOL d2d_geometry_outline_add_arc_quadrant(struct d2d_geometry *geometry, static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry, struct d2d_figure *figure, D2D1_FIGURE_END figure_end) { - const D2D1_POINT_2F *prev, *p0, *next; - enum d2d_vertex_type prev_type, type; - size_t bezier_idx, i; + const D2D1_POINT_2F *prev, *p0, *p1, *next, *next_prev; + enum d2d_vertex_type type; + size_t bezier_idx, i, vertex_count; + + vertex_count = figure->vertex_count; + /* An OPEN path needs at least 2 vertices, a CLOSED one + * needs at least 1 vertex */ + if (vertex_count < 2 + && !(figure_end == D2D1_FIGURE_END_CLOSED && vertex_count >= 1)) + return TRUE; + + if (figure_end == D2D1_FIGURE_END_OPEN) + vertex_count--; + + prev = p0 = &figure->vertices[0]; + if (figure_end == D2D1_FIGURE_END_CLOSED) + { + /* In case of a CLOSED path, a join between first and last vertex is required */ + if (d2d_vertex_type_is_bezier(figure->vertex_types[vertex_count - 1])) + prev = &figure->bezier_controls[figure->bezier_control_count - 1]; + else + prev = &figure->vertices[vertex_count - 1]; + }
- for (i = 0, bezier_idx = 0; i < figure->vertex_count; ++i) + for (i = 0, bezier_idx = 0; i < vertex_count; ++i) { type = figure->vertex_types[i]; if (type == D2D_VERTEX_TYPE_NONE) + { + prev = next_prev = &figure->vertices[i]; continue; + }
- p0 = &figure->vertices[i]; - - if (!i) + /* next: tangent along next segment, at p0 + * p1: next vertex */ + if (d2d_vertex_type_is_bezier(type)) { - prev_type = figure->vertex_types[figure->vertex_count - 1]; - if (d2d_vertex_type_is_bezier(prev_type)) - prev = &figure->bezier_controls[figure->bezier_control_count - 1]; - else - prev = &figure->vertices[figure->vertex_count - 1]; + next_prev = next = &figure->bezier_controls[bezier_idx++]; + /* type BEZIER implies i + 1 < figure->vertex_count */ + p1 = &figure->vertices[i + 1]; + + if (!d2d_geometry_outline_add_bezier_segment(geometry, p0, next, p1)) + { + ERR("Failed to add bezier segment.\n"); + return FALSE; + } } else { - prev_type = figure->vertex_types[i - 1]; - if (d2d_vertex_type_is_bezier(prev_type)) - prev = &figure->bezier_controls[bezier_idx - 1]; + if (i + 1 == figure->vertex_count) + next = p1 = &figure->vertices[0]; else - prev = &figure->vertices[i - 1]; - } + next = p1 = &figure->vertices[i + 1]; + next_prev = p0;
- if (d2d_vertex_type_is_bezier(type)) - next = &figure->bezier_controls[bezier_idx++]; - else if (i == figure->vertex_count - 1) - next = &figure->vertices[0]; - else - next = &figure->vertices[i + 1]; + if (!d2d_geometry_outline_add_line_segment(geometry, p0, p1)) + { + ERR("Failed to add line segment.\n"); + return FALSE; + } + }
- if (figure_end == D2D1_FIGURE_END_CLOSED || (i && i < figure->vertex_count - 1)) + if (i || figure_end == D2D1_FIGURE_END_CLOSED) { D2D1_POINT_2F q_next, q_prev;
@@ -2650,27 +2676,8 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry, } }
- if (type == D2D_VERTEX_TYPE_LINE && (figure_end == D2D1_FIGURE_END_CLOSED || i < figure->vertex_count - 1) - && !d2d_geometry_outline_add_line_segment(geometry, p0, next)) - { - ERR("Failed to add line segment.\n"); - return FALSE; - } - else if (d2d_vertex_type_is_bezier(type)) - { - const D2D1_POINT_2F *p2; - - if (i == figure->vertex_count - 1) - p2 = &figure->vertices[0]; - else - p2 = &figure->vertices[i + 1]; - - if (!d2d_geometry_outline_add_bezier_segment(geometry, p0, next, p2)) - { - ERR("Failed to add bezier segment.\n"); - return FALSE; - } - } + p0 = p1; + prev = next_prev; }
return TRUE;
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de wrote:
prev_type = figure->vertex_types[figure->vertex_count - 1];
if (d2d_vertex_type_is_bezier(prev_type))
prev = &figure->bezier_controls[figure->bezier_control_count - 1];
else
prev = &figure->vertices[figure->vertex_count - 1];
next_prev = next = &figure->bezier_controls[bezier_idx++];
/* type BEZIER implies i + 1 < figure->vertex_count */
p1 = &figure->vertices[i + 1];
Is that already true at this point in the series? It would be true after patch 6/8 in this series, but at this point in the series the end point could still have been removed in d2d_geometry_sink_EndFigure(), right?
On Freitag, 7. Januar 2022 18:10:27 CET you wrote:
On Fri, 7 Jan 2022 at 09:00, Stefan Brüns stefan.bruens@rwth-aachen.de
wrote:
prev_type = figure->vertex_types[figure->vertex_count - 1];
if (d2d_vertex_type_is_bezier(prev_type))
prev =
&figure->bezier_controls[figure->bezier_control_count - 1]; - else
prev = &figure->vertices[figure->vertex_count - 1];
next_prev = next = &figure->bezier_controls[bezier_idx++];
/* type BEZIER implies i + 1 < figure->vertex_count */
p1 = &figure->vertices[i + 1];
Is that already true at this point in the series? It would be true after patch 6/8 in this series, but at this point in the series the end point could still have been removed in d2d_geometry_sink_EndFigure(), right?
The code is valid.
Either the last and first vertex is not cooincident, then the last segment is a line.
Or they are coincident, but he figure is OPEN. Then again the last segment is a line.
Or they are coincident, the figure is CLOSED, thus vertex_count is decremented. Then the last segment starts a `i == vertex_count - 1 == real_vertex_count - 2`. As `vertex[i + 1] == vertex[0]` holds, we can ignore the wraparound.
The comment is slightly off in this case - maybe `i + 1 < real_vertex_count`, but I am not sure this is really relevant, as this becomes fully correct with patch 6.
Kind regards,
Stefan
On Fri, 7 Jan 2022 at 19:33, Stefan Brüns stefan.bruens@rwth-aachen.de wrote:
Or they are coincident, the figure is CLOSED, thus vertex_count is decremented. Then the last segment starts a `i == vertex_count - 1 == real_vertex_count - 2`. As `vertex[i + 1] == vertex[0]` holds, we can ignore the wraparound.
The comment is slightly off in this case - maybe `i + 1 < real_vertex_count`, but I am not sure this is really relevant, as this becomes fully correct with patch 6.
Ah, right, this is relying on the last vertex still being available, even though we decremented the vertex count in d2d_geometry_sink_EndFigure(). That would normally be a little too subtle/fragile for our taste, but as patch 6 makes it more obviously correct, it's probably fine.
When the last vertex is coincident with the first vertex, the last segment should be suppressed for both END_OPEN and END_CLOSED. Only when last and first vertex are not coincident the additional line segment may be added - always for intersection tests and similar, and for stroking opereations when the figure is CLOSED.
Trying to use an zero-length segment in d2d_geometry_intersect_self will create invalid segments, causing infinite loops later.
Instead of reducing the vertex_count for cooincident first/last vertices add a dedicated type. This is required as some operations need the last segment, others do not.
This also allows to remove some replicated code in StrokeContains/GetBounds/Simplify, as a last Bezier segment is always processed in the regular loop.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51139 Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- dlls/d2d1/geometry.c | 98 ++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 72 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index 41987771ed4..e3fe65e4d9e 100644 --- a/dlls/d2d1/geometry.c +++ b/dlls/d2d1/geometry.c @@ -50,6 +50,7 @@ enum d2d_vertex_type D2D_VERTEX_TYPE_LINE, D2D_VERTEX_TYPE_BEZIER, D2D_VERTEX_TYPE_SPLIT_BEZIER, + D2D_VERTEX_TYPE_END, };
struct d2d_segment_idx @@ -2220,6 +2221,9 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry) for (idx_p.vertex_idx = 0; idx_p.vertex_idx < figure_p->vertex_count; ++idx_p.vertex_idx) { type_p = figure_p->vertex_types[idx_p.vertex_idx]; + if (type_p == D2D_VERTEX_TYPE_END) + continue; + for (idx_q.figure_idx = 0; idx_q.figure_idx <= idx_p.figure_idx; ++idx_q.figure_idx) { figure_q = &geometry->u.path.figures[idx_q.figure_idx]; @@ -2228,6 +2232,8 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry) if (!d2d_rect_check_overlap(&figure_p->bounds, &figure_q->bounds)) continue; max_q = figure_q->vertex_count; + if (max_q && figure_q->vertex_types[max_q - 1] == D2D_VERTEX_TYPE_END) + max_q--; } else { @@ -2238,6 +2244,7 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry) for (idx_q.vertex_idx = 0; idx_q.vertex_idx < max_q; ++idx_q.vertex_idx) { type_q = figure_q->vertex_types[idx_q.vertex_idx]; + if (d2d_vertex_type_is_bezier(type_q)) { if (d2d_vertex_type_is_bezier(type_p)) @@ -2608,7 +2615,8 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry, && !(figure_end == D2D1_FIGURE_END_CLOSED && vertex_count >= 1)) return TRUE;
- if (figure_end == D2D1_FIGURE_END_OPEN) + if (figure->vertex_types[vertex_count - 1] == D2D_VERTEX_TYPE_END + || figure_end == D2D1_FIGURE_END_OPEN) vertex_count--;
prev = p0 = &figure->vertices[0]; @@ -2919,13 +2927,15 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_EndFigure(ID2D1GeometrySink *ifa }
figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1]; - figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_LINE; if (figure_end == D2D1_FIGURE_END_CLOSED) { ++geometry->u.path.segment_count; figure->flags |= D2D_FIGURE_FLAG_CLOSED; - if (!memcmp(&figure->vertices[0], &figure->vertices[figure->vertex_count - 1], sizeof(*figure->vertices))) - --figure->vertex_count; + } + figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_END; + if (memcmp(&figure->vertices[0], &figure->vertices[figure->vertex_count - 1], sizeof(*figure->vertices))) + { + figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_LINE; }
if (!d2d_geometry_add_figure_outline(geometry, figure, figure_end)) @@ -3474,14 +3484,6 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry * if (figure->flags & D2D_FIGURE_FLAG_HOLLOW) continue;
- /* Single vertex figures are reduced by CloseFigure(). */ - if (figure->vertex_count == 0) - { - d2d_point_transform(&p, transform, figure->bounds.left, figure->bounds.top); - d2d_rect_expand(bounds, &p); - continue; - } - for (j = 0; j < figure->vertex_count; ++j) { if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE) @@ -3496,8 +3498,8 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j) { - if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE - || d2d_vertex_type_is_split_bezier(figure->vertex_types[j])) + enum d2d_vertex_type next_type = figure->vertex_types[j]; + if (next_type == D2D_VERTEX_TYPE_NONE || d2d_vertex_type_is_split_bezier(next_type)) continue;
switch (type) @@ -3535,26 +3537,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry * break; }
- type = figure->vertex_types[j]; - } - - if (d2d_vertex_type_is_bezier(type)) - { - /* FIXME: This attempts to approximate a cubic Bézier with - * a quadratic one. */ - p1 = figure->original_bezier_controls[bezier_idx++]; - d2d_point_transform(&p1, transform, p1.x, p1.y); - p2 = figure->original_bezier_controls[bezier_idx++]; - d2d_point_transform(&p2, transform, p2.x, p2.y); - p1.x = (p1.x + p2.x) * 0.75f; - p1.y = (p1.y + p2.y) * 0.75f; - p2 = figure->vertices[0]; - d2d_point_transform(&p2, transform, p2.x, p2.y); - p1.x -= (p.x + p2.x) * 0.25f; - p1.y -= (p.y + p2.y) * 0.25f; - - d2d_rect_get_bezier_bounds(&bezier_bounds, &p, &p1, &p2); - d2d_rect_union(bounds, &bezier_bounds); + type = next_type; } }
@@ -3617,8 +3600,8 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_StrokeContainsPoint(ID2D1Path
for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j) { - if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE - || d2d_vertex_type_is_split_bezier(figure->vertex_types[j])) + enum d2d_vertex_type next_type = figure->vertex_types[j]; + if (next_type == D2D_VERTEX_TYPE_NONE || d2d_vertex_type_is_split_bezier(next_type)) continue;
switch (type) @@ -3644,25 +3627,14 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_StrokeContainsPoint(ID2D1Path } if (*contains) return S_OK; - type = figure->vertex_types[j]; + type = next_type; }
- if (figure->flags & D2D_FIGURE_FLAG_CLOSED && (!*contains)) + if (type == D2D_VERTEX_TYPE_LINE) { - if (type == D2D_VERTEX_TYPE_LINE) - { - p1 = figure->vertices[0]; + p1 = figure->vertices[0]; + if (figure->flags & D2D_FIGURE_FLAG_CLOSED) *contains = d2d_point_on_line_segment(&point, &p, &p1, transform, stroke_width * 0.5f, tolerance); - p = p1; - } - else if (d2d_vertex_type_is_bezier(type)) - { - b.point1 = figure->original_bezier_controls[bezier_idx++]; - b.point2 = figure->original_bezier_controls[bezier_idx++]; - b.point3 = figure->vertices[0]; - *contains = d2d_point_on_bezier_segment(&point, &p, &b, transform, stroke_width, tolerance); - p = b.point3; - } }
if (*contains) @@ -3785,8 +3757,8 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j) { - if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE - || d2d_vertex_type_is_split_bezier(figure->vertex_types[j])) + enum d2d_vertex_type next_type = figure->vertex_types[j]; + if (next_type == D2D_VERTEX_TYPE_NONE || d2d_vertex_type_is_split_bezier(next_type)) continue;
switch (type) @@ -3825,25 +3797,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i break; }
- type = figure->vertex_types[j]; - } - - if (d2d_vertex_type_is_bezier(type)) - { - b.point1 = figure->original_bezier_controls[bezier_idx++]; - b.point2 = figure->original_bezier_controls[bezier_idx++]; - b.point3 = figure->vertices[0]; - if (transform) - { - d2d_point_transform(&b.point1, transform, b.point1.x, b.point1.y); - d2d_point_transform(&b.point2, transform, b.point2.x, b.point2.y); - d2d_point_transform(&b.point3, transform, b.point3.x, b.point3.y); - } - - if (option == D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES) - d2d_geometry_flatten_cubic(sink, &p, &b, tolerance); - else - ID2D1SimplifiedGeometrySink_AddBeziers(sink, &b, 1); + type = next_type; }
end = figure->flags & D2D_FIGURE_FLAG_CLOSED ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=104984
Your paranoid android.
=== debian11 (32 bit report) ===
d2d1: d2d1.c:6812: Test failed: Test 3: Got unexpected hr 0x88990029.
=== debian11 (64 bit WoW report) ===
d2d1: d2d1.c:6788: Test failed: d2d1.c:9939: Test marked todo: Test 1: Got unexpected hr 0x88990029.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51139 Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- dlls/d2d1/tests/d2d1.c | 10 ---------- 1 file changed, 10 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 27d78a01ff0..e888aafbb89 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -3898,7 +3898,6 @@ static void test_path_geometry(BOOL d3d11) hr = ID2D1PathGeometry_Open(geometry, &sink); ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
-#if 0 set_point(&point, 20.0f, 80.0f); ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED); line_to(sink, 40.0f, 100.0f); @@ -3910,7 +3909,6 @@ static void test_path_geometry(BOOL d3d11) line_to(sink, 60.0f, 40.0f); quadratic_to(sink, 95.0f, 40.0f, 80.0f, 20.0f); ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN); -#endif
set_point(&point, 120.0f, 180.0f); ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED); @@ -3931,11 +3929,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr); -#if 0 match = compare_rect(&rect, 20.0f, 20.0f, 180.0f, 180.0f, 0); -#else - match = compare_rect(&rect, 115.5f, 110.0f, 180.0f, 180.0f, 0); -#endif ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom);
@@ -3944,11 +3938,7 @@ static void test_path_geometry(BOOL d3d11) NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface); ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr); trace("SIMPLIFY done\n"); -#if 0 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[29], 1); -#else - geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 2, &expected_figures[31], 1); -#endif geometry_sink_cleanup(&simplify_sink);
ID2D1PathGeometry_Release(geometry);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=104985
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w7u_adm (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w7u_el (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w8 (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w8adm (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w864 (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064v1507 (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064v1809 (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064 (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064_tsign (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w10pro64 (32 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w864 (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064v1507 (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064v1809 (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064 (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064_2qxl (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w1064_tsign (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w10pro64 (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w10pro64_ar (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w10pro64_he (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w10pro64_ja (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
=== w10pro64_zh_CN (64 bit report) ===
d2d1: d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7027: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match. d2d1.c:7033: Test failed: Figure does not match.
The very last vertex of a figure can only be a of type LINE (non-coincident last/first vertices) or type END (otherwise). In case the current vertex starts a bezier path, there is always at least one more vertex, i.e. (vertex_idx + 1) < vertex_count is always true.
Signed-off-by: Stefan Brüns stefan.bruens@rwth-aachen.de --- dlls/d2d1/geometry.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index e3fe65e4d9e..8610dd560b4 100644 --- a/dlls/d2d1/geometry.c +++ b/dlls/d2d1/geometry.c @@ -2007,8 +2007,6 @@ static BOOL d2d_geometry_intersect_bezier_line(struct d2d_geometry *geometry, p[0] = &figure->vertices[idx_p->vertex_idx]; p[1] = &figure->bezier_controls[idx_p->control_idx]; next = idx_p->vertex_idx + 1; - if (next == figure->vertex_count) - next = 0; p[2] = &figure->vertices[next];
figure = &geometry->u.path.figures[idx_q->figure_idx]; @@ -2085,16 +2083,12 @@ static BOOL d2d_geometry_intersect_bezier_bezier(struct d2d_geometry *geometry, p[0] = &figure->vertices[idx_p->vertex_idx]; p[1] = &figure->bezier_controls[idx_p->control_idx]; next = idx_p->vertex_idx + 1; - if (next == figure->vertex_count) - next = 0; p[2] = &figure->vertices[next];
figure = &geometry->u.path.figures[idx_q->figure_idx]; q[0] = &figure->vertices[idx_q->vertex_idx]; q[1] = &figure->bezier_controls[idx_q->control_idx]; next = idx_q->vertex_idx + 1; - if (next == figure->vertex_count) - next = 0; q[2] = &figure->vertices[next];
d2d_rect_get_bezier_segment_bounds(&p_bounds, p[0], p[1], p[2], start_p, end_p); @@ -2178,8 +2172,6 @@ static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry, p[0] = &figure->vertices[inter->vertex_idx + vertex_offset]; p[1] = &figure->bezier_controls[inter->control_idx + control_offset]; next = inter->vertex_idx + vertex_offset + 1; - if (next == figure->vertex_count) - next = 0; p[2] = &figure->vertices[next];
d2d_point_lerp(&q[0], p[0], p[1], t); @@ -3015,18 +3007,12 @@ static BOOL d2d_geometry_check_bezier_overlap(struct d2d_geometry *geometry, figure = &geometry->u.path.figures[idx_p->figure_idx]; a[0] = &figure->vertices[idx_p->vertex_idx]; a[1] = &figure->bezier_controls[idx_p->control_idx]; - if (idx_p->vertex_idx == figure->vertex_count - 1) - a[2] = &figure->vertices[0]; - else - a[2] = &figure->vertices[idx_p->vertex_idx + 1]; + a[2] = &figure->vertices[idx_p->vertex_idx + 1];
figure = &geometry->u.path.figures[idx_q->figure_idx]; b[0] = &figure->vertices[idx_q->vertex_idx]; b[1] = &figure->bezier_controls[idx_q->control_idx]; - if (idx_q->vertex_idx == figure->vertex_count - 1) - b[2] = &figure->vertices[0]; - else - b[2] = &figure->vertices[idx_q->vertex_idx + 1]; + b[2] = &figure->vertices[idx_q->vertex_idx + 1];
if (d2d_point_ccw(a[0], a[1], a[2]) == 0.0f || d2d_point_ccw(b[0], b[1], b[2]) == 0.0f) return FALSE; @@ -3096,8 +3082,6 @@ static float d2d_geometry_bezier_ccw(struct d2d_geometry *geometry, const struct const struct d2d_figure *figure = &geometry->u.path.figures[idx->figure_idx]; size_t next = idx->vertex_idx + 1;
- if (next == figure->vertex_count) - next = 0;
return d2d_point_ccw(&figure->vertices[idx->vertex_idx], &figure->bezier_controls[idx->control_idx], &figure->vertices[next]); @@ -3114,8 +3098,6 @@ static BOOL d2d_geometry_split_bezier(struct d2d_geometry *geometry, const struc p[0] = &figure->vertices[idx->vertex_idx]; p[1] = &figure->bezier_controls[idx->control_idx]; next = idx->vertex_idx + 1; - if (next == figure->vertex_count) - next = 0; p[2] = &figure->vertices[next];
d2d_point_lerp(&q[0], p[0], p[1], 0.5f);