[PATCH 08/12] d2d1: Add function for getting figure orientation.

Connor McAdams conmanx360 at gmail.com
Mon Feb 24 20:32:19 CST 2020


Add a function for getting figure orientation to find the correct fill
side of a cubic bezier.

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

diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index c9ea108484..a231bed986 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -2915,11 +2915,19 @@ struct d2d_cubic_triangles
     D2D1_POINT_2F p[4];
 };
 
+enum figure_orientation
+{
+    ORIENTATION_CW,  /* Clockwise. */
+    ORIENTATION_CCW, /* Counter clockwise. */
+};
+
 struct d2d_cubic_triangulation
 {
     struct d2d_cubic_triangles *cubic_tri;
     size_t cubic_tri_count;
     size_t cubic_tri_size;
+
+    unsigned int orientation;
 };
 
 static BOOL d2d_point_approximately_equal(const D2D1_POINT_2F *a, const D2D1_POINT_2F *b)
@@ -3151,6 +3159,69 @@ static HRESULT d2d_geometry_triangulate_beziers(struct d2d_geometry *geometry,
     return S_OK;
 }
 
+static float d2d_geometry_point_orientation(const D2D1_POINT_2F *a, const D2D1_POINT_2F *b)
+{
+    return (b->x - a->x) * (b->y + a->y);
+}
+
+static void d2d_geometry_get_figure_orientation(struct d2d_geometry *geometry,
+        struct d2d_cubic_triangulation *triangles)
+{
+    const struct d2d_figure *figure;
+    struct d2d_segment_idx idx;
+    struct d2d_cubic_triangulation *fig_tri;
+    enum d2d_vertex_type type;
+    const D2D1_POINT_2F *p[4];
+    float orientation;
+    size_t next;
+    unsigned int i;
+
+    for (idx.figure_idx = 0; idx.figure_idx < geometry->u.path.figure_count; ++idx.figure_idx)
+    {
+        figure = &geometry->u.path.figures[idx.figure_idx];
+        fig_tri = &triangles[idx.figure_idx];
+        orientation = 0.0f;
+
+        for (idx.vertex_idx = 0, idx.control_idx = 0; idx.vertex_idx < figure->vertex_count; ++idx.vertex_idx)
+        {
+            type = figure->vertex_types[idx.vertex_idx];
+            next = idx.vertex_idx + 1;
+            if (next == figure->vertex_count)
+                next = 0;
+
+            switch (type)
+            {
+                case D2D_VERTEX_TYPE_LINE:
+                    p[0] = &figure->vertices[idx.vertex_idx];
+                    p[1] = &figure->vertices[next];
+                    orientation += d2d_geometry_point_orientation(p[0], p[1]);
+                    break;
+
+                case D2D_VERTEX_TYPE_BEZIER:
+                case D2D_VERTEX_TYPE_SPLIT_BEZIER:
+                    p[0] = &figure->vertices[idx.vertex_idx];
+                    p[1] = &figure->bezier_controls[idx.control_idx].c0;
+                    p[2] = &figure->bezier_controls[idx.control_idx++].c1;
+                    p[3] = &figure->vertices[next];
+
+                    for (i = 1; i < 4; i++)
+                        orientation += d2d_geometry_point_orientation(p[i - 1], p[i]);
+                    break;
+
+                default:
+                    break;
+            }
+        }
+
+        /* Depending on orientation value, set either clockwise or
+         * counter-clockwise. */
+        if (orientation < 0.0f)
+            fig_tri->orientation = ORIENTATION_CW;
+        else
+            fig_tri->orientation = ORIENTATION_CCW;
+    }
+}
+
 static BOOL d2d_geometry_check_bezier_overlap(struct d2d_geometry *geometry,
         const struct d2d_segment_idx *idx_p, const struct d2d_segment_idx *idx_q)
 {
@@ -3337,6 +3408,8 @@ static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
         }
     }
 
+    d2d_geometry_get_figure_orientation(geometry, triangles);
+
     for (i = 0; i < geometry->u.path.figure_count; ++i)
     {
         if (geometry->u.path.figures[i].flags & D2D_FIGURE_FLAG_HOLLOW)
-- 
2.20.1




More information about the wine-devel mailing list