[RFC PATCH 5/5] d2d1: Update apply_intersections for cubic beziers.

Connor McAdams conmanx360 at gmail.com
Sun Mar 15 14:42:58 CDT 2020


Signed-off-by: Connor McAdams <conmanx360 at gmail.com>
---
 dlls/d2d1/geometry.c | 84 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 66 insertions(+), 18 deletions(-)

diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index dd6f50bbec..154741a364 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -830,6 +830,26 @@ static BOOL d2d_figure_add_quadratic_bezier_control(struct d2d_figure *figure, c
     return TRUE;
 }
 
+static BOOL d2d_figure_insert_cubic_bezier_control(struct d2d_figure *figure, size_t idx, const D2D1_POINT_2F *c0,
+        const D2D1_POINT_2F *c1)
+{
+    if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size,
+            figure->bezier_control_points + 2, sizeof(*figure->bezier_controls)))
+    {
+        ERR("Failed to grow bezier controls array.\n");
+        return FALSE;
+    }
+
+    memmove(&figure->bezier_controls[idx + 2], &figure->bezier_controls[idx],
+            (figure->bezier_control_count - idx) * sizeof(*figure->bezier_controls));
+    figure->bezier_controls[idx] = *c0;
+    figure->bezier_controls[idx + 1] = *c1;
+    figure->bezier_control_points += 2;
+    ++figure->bezier_control_count;
+
+    return TRUE;
+}
+
 static void d2d_cdt_edge_rot(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
 {
     dst->idx = src->idx;
@@ -2237,8 +2257,9 @@ static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry,
     size_t vertex_offset, control_offset, next, i;
     struct d2d_geometry_intersection *inter;
     enum d2d_vertex_type vertex_type;
-    const D2D1_POINT_2F *p[3];
+    const D2D1_POINT_2F *p[4];
     struct d2d_figure *figure;
+    D2D1_BEZIER_SEGMENT left, right;
     D2D1_POINT_2F q[2];
     float t, t_prev;
 
@@ -2272,25 +2293,52 @@ static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry,
             t = (t - t_prev) / (1.0f - t_prev);
         }
 
-        p[0] = &figure->vertices[inter->vertex_idx + vertex_offset];
-        p[1] = &figure->bezier_controls[inter->control_idx + control_offset];
-        next = inter->vertex_idx + vertex_offset + 1;
-        if (next == figure->vertex_count)
-            next = 0;
-        p[2] = &figure->vertices[next];
-
-        d2d_point_lerp(&q[0], p[0], p[1], t);
-        d2d_point_lerp(&q[1], p[1], p[2], t);
+        if (vertex_type == D2D_VERTEX_TYPE_CUBIC_BEZIER || vertex_type == D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER)
+        {
+            p[0] = &figure->vertices[inter->vertex_idx + vertex_offset];
+            p[1] = &figure->bezier_controls[inter->control_idx + control_offset];
+            p[2] = &figure->bezier_controls[inter->control_idx + control_offset + 1];
+            next = inter->vertex_idx + vertex_offset + 1;
+            if (next == figure->vertex_count)
+                next = 0;
+            p[3] = &figure->vertices[next];
+
+            d2d_bezier_split_cubic(p[0], p[1], p[2], p[3], t, &left, &right, NULL);
+
+            figure->bezier_controls[inter->control_idx + control_offset] = left.point1;
+            figure->bezier_controls[inter->control_idx + control_offset + 1] = left.point2;
+            if (!(d2d_figure_insert_cubic_bezier_control(figure, inter->control_idx + control_offset + 1, &right.point1,
+                            &right.point2)))
+                return FALSE;
+            control_offset += 2;
 
-        figure->bezier_controls[inter->control_idx + control_offset] = q[0];
-        if (!(d2d_figure_insert_quadratic_bezier_control(figure, inter->control_idx + control_offset + 1, &q[1])))
-            return FALSE;
-        ++control_offset;
+            if (!(d2d_figure_insert_vertex(figure, inter->vertex_idx + vertex_offset + 1, inter->p)))
+                return FALSE;
+            figure->vertex_types[inter->vertex_idx + vertex_offset + 1] = D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER;
+            ++vertex_offset;
+        }
+        else
+        {
+            p[0] = &figure->vertices[inter->vertex_idx + vertex_offset];
+            p[1] = &figure->bezier_controls[inter->control_idx + control_offset];
+            next = inter->vertex_idx + vertex_offset + 1;
+            if (next == figure->vertex_count)
+                next = 0;
+            p[2] = &figure->vertices[next];
+
+            d2d_point_lerp(&q[0], p[0], p[1], t);
+            d2d_point_lerp(&q[1], p[1], p[2], t);
+
+            figure->bezier_controls[inter->control_idx + control_offset] = q[0];
+            if (!(d2d_figure_insert_quadratic_bezier_control(figure, inter->control_idx + control_offset + 1, &q[1])))
+                return FALSE;
+            ++control_offset;
 
-        if (!(d2d_figure_insert_vertex(figure, inter->vertex_idx + vertex_offset + 1, inter->p)))
-            return FALSE;
-        figure->vertex_types[inter->vertex_idx + vertex_offset + 1] = D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER;
-        ++vertex_offset;
+            if (!(d2d_figure_insert_vertex(figure, inter->vertex_idx + vertex_offset + 1, inter->p)))
+                return FALSE;
+            figure->vertex_types[inter->vertex_idx + vertex_offset + 1] = D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER;
+            ++vertex_offset;
+        }
     }
 
     return TRUE;
-- 
2.20.1




More information about the wine-devel mailing list