[PATCH 2/4] d2d1: Implement d2d_path_geometry_Simplify().
Henri Verbeet
hverbeet at codeweavers.com
Wed Jun 7 14:31:52 CDT 2017
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/d2d1/geometry.c | 165 +++++++++++++-
dlls/d2d1/tests/d2d1.c | 577 ++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 660 insertions(+), 82 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index c2de634..6327923 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -26,6 +26,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
+#define D2D_FIGURE_FLAG_CLOSED 0x00000001u
+#define D2D_FIGURE_FLAG_HOLLOW 0x00000002u
+
#define D2D_CDT_EDGE_FLAG_FREED 0x80000000u
#define D2D_CDT_EDGE_FLAG_VISITED(r) (1u << (r))
@@ -66,6 +69,7 @@ struct d2d_figure
size_t bezier_control_count;
D2D1_RECT_F bounds;
+ unsigned int flags;
};
struct d2d_cdt_edge_ref
@@ -2054,6 +2058,8 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_SetFillMode(ID2D1GeometrySink *i
TRACE("iface %p, mode %#x.\n", iface, mode);
+ if (geometry->u.path.state == D2D_GEOMETRY_STATE_CLOSED)
+ return;
geometry->u.path.fill_mode = mode;
}
@@ -2066,6 +2072,7 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_BeginFigure(ID2D1GeometrySink *i
D2D1_POINT_2F start_point, D2D1_FIGURE_BEGIN figure_begin)
{
struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
+ struct d2d_figure *figure;
TRACE("iface %p, start_point {%.8e, %.8e}, figure_begin %#x.\n",
iface, start_point.x, start_point.y, figure_begin);
@@ -2086,7 +2093,11 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_BeginFigure(ID2D1GeometrySink *i
return;
}
- if (!d2d_figure_add_vertex(&geometry->u.path.figures[geometry->u.path.figure_count - 1], start_point))
+ figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
+ if (figure_begin == D2D1_FIGURE_BEGIN_HOLLOW)
+ figure->flags |= D2D_FIGURE_FLAG_HOLLOW;
+
+ if (!d2d_figure_add_vertex(figure, start_point))
{
ERR("Failed to add vertex.\n");
geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
@@ -2183,9 +2194,12 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_EndFigure(ID2D1GeometrySink *ifa
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 && !memcmp(&figure->vertices[0],
- &figure->vertices[figure->vertex_count - 1], sizeof(*figure->vertices)))
- --figure->vertex_count;
+ if (figure_end == D2D1_FIGURE_END_CLOSED)
+ {
+ figure->flags |= D2D_FIGURE_FLAG_CLOSED;
+ if (!memcmp(&figure->vertices[0], &figure->vertices[figure->vertex_count - 1], sizeof(*figure->vertices)))
+ --figure->vertex_count;
+ }
if (!d2d_geometry_add_figure_outline(geometry, figure, figure_end))
{
@@ -2526,14 +2540,153 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_CompareWithGeometry(ID2D1Path
return E_NOTIMPL;
}
+static void d2d_geometry_flatten_cubic(ID2D1SimplifiedGeometrySink *sink, const D2D1_POINT_2F *p0,
+ const D2D1_BEZIER_SEGMENT *b, float tolerance)
+{
+ D2D1_BEZIER_SEGMENT b0, b1;
+ D2D1_POINT_2F q;
+ float d;
+
+ /* It's certainly possible to calculate the maximum deviation of the
+ * approximation from the curve, but it's a little involved. Instead, note
+ * that if the control points were evenly spaced and collinear, p1 would
+ * be exactly between p0 and p2, and p2 would be exactly between p1 and
+ * p3. The deviation is a decent enough approximation, and much easier to
+ * calculate.
+ *
+ * p1' = (p0 + p2) / 2
+ * p2' = (p1 + p3) / 2
+ * d = ‖p1 - p1'‖₁ + ‖p2 - p2'‖₁ */
+ d2d_point_lerp(&q, p0, &b->point2, 0.5f);
+ d2d_point_subtract(&q, &b->point1, &q);
+ d = fabsf(q.x) + fabsf(q.y);
+ d2d_point_lerp(&q, &b->point1, &b->point3, 0.5f);
+ d2d_point_subtract(&q, &b->point2, &q);
+ d += fabsf(q.x) + fabsf(q.y);
+ if (d < tolerance)
+ {
+ ID2D1SimplifiedGeometrySink_AddLines(sink, &b->point3, 1);
+ return;
+ }
+
+ d2d_point_lerp(&q, &b->point1, &b->point2, 0.5f);
+
+ b1.point3 = b->point3;
+ d2d_point_lerp(&b1.point2, &b1.point3, &b->point2, 0.5f);
+ d2d_point_lerp(&b1.point1, &b1.point2, &q, 0.5f);
+
+ d2d_point_lerp(&b0.point1, p0, &b->point1, 0.5f);
+ d2d_point_lerp(&b0.point2, &b0.point1, &q, 0.5f);
+ d2d_point_lerp(&b0.point3, &b0.point2, &b1.point1, 0.5f);
+
+ d2d_geometry_flatten_cubic(sink, p0, &b0, tolerance);
+ ID2D1SimplifiedGeometrySink_SetSegmentFlags(sink, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN);
+ d2d_geometry_flatten_cubic(sink, &b0.point3, &b1, tolerance);
+ ID2D1SimplifiedGeometrySink_SetSegmentFlags(sink, D2D1_PATH_SEGMENT_NONE);
+}
+
+static void d2d_geometry_simplify_quadratic(ID2D1SimplifiedGeometrySink *sink,
+ D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_POINT_2F *p0,
+ const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, float tolerance)
+{
+ D2D1_BEZIER_SEGMENT b;
+
+ d2d_point_lerp(&b.point1, p0, p1, 2.0f / 3.0f);
+ d2d_point_lerp(&b.point2, p2, p1, 2.0f / 3.0f);
+ b.point3 = *p2;
+
+ if (option == D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES)
+ d2d_geometry_flatten_cubic(sink, p0, &b, tolerance);
+ else
+ ID2D1SimplifiedGeometrySink_AddBeziers(sink, &b, 1);
+}
+
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *iface,
D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance,
ID2D1SimplifiedGeometrySink *sink)
{
- FIXME("iface %p, option %#x, transform %p, tolerance %.8e, sink %p stub!\n",
+ struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry(iface);
+ enum d2d_vertex_type type = D2D_VERTEX_TYPE_NONE;
+ unsigned int i, j, bezier_idx;
+ D2D1_FIGURE_BEGIN begin;
+ D2D1_POINT_2F p, p1, p2;
+ D2D1_FIGURE_END end;
+
+ TRACE("iface %p, option %#x, transform %p, tolerance %.8e, sink %p.\n",
iface, option, transform, tolerance, sink);
- return E_NOTIMPL;
+ ID2D1SimplifiedGeometrySink_SetFillMode(sink, geometry->u.path.fill_mode);
+ 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];
+ if (transform)
+ d2d_point_transform(&p, transform, p.x, p.y);
+ begin = figure->flags & D2D_FIGURE_FLAG_HOLLOW ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
+ ID2D1SimplifiedGeometrySink_BeginFigure(sink, p, begin);
+ type = figure->vertex_types[j];
+ break;
+ }
+
+ for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j)
+ {
+ if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE)
+ continue;
+
+ switch (type)
+ {
+ case D2D_VERTEX_TYPE_LINE:
+ p = figure->vertices[j];
+ if (transform)
+ d2d_point_transform(&p, transform, p.x, p.y);
+ ID2D1SimplifiedGeometrySink_AddLines(sink, &p, 1);
+ break;
+
+ case D2D_VERTEX_TYPE_BEZIER:
+ p1 = figure->bezier_controls[bezier_idx++];
+ if (transform)
+ d2d_point_transform(&p1, transform, p1.x, p1.y);
+ p2 = figure->vertices[j];
+ if (transform)
+ d2d_point_transform(&p2, transform, p2.x, p2.y);
+ d2d_geometry_simplify_quadratic(sink, option, &p, &p1, &p2, tolerance);
+ p = p2;
+ break;
+
+ default:
+ FIXME("Unhandled vertex type %#x.\n", type);
+ p = figure->vertices[j];
+ if (transform)
+ d2d_point_transform(&p, transform, p.x, p.y);
+ ID2D1SimplifiedGeometrySink_AddLines(sink, &p, 1);
+ break;
+ }
+
+ type = figure->vertex_types[j];
+ }
+
+ if (type == D2D_VERTEX_TYPE_BEZIER)
+ {
+ p1 = figure->bezier_controls[bezier_idx++];
+ if (transform)
+ d2d_point_transform(&p1, transform, p1.x, p1.y);
+ p2 = figure->vertices[0];
+ if (transform)
+ d2d_point_transform(&p2, transform, p2.x, p2.y);
+ d2d_geometry_simplify_quadratic(sink, option, &p, &p1, &p2, tolerance);
+ }
+
+ end = figure->flags & D2D_FIGURE_FLAG_CLOSED ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN;
+ ID2D1SimplifiedGeometrySink_EndFigure(sink, end);
+ }
+
+ return S_OK;
}
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Tessellate(ID2D1PathGeometry *iface,
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 768f8e7..d1f8398 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -54,6 +54,7 @@ struct geometry_sink
D2D1_BEZIER_SEGMENT bezier;
D2D1_POINT_2F line;
} u;
+ DWORD flags;
} *segments;
unsigned int segments_size;
unsigned int segment_count;
@@ -62,6 +63,7 @@ struct geometry_sink
unsigned int figure_count;
D2D1_FILL_MODE fill_mode;
+ DWORD segment_flags;
BOOL closed;
};
@@ -709,7 +711,9 @@ static void STDMETHODCALLTYPE geometry_sink_SetFillMode(ID2D1SimplifiedGeometryS
static void STDMETHODCALLTYPE geometry_sink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface,
D2D1_PATH_SEGMENT flags)
{
- ok(0, "Got unexpected segment flags %#x.\n", flags);
+ struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
+
+ sink->segment_flags = flags;
}
static void STDMETHODCALLTYPE geometry_sink_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
@@ -757,6 +761,7 @@ static void STDMETHODCALLTYPE geometry_sink_AddLines(ID2D1SimplifiedGeometrySink
segment = geometry_figure_add_segment(figure);
segment->type = SEGMENT_LINE;
segment->u.line = points[i];
+ segment->flags = sink->segment_flags;
}
}
@@ -773,6 +778,7 @@ static void STDMETHODCALLTYPE geometry_sink_AddBeziers(ID2D1SimplifiedGeometrySi
segment = geometry_figure_add_segment(figure);
segment->type = SEGMENT_BEZIER;
segment->u.bezier = beziers[i];
+ segment->flags = sink->segment_flags;
}
}
@@ -828,6 +834,84 @@ static void geometry_sink_cleanup(struct geometry_sink *sink)
HeapFree(GetProcessHeap(), 0, sink->figures);
}
+#define geometry_sink_check(a, b, c, d, e) geometry_sink_check_(__LINE__, a, b, c, d, e)
+static void geometry_sink_check_(unsigned int line, const struct geometry_sink *sink, D2D1_FILL_MODE fill_mode,
+ unsigned int figure_count, const struct expected_geometry_figure *expected_figures, unsigned int ulps)
+{
+ const struct geometry_segment *segment, *expected_segment;
+ const struct expected_geometry_figure *expected_figure;
+ const struct geometry_figure *figure;
+ unsigned int i, j;
+ BOOL match;
+
+ ok_(__FILE__, line)(sink->fill_mode == fill_mode,
+ "Got unexpected fill mode %#x.\n", sink->fill_mode);
+ ok_(__FILE__, line)(sink->figure_count == figure_count,
+ "Got unexpected figure count %u, expected %u.\n", sink->figure_count, figure_count);
+ ok_(__FILE__, line)(!sink->closed, "Sink is closed.\n");
+
+ for (i = 0; i < figure_count; ++i)
+ {
+ expected_figure = &expected_figures[i];
+ figure = &sink->figures[i];
+
+ ok_(__FILE__, line)(figure->begin == expected_figure->begin,
+ "Got unexpected figure %u begin %#x, expected %#x.\n",
+ i, figure->begin, expected_figure->begin);
+ ok_(__FILE__, line)(figure->end == expected_figure->end,
+ "Got unexpected figure %u end %#x, expected %#x.\n",
+ i, figure->end, expected_figure->end);
+ match = compare_point(&figure->start_point,
+ expected_figure->start_point.x, expected_figure->start_point.y, ulps);
+ ok_(__FILE__, line)(match, "Got unexpected figure %u start point {%.8e, %.8e}, expected {%.8e, %.8e}.\n",
+ i, figure->start_point.x, figure->start_point.y,
+ expected_figure->start_point.x, expected_figure->start_point.y);
+ ok_(__FILE__, line)(figure->segment_count == expected_figure->segment_count,
+ "Got unexpected figure %u segment count %u, expected %u.\n",
+ i, figure->segment_count, expected_figure->segment_count);
+
+ for (j = 0; j < figure->segment_count; ++j)
+ {
+ expected_segment = &expected_figure->segments[j];
+ segment = &figure->segments[j];
+ ok_(__FILE__, line)(segment->type == expected_segment->type,
+ "Got unexpected figure %u, segment %u type %#x, expected %#x.\n",
+ i, j, segment->type, expected_segment->type);
+ ok_(__FILE__, line)(segment->flags == expected_segment->flags,
+ "Got unexpected figure %u, segment %u flags %#x, expected %#x.\n",
+ i, j, segment->flags, expected_segment->flags);
+ switch (segment->type)
+ {
+ case SEGMENT_LINE:
+ match = compare_point(&segment->u.line,
+ expected_segment->u.line.x, expected_segment->u.line.y, ulps);
+ ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u {%.8e, %.8e}, "
+ "expected {%.8e, %.8e}.\n",
+ i, j, segment->u.line.x, segment->u.line.y,
+ expected_segment->u.line.x, expected_segment->u.line.y);
+ break;
+
+ case SEGMENT_BEZIER:
+ match = compare_bezier_segment(&segment->u.bezier,
+ expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
+ expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
+ expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y,
+ ulps);
+ ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u "
+ "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, "
+ "expected {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
+ i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y,
+ segment->u.bezier.point2.x, segment->u.bezier.point2.y,
+ segment->u.bezier.point3.x, segment->u.bezier.point3.y,
+ expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
+ expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
+ expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y);
+ break;
+ }
+ }
+ }
+}
+
static void test_clip(void)
{
IDXGISwapChain *swapchain;
@@ -1571,6 +1655,7 @@ static void test_path_geometry(void)
ID2D1TransformedGeometry *transformed_geometry;
D2D1_MATRIX_3X2_F matrix, tmp_matrix;
ID2D1GeometrySink *sink, *tmp_sink;
+ struct geometry_sink simplify_sink;
D2D1_POINT_2F point = {0.0f, 0.0f};
ID2D1SolidColorBrush *brush;
ID2D1PathGeometry *geometry;
@@ -1587,6 +1672,320 @@ static void test_path_geometry(void)
HWND window;
HRESULT hr;
+ static const struct geometry_segment expected_segments[] =
+ {
+ /* Figure 0. */
+ {SEGMENT_LINE, {{{ 55.0f, 20.0f}}}},
+ {SEGMENT_LINE, {{{ 55.0f, 220.0f}}}},
+ {SEGMENT_LINE, {{{ 25.0f, 220.0f}}}},
+ {SEGMENT_LINE, {{{ 25.0f, 100.0f}}}},
+ {SEGMENT_LINE, {{{ 75.0f, 100.0f}}}},
+ {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
+ {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
+ {SEGMENT_LINE, {{{ 5.0f, 60.0f}}}},
+ {SEGMENT_LINE, {{{ 45.0f, 60.0f}}}},
+ {SEGMENT_LINE, {{{ 45.0f, 180.0f}}}},
+ {SEGMENT_LINE, {{{ 35.0f, 180.0f}}}},
+ {SEGMENT_LINE, {{{ 35.0f, 140.0f}}}},
+ {SEGMENT_LINE, {{{ 65.0f, 140.0f}}}},
+ {SEGMENT_LINE, {{{ 65.0f, 260.0f}}}},
+ {SEGMENT_LINE, {{{ 15.0f, 260.0f}}}},
+ /* Figure 1. */
+ {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
+ {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
+ {SEGMENT_LINE, {{{ 85.0f, 300.0f}}}},
+ {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
+ {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
+ {SEGMENT_LINE, {{{155.0f, 20.0f}}}},
+ {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
+ {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
+ {SEGMENT_LINE, {{{ 85.0f, 20.0f}}}},
+ {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
+ {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
+ /* Figure 2. */
+ {SEGMENT_LINE, {{{165.0f, 300.0f}}}},
+ {SEGMENT_LINE, {{{235.0f, 300.0f}}}},
+ {SEGMENT_LINE, {{{235.0f, 20.0f}}}},
+ /* Figure 3. */
+ {SEGMENT_LINE, {{{225.0f, 260.0f}}}},
+ {SEGMENT_LINE, {{{175.0f, 260.0f}}}},
+ {SEGMENT_LINE, {{{175.0f, 60.0f}}}},
+ /* Figure 4. */
+ {SEGMENT_LINE, {{{185.0f, 220.0f}}}},
+ {SEGMENT_LINE, {{{185.0f, 100.0f}}}},
+ {SEGMENT_LINE, {{{215.0f, 100.0f}}}},
+ /* Figure 5. */
+ {SEGMENT_LINE, {{{205.0f, 180.0f}}}},
+ {SEGMENT_LINE, {{{205.0f, 140.0f}}}},
+ {SEGMENT_LINE, {{{195.0f, 140.0f}}}},
+ /* Figure 6. */
+ {SEGMENT_LINE, {{{135.0f, 620.0f}}}},
+ {SEGMENT_LINE, {{{135.0f, 420.0f}}}},
+ {SEGMENT_LINE, {{{105.0f, 420.0f}}}},
+ {SEGMENT_LINE, {{{105.0f, 540.0f}}}},
+ {SEGMENT_LINE, {{{155.0f, 540.0f}}}},
+ {SEGMENT_LINE, {{{155.0f, 340.0f}}}},
+ {SEGMENT_LINE, {{{ 85.0f, 340.0f}}}},
+ {SEGMENT_LINE, {{{ 85.0f, 580.0f}}}},
+ {SEGMENT_LINE, {{{125.0f, 580.0f}}}},
+ {SEGMENT_LINE, {{{125.0f, 460.0f}}}},
+ {SEGMENT_LINE, {{{115.0f, 460.0f}}}},
+ {SEGMENT_LINE, {{{115.0f, 500.0f}}}},
+ {SEGMENT_LINE, {{{145.0f, 500.0f}}}},
+ {SEGMENT_LINE, {{{145.0f, 380.0f}}}},
+ {SEGMENT_LINE, {{{ 95.0f, 380.0f}}}},
+ /* Figure 7. */
+ {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
+ {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
+ {SEGMENT_LINE, {{{165.0f, 340.0f}}}},
+ {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
+ {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
+ {SEGMENT_LINE, {{{235.0f, 620.0f}}}},
+ {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
+ {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
+ {SEGMENT_LINE, {{{165.0f, 620.0f}}}},
+ {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
+ {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
+ /* Figure 8. */
+ {SEGMENT_LINE, {{{245.0f, 340.0f}}}},
+ {SEGMENT_LINE, {{{315.0f, 340.0f}}}},
+ {SEGMENT_LINE, {{{315.0f, 620.0f}}}},
+ /* Figure 9. */
+ {SEGMENT_LINE, {{{305.0f, 380.0f}}}},
+ {SEGMENT_LINE, {{{255.0f, 380.0f}}}},
+ {SEGMENT_LINE, {{{255.0f, 580.0f}}}},
+ /* Figure 10. */
+ {SEGMENT_LINE, {{{265.0f, 420.0f}}}},
+ {SEGMENT_LINE, {{{265.0f, 540.0f}}}},
+ {SEGMENT_LINE, {{{295.0f, 540.0f}}}},
+ /* Figure 11. */
+ {SEGMENT_LINE, {{{285.0f, 460.0f}}}},
+ {SEGMENT_LINE, {{{285.0f, 500.0f}}}},
+ {SEGMENT_LINE, {{{275.0f, 500.0f}}}},
+ /* Figure 12. */
+ {SEGMENT_BEZIER, {{{2.83333340e+01f, 1.60000000e+02f},
+ {4.00000000e+01f, 1.13333336e+02f},
+ {4.00000000e+01f, 2.00000000e+01f}}}},
+ {SEGMENT_BEZIER, {{{4.00000000e+01f, 1.13333336e+02f},
+ {5.16666641e+01f, 1.60000000e+02f},
+ {7.50000000e+01f, 1.60000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{5.16666641e+01f, 1.60000000e+02f},
+ {4.00000000e+01f, 2.06666656e+02f},
+ {4.00000000e+01f, 3.00000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{4.00000000e+01f, 2.06666656e+02f},
+ {2.83333340e+01f, 1.60000000e+02f},
+ {5.00000000e+00f, 1.60000000e+02f}}}},
+ /* Figure 13. */
+ {SEGMENT_BEZIER, {{{2.00000000e+01f, 1.06666664e+02f},
+ {2.66666660e+01f, 8.00000000e+01f},
+ {4.00000000e+01f, 8.00000000e+01f}}}},
+ {SEGMENT_BEZIER, {{{5.33333321e+01f, 8.00000000e+01f},
+ {6.00000000e+01f, 1.06666664e+02f},
+ {6.00000000e+01f, 1.60000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{6.00000000e+01f, 2.13333328e+02f},
+ {5.33333321e+01f, 2.40000000e+02f},
+ {4.00000000e+01f, 2.40000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{2.66666660e+01f, 2.40000000e+02f},
+ {2.00000000e+01f, 2.13333328e+02f},
+ {2.00000000e+01f, 1.60000000e+02f}}}},
+ /* Figure 14. */
+ {SEGMENT_BEZIER, {{{2.83333340e+01f, 6.12000000e+02f},
+ {4.00000000e+01f, 6.58666687e+02f},
+ {4.00000000e+01f, 7.52000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{4.00000000e+01f, 6.58666687e+02f},
+ {5.16666641e+01f, 6.12000000e+02f},
+ {7.50000000e+01f, 6.12000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{5.16666641e+01f, 6.12000000e+02f},
+ {4.00000000e+01f, 5.65333313e+02f},
+ {4.00000000e+01f, 4.72000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{4.00000000e+01f, 5.65333313e+02f},
+ {2.83333340e+01f, 6.12000000e+02f},
+ {5.00000000e+00f, 6.12000000e+02f}}}},
+ /* Figure 15. */
+ {SEGMENT_BEZIER, {{{2.00000000e+01f, 6.65333313e+02f},
+ {2.66666660e+01f, 6.92000000e+02f},
+ {4.00000000e+01f, 6.92000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{5.33333321e+01f, 6.92000000e+02f},
+ {6.00000000e+01f, 6.65333313e+02f},
+ {6.00000000e+01f, 6.12000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{6.00000000e+01f, 5.58666687e+02f},
+ {5.33333321e+01f, 5.32000000e+02f},
+ {4.00000000e+01f, 5.32000000e+02f}}}},
+ {SEGMENT_BEZIER, {{{2.66666660e+01f, 5.32000000e+02f},
+ {2.00000000e+01f, 5.58666687e+02f},
+ {2.00000000e+01f, 6.12000000e+02f}}}},
+ /* Figure 16. */
+ {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.27275856e+02f},
+ {2.08249573e+02f, 1.27275856e+02f},
+ {2.24748734e+02f, 6.12792168e+01f}}}},
+ {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.27275856e+02f},
+ {2.08249573e+02f, 1.93272476e+02f},
+ {2.24748734e+02f, 2.59269104e+02f}}}},
+ {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.93272476e+02f},
+ {1.91750427e+02f, 1.93272476e+02f},
+ {1.75251266e+02f, 2.59269104e+02f}}}},
+ {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.93272476e+02f},
+ {1.91750427e+02f, 1.27275856e+02f},
+ {1.75251266e+02f, 6.12792168e+01f}}}},
+ /* Figure 17. */
+ {SEGMENT_BEZIER, {{{1.95285950e+02f, 6.59932632e+01f},
+ {2.04714050e+02f, 6.59932632e+01f},
+ {2.14142136e+02f, 1.03705627e+02f}}}},
+ {SEGMENT_BEZIER, {{{2.23570221e+02f, 1.41417984e+02f},
+ {2.23570221e+02f, 1.79130356e+02f},
+ {2.14142136e+02f, 2.16842712e+02f}}}},
+ {SEGMENT_BEZIER, {{{2.04714050e+02f, 2.54555069e+02f},
+ {1.95285950e+02f, 2.54555069e+02f},
+ {1.85857864e+02f, 2.16842712e+02f}}}},
+ {SEGMENT_BEZIER, {{{1.76429779e+02f, 1.79130356e+02f},
+ {1.76429779e+02f, 1.41417984e+02f},
+ {1.85857864e+02f, 1.03705627e+02f}}}},
+ /* Figure 18. */
+ {SEGMENT_BEZIER, {{{1.11847351e+02f, 4.46888092e+02f},
+ {1.11847351e+02f, 5.12884705e+02f},
+ {9.53481979e+01f, 5.78881348e+02f}}}},
+ {SEGMENT_BEZIER, {{{1.11847351e+02f, 5.12884705e+02f},
+ {1.28346512e+02f, 5.12884705e+02f},
+ {1.44845673e+02f, 5.78881348e+02f}}}},
+ {SEGMENT_BEZIER, {{{1.28346512e+02f, 5.12884705e+02f},
+ {1.28346512e+02f, 4.46888092e+02f},
+ {1.44845673e+02f, 3.80891479e+02f}}}},
+ {SEGMENT_BEZIER, {{{1.28346512e+02f, 4.46888092e+02f},
+ {1.11847351e+02f, 4.46888092e+02f},
+ {9.53481979e+01f, 3.80891479e+02f}}}},
+ /* Figure 19. */
+ {SEGMENT_BEZIER, {{{9.65267105e+01f, 4.61030243e+02f},
+ {9.65267105e+01f, 4.98742584e+02f},
+ {1.05954803e+02f, 5.36454956e+02f}}}},
+ {SEGMENT_BEZIER, {{{1.15382889e+02f, 5.74167297e+02f},
+ {1.24810982e+02f, 5.74167297e+02f},
+ {1.34239075e+02f, 5.36454956e+02f}}}},
+ {SEGMENT_BEZIER, {{{1.43667160e+02f, 4.98742584e+02f},
+ {1.43667160e+02f, 4.61030243e+02f},
+ {1.34239075e+02f, 4.23317871e+02f}}}},
+ {SEGMENT_BEZIER, {{{1.24810982e+02f, 3.85605499e+02f},
+ {1.15382889e+02f, 3.85605499e+02f},
+ {1.05954803e+02f, 4.23317871e+02f}}}},
+ /* Figure 20. */
+ {SEGMENT_LINE, {{{ 40.0f, 20.0f}}}},
+ {SEGMENT_LINE, {{{ 75.0f, 160.0f}}}},
+ {SEGMENT_LINE, {{{ 40.0f, 300.0f}}}},
+ {SEGMENT_LINE, {{{ 5.0f, 160.0f}}}},
+ /* Figure 21. */
+ {SEGMENT_LINE, {{{ 40.0f, 80.0f}}}},
+ {SEGMENT_LINE, {{{ 60.0f, 160.0f}}}},
+ {SEGMENT_LINE, {{{ 40.0f, 240.0f}}}},
+ {SEGMENT_LINE, {{{ 20.0f, 160.0f}}}},
+ /* Figure 22. */
+ {SEGMENT_LINE, {{{ 40.0f, 752.0f}}}},
+ {SEGMENT_LINE, {{{ 75.0f, 612.0f}}}},
+ {SEGMENT_LINE, {{{ 40.0f, 472.0f}}}},
+ {SEGMENT_LINE, {{{ 5.0f, 612.0f}}}},
+ /* Figure 23. */
+ {SEGMENT_LINE, {{{ 40.0f, 692.0f}}}},
+ {SEGMENT_LINE, {{{ 60.0f, 612.0f}}}},
+ {SEGMENT_LINE, {{{ 40.0f, 532.0f}}}},
+ {SEGMENT_LINE, {{{ 20.0f, 612.0f}}}},
+ /* Figure 24. */
+ {SEGMENT_LINE, {{{2.03125019e+01f, 1.51250000e+02f}}}},
+ {SEGMENT_LINE, {{{3.12500019e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{3.78125000e+01f, 8.12500076e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{4.00000000e+01f, 2.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{4.21875000e+01f, 8.12500076e+01f}}}},
+ {SEGMENT_LINE, {{{4.87500000e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.96875000e+01f, 1.51250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{7.50000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.96875000e+01f, 1.68750000e+02f}}}},
+ {SEGMENT_LINE, {{{4.87500000e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{4.21875000e+01f, 2.38750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{4.00000000e+01f, 3.00000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{3.78125000e+01f, 2.38750000e+02f}}}},
+ {SEGMENT_LINE, {{{3.12500019e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{2.03125019e+01f, 1.68750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.00000000e+00f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ /* Figure 25. */
+ {SEGMENT_LINE, {{{2.50000000e+01f, 1.00000000e+02f}}}},
+ {SEGMENT_LINE, {{{4.00000000e+01f, 8.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.50000000e+01f, 1.00000000e+02f}}}},
+ {SEGMENT_LINE, {{{6.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.50000000e+01f, 2.20000000e+02f}}}},
+ {SEGMENT_LINE, {{{4.00000000e+01f, 2.40000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{2.50000000e+01f, 2.20000000e+02f}}}},
+ {SEGMENT_LINE, {{{2.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ /* Figure 26. */
+ {SEGMENT_LINE, {{{2.03125019e+01f, 6.20750000e+02f}}}},
+ {SEGMENT_LINE, {{{3.12500019e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{3.78125000e+01f, 6.90750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{4.00000000e+01f, 7.52000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{4.21875000e+01f, 6.90750000e+02f}}}},
+ {SEGMENT_LINE, {{{4.87500000e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.96875000e+01f, 6.20750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{7.50000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.96875000e+01f, 6.03250000e+02f}}}},
+ {SEGMENT_LINE, {{{4.87500000e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{4.21875000e+01f, 5.33250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{4.00000000e+01f, 4.72000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{3.78125000e+01f, 5.33250000e+02f}}}},
+ {SEGMENT_LINE, {{{3.12500019e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{2.03125019e+01f, 6.03250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.00000000e+00f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ /* Figure 27. */
+ {SEGMENT_LINE, {{{2.50000000e+01f, 6.72000000e+02f}}}},
+ {SEGMENT_LINE, {{{4.00000000e+01f, 6.92000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.50000000e+01f, 6.72000000e+02f}}}},
+ {SEGMENT_LINE, {{{6.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{5.50000000e+01f, 5.52000000e+02f}}}},
+ {SEGMENT_LINE, {{{4.00000000e+01f, 5.32000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ {SEGMENT_LINE, {{{2.50000000e+01f, 5.52000000e+02f}}}},
+ {SEGMENT_LINE, {{{2.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
+ /* Figure 28. */
+ {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
+ {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
+ };
+ static const struct expected_geometry_figure expected_figures[] =
+ {
+ /* 0 */
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 15.0f, 20.0f}, 15, &expected_segments[0]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {155.0f, 300.0f}, 11, &expected_segments[15]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {165.0f, 20.0f}, 3, &expected_segments[26]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {225.0f, 60.0f}, 3, &expected_segments[29]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {215.0f, 220.0f}, 3, &expected_segments[32]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {195.0f, 180.0f}, 3, &expected_segments[35]},
+ /* 6 */
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 95.0f, 620.0f}, 15, &expected_segments[38]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {235.0f, 340.0f}, 11, &expected_segments[53]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {245.0f, 620.0f}, 3, &expected_segments[64]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {305.0f, 580.0f}, 3, &expected_segments[67]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {295.0f, 420.0f}, 3, &expected_segments[70]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {275.0f, 460.0f}, 3, &expected_segments[73]},
+ /* 12 */
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[76]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[80]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[84]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[88]},
+ /* 16 */
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
+ {1.75251266e+02f, 6.12792168e+01f}, 4, &expected_segments[92]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
+ {1.85857864e+02f, 1.03705627e+02f}, 4, &expected_segments[96]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
+ {9.53481979e+01f, 3.80891479e+02f}, 4, &expected_segments[100]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
+ {1.05954803e+02f, 4.23317871e+02f}, 4, &expected_segments[104]},
+ /* 20 */
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[108]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[112]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[116]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[120]},
+ /* 24 */
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 16, &expected_segments[124]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 8, &expected_segments[140]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 16, &expected_segments[148]},
+ {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 8, &expected_segments[164]},
+ /* 28 */
+ {D2D1_FIGURE_BEGIN_HOLLOW, D2D1_FIGURE_END_OPEN, { 40.0f, 20.0f}, 2, &expected_segments[172]},
+ };
+
if (!(device = create_device()))
{
skip("Failed to create device, skipping tests.\n");
@@ -1778,21 +2177,47 @@ static void test_path_geometry(void)
ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
ID2D1GeometrySink_Release(sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
+ geometry_sink_cleanup(&simplify_sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
+ NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
+ geometry_sink_cleanup(&simplify_sink);
+
set_matrix_identity(&matrix);
translate_matrix(&matrix, 80.0f, 640.0f);
scale_matrix(&matrix, 1.0f, -1.0f);
hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
+ geometry_sink_cleanup(&simplify_sink);
+
ID2D1TransformedGeometry_GetSourceGeometry(transformed_geometry, &tmp_geometry);
ok(tmp_geometry == (ID2D1Geometry *)geometry,
"Got unexpected source geometry %p, expected %p.\n", tmp_geometry, geometry);
- ID2D1Geometry_Release(tmp_geometry);
ID2D1TransformedGeometry_GetTransform(transformed_geometry, &tmp_matrix);
ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
"Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1Geometry_Simplify(tmp_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ &tmp_matrix, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
+ geometry_sink_cleanup(&simplify_sink);
+ ID2D1Geometry_Release(tmp_geometry);
ID2D1RenderTarget_BeginDraw(rt);
set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
@@ -1845,6 +2270,13 @@ static void test_path_geometry(void)
ok(count == 44, "Got unexpected segment count %u.\n", count);
ID2D1GeometrySink_Release(sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 6, &expected_figures[0], 0);
+ geometry_sink_cleanup(&simplify_sink);
+
set_matrix_identity(&matrix);
translate_matrix(&matrix, 320.0f, 320.0f);
scale_matrix(&matrix, -1.0f, 1.0f);
@@ -1877,6 +2309,25 @@ static void test_path_geometry(void)
ok(count == 20, "Got unexpected segment count %u.\n", count);
ID2D1GeometrySink_Release(sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
+ NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[12], 1);
+ geometry_sink_cleanup(&simplify_sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[20], 1);
+ geometry_sink_cleanup(&simplify_sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[24], 1);
+ geometry_sink_cleanup(&simplify_sink);
+
set_matrix_identity(&matrix);
scale_matrix(&matrix, 0.5f, 2.0f);
translate_matrix(&matrix, 400.0f, -33.0f);
@@ -1885,6 +2336,13 @@ static void test_path_geometry(void)
hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
+ NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[16], 4);
+ geometry_sink_cleanup(&simplify_sink);
+
ID2D1RenderTarget_BeginDraw(rt);
ID2D1RenderTarget_Clear(rt, &color);
ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
@@ -1954,6 +2412,25 @@ static void test_path_geometry(void)
ok(count == 20, "Got unexpected segment count %u.\n", count);
ID2D1GeometrySink_Release(sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
+ NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[12], 1);
+ geometry_sink_cleanup(&simplify_sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[20], 1);
+ geometry_sink_cleanup(&simplify_sink);
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[24], 1);
+ geometry_sink_cleanup(&simplify_sink);
+
set_matrix_identity(&matrix);
scale_matrix(&matrix, 0.5f, 2.0f);
translate_matrix(&matrix, 127.0f, 80.0f);
@@ -2039,6 +2516,28 @@ static void test_path_geometry(void)
ok(match, "Surface does not match.\n");
ID2D1PathGeometry_Release(geometry);
+ hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
+ ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
+ hr = ID2D1PathGeometry_Open(geometry, &sink);
+ ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
+ set_point(&point, 40.0f, 20.0f);
+ ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
+ line_to(sink, 75.0f, 300.0f);
+ line_to(sink, 5.0f, 300.0f);
+ ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
+ hr = ID2D1GeometrySink_Close(sink);
+ ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
+ ID2D1GeometrySink_Release(sink);
+
+ geometry_sink_init(&simplify_sink);
+ hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
+ NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
+ ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
+ geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[28], 1);
+ geometry_sink_cleanup(&simplify_sink);
+
+ ID2D1PathGeometry_Release(geometry);
+
ID2D1SolidColorBrush_Release(brush);
ID2D1RenderTarget_Release(rt);
refcount = ID2D1Factory_Release(factory);
@@ -2049,80 +2548,6 @@ static void test_path_geometry(void)
DestroyWindow(window);
}
-#define geometry_sink_check(a, b, c, d, e) geometry_sink_check_(__LINE__, a, b, c, d, e)
-static void geometry_sink_check_(unsigned int line, const struct geometry_sink *sink, D2D1_FILL_MODE fill_mode,
- unsigned int figure_count, const struct expected_geometry_figure *expected_figures, unsigned int ulps)
-{
- const struct geometry_segment *segment, *expected_segment;
- const struct expected_geometry_figure *expected_figure;
- const struct geometry_figure *figure;
- unsigned int i, j;
- BOOL match;
-
- ok_(__FILE__, line)(sink->fill_mode == D2D1_FILL_MODE_ALTERNATE,
- "Got unexpected fill mode %#x.\n", sink->fill_mode);
- ok_(__FILE__, line)(sink->figure_count == 1, "Got unexpected figure count %u.\n", sink->figure_count);
- ok_(__FILE__, line)(!sink->closed, "Sink is closed.\n");
-
- for (i = 0; i < figure_count; ++i)
- {
- expected_figure = &expected_figures[i];
- figure = &sink->figures[i];
-
- ok_(__FILE__, line)(figure->begin == expected_figure->begin,
- "Got unexpected figure %u begin %#x, expected %#x.\n",
- i, figure->begin, expected_figure->begin);
- ok_(__FILE__, line)(figure->end == expected_figure->end,
- "Got unexpected figure %u end %#x, expected %#x.\n",
- i, figure->end, expected_figure->end);
- match = compare_point(&figure->start_point,
- expected_figure->start_point.x, expected_figure->start_point.y, ulps);
- ok_(__FILE__, line)(match, "Got unexpected figure %u start point {%.8e, %.8e}, expected {%.8e, %.8e}.\n",
- i, figure->start_point.x, figure->start_point.y,
- expected_figure->start_point.x, expected_figure->start_point.y);
- ok_(__FILE__, line)(figure->segment_count == expected_figure->segment_count,
- "Got unexpected figure %u segment count %u, expected %u.\n",
- i, figure->segment_count, expected_figure->segment_count);
-
- for (j = 0; j < figure->segment_count; ++j)
- {
- expected_segment = &expected_figure->segments[j];
- segment = &figure->segments[j];
- ok_(__FILE__, line)(segment->type == expected_segment->type,
- "Got unexpected figure %u, segment %u type %#x, expected %#x.\n",
- i, j, segment->type, expected_segment->type);
- switch (segment->type)
- {
- case SEGMENT_LINE:
- match = compare_point(&segment->u.line,
- expected_segment->u.line.x, expected_segment->u.line.y, ulps);
- ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u {%.8e, %.8e}, "
- "expected {%.8e, %.8e}.\n",
- i, j, segment->u.line.x, segment->u.line.y,
- expected_segment->u.line.x, expected_segment->u.line.y);
- break;
-
- case SEGMENT_BEZIER:
- match = compare_bezier_segment(&segment->u.bezier,
- expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
- expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
- expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y,
- ulps);
- ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u "
- "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, "
- "expected {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
- i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y,
- segment->u.bezier.point2.x, segment->u.bezier.point2.y,
- segment->u.bezier.point3.x, segment->u.bezier.point3.y,
- expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
- expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
- expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y);
- break;
- }
- }
- }
-}
-
static void test_rectangle_geometry(void)
{
ID2D1TransformedGeometry *transformed_geometry;
--
2.1.4
More information about the wine-patches
mailing list