From e9fc8c7c52db5fb1bf48420e5d6ee433661fd7e0 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Mon, 5 Dec 2016 13:16:06 +0100 Subject: [PATCH] d2d1: Properly test which side of a bezier curve is the inside. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d2d1/geometry.c | 228 +++++++++++++++++++++++++++-------------- dlls/d2d1/tests/d2d1.c | 110 ++++++++++++++++---- 2 files changed, 237 insertions(+), 101 deletions(-) diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index cb6fab819e5..522432f3946 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; - } + figure->bezier_controls[figure->bezier_control_count++] = *p; - 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; 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_geometry_resolve_beziers(geometry))) + goto done; if (FAILED(hr = d2d_path_geometry_triangulate(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; - 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 f2711039ea0..941a43a2571 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);