[RFC PATCH 1/5] d2d1: Store cubic bezier control points.

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


Store cubic bezier control points, instead of storing them as
quadratics.

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

diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index c18b648aef..6f48980eb8 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -44,12 +44,17 @@ enum d2d_cdt_edge_next
     D2D_EDGE_NEXT_TOR = 3,
 };
 
+/* Flag bit for bezier vertices. */
+#define D2D_VERTEX_TYPE_SPLIT_BEZIER 0x40
+#define D2D_VERTEX_TYPE_BEZIER 0x80
 enum d2d_vertex_type
 {
-    D2D_VERTEX_TYPE_NONE,
-    D2D_VERTEX_TYPE_LINE,
-    D2D_VERTEX_TYPE_BEZIER,
-    D2D_VERTEX_TYPE_SPLIT_BEZIER,
+    D2D_VERTEX_TYPE_NONE = 0,
+    D2D_VERTEX_TYPE_LINE = 1,
+    D2D_VERTEX_TYPE_QUADRATIC_BEZIER = 2 | D2D_VERTEX_TYPE_BEZIER,
+    D2D_VERTEX_TYPE_CUBIC_BEZIER = 3 | D2D_VERTEX_TYPE_BEZIER,
+    D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER = 4 | D2D_VERTEX_TYPE_SPLIT_BEZIER,
+    D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER = 5 | D2D_VERTEX_TYPE_SPLIT_BEZIER,
 };
 
 struct d2d_segment_idx
@@ -57,6 +62,7 @@ struct d2d_segment_idx
     size_t figure_idx;
     size_t vertex_idx;
     size_t control_idx;
+    size_t bezier_idx;
 };
 
 struct d2d_figure
@@ -70,6 +76,7 @@ struct d2d_figure
     D2D1_POINT_2F *bezier_controls;
     size_t bezier_controls_size;
     size_t bezier_control_count;
+    size_t bezier_control_points;
 
     D2D1_POINT_2F *original_bezier_controls;
     size_t original_bezier_control_count;
@@ -409,6 +416,15 @@ static void d2d_point_normalise(D2D1_POINT_2F *p)
         d2d_point_scale(p, 1.0f / l);
 }
 
+static void d2d_bezier_cubic_to_quad(const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1,
+        const D2D1_POINT_2F *p2, const D2D1_POINT_2F *p3, D2D1_POINT_2F *c0)
+{
+    c0->x =  (p1->x + p2->x) * 0.75f;
+    c0->y =  (p1->y + p2->y) * 0.75f;
+    c0->x -= (p0->x + p3->x) * 0.25f;
+    c0->y -= (p0->y + p3->y) * 0.25f;
+}
+
 /* This implementation is based on the paper "Adaptive Precision
  * Floating-Point Arithmetic and Fast Robust Geometric Predicates" and
  * associated (Public Domain) code by Jonathan Richard Shewchuk. */
@@ -613,33 +629,35 @@ static BOOL d2d_figure_add_vertex(struct d2d_figure *figure, D2D1_POINT_2F verte
     return TRUE;
 }
 
-static BOOL d2d_figure_insert_bezier_control(struct d2d_figure *figure, size_t idx, const D2D1_POINT_2F *p)
+static BOOL d2d_figure_insert_quadratic_bezier_control(struct d2d_figure *figure, size_t idx, const D2D1_POINT_2F *p)
 {
     if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size,
-            figure->bezier_control_count + 1, sizeof(*figure->bezier_controls)))
+            figure->bezier_control_points + 1, sizeof(*figure->bezier_controls)))
     {
         ERR("Failed to grow bezier controls array.\n");
         return FALSE;
     }
 
     memmove(&figure->bezier_controls[idx + 1], &figure->bezier_controls[idx],
-            (figure->bezier_control_count - idx) * sizeof(*figure->bezier_controls));
+            (figure->bezier_control_points - idx) * sizeof(*figure->bezier_controls));
     figure->bezier_controls[idx] = *p;
+    ++figure->bezier_control_points;
     ++figure->bezier_control_count;
 
     return TRUE;
 }
 
-static BOOL d2d_figure_add_bezier_control(struct d2d_figure *figure, const D2D1_POINT_2F *p)
+static BOOL d2d_figure_add_quadratic_bezier_control(struct d2d_figure *figure, const D2D1_POINT_2F *p)
 {
     if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size,
-            figure->bezier_control_count + 1, sizeof(*figure->bezier_controls)))
+            figure->bezier_control_points + 1, sizeof(*figure->bezier_controls)))
     {
         ERR("Failed to grow bezier controls array.\n");
         return FALSE;
     }
 
-    figure->bezier_controls[figure->bezier_control_count++] = *p;
+    figure->bezier_controls[figure->bezier_control_points++] = *p;
+    ++figure->bezier_control_count;
 
     return TRUE;
 }
@@ -1875,7 +1893,7 @@ static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry,
 
         figure = &geometry->u.path.figures[inter->figure_idx];
         vertex_type = figure->vertex_types[inter->vertex_idx + vertex_offset];
-        if (vertex_type != D2D_VERTEX_TYPE_BEZIER && vertex_type != D2D_VERTEX_TYPE_SPLIT_BEZIER)
+        if (!(vertex_type & D2D_VERTEX_TYPE_BEZIER) && !(vertex_type & D2D_VERTEX_TYPE_SPLIT_BEZIER))
         {
             if (!d2d_figure_insert_vertex(&geometry->u.path.figures[inter->figure_idx],
                     inter->vertex_idx + vertex_offset + 1, inter->p))
@@ -1908,13 +1926,13 @@ static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry,
         d2d_point_lerp(&q[1], p[1], p[2], t);
 
         figure->bezier_controls[inter->control_idx + control_offset] = q[0];
-        if (!(d2d_figure_insert_bezier_control(figure, inter->control_idx + control_offset + 1, &q[1])))
+        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_BEZIER;
+        figure->vertex_types[inter->vertex_idx + vertex_offset + 1] = D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER;
         ++vertex_offset;
     }
 
@@ -1961,9 +1979,9 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry)
                 for (idx_q.vertex_idx = 0; idx_q.vertex_idx < max_q; ++idx_q.vertex_idx)
                 {
                     type_q = figure_q->vertex_types[idx_q.vertex_idx];
-                    if (type_q == D2D_VERTEX_TYPE_BEZIER)
+                    if (type_q & D2D_VERTEX_TYPE_BEZIER)
                     {
-                        if (type_p == D2D_VERTEX_TYPE_BEZIER)
+                        if (type_p & D2D_VERTEX_TYPE_BEZIER)
                         {
                             if (!d2d_geometry_intersect_bezier_bezier(geometry, &intersections,
                                     &idx_p, 0.0f, 1.0f, &idx_q, 0.0f, 1.0f))
@@ -1974,11 +1992,14 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry)
                             if (!d2d_geometry_intersect_bezier_line(geometry, &intersections, &idx_q, &idx_p))
                                 goto done;
                         }
-                        ++idx_q.control_idx;
+                        if (type_q == D2D_VERTEX_TYPE_QUADRATIC_BEZIER)
+                            ++idx_q.control_idx;
+                        else if (type_q == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+                            idx_q.control_idx += 2;
                     }
                     else
                     {
-                        if (type_p == D2D_VERTEX_TYPE_BEZIER)
+                        if (type_p & D2D_VERTEX_TYPE_BEZIER)
                         {
                             if (!d2d_geometry_intersect_bezier_line(geometry, &intersections, &idx_p, &idx_q))
                                 goto done;
@@ -1991,8 +2012,10 @@ static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry)
                     }
                 }
             }
-            if (type_p == D2D_VERTEX_TYPE_BEZIER)
+            if (type_p == D2D_VERTEX_TYPE_QUADRATIC_BEZIER)
                 ++idx_p.control_idx;
+            else if (type_p == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+                idx_p.control_idx += 2;
         }
     }
 
@@ -2328,27 +2351,30 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
         if (!i)
         {
             prev_type = figure->vertex_types[figure->vertex_count - 1];
-            if (prev_type == D2D_VERTEX_TYPE_BEZIER)
-                prev = &figure->bezier_controls[figure->bezier_control_count - 1];
+            if (prev_type & D2D_VERTEX_TYPE_BEZIER)
+                prev = &figure->bezier_controls[figure->bezier_control_points - 1];
             else
                 prev = &figure->vertices[figure->vertex_count - 1];
         }
         else
         {
             prev_type = figure->vertex_types[i - 1];
-            if (prev_type == D2D_VERTEX_TYPE_BEZIER)
+            if (prev_type & D2D_VERTEX_TYPE_BEZIER)
                 prev = &figure->bezier_controls[bezier_idx - 1];
             else
                 prev = &figure->vertices[i - 1];
         }
 
-        if (type == D2D_VERTEX_TYPE_BEZIER)
+        if (type & D2D_VERTEX_TYPE_BEZIER)
             next = &figure->bezier_controls[bezier_idx++];
         else if (i == figure->vertex_count - 1)
             next = &figure->vertices[0];
         else
             next = &figure->vertices[i + 1];
 
+        if (type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+            bezier_idx++;
+
         if (figure_end == D2D1_FIGURE_END_CLOSED || (i && i < figure->vertex_count - 1))
         {
             D2D1_POINT_2F q_next, q_prev;
@@ -2372,15 +2398,23 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
             ERR("Failed to add line segment.\n");
             return FALSE;
         }
-        else if (type == D2D_VERTEX_TYPE_BEZIER)
+        else if (type & D2D_VERTEX_TYPE_BEZIER)
         {
             const D2D1_POINT_2F *p2;
+            D2D1_POINT_2F tmp;
 
             if (i == figure->vertex_count - 1)
                 p2 = &figure->vertices[0];
             else
                 p2 = &figure->vertices[i + 1];
 
+            if (type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+            {
+                d2d_bezier_cubic_to_quad(p0, &figure->bezier_controls[bezier_idx - 2],
+                    &figure->bezier_controls[bezier_idx - 1], p2, &tmp);
+                next = &tmp;
+            }
+
             if (!d2d_geometry_outline_add_bezier_segment(geometry, p0, next, p2))
             {
                 ERR("Failed to add bezier segment.\n");
@@ -2581,12 +2615,12 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddBeziers(ID2D1GeometrySink *if
         p.y = (beziers[i].point1.y + beziers[i].point2.y) * 0.75f;
         p.x -= (figure->vertices[figure->vertex_count - 1].x + beziers[i].point3.x) * 0.25f;
         p.y -= (figure->vertices[figure->vertex_count - 1].y + beziers[i].point3.y) * 0.25f;
-        figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER;
+        figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_QUADRATIC_BEZIER;
 
         d2d_rect_get_bezier_bounds(&bezier_bounds, &figure->vertices[figure->vertex_count - 1],
                 &p, &beziers[i].point3);
 
-        if (!d2d_figure_add_bezier_control(figure, &p))
+        if (!d2d_figure_add_quadratic_bezier_control(figure, &p))
         {
             ERR("Failed to add bezier control.\n");
             geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
@@ -2659,23 +2693,31 @@ static void d2d_path_geometry_free_figures(struct d2d_geometry *geometry)
 
 static BOOL d2d_geometry_get_bezier_segment_idx(struct d2d_geometry *geometry, struct d2d_segment_idx *idx, BOOL next)
 {
+    struct d2d_figure *figure = &geometry->u.path.figures[idx->figure_idx];
+    enum d2d_vertex_type type = figure->vertex_types[idx->vertex_idx];
+
     if (next)
     {
+        if (type == D2D_VERTEX_TYPE_SPLIT_CUBIC_BEZIER || type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+            ++idx->control_idx;
+
         ++idx->vertex_idx;
         ++idx->control_idx;
+        ++idx->bezier_idx;
     }
 
-    for (; idx->figure_idx < geometry->u.path.figure_count; ++idx->figure_idx, idx->vertex_idx = idx->control_idx = 0)
+    for (; idx->figure_idx < geometry->u.path.figure_count; ++idx->figure_idx,
+            idx->vertex_idx = idx->control_idx = idx->bezier_idx = 0)
     {
-        struct d2d_figure *figure = &geometry->u.path.figures[idx->figure_idx];
+        figure = &geometry->u.path.figures[idx->figure_idx];
 
         if (!figure->bezier_control_count || figure->flags & D2D_FIGURE_FLAG_HOLLOW)
             continue;
 
         for (; idx->vertex_idx < figure->vertex_count; ++idx->vertex_idx)
         {
-            if (figure->vertex_types[idx->vertex_idx] == D2D_VERTEX_TYPE_BEZIER
-                    || figure->vertex_types[idx->vertex_idx] == D2D_VERTEX_TYPE_SPLIT_BEZIER)
+            type = figure->vertex_types[idx->vertex_idx];
+            if (type & D2D_VERTEX_TYPE_BEZIER || type & D2D_VERTEX_TYPE_SPLIT_BEZIER)
                 return TRUE;
         }
     }
@@ -2815,11 +2857,11 @@ static BOOL d2d_geometry_split_bezier(struct d2d_geometry *geometry, const struc
     d2d_point_lerp(&q[2], &q[0], &q[1], 0.5f);
 
     figure->bezier_controls[idx->control_idx] = q[0];
-    if (!(d2d_figure_insert_bezier_control(figure, idx->control_idx + 1, &q[1])))
+    if (!(d2d_figure_insert_quadratic_bezier_control(figure, idx->control_idx + 1, &q[1])))
         return FALSE;
     if (!(d2d_figure_insert_vertex(figure, idx->vertex_idx + 1, q[2])))
         return FALSE;
-    figure->vertex_types[idx->vertex_idx + 1] = D2D_VERTEX_TYPE_SPLIT_BEZIER;
+    figure->vertex_types[idx->vertex_idx + 1] = D2D_VERTEX_TYPE_SPLIT_QUAD_BEZIER;
 
     return TRUE;
 }
@@ -2867,7 +2909,7 @@ static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
     {
         if (geometry->u.path.figures[i].flags & D2D_FIGURE_FLAG_HOLLOW)
             continue;
-        geometry->fill.bezier_vertex_count += 3 * geometry->u.path.figures[i].bezier_control_count;
+        geometry->fill.bezier_vertex_count += 3 * geometry->u.path.figures[i].bezier_control_points;
     }
 
     if (!(geometry->fill.bezier_vertices = heap_calloc(geometry->fill.bezier_vertex_count,
@@ -2934,7 +2976,7 @@ static HRESULT STDMETHODCALLTYPE d2d_geometry_sink_Close(ID2D1GeometrySink *ifac
     for (i = 0; i < geometry->u.path.figure_count; ++i)
     {
         struct d2d_figure *figure = &geometry->u.path.figures[i];
-        size_t size = figure->bezier_control_count * sizeof(*figure->original_bezier_controls);
+        size_t size = figure->bezier_control_points * sizeof(*figure->original_bezier_controls);
         if (!(figure->original_bezier_controls = heap_alloc(size)))
             goto done;
         memcpy(figure->original_bezier_controls, figure->bezier_controls, size);
@@ -3002,8 +3044,8 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddQuadraticBeziers(ID2D1Geometr
         d2d_rect_get_bezier_bounds(&bezier_bounds, &figure->vertices[figure->vertex_count - 1],
                 &beziers[i].point1, &beziers[i].point2);
 
-        figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER;
-        if (!d2d_figure_add_bezier_control(figure, &beziers[i].point1))
+        figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_QUADRATIC_BEZIER;
+        if (!d2d_figure_add_quadratic_bezier_control(figure, &beziers[i].point1))
         {
             ERR("Failed to add bezier.\n");
             geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
@@ -3198,7 +3240,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
         for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j)
         {
             if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE
-                    || figure->vertex_types[j] == D2D_VERTEX_TYPE_SPLIT_BEZIER)
+                    || figure->vertex_types[j] & D2D_VERTEX_TYPE_SPLIT_BEZIER)
                 continue;
 
             switch (type)
@@ -3209,7 +3251,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
                     d2d_rect_expand(bounds, &p);
                     break;
 
-                case D2D_VERTEX_TYPE_BEZIER:
+                case D2D_VERTEX_TYPE_QUADRATIC_BEZIER:
                     p1 = figure->original_bezier_controls[bezier_idx++];
                     d2d_point_transform(&p1, transform, p1.x, p1.y);
                     p2 = figure->vertices[j];
@@ -3219,6 +3261,20 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
                     p = p2;
                     break;
 
+                case D2D_VERTEX_TYPE_CUBIC_BEZIER:
+                    d2d_bezier_cubic_to_quad(&figure->vertices[j - 1],
+                        &figure->original_bezier_controls[bezier_idx],
+                        &figure->original_bezier_controls[bezier_idx + 1],
+                        &figure->vertices[j], &p1);
+                    bezier_idx += 2;
+                    d2d_point_transform(&p1, transform, p1.x, p1.y);
+                    p2 = figure->vertices[j];
+                    d2d_point_transform(&p2, transform, p2.x, p2.y);
+                    d2d_rect_get_bezier_bounds(&bezier_bounds, &p, &p1, &p2);
+                    d2d_rect_union(bounds, &bezier_bounds);
+                    p = p2;
+                    break;
+
                 default:
                     FIXME("Unhandled vertex type %#x.\n", type);
                     p = figure->vertices[j];
@@ -3230,9 +3286,20 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry *
             type = figure->vertex_types[j];
         }
 
-        if (type == D2D_VERTEX_TYPE_BEZIER)
+        if (type & D2D_VERTEX_TYPE_BEZIER)
         {
-            p1 = figure->original_bezier_controls[bezier_idx++];
+            if (type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+            {
+                d2d_bezier_cubic_to_quad(&figure->vertices[j - 1],
+                    &figure->original_bezier_controls[bezier_idx],
+                    &figure->original_bezier_controls[bezier_idx + 1],
+                    &figure->vertices[0], &p1);
+
+                bezier_idx += 2;
+            }
+            else
+                p1 = figure->original_bezier_controls[bezier_idx++];
+
             d2d_point_transform(&p1, transform, p1.x, p1.y);
             p2 = figure->vertices[0];
             d2d_point_transform(&p2, transform, p2.x, p2.y);
@@ -3365,6 +3432,23 @@ static void d2d_geometry_simplify_quadratic(ID2D1SimplifiedGeometrySink *sink,
         ID2D1SimplifiedGeometrySink_AddBeziers(sink, &b, 1);
 }
 
+static void d2d_geometry_simplify_cubic(ID2D1SimplifiedGeometrySink *sink,
+        D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_POINT_2F *p0,
+        const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, const D2D1_POINT_2F *p3,
+        float tolerance)
+{
+    D2D1_BEZIER_SEGMENT b;
+
+    b.point1 = *p1;
+    b.point2 = *p2;
+    b.point3 = *p3;
+
+    if (option == D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES)
+        d2d_geometry_flatten_cubic(sink, p0, &b, tolerance);
+    else
+        ID2D1SimplifiedGeometrySink_AddBeziers(sink, &b, 1);
+}
+
 static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *iface,
         D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance,
         ID2D1SimplifiedGeometrySink *sink)
@@ -3373,7 +3457,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
     enum d2d_vertex_type type = D2D_VERTEX_TYPE_NONE;
     unsigned int i, j, bezier_idx;
     D2D1_FIGURE_BEGIN begin;
-    D2D1_POINT_2F p, p1, p2;
+    D2D1_POINT_2F p, p1, p2, p3;
     D2D1_FIGURE_END end;
 
     TRACE("iface %p, option %#x, transform %p, tolerance %.8e, sink %p.\n",
@@ -3401,7 +3485,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
         for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j)
         {
             if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE
-                    || figure->vertex_types[j] == D2D_VERTEX_TYPE_SPLIT_BEZIER)
+                    || figure->vertex_types[j] & D2D_VERTEX_TYPE_SPLIT_BEZIER)
                 continue;
 
             switch (type)
@@ -3413,7 +3497,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
                     ID2D1SimplifiedGeometrySink_AddLines(sink, &p, 1);
                     break;
 
-                case D2D_VERTEX_TYPE_BEZIER:
+                case D2D_VERTEX_TYPE_QUADRATIC_BEZIER:
                     p1 = figure->original_bezier_controls[bezier_idx++];
                     if (transform)
                         d2d_point_transform(&p1, transform, p1.x, p1.y);
@@ -3424,6 +3508,20 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
                     p = p2;
                     break;
 
+                case D2D_VERTEX_TYPE_CUBIC_BEZIER:
+                    p1 = figure->original_bezier_controls[bezier_idx++];
+                    if (transform)
+                        d2d_point_transform(&p1, transform, p1.x, p1.y);
+                    p2 = figure->original_bezier_controls[bezier_idx++];
+                    if (transform)
+                        d2d_point_transform(&p2, transform, p2.x, p2.y);
+                    p3 = figure->vertices[j];
+                    if (transform)
+                        d2d_point_transform(&p3, transform, p3.x, p3.y);
+                    d2d_geometry_simplify_cubic(sink, option, &p, &p1, &p2, &p3, tolerance);
+                    p = p3;
+                    break;
+
                 default:
                     FIXME("Unhandled vertex type %#x.\n", type);
                     p = figure->vertices[j];
@@ -3436,7 +3534,7 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
             type = figure->vertex_types[j];
         }
 
-        if (type == D2D_VERTEX_TYPE_BEZIER)
+        if (type == D2D_VERTEX_TYPE_QUADRATIC_BEZIER)
         {
             p1 = figure->original_bezier_controls[bezier_idx++];
             if (transform)
@@ -3446,6 +3544,19 @@ static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry *i
                 d2d_point_transform(&p2, transform, p2.x, p2.y);
             d2d_geometry_simplify_quadratic(sink, option, &p, &p1, &p2, tolerance);
         }
+        else if (type == D2D_VERTEX_TYPE_CUBIC_BEZIER)
+        {
+            p1 = figure->original_bezier_controls[bezier_idx++];
+            if (transform)
+                d2d_point_transform(&p1, transform, p1.x, p1.y);
+            p2 = figure->original_bezier_controls[bezier_idx++];
+            if (transform)
+                d2d_point_transform(&p2, transform, p2.x, p2.y);
+            p3 = figure->vertices[0];
+            if (transform)
+                d2d_point_transform(&p3, transform, p3.x, p3.y);
+            d2d_geometry_simplify_cubic(sink, option, &p, &p1, &p2, &p3, tolerance);
+        }
 
         end = figure->flags & D2D_FIGURE_FLAG_CLOSED ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN;
         ID2D1SimplifiedGeometrySink_EndFigure(sink, end);
-- 
2.20.1




More information about the wine-devel mailing list