[PATCH 5/5] d2d1: Properly test which side of a bezier curve is the inside.

Henri Verbeet hverbeet at codeweavers.com
Mon Dec 5 06:16:06 CST 2016


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/d2d1/geometry.c   | 230 ++++++++++++++++++++++++++++++++-----------------
 dlls/d2d1/tests/d2d1.c | 110 ++++++++++++++++++-----
 2 files changed, 238 insertions(+), 102 deletions(-)

diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index cb6fab8..522432f 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -46,15 +46,24 @@ enum d2d_cdt_edge_next
     D2D_EDGE_NEXT_TOR = 3,
 };
 
+enum d2d_vertex_type
+{
+    D2D_VERTEX_TYPE_NONE,
+    D2D_VERTEX_TYPE_LINE,
+    D2D_VERTEX_TYPE_BEZIER,
+};
+
 struct d2d_figure
 {
     D2D1_POINT_2F *vertices;
     size_t vertices_size;
+    enum d2d_vertex_type *vertex_types;
+    size_t vertex_types_size;
     size_t vertex_count;
 
-    struct d2d_bezier *beziers;
-    size_t beziers_size;
-    size_t bezier_count;
+    D2D1_POINT_2F *bezier_controls;
+    size_t bezier_controls_size;
+    size_t bezier_control_count;
 
     D2D1_RECT_F bounds;
 };
@@ -460,9 +469,19 @@ static BOOL d2d_figure_insert_vertex(struct d2d_figure *figure, size_t idx, D2D1
         return FALSE;
     }
 
+    if (!d2d_array_reserve((void **)&figure->vertex_types, &figure->vertex_types_size,
+            figure->vertex_count + 1, sizeof(*figure->vertex_types)))
+    {
+        ERR("Failed to grow vertex types array.\n");
+        return FALSE;
+    }
+
     memmove(&figure->vertices[idx + 1], &figure->vertices[idx],
             (figure->vertex_count - idx) * sizeof(*figure->vertices));
+    memmove(&figure->vertex_types[idx + 1], &figure->vertex_types[idx],
+            (figure->vertex_count - idx) * sizeof(*figure->vertex_types));
     figure->vertices[idx] = vertex;
+    figure->vertex_types[idx] = D2D_VERTEX_TYPE_NONE;
     d2d_figure_update_bounds(figure, vertex);
     ++figure->vertex_count;
     return TRUE;
@@ -477,58 +496,31 @@ static BOOL d2d_figure_add_vertex(struct d2d_figure *figure, D2D1_POINT_2F verte
         return FALSE;
     }
 
+    if (!d2d_array_reserve((void **)&figure->vertex_types, &figure->vertex_types_size,
+            figure->vertex_count + 1, sizeof(*figure->vertex_types)))
+    {
+        ERR("Failed to grow vertex types array.\n");
+        return FALSE;
+    }
+
     figure->vertices[figure->vertex_count] = vertex;
+    figure->vertex_types[figure->vertex_count] = D2D_VERTEX_TYPE_NONE;
     d2d_figure_update_bounds(figure, vertex);
     ++figure->vertex_count;
     return TRUE;
 }
 
-/* FIXME: No inside/outside testing is done for beziers. */
-static BOOL d2d_figure_add_bezier(struct d2d_figure *figure, D2D1_POINT_2F p0, D2D1_POINT_2F p1, D2D1_POINT_2F p2)
+static BOOL d2d_figure_add_bezier_control(struct d2d_figure *figure, const D2D1_POINT_2F *p)
 {
-    struct d2d_bezier *b;
-    unsigned int idx1, idx2;
-    float sign;
-
-    if (!d2d_array_reserve((void **)&figure->beziers, &figure->beziers_size,
-            figure->bezier_count + 1, sizeof(*figure->beziers)))
+    if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size,
+            figure->bezier_control_count + 1, sizeof(*figure->bezier_controls)))
     {
-        ERR("Failed to grow beziers array.\n");
+        ERR("Failed to grow bezier controls array.\n");
         return FALSE;
     }
 
-    if (d2d_point_ccw(&p0, &p1, &p2) > 0.0f)
-    {
-        sign = -1.0f;
-        idx1 = 1;
-        idx2 = 2;
-    }
-    else
-    {
-        sign = 1.0f;
-        idx1 = 2;
-        idx2 = 1;
-    }
-
-    b = &figure->beziers[figure->bezier_count];
-    b->v[0].position = p0;
-    b->v[0].texcoord.u = 0.0f;
-    b->v[0].texcoord.v = 0.0f;
-    b->v[0].texcoord.sign = sign;
-    b->v[idx1].position = p1;
-    b->v[idx1].texcoord.u = 0.5f;
-    b->v[idx1].texcoord.v = 0.0f;
-    b->v[idx1].texcoord.sign = sign;
-    b->v[idx2].position = p2;
-    b->v[idx2].texcoord.u = 1.0f;
-    b->v[idx2].texcoord.v = 1.0f;
-    b->v[idx2].texcoord.sign = sign;
-    ++figure->bezier_count;
-
-    if (sign > 0.0f && !d2d_figure_add_vertex(figure, p1))
-        return FALSE;
-    if (!d2d_figure_add_vertex(figure, p2))
-        return FALSE;
+    figure->bezier_controls[figure->bezier_control_count++] = *p;
+
     return TRUE;
 }
 
@@ -1174,7 +1166,8 @@ static int d2d_cdt_compare_vertices(const void *a, const void *b)
 
 /* Determine whether a given point is inside the geometry, using the current
  * fill mode rule. */
-static BOOL d2d_path_geometry_point_inside(const struct d2d_geometry *geometry, const D2D1_POINT_2F *probe)
+static BOOL d2d_path_geometry_point_inside(const struct d2d_geometry *geometry,
+        const D2D1_POINT_2F *probe, BOOL triangles_only)
 {
     const D2D1_POINT_2F *p0, *p1;
     D2D1_POINT_2F v_p, v_probe;
@@ -1190,8 +1183,11 @@ static BOOL d2d_path_geometry_point_inside(const struct d2d_geometry *geometry,
             continue;
 
         p0 = &figure->vertices[figure->vertex_count - 1];
-        for (j = 0; j < figure->vertex_count; p0 = p1, ++j)
+        for (j = 0; j < figure->vertex_count; ++j)
         {
+            if (!triangles_only && figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE)
+                continue;
+
             p1 = &figure->vertices[j];
             d2d_point_subtract(&v_p, p1, p0);
             d2d_point_subtract(&v_probe, probe, p0);
@@ -1203,6 +1199,8 @@ static BOOL d2d_path_geometry_point_inside(const struct d2d_geometry *geometry,
                 else
                     --score;
             }
+
+            p0 = p1;
         }
     }
 
@@ -1249,7 +1247,7 @@ static BOOL d2d_path_geometry_add_face(struct d2d_geometry *geometry, const stru
     probe.x += cdt->vertices[d2d_cdt_edge_origin(cdt, &tmp)].x * 0.50f;
     probe.y += cdt->vertices[d2d_cdt_edge_origin(cdt, &tmp)].y * 0.50f;
 
-    if (d2d_cdt_leftof(cdt, face->v[2], base_edge) && d2d_path_geometry_point_inside(geometry, &probe))
+    if (d2d_cdt_leftof(cdt, face->v[2], base_edge) && d2d_path_geometry_point_inside(geometry, &probe, TRUE))
         ++geometry->face_count;
 
     return TRUE;
@@ -1791,6 +1789,7 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddLines(ID2D1GeometrySink *ifac
         const D2D1_POINT_2F *points, UINT32 count)
 {
     struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
+    struct d2d_figure *figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
     unsigned int i;
 
     TRACE("iface %p, points %p, count %u.\n", iface, points, count);
@@ -1803,7 +1802,8 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddLines(ID2D1GeometrySink *ifac
 
     for (i = 0; i < count; ++i)
     {
-        if (!d2d_figure_add_vertex(&geometry->u.path.figures[geometry->u.path.figure_count - 1], points[i]))
+        figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_LINE;
+        if (!d2d_figure_add_vertex(figure, points[i]))
         {
             ERR("Failed to add vertex.\n");
             return;
@@ -1836,9 +1836,19 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddBeziers(ID2D1GeometrySink *if
         p.y = (beziers[i].point1.y + beziers[i].point2.y) * 0.75f;
         p.x -= (figure->vertices[figure->vertex_count - 1].x + beziers[i].point3.x) * 0.25f;
         p.y -= (figure->vertices[figure->vertex_count - 1].y + beziers[i].point3.y) * 0.25f;
-        if (!d2d_figure_add_bezier(figure, figure->vertices[figure->vertex_count - 1], p, beziers[i].point3))
+        figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER;
+
+        if (!d2d_figure_add_bezier_control(figure, &p))
         {
-            ERR("Failed to add bezier.\n");
+            ERR("Failed to add bezier control.\n");
+            geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
+            return;
+        }
+
+        if (!d2d_figure_add_vertex(figure, beziers[i].point3))
+        {
+            ERR("Failed to add bezier vertex.\n");
+            geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
             return;
         }
     }
@@ -1849,6 +1859,7 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddBeziers(ID2D1GeometrySink *if
 static void STDMETHODCALLTYPE d2d_geometry_sink_EndFigure(ID2D1GeometrySink *iface, D2D1_FIGURE_END figure_end)
 {
     struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
+    struct d2d_figure *figure;
 
     TRACE("iface %p, figure_end %#x.\n", iface, figure_end);
 
@@ -1858,6 +1869,8 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_EndFigure(ID2D1GeometrySink *ifa
         return;
     }
 
+    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)
         FIXME("Ignoring figure_end %#x.\n", figure_end);
 
@@ -1873,7 +1886,7 @@ static void d2d_path_geometry_free_figures(struct d2d_geometry *geometry)
 
     for (i = 0; i < geometry->u.path.figure_count; ++i)
     {
-        HeapFree(GetProcessHeap(), 0, geometry->u.path.figures[i].beziers);
+        HeapFree(GetProcessHeap(), 0, geometry->u.path.figures[i].bezier_controls);
         HeapFree(GetProcessHeap(), 0, geometry->u.path.figures[i].vertices);
     }
     HeapFree(GetProcessHeap(), 0, geometry->u.path.figures);
@@ -1881,11 +1894,81 @@ static void d2d_path_geometry_free_figures(struct d2d_geometry *geometry)
     geometry->u.path.figures_size = 0;
 }
 
+static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
+{
+    size_t bezier_idx, control_idx, i, j;
+
+    for (i = 0; i < geometry->u.path.figure_count; ++i)
+    {
+        geometry->bezier_count += geometry->u.path.figures[i].bezier_control_count;
+    }
+
+    if (!(geometry->beziers = HeapAlloc(GetProcessHeap(), 0,
+            geometry->bezier_count * sizeof(*geometry->beziers))))
+    {
+        ERR("Failed to allocate beziers array.\n");
+        geometry->bezier_count = 0;
+        return E_OUTOFMEMORY;
+    }
+
+    for (i = 0, bezier_idx = 0; i < geometry->u.path.figure_count; ++i)
+    {
+        struct d2d_figure *figure = &geometry->u.path.figures[i];
+        if (figure->bezier_control_count)
+        {
+            for (j = 0, control_idx = 0; j < figure->vertex_count; ++j)
+            {
+                const D2D1_POINT_2F *p0, *p1, *p2;
+                struct d2d_bezier *b;
+
+                if (figure->vertex_types[j] != D2D_VERTEX_TYPE_BEZIER)
+                    continue;
+
+                b = &geometry->beziers[bezier_idx];
+                p0 = &figure->vertices[j];
+                p1 = &figure->bezier_controls[control_idx++];
+                if (j == figure->vertex_count - 1)
+                    p2 = &figure->vertices[0];
+                else
+                    p2 = &figure->vertices[j + 1];
+
+                b->v[0].position = *p0;
+                b->v[0].texcoord.u = 0.0f;
+                b->v[0].texcoord.v = 0.0f;
+                b->v[1].position = *p1;
+                b->v[1].texcoord.u = 0.5f;
+                b->v[1].texcoord.v = 0.0f;
+                b->v[2].position = *p2;
+                b->v[2].texcoord.u = 1.0f;
+                b->v[2].texcoord.v = 1.0f;
+
+                if (d2d_path_geometry_point_inside(geometry, p1, FALSE))
+                {
+                    b->v[0].texcoord.sign = 1.0f;
+                    b->v[1].texcoord.sign = 1.0f;
+                    b->v[2].texcoord.sign = 1.0f;
+                    d2d_figure_insert_vertex(figure, j + 1, *p1);
+                    ++j;
+                }
+                else
+                {
+                    b->v[0].texcoord.sign = -1.0f;
+                    b->v[1].texcoord.sign = -1.0f;
+                    b->v[2].texcoord.sign = -1.0f;
+                }
+
+                ++bezier_idx;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
 static HRESULT STDMETHODCALLTYPE d2d_geometry_sink_Close(ID2D1GeometrySink *iface)
 {
     struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
     HRESULT hr = E_FAIL;
-    size_t i, start;
 
     TRACE("iface %p.\n", iface);
 
@@ -1899,37 +1982,16 @@ static HRESULT STDMETHODCALLTYPE d2d_geometry_sink_Close(ID2D1GeometrySink *ifac
 
     if (!d2d_geometry_intersect_self(geometry))
         goto done;
-    if (FAILED(hr = d2d_path_geometry_triangulate(geometry)))
+    if (FAILED(hr = d2d_geometry_resolve_beziers(geometry)))
         goto done;
-
-    for (i = 0; i < geometry->u.path.figure_count; ++i)
-    {
-        geometry->bezier_count += geometry->u.path.figures[i].bezier_count;
-    }
-
-    if (!(geometry->beziers = HeapAlloc(GetProcessHeap(), 0,
-            geometry->bezier_count * sizeof(*geometry->beziers))))
-    {
-        ERR("Failed to allocate beziers array.\n");
-        geometry->bezier_count = 0;
-        hr = E_OUTOFMEMORY;
+    if (FAILED(hr = d2d_path_geometry_triangulate(geometry)))
         goto done;
-    }
-
-    for (i = 0, start = 0; i < geometry->u.path.figure_count; ++i)
-    {
-        struct d2d_figure *figure = &geometry->u.path.figures[i];
-        if (figure->bezier_count)
-        {
-            memcpy(&geometry->beziers[start], figure->beziers,
-                    figure->bezier_count * sizeof(*figure->beziers));
-            start += figure->bezier_count;
-        }
-    }
 
 done:
     if (FAILED(hr))
     {
+        HeapFree(GetProcessHeap(), 0, geometry->beziers);
+        geometry->bezier_count = 0;
         d2d_path_geometry_free_figures(geometry);
         geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
     }
@@ -1975,10 +2037,18 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddQuadraticBeziers(ID2D1Geometr
 
     for (i = 0; i < bezier_count; ++i)
     {
-        if (!d2d_figure_add_bezier(figure, figure->vertices[figure->vertex_count - 1],
-                beziers[i].point1, beziers[i].point2))
+        figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER;
+        if (!d2d_figure_add_bezier_control(figure, &beziers[i].point1))
         {
             ERR("Failed to add bezier.\n");
+            geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
+            return;
+        }
+
+        if (!d2d_figure_add_vertex(figure, beziers[i].point2))
+        {
+            ERR("Failed to add bezier vertex.\n");
+            geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
             return;
         }
     }
@@ -2131,7 +2201,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_FillContainsPoint(ID2D1PathGe
         d2d_point_transform(&point, &g_i, point.x, point.y);
     }
 
-    *contains = !!d2d_path_geometry_point_inside(geometry, &point);
+    *contains = !!d2d_path_geometry_point_inside(geometry, &point, FALSE);
 
     TRACE("-> %#x.\n", *contains);
 
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index f271103..941a43a 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -358,6 +358,29 @@ static void deserialize_figure(struct figure *figure, const BYTE *s)
     }
 }
 
+static void read_figure(struct figure *figure, BYTE *data, unsigned int pitch,
+        unsigned int x, unsigned int y,  unsigned int w, unsigned int h, DWORD prev)
+{
+    unsigned int i, j, span;
+
+    figure->span_count = 0;
+    for (i = 0, span = 0; i < h; ++i)
+    {
+        const DWORD *row = (DWORD *)&data[(y + i) * pitch + x * 4];
+        for (j = 0; j < w; ++j, ++span)
+        {
+            if ((i || j) && prev != row[j])
+            {
+                figure_add_span(figure, span);
+                prev = row[j];
+                span = 0;
+            }
+        }
+    }
+    if (span)
+        figure_add_span(figure, span);
+}
+
 static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y,
         unsigned int w, unsigned int h, DWORD prev, unsigned int max_diff, const char *ref)
 {
@@ -399,21 +422,7 @@ static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y
     figure.spans_size = 64;
     figure.spans = HeapAlloc(GetProcessHeap(), 0, figure.spans_size * sizeof(*figure.spans));
 
-    for (i = 0, span = 0; i < h; ++i)
-    {
-        const DWORD *row = (DWORD *)((BYTE *)mapped_texture.pData + (y + i) * mapped_texture.RowPitch + x * 4);
-        for (j = 0; j < w; ++j, ++span)
-        {
-            if ((i || j) && prev != row[j])
-            {
-                figure_add_span(&figure, span);
-                prev = row[j];
-                span = 0;
-            }
-        }
-    }
-    if (span)
-        figure_add_span(&figure, span);
+    read_figure(&figure, mapped_texture.pData, mapped_texture.RowPitch, x, y, w, h, prev);
 
     deserialize_figure(&ref_figure, (BYTE *)ref);
     span = w * h;
@@ -449,7 +458,10 @@ static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y
         }
     }
     if (diff > max_diff)
+    {
+        read_figure(&figure, mapped_texture.pData, mapped_texture.RowPitch, x, y, w, h, prev);
         serialize_figure(&figure);
+    }
 
     HeapFree(GetProcessHeap(), 0, ref_figure.spans);
     HeapFree(GetProcessHeap(), 0, figure.spans);
@@ -1280,6 +1292,22 @@ static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink)
     quadratic_to(sink, 60.0f, 240.0f, 40.0f, 240.0f);
     quadratic_to(sink, 20.0f, 240.0f, 20.0f, 160.0f);
     ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
+
+    set_point(&point, 5.0f, 612.0f);
+    ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
+    quadratic_to(sink, 40.0f, 612.0f, 40.0f, 752.0f);
+    quadratic_to(sink, 40.0f, 612.0f, 75.0f, 612.0f);
+    quadratic_to(sink, 40.0f, 612.0f, 40.0f, 472.0f);
+    quadratic_to(sink, 40.0f, 612.0f,  5.0f, 612.0f);
+    ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
+
+    set_point(&point, 20.0f, 612.0f);
+    ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
+    quadratic_to(sink, 20.0f, 692.0f, 40.0f, 692.0f);
+    quadratic_to(sink, 60.0f, 692.0f, 60.0f, 612.0f);
+    quadratic_to(sink, 60.0f, 532.0f, 40.0f, 532.0f);
+    quadratic_to(sink, 20.0f, 532.0f, 20.0f, 612.0f);
+    ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
 }
 
 static void test_path_geometry(void)
@@ -1587,15 +1615,15 @@ static void test_path_geometry(void)
     ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
     hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
     ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
-    ok(count == 2, "Got unexpected figure count %u.\n", count);
+    ok(count == 4, "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 == 10, "Got unexpected segment count %u.\n", count);
+    ok(count == 20, "Got unexpected segment count %u.\n", count);
     ID2D1GeometrySink_Release(sink);
 
     set_matrix_identity(&matrix);
     scale_matrix(&matrix, 0.5f, 2.0f);
-    translate_matrix(&matrix, 240.0f, -33.0f);
+    translate_matrix(&matrix, 400.0f, -33.0f);
     rotate_matrix(&matrix, M_PI / 4.0f);
     scale_matrix(&matrix, 2.0f, 0.5f);
     hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
@@ -1617,8 +1645,18 @@ static void test_path_geometry(void)
             "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
             "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
     todo_wine ok(match, "Figure does not match.\n");
+    match = compare_figure(surface, 0, 226, 160, 160, 0xff652e89, 64,
+            "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
+            "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
+            "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
+            "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
+            "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
+            "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
+            "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
+            "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
+    todo_wine ok(match, "Figure does not match.\n");
     match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
-            "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
+            "gVQBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
             "A/MBBBAkEAT0AQUOJw0F9QEGCioKBvcBBggsCAb4AQgFLgUI+QEJATIBCfsBCAIwAgj8AQcFLAUH"
             "/QEFCCgIBf4BBAwiDAT/AQIQHBAClwISlwIBPgGAAgI8Av8BAzwD/QEEPAT7AQY6BvkBBzoH+AEI"
             "OAj3AQk4CfYBCTgK9AELNgvzAQw2DPIBDDYM8QEONA7wAQ40DvABDjQO7wEPNA/uAQ80D+4BEDIQ"
@@ -1627,7 +1665,19 @@ static void test_path_geometry(void)
             "C/QBCzcK9QEJOAn3AQg4CfcBBzoH+QEGOgb7AQU6BfwBBDwE/QEDPAP/AQE+AZkCDpkCAhIYEgKA"
             "AgMNIA0D/wEFCSYJBf4BBgYqBgf8AQgDLgMI+wFG+gEIAzADCPkBBwYuBgf3AQYKKgoG9gEFDCgM"
             "BfUBBBAlDwTzAQQSIhIE8QEDFh4WA/ABAhkaGQLvAQIcFhwC7QECIBAgAusBASgEKAHpAQFWAecB"
-            "AVgB5QEBWgHAAgEA");
+            "AVgB5QEBWgHAAgHhUgAA");
+    todo_wine ok(match, "Figure does not match.\n");
+    match = compare_figure(surface, 160, 160, 320, 160, 0xff652e89, 64,
+            "/VUB5QEBWAHnAQFWAekBAVQB6wECIQ8hAe0BAh0VHQLuAQIZGhkD7wEDFh4WA/EBBBMhEwPzAQQQ"
+            "JQ8F9AEFDCgNBfUBBgoqCgb3AQcHLQcG+QEIBC8ECPkBPAEJ+wEIAy8CCP0BBgYrBQf9AQUJJgkF"
+            "/wEDDSANBP8BAhEaEQKYAhAXAYACAT4BgAICPQL+AQM8BPwBBTsE+wEGOgb6AQc5B/gBCDgJ9gEJ"
+            "OAn2AQo3CvQBCzcK8wEMNgzyAQ01DPIBDTUN8AEONA7wAQ40D+4BDzQP7gEQMw/uARAzEO0BEDIR"
+            "7AERMhHsAREyEewBETIR7AERMhLrAREyEusBETIS6wERMhLrAREyEusBETIS6wERMhHsAREyEewB"
+            "ETIR7QEQMhHtARAzEO0BEDMP7gEPNA/vAQ40D+8BDjQO8QENNQ3xAQ01DPMBCzYM8wELNwr1AQo3"
+            "CvUBCTgJ9wEIOAn4AQc5B/kBBjoG+wEFOwT9AQM8BP4BAj0C/wEBPgGYAhAXAYACAhEaEQKAAgMN"
+            "IA0E/gEFCSYJBf4BBgYrBQf8AQgDLwII+wE8AQn6AQgELwQI+AEHBy0HBvcBBgoqCgb2AQUNJw0F"
+            "9AEEECQQBfIBBBMhEwPxAQMWHhYD8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB"
+            "wAIBwlYA");
     todo_wine ok(match, "Figure does not match.\n");
     ID2D1TransformedGeometry_Release(transformed_geometry);
     ID2D1PathGeometry_Release(geometry);
@@ -1642,10 +1692,10 @@ static void test_path_geometry(void)
     ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
     hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
     ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
-    ok(count == 2, "Got unexpected figure count %u.\n", count);
+    ok(count == 4, "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 == 10, "Got unexpected segment count %u.\n", count);
+    ok(count == 20, "Got unexpected segment count %u.\n", count);
     ID2D1GeometrySink_Release(sink);
 
     set_matrix_identity(&matrix);
@@ -1669,6 +1719,13 @@ static void test_path_geometry(void)
             "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
             "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
     ok(match, "Figure does not match.\n");
+    match = compare_figure(surface, 0, 226, 160, 160, 0xff652e89, 64,
+            "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
+            "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
+            "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
+            "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
+            "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
+    ok(match, "Figure does not match.\n");
     match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
             "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQIhDiIB7QECHRUdAu4BAhkaGQPvAQMWHhYD8QEEEyET"
             "A/MBBBAkEAT1AQUMKA0F9QEGCioKBvcBBwctBwb5AQgELwQI+QEJATIBCfsBRP0BQ/0BQv8BQf8B"
@@ -1678,6 +1735,15 @@ static void test_path_geometry(void)
             "RPsBCQEyAQn6AQgELwQI+AEHBy0GB/cBBgoqCgb2AQUMKA0F9AEEECUPBPMBBBIiEwPxAQMWHhYD"
             "8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB5QEBWgHAAgEA");
     ok(match, "Figure does not match.\n");
+    match = compare_figure(surface, 160, 160, 320, 160, 0xff652e89, 64,
+            "gVQBXAHjAQFaAeUBAVgB5wEBVgHpAQEpAikB6wECIBAgAu0BAhwWHALvAQIZGhkC8AEDFh4WA/EB"
+            "BBIiEgTzAQQPJRAE9QEFDCgMBfYBBgoqCgb3AQcGLgYH+QEIAzADCPoBRvsBRPwBRP0BQv8BQIAC"
+            "QIECPoECQP8BQv0BRPwBRPsBRvkBSPgBSPcBSvUBTPQBTPMBTvIBTvEBUPABUO8BUu4BUu4BUu4B"
+            "Uu0BVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVO0BUu4BUu4BUu8BUPAB"
+            "UPABUPEBTvIBTvMBTPQBS/YBSvcBSPgBSPkBRvsBRP0BQv8BQIACQIECPoECQP8BQv4BQv0BRPwB"
+            "RPsBCQEyAQn5AQgFLgUI+AEGCCwIBvcBBgoqCgb1AQUNJw4F9AEEECQQBPMBAxQgFAPxAQMWHhYD"
+            "7wEDGhgaA+0BAh4UHgLsAQEjDCMB6wEBVAHpAQFWAecBAVgB5QEBWgGiVQAA");
+    ok(match, "Figure does not match.\n");
     ID2D1TransformedGeometry_Release(transformed_geometry);
     ID2D1PathGeometry_Release(geometry);
 
-- 
2.1.4




More information about the wine-patches mailing list