As the test shows, we can create geometries that have less than two vertices after eliminating duplicates. Calling d2d_cdt_triangulate() on those would lead to infinite recursion. In principle we could now get rid of the original vertex count check, but it seems cheap enough that it's worth keeping in order to avoid some unnecessary work in the somewhat more common case that we have less than three vertices before duplicate removal.
Based on a patch by Changsheng Chen.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- dlls/d2d1/geometry.c | 7 +++++++ dlls/d2d1/tests/d2d1.c | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index 6da93de3eb4..c7d0d94f1ad 100644 --- a/dlls/d2d1/geometry.c +++ b/dlls/d2d1/geometry.c @@ -2061,6 +2061,13 @@ static HRESULT d2d_path_geometry_triangulate(struct d2d_geometry *geometry) } }
+ if (vertex_count < 3) + { + WARN("Geometry has %lu vertices after eliminating duplicates.\n", (long)vertex_count); + heap_free(vertices); + return S_OK; + } + geometry->fill.vertices = vertices; geometry->fill.vertex_count = vertex_count;
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 3e2eda8a4a4..d38d49cd139 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -3268,6 +3268,28 @@ static void test_path_geometry(BOOL d3d11)
ID2D1PathGeometry_Release(geometry);
+ /* Degenerate figure. */ + 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, 123.0f, 456.0f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED); + quadratic_to(sink, 123.0f, 456.0f, 123.0f, 456.0f); + quadratic_to(sink, 123.0f, 456.0f, 123.0f, 456.0f); + quadratic_to(sink, 123.0f, 456.0f, 123.0f, 456.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); + hr = ID2D1PathGeometry_GetFigureCount(geometry, &count); + ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr); + ok(count == 1, "Got unexpected figure count %u.\n", count); + hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count); + ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr); + ok(count == 4, "Got unexpected segment count %u.\n", count); + ID2D1PathGeometry_Release(geometry); + /* Close right after Open(). */ hr = ID2D1Factory_CreatePathGeometry(factory, &geometry); ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);