d2d1: Properly test which side of a bezier curve is the inside.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2016-12-05 13:16:06 +01:00 committed by Alexandre Julliard
parent 3d51a7164b
commit e9fc8c7c52
2 changed files with 237 additions and 101 deletions

View File

@ -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);

View File

@ -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);