[PATCH 2/3] d2d1: Implement rounded rectangle drawing.

Henri Verbeet hverbeet at gmail.com
Mon Jan 27 07:07:27 CST 2020


On Tue, 21 Jan 2020 at 15:40, Giovanni Mascellani <gio at debian.org> wrote:
> +static inline const char *debug_d2d_rounded_rect(const D2D1_ROUNDED_RECT *rounded_rect)
> +{
> +    if (!rounded_rect) return "(null)";
> +    return wine_dbg_sprintf("(%.8e,%.8e)-(%.8e,%.8e)[%.8e,%.8e]", rounded_rect->rect.left, rounded_rect->rect.top, rounded_rect->rect.right, rounded_rect->rect.bottom, rounded_rect->radiusX, rounded_rect->radiusY );

This line seems a bit on the long side. For reference, we try to stick
to 100-120 columns.

> +HRESULT d2d_rounded_rectangle_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, const D2D1_ROUNDED_RECT *rounded_rect)
> +{
> +    struct d2d_face *f;
> +    struct d2d_bezier_vertex *bv;
> +    D2D1_POINT_2F *v, v1, v2, v3, v4;
> +    float l, r, t, b;
> +    float rX, rY;
> +
> +    d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_rounded_rectangle_geometry_vtbl);
> +    geometry->u.rounded_rectangle.rounded_rect = *rounded_rect;
> +
> +    if (!(geometry->fill.vertices = heap_alloc(8 * sizeof(*geometry->fill.vertices))))
> +        goto fail;
> +    if (!d2d_array_reserve((void **)&geometry->fill.faces,
> +            &geometry->fill.faces_size, 6, sizeof(*geometry->fill.faces)))
> +        goto fail;
> +    if (!(geometry->fill.bezier_vertices = heap_alloc(12 * sizeof(*geometry->fill.bezier_vertices))))
> +        goto fail;
> +
> +    l = min(rounded_rect->rect.left, rounded_rect->rect.right);
> +    r = max(rounded_rect->rect.left, rounded_rect->rect.right);
> +    t = min(rounded_rect->rect.top, rounded_rect->rect.bottom);
> +    b = max(rounded_rect->rect.top, rounded_rect->rect.bottom);
> +
> +    rX = min(rounded_rect->radiusX, 0.5f*(r-l));
> +    rY = min(rounded_rect->radiusY, 0.5f*(b-t));
> +
> +    d2d_point_set(&v1, r, t);
> +    d2d_point_set(&v2, r, b);
> +    d2d_point_set(&v3, l, b);
> +    d2d_point_set(&v4, l, t);
> +
> +    v = geometry->fill.vertices;
> +    d2d_point_set(&v[0], l+rX, t);
> +    d2d_point_set(&v[1], r-rX, t);
> +    d2d_point_set(&v[2], r, t+rY);
> +    d2d_point_set(&v[3], r, b-rY);
> +    d2d_point_set(&v[4], r-rX, b);
> +    d2d_point_set(&v[5], l+rX, b);
> +    d2d_point_set(&v[6], l, b-rY);
> +    d2d_point_set(&v[7], l, t+rY);
> +    geometry->fill.vertex_count = 8;
> +
> +    f = geometry->fill.faces;
> +    d2d_face_set(&f[0], 0, 7, 6);
> +    d2d_face_set(&f[1], 0, 6, 5);
> +    d2d_face_set(&f[2], 0, 5, 4);
> +    d2d_face_set(&f[3], 0, 4, 1);
> +    d2d_face_set(&f[4], 1, 4, 3);
> +    d2d_face_set(&f[5], 1, 3, 2);
> +    geometry->fill.face_count = 6;
> +
> +    bv = geometry->fill.bezier_vertices;
> +    d2d_bezier_vertex_set(&bv[0], &v[1], 0.0f, 0.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[1], &v1, 0.5f, 0.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[2], &v[2], 1.0f, 1.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[3], &v[3], 0.0f, 0.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[4], &v2, 0.5f, 0.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[5], &v[4], 1.0f, 1.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[6], &v[5], 0.0f, 0.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[7], &v3, 0.5f, 0.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[8], &v[6], 1.0f, 1.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[9], &v[7], 0.0f, 0.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[10], &v4, 0.5f, 0.0f, -1.0f);
> +    d2d_bezier_vertex_set(&bv[11], &v[0], 1.0f, 1.0f, -1.0f);
> +    geometry->fill.bezier_vertex_count = 12;
> +
> +    if (!d2d_geometry_outline_add_line_segment(geometry, &v[0], &v[1]))
> +        goto fail;
> +    if (!d2d_geometry_outline_add_bezier_segment(geometry, &v[1], &v1, &v[2]))
> +        goto fail;
> +    if (!d2d_geometry_outline_add_line_segment(geometry, &v[2], &v[3]))
> +        goto fail;
> +    if (!d2d_geometry_outline_add_bezier_segment(geometry, &v[3], &v2, &v[4]))
> +        goto fail;
> +    if (!d2d_geometry_outline_add_line_segment(geometry, &v[4], &v[5]))
> +        goto fail;
> +    if (!d2d_geometry_outline_add_bezier_segment(geometry, &v[5], &v3, &v[6]))
> +        goto fail;
> +    if (!d2d_geometry_outline_add_line_segment(geometry, &v[6], &v[7]))
> +        goto fail;
> +    if (!d2d_geometry_outline_add_bezier_segment(geometry, &v[7], &v4, &v[0]))
> +        goto fail;
> +
> +    return S_OK;
> +
> +fail:
> +    d2d_geometry_cleanup(geometry);
> +    return E_OUTOFMEMORY;
> +}

It seems tempting to first approximate arc primitives on top of
beziers, and to then use those primitives here, instead of directly
using beziers here. Any reason not to?



More information about the wine-devel mailing list