David White : d2d1: Implement path_geometry_StrokeContainsPoint() for line segments.
Alexandre Julliard
julliard at winehq.org
Wed Dec 8 15:46:31 CST 2021
Module: wine
Branch: master
Commit: f467f6385ed85dd7f8cbc857d82dc56e53f055a6
URL: https://source.winehq.org/git/wine.git/?a=commit;h=f467f6385ed85dd7f8cbc857d82dc56e53f055a6
Author: David White <dwhite at codeweavers.com>
Date: Wed Dec 8 20:14:21 2021 +0100
d2d1: Implement path_geometry_StrokeContainsPoint() for line segments.
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/d2d1/geometry.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++---
dlls/d2d1/tests/d2d1.c | 57 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 123 insertions(+), 3 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index af92df4f6c5..d5a430e1f74 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -3409,11 +3409,74 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_StrokeContainsPoint(ID2D1Path
D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
float tolerance, BOOL *contains)
{
- FIXME("iface %p, point %s, stroke_width %.8e, stroke_style %p, "
- "transform %p, tolerance %.8e, contains %p stub!\n",
+ struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry(iface);
+ enum d2d_vertex_type type = D2D_VERTEX_TYPE_NONE;
+ D2D1_POINT_2F p, p1;
+ unsigned int i, j;
+
+ TRACE("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p.\n",
iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
- return E_NOTIMPL;
+ if (stroke_style)
+ FIXME("Ignoring stroke style %p.\n", stroke_style);
+
+ if (!transform)
+ transform = &identity;
+
+ if (tolerance <= 0.0f)
+ tolerance = D2D1_DEFAULT_FLATTENING_TOLERANCE;
+
+ *contains = FALSE;
+ for (i = 0; i < geometry->u.path.figure_count; ++i)
+ {
+ const struct d2d_figure *figure = &geometry->u.path.figures[i];
+
+ for (j = 0; j < figure->vertex_count; ++j)
+ {
+ if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE)
+ continue;
+
+ p = figure->vertices[j];
+ type = figure->vertex_types[j];
+ break;
+ }
+
+ for (++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]))
+ continue;
+
+ switch (type)
+ {
+ case D2D_VERTEX_TYPE_LINE:
+ p1 = figure->vertices[j];
+ *contains = d2d_point_on_line_segment(&point, &p, &p1, transform, stroke_width * 0.5f, tolerance);
+ p = p1;
+ break;
+
+ default:
+ FIXME("Unhandled vertex type %#x.\n", type);
+ p = figure->vertices[j];
+ break;
+ }
+ if (*contains)
+ return S_OK;
+ type = figure->vertex_types[j];
+ }
+
+ if (figure->flags & D2D_FIGURE_FLAG_CLOSED && (!*contains) && type == D2D_VERTEX_TYPE_LINE)
+ {
+ p1 = figure->vertices[0];
+ *contains = d2d_point_on_line_segment(&point, &p, &p1, transform, stroke_width * 0.5f, tolerance);
+ p = p1;
+ }
+
+ if (*contains)
+ return S_OK;
+ }
+
+ return S_OK;
}
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_FillContainsPoint(ID2D1PathGeometry *iface,
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 22381ca3782..15088d679df 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -10137,7 +10137,10 @@ static void test_effect_crop(BOOL d3d11)
static void test_stroke_contains_point(BOOL d3d11)
{
ID2D1RectangleGeometry *rectangle;
+ ID2D1GeometrySink *sink;
+ ID2D1PathGeometry *path;
ID2D1Factory *factory;
+ D2D1_POINT_2F point;
D2D1_RECT_F rect;
unsigned int i;
BOOL contains;
@@ -10220,6 +10223,27 @@ static void test_stroke_contains_point(BOOL d3d11)
{{{{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 21.0f}}}, {10.0f, 31.0f}, 0.0f, 1.0f, TRUE, TRUE},
{{{{1.0f, 0.0f, 0.0f, 1.0f, 11.0f, 0.0f}}}, {16.0f, 0.0f}, 0.0f, 1.0f, TRUE, TRUE},
{{{{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -21.0f}}}, { 0.0f, -11.0f}, 0.0f, 1.0f, TRUE, TRUE},
+ },
+ path_tests[] =
+ {
+ /* 0. Stroked area hittesting. Edge. */
+ {{{{0.0f}}}, {160.0f, 600.0f}, 0.0f, 1.0f, FALSE, FALSE},
+ {{{{0.0f}}}, {239.24f, 600.0f}, 0.0f, 1.0f, FALSE, FALSE},
+ {{{{0.0f}}}, {239.26f, 600.0f}, 0.0f, 1.0f, FALSE, TRUE},
+ {{{{0.0f}}}, {240.74f, 600.0f}, 0.0f, 1.0f, FALSE, TRUE},
+ {{{{0.0f}}}, {240.76f, 600.0f}, 0.0f, 1.0f, FALSE, FALSE},
+
+ /* 5. Negative tolerance. */
+ {{{{0.0f}}}, {239.24f, 600.0f}, -1.0f, 1.0f, FALSE, FALSE},
+ {{{{0.0f}}}, {239.26f, 600.0f}, -1.0f, 1.0f, FALSE, TRUE},
+ {{{{0.0f}}}, {240.74f, 600.0f}, -1.0f, 1.0f, FALSE, TRUE},
+ {{{{0.0f}}}, {240.76f, 600.0f}, -1.0f, 1.0f, FALSE, FALSE},
+
+ /* 9. Less than default tolerance. */
+ {{{{0.0f}}}, {239.39f, 600.0f}, 0.1f, 1.0f, FALSE, FALSE},
+ {{{{0.0f}}}, {239.41f, 600.0f}, 0.1f, 1.0f, FALSE, TRUE},
+ {{{{0.0f}}}, {240.59f, 600.0f}, 0.1f, 1.0f, FALSE, TRUE},
+ {{{{0.0f}}}, {240.61f, 600.0f}, 0.1f, 1.0f, FALSE, FALSE},
};
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
@@ -10244,6 +10268,39 @@ static void test_stroke_contains_point(BOOL d3d11)
}
ID2D1RectangleGeometry_Release(rectangle);
+ hr = ID2D1Factory_CreatePathGeometry(factory, &path);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ hr = ID2D1PathGeometry_Open(path, &sink);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ set_point(&point, 160.0f, 240.0f);
+ ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
+ line_to(sink, 240.0f, 240.0f);
+ line_to(sink, 240.0f, 720.0f);
+ line_to(sink, 160.0f, 720.0f);
+ ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
+
+ hr = ID2D1GeometrySink_Close(sink);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ ID2D1GeometrySink_Release(sink);
+
+ for (i = 0; i < ARRAY_SIZE(path_tests); ++i)
+ {
+ const struct contains_point_test *test = &path_tests[i];
+
+ winetest_push_context("Test %u", i);
+
+ contains = !test->contains;
+ hr = ID2D1PathGeometry_StrokeContainsPoint(path, test->point, test->stroke_width,
+ NULL, test->matrix ? &test->transform : NULL, test->tolerance, &contains);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ ok(contains == test->contains, "Got unexpected result %#x.\n", contains);
+
+ winetest_pop_context();
+ }
+
+ ID2D1PathGeometry_Release(path);
+
ID2D1Factory_Release(factory);
}
More information about the wine-cvs
mailing list