On Tue, 21 Jan 2020 at 15:40, Giovanni Mascellani <gio(a)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?