From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/geometry.c | 75 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 2 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index 9867e6171e7..09c6fbcc956 100644 --- a/dlls/d2d1/geometry.c +++ b/dlls/d2d1/geometry.c @@ -4089,10 +4089,81 @@ static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_Simplify(ID2D1EllipseGeome 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_ID2D1EllipseGeometry(iface); + const D2D1_ELLIPSE *ellipse = &geometry->u.ellipse.ellipse; + struct d2d_figure figure = { 0 }; + D2D1_BEZIER_SEGMENT segments[4]; + D2D1_POINT_2F start_point; + D2D1_MATRIX_3X2_F m; + unsigned int i; + float coeff; + + TRACE("iface %p, option %#x, transform %p, tolerance %.8e, sink %p.\n", iface, option, transform, tolerance, sink);
- return E_NOTIMPL; + /* Use four Bézier segments to approximate a unit circle. + Endpoints tangents are tangential to the circle. Endpoints and the midpoint + are lying on the circle. */ + coeff = 4.0f * (M_SQRT2 - 1.0f) / 3.0f; + + start_point.x = -1.0f; + start_point.y = 0.0f; + + segments[0].point1.x = -1.0f; + segments[0].point1.y = -coeff; + segments[0].point2.x = -coeff; + segments[0].point2.y = -1.0f; + segments[0].point3.x = 0.0f; + segments[0].point3.y = -1.0f; + + segments[1].point1.x = coeff; + segments[1].point1.y = -1.0f; + segments[1].point2.x = 1.0f; + segments[1].point2.y = -coeff; + segments[1].point3.x = 1.0f; + segments[1].point3.y = 0.0f; + + segments[2].point1.x = 1.0f; + segments[2].point1.y = coeff; + segments[2].point2.x = coeff; + segments[2].point2.y = 1.0f; + segments[2].point3.x = 0.0f; + segments[2].point3.y = 1.0f; + + segments[3].point1.x = -coeff; + segments[3].point1.y = 1.0f; + segments[3].point2.x = -1.0f; + segments[3].point2.y = coeff; + segments[3].point3 = start_point; + + m._11 = ellipse->radiusX; + m._12 = 0.0f; + m._21 = 0.0f; + m._22 = ellipse->radiusY; + m._31 = ellipse->point.x; + m._32 = ellipse->point.y; + + d2d_point_transform(&start_point, &m, start_point.x, start_point.y); + for (i = 0; i < ARRAY_SIZE(segments); ++i) + { + d2d_point_transform(&segments[i].point1, &m, segments[i].point1.x, segments[i].point1.y); + d2d_point_transform(&segments[i].point2, &m, segments[i].point2.x, segments[i].point2.y); + d2d_point_transform(&segments[i].point3, &m, segments[i].point3.x, segments[i].point3.y); + } + + if (!d2d_figure_begin(&figure, start_point, D2D1_FIGURE_BEGIN_FILLED)) + return E_OUTOFMEMORY; + if (!d2d_figure_add_beziers(&figure, segments, ARRAY_SIZE(segments))) + { + d2d_figure_cleanup(&figure); + return E_OUTOFMEMORY; + } + d2d_figure_end(&figure, D2D1_FIGURE_END_CLOSED); + + d2d_figure_simplify(&figure, option, transform, tolerance, sink); + d2d_figure_cleanup(&figure); + + return S_OK; }
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_Tessellate(ID2D1EllipseGeometry *iface,