Signed-off-by: Connor McAdams conmanx360@gmail.com --- dlls/d2d1/geometry.c | 69 +++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 29 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index b1d22d7264..5fe33246b2 100644 --- a/dlls/d2d1/geometry.c +++ b/dlls/d2d1/geometry.c @@ -732,8 +732,9 @@ static void d2d_rect_get_cubic_bezier_bounds(D2D_RECT_F *bounds, const D2D1_POIN } }
-static void d2d_rect_get_bezier_segment_bounds(D2D_RECT_F *bounds, const D2D1_POINT_2F *p0, - const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, float start, float end) +static void d2d_rect_get_quadratic_bezier_segment_bounds(D2D_RECT_F *bounds, + const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, + float start, float end) { D2D1_POINT_2F q[3], r[2];
@@ -749,6 +750,21 @@ static void d2d_rect_get_bezier_segment_bounds(D2D_RECT_F *bounds, const D2D1_PO d2d_rect_get_quadratic_bezier_bounds(bounds, &q[0], &q[1], &q[2]); }
+static void d2d_rect_get_cubic_bezier_segment_bounds(D2D_RECT_F *bounds, + const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, + const D2D1_POINT_2F *p3, float start, float end) +{ + D2D1_BEZIER_SEGMENT left, right; + D2D1_POINT_2F mid; + + d2d_bezier_split_cubic(p0, p1, p2, p3, start, NULL, &right, &mid); + + end = (end - start) / (1.0f - start); + d2d_bezier_split_cubic(&mid, &right.point1, &right.point2, p3, end, &left, NULL, NULL); + + d2d_rect_get_cubic_bezier_bounds(bounds, &mid, &left.point1, &left.point2, &left.point3); +} + static BOOL d2d_figure_insert_vertex(struct d2d_figure *figure, size_t idx, D2D1_POINT_2F vertex) { if (!d2d_array_reserve((void **)&figure->vertices, &figure->vertices_size, @@ -2035,10 +2051,10 @@ static BOOL d2d_geometry_intersect_bezier_bezier(struct d2d_geometry *geometry, const struct d2d_segment_idx *idx_p, float start_p, float end_p, const struct d2d_segment_idx *idx_q, float start_q, float end_q) { - const D2D1_POINT_2F *p[3], *q[3]; + const D2D1_POINT_2F *p[4], *q[4]; const struct d2d_figure *figure; D2D_RECT_F p_bounds, q_bounds; - D2D1_POINT_2F intersection, tmp_p, tmp_q; + D2D1_POINT_2F intersection; enum d2d_vertex_type type_p, type_q; float centre_p, centre_q; size_t next; @@ -2046,43 +2062,34 @@ static BOOL d2d_geometry_intersect_bezier_bezier(struct d2d_geometry *geometry, figure = &geometry->u.path.figures[idx_p->figure_idx]; type_p = figure->vertex_types[idx_p->vertex_idx]; p[0] = &figure->vertices[idx_p->vertex_idx]; + p[1] = &figure->bezier_controls[idx_p->control_idx]; + if (type_p == D2D_VERTEX_TYPE_CUBIC_BEZIER) + p[2] = &figure->bezier_controls[idx_p->control_idx + 1]; next = idx_p->vertex_idx + 1; if (next == figure->vertex_count) next = 0; - p[2] = &figure->vertices[next]; - if (d2d_vertex_type_is_cubic_bezier(type_p)) - { - d2d_bezier_cubic_to_quad(p[0], - &figure->bezier_controls[idx_p->control_idx], - &figure->bezier_controls[idx_p->control_idx + 1], - p[2], &tmp_p); - - p[1] = &tmp_p; - } - else - p[1] = &figure->bezier_controls[idx_p->control_idx]; + p[3] = &figure->vertices[next];
figure = &geometry->u.path.figures[idx_q->figure_idx]; type_q = figure->vertex_types[idx_q->vertex_idx]; q[0] = &figure->vertices[idx_q->vertex_idx]; + q[1] = &figure->bezier_controls[idx_q->control_idx]; + if (type_q == D2D_VERTEX_TYPE_CUBIC_BEZIER) + q[2] = &figure->bezier_controls[idx_q->control_idx + 1]; next = idx_q->vertex_idx + 1; if (next == figure->vertex_count) next = 0; - q[2] = &figure->vertices[next]; - if (d2d_vertex_type_is_cubic_bezier(type_q)) - { - d2d_bezier_cubic_to_quad(q[0], - &figure->bezier_controls[idx_q->control_idx], - &figure->bezier_controls[idx_q->control_idx + 1], - q[2], &tmp_q); + q[3] = &figure->vertices[next];
- q[1] = &tmp_q; - } + if (type_p == D2D_VERTEX_TYPE_CUBIC_BEZIER) + d2d_rect_get_cubic_bezier_segment_bounds(&p_bounds, p[0], p[1], p[2], p[3], start_p, end_p); else - q[1] = &figure->bezier_controls[idx_q->control_idx]; + d2d_rect_get_quadratic_bezier_segment_bounds(&p_bounds, p[0], p[1], p[3], start_p, end_p);
- d2d_rect_get_bezier_segment_bounds(&p_bounds, p[0], p[1], p[2], start_p, end_p); - d2d_rect_get_bezier_segment_bounds(&q_bounds, q[0], q[1], q[2], start_q, end_q); + if (type_q == D2D_VERTEX_TYPE_CUBIC_BEZIER) + d2d_rect_get_cubic_bezier_segment_bounds(&q_bounds, q[0], q[1], q[2], q[3], start_q, end_q); + else + d2d_rect_get_quadratic_bezier_segment_bounds(&q_bounds, q[0], q[1], q[3], start_q, end_q);
if (!d2d_rect_check_overlap(&p_bounds, &q_bounds)) return TRUE; @@ -2092,7 +2099,11 @@ static BOOL d2d_geometry_intersect_bezier_bezier(struct d2d_geometry *geometry,
if (end_p - start_p < 1e-3f) { - d2d_point_calculate_quadratic_bezier(&intersection, p[0], p[1], p[2], centre_p); + if (type_p == D2D_VERTEX_TYPE_CUBIC_BEZIER) + d2d_point_calculate_cubic_bezier(&intersection, p[0], p[1], p[2], p[3], centre_p); + else + d2d_point_calculate_quadratic_bezier(&intersection, p[0], p[1], p[3], centre_p); + if (start_p > 0.0f && end_p < 1.0f && !d2d_geometry_intersections_add(intersections, idx_p, centre_p, intersection)) return FALSE;