Commit 873e3d06 authored by Giovanni Mascellani's avatar Giovanni Mascellani Committed by Alexandre Julliard

d2d1: Implement ellipse and rounded rectangle stroking with arcs.

parent a6bf2c42
...@@ -45,6 +45,7 @@ enum d2d_shape_type ...@@ -45,6 +45,7 @@ enum d2d_shape_type
{ {
D2D_SHAPE_TYPE_OUTLINE, D2D_SHAPE_TYPE_OUTLINE,
D2D_SHAPE_TYPE_BEZIER_OUTLINE, D2D_SHAPE_TYPE_BEZIER_OUTLINE,
D2D_SHAPE_TYPE_ARC_OUTLINE,
D2D_SHAPE_TYPE_TRIANGLE, D2D_SHAPE_TYPE_TRIANGLE,
D2D_SHAPE_TYPE_CURVE, D2D_SHAPE_TYPE_CURVE,
D2D_SHAPE_TYPE_COUNT, D2D_SHAPE_TYPE_COUNT,
...@@ -415,7 +416,7 @@ struct d2d_outline_vertex ...@@ -415,7 +416,7 @@ struct d2d_outline_vertex
D2D1_POINT_2F next; D2D1_POINT_2F next;
}; };
struct d2d_bezier_outline_vertex struct d2d_curve_outline_vertex
{ {
D2D1_POINT_2F position; D2D1_POINT_2F position;
D2D1_POINT_2F p0, p1, p2; D2D1_POINT_2F p0, p1, p2;
...@@ -459,13 +460,21 @@ struct d2d_geometry ...@@ -459,13 +460,21 @@ struct d2d_geometry
size_t faces_size; size_t faces_size;
size_t face_count; size_t face_count;
struct d2d_bezier_outline_vertex *beziers; struct d2d_curve_outline_vertex *beziers;
size_t beziers_size; size_t beziers_size;
size_t bezier_count; size_t bezier_count;
struct d2d_face *bezier_faces; struct d2d_face *bezier_faces;
size_t bezier_faces_size; size_t bezier_faces_size;
size_t bezier_face_count; size_t bezier_face_count;
struct d2d_curve_outline_vertex *arcs;
size_t arcs_size;
size_t arc_count;
struct d2d_face *arc_faces;
size_t arc_faces_size;
size_t arc_face_count;
} outline; } outline;
union union
......
...@@ -153,16 +153,16 @@ static void d2d_outline_vertex_set(struct d2d_outline_vertex *v, float x, float ...@@ -153,16 +153,16 @@ static void d2d_outline_vertex_set(struct d2d_outline_vertex *v, float x, float
d2d_point_set(&v->next, next_x, next_y); d2d_point_set(&v->next, next_x, next_y);
} }
static void d2d_bezier_outline_vertex_set(struct d2d_bezier_outline_vertex *b, const D2D1_POINT_2F *position, static void d2d_curve_outline_vertex_set(struct d2d_curve_outline_vertex *a, const D2D1_POINT_2F *position,
const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2,
float prev_x, float prev_y, float next_x, float next_y) float prev_x, float prev_y, float next_x, float next_y)
{ {
b->position = *position; a->position = *position;
b->p0 = *p0; a->p0 = *p0;
b->p1 = *p1; a->p1 = *p1;
b->p2 = *p2; a->p2 = *p2;
d2d_point_set(&b->prev, prev_x, prev_y); d2d_point_set(&a->prev, prev_x, prev_y);
d2d_point_set(&b->next, next_x, next_y); d2d_point_set(&a->next, next_x, next_y);
} }
static void d2d_fp_two_sum(float *out, float a, float b) static void d2d_fp_two_sum(float *out, float a, float b)
...@@ -2197,7 +2197,7 @@ static BOOL d2d_geometry_outline_add_line_segment(struct d2d_geometry *geometry, ...@@ -2197,7 +2197,7 @@ static BOOL d2d_geometry_outline_add_line_segment(struct d2d_geometry *geometry,
static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometry, static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometry,
const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2) const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
{ {
struct d2d_bezier_outline_vertex *b; struct d2d_curve_outline_vertex *b;
D2D1_POINT_2F r0, r1, r2; D2D1_POINT_2F r0, r1, r2;
D2D1_POINT_2F q0, q1, q2; D2D1_POINT_2F q0, q1, q2;
struct d2d_face *f; struct d2d_face *f;
...@@ -2239,13 +2239,13 @@ static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometr ...@@ -2239,13 +2239,13 @@ static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometr
d2d_point_scale(&r2, -1.0f); d2d_point_scale(&r2, -1.0f);
} }
d2d_bezier_outline_vertex_set(&b[0], p0, p0, p1, p2, r0.x, r0.y, r0.x, r0.y); d2d_curve_outline_vertex_set(&b[0], p0, p0, p1, p2, r0.x, r0.y, r0.x, r0.y);
d2d_bezier_outline_vertex_set(&b[1], p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y); d2d_curve_outline_vertex_set(&b[1], p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y);
d2d_bezier_outline_vertex_set(&b[2], &q0, p0, p1, p2, r0.x, r0.y, r1.x, r1.y); d2d_curve_outline_vertex_set(&b[2], &q0, p0, p1, p2, r0.x, r0.y, r1.x, r1.y);
d2d_bezier_outline_vertex_set(&b[3], &q2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y); d2d_curve_outline_vertex_set(&b[3], &q2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y);
d2d_bezier_outline_vertex_set(&b[4], &q1, p0, p1, p2, r1.x, r1.y, r2.x, r2.y); d2d_curve_outline_vertex_set(&b[4], &q1, p0, p1, p2, r1.x, r1.y, r2.x, r2.y);
d2d_bezier_outline_vertex_set(&b[5], p2, p0, p1, p2, -r2.x, -r2.y, -r2.x, -r2.y); d2d_curve_outline_vertex_set(&b[5], p2, p0, p1, p2, -r2.x, -r2.y, -r2.x, -r2.y);
d2d_bezier_outline_vertex_set(&b[6], p2, p0, p1, p2, r2.x, r2.y, r2.x, r2.y); d2d_curve_outline_vertex_set(&b[6], p2, p0, p1, p2, r2.x, r2.y, r2.x, r2.y);
geometry->outline.bezier_count += 7; geometry->outline.bezier_count += 7;
d2d_face_set(&f[0], base_idx + 0, base_idx + 1, base_idx + 2); d2d_face_set(&f[0], base_idx + 0, base_idx + 1, base_idx + 2);
...@@ -2261,9 +2261,53 @@ static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometr ...@@ -2261,9 +2261,53 @@ static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometr
static BOOL d2d_geometry_outline_add_arc_quadrant(struct d2d_geometry *geometry, static BOOL d2d_geometry_outline_add_arc_quadrant(struct d2d_geometry *geometry,
const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2) const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
{ {
FIXME("Approximating arc quadrant with Bezier curve.\n"); struct d2d_curve_outline_vertex *a;
D2D1_POINT_2F r0, r1;
struct d2d_face *f;
size_t base_idx;
if (!d2d_array_reserve((void **)&geometry->outline.arcs, &geometry->outline.arcs_size,
geometry->outline.arc_count + 5, sizeof(*geometry->outline.arcs)))
{
ERR("Failed to grow outline arcs array.\n");
return FALSE;
}
base_idx = geometry->outline.arc_count;
a = &geometry->outline.arcs[base_idx];
if (!d2d_array_reserve((void **)&geometry->outline.arc_faces, &geometry->outline.arc_faces_size,
geometry->outline.arc_face_count + 3, sizeof(*geometry->outline.arc_faces)))
{
ERR("Failed to grow outline faces array.\n");
return FALSE;
}
f = &geometry->outline.arc_faces[geometry->outline.arc_face_count];
d2d_point_subtract(&r0, p1, p0);
d2d_point_subtract(&r1, p2, p1);
d2d_point_normalise(&r0);
d2d_point_normalise(&r1);
return d2d_geometry_outline_add_bezier_segment(geometry, p0, p1, p2); if (d2d_point_ccw(p0, p1, p2) > 0.0f)
{
d2d_point_scale(&r0, -1.0f);
d2d_point_scale(&r1, -1.0f);
}
d2d_curve_outline_vertex_set(&a[0], p0, p0, p1, p2, r0.x, r0.y, r0.x, r0.y);
d2d_curve_outline_vertex_set(&a[1], p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y);
d2d_curve_outline_vertex_set(&a[2], p1, p0, p1, p2, r0.x, r0.y, r1.x, r1.y);
d2d_curve_outline_vertex_set(&a[3], p2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y);
d2d_curve_outline_vertex_set(&a[4], p2, p0, p1, p2, r1.x, r1.y, r1.x, r1.y);
geometry->outline.arc_count += 5;
d2d_face_set(&f[0], base_idx + 0, base_idx + 1, base_idx + 2);
d2d_face_set(&f[1], base_idx + 2, base_idx + 1, base_idx + 3);
d2d_face_set(&f[2], base_idx + 2, base_idx + 4, base_idx + 3);
geometry->outline.arc_face_count += 3;
return TRUE;
} }
static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry, static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
...@@ -2368,6 +2412,8 @@ static BOOL d2d_geometry_fill_add_arc_triangle(struct d2d_geometry *geometry, ...@@ -2368,6 +2412,8 @@ static BOOL d2d_geometry_fill_add_arc_triangle(struct d2d_geometry *geometry,
static void d2d_geometry_cleanup(struct d2d_geometry *geometry) static void d2d_geometry_cleanup(struct d2d_geometry *geometry)
{ {
heap_free(geometry->outline.arc_faces);
heap_free(geometry->outline.arcs);
heap_free(geometry->outline.bezier_faces); heap_free(geometry->outline.bezier_faces);
heap_free(geometry->outline.beziers); heap_free(geometry->outline.beziers);
heap_free(geometry->outline.faces); heap_free(geometry->outline.faces);
...@@ -4519,6 +4565,8 @@ static ULONG STDMETHODCALLTYPE d2d_transformed_geometry_Release(ID2D1Transformed ...@@ -4519,6 +4565,8 @@ static ULONG STDMETHODCALLTYPE d2d_transformed_geometry_Release(ID2D1Transformed
if (!refcount) if (!refcount)
{ {
geometry->outline.arc_faces = NULL;
geometry->outline.arcs = NULL;
geometry->outline.bezier_faces = NULL; geometry->outline.bezier_faces = NULL;
geometry->outline.beziers = NULL; geometry->outline.beziers = NULL;
geometry->outline.faces = NULL; geometry->outline.faces = NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment