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