[PATCH 2/2] d2d1: Implement ellipse and rounded rectangle stroking with arcs.

Giovanni Mascellani gio at debian.org
Fri Feb 14 12:40:53 CST 2020


Signed-off-by: Giovanni Mascellani <gio at debian.org>
---
 dlls/d2d1/d2d1_private.h |  16 +++
 dlls/d2d1/device.c       | 282 +++++++++++++++++++++++++++++++++------
 dlls/d2d1/geometry.c     |  64 ++++++++-
 3 files changed, 322 insertions(+), 40 deletions(-)

diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 366c8418ad..2781155712 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -45,6 +45,7 @@ enum d2d_shape_type
 {
     D2D_SHAPE_TYPE_OUTLINE,
     D2D_SHAPE_TYPE_BEZIER_OUTLINE,
+    D2D_SHAPE_TYPE_ARC_OUTLINE,
     D2D_SHAPE_TYPE_TRIANGLE,
     D2D_SHAPE_TYPE_BEZIER,
     D2D_SHAPE_TYPE_ARC,
@@ -432,6 +433,13 @@ struct d2d_bezier_outline_vertex
     D2D1_POINT_2F prev, next;
 };
 
+struct d2d_arc_outline_vertex
+{
+    D2D1_POINT_2F position;
+    D2D1_POINT_2F p0, p1, p2;
+    D2D1_POINT_2F prev, next;
+};
+
 struct d2d_geometry
 {
     ID2D1Geometry ID2D1Geometry_iface;
@@ -476,6 +484,14 @@ struct d2d_geometry
         struct d2d_face *bezier_faces;
         size_t bezier_faces_size;
         size_t bezier_face_count;
+
+        struct d2d_arc_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;
 
     union
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c
index c7960fa779..ba253b66e4 100644
--- a/dlls/d2d1/device.c
+++ b/dlls/d2d1/device.c
@@ -698,7 +698,7 @@ static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext
 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
         const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
 {
-    ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
+    ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb_bezier, *ps_cb_arc;
     D3D10_SUBRESOURCE_DATA buffer_data;
     D3D10_BUFFER_DESC buffer_desc;
     const D2D1_MATRIX_3X2_F *w;
@@ -754,13 +754,21 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         return;
     }
 
-    if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, FALSE, render_target, &ps_cb)))
+    if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, FALSE, render_target, &ps_cb_bezier)))
     {
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
         return;
     }
 
+    if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, TRUE, render_target, &ps_cb_arc)))
+    {
+        WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
+        ID3D10Buffer_Release(vs_cb);
+        ID3D10Buffer_Release(ps_cb_bezier);
+        return;
+    }
+
     if (geometry->outline.face_count)
     {
         buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
@@ -785,7 +793,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         }
 
         d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
-                sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
+                sizeof(*geometry->outline.vertices), vs_cb, ps_cb_bezier, brush, NULL);
 
         ID3D10Buffer_Release(vb);
         ID3D10Buffer_Release(ib);
@@ -816,14 +824,46 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
 
         d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
                 3 * geometry->outline.bezier_face_count, vb,
-                sizeof(*geometry->outline.beziers), vs_cb, ps_cb, brush, NULL);
+                sizeof(*geometry->outline.beziers), vs_cb, ps_cb_bezier, brush, NULL);
+
+        ID3D10Buffer_Release(vb);
+        ID3D10Buffer_Release(ib);
+    }
+
+    if (geometry->outline.arc_face_count)
+    {
+        buffer_desc.ByteWidth = geometry->outline.arc_face_count * sizeof(*geometry->outline.arc_faces);
+        buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
+        buffer_data.pSysMem = geometry->outline.arc_faces;
+
+        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
+        {
+            WARN("Failed to create arcs index buffer, hr %#x.\n", hr);
+            goto done;
+        }
+
+        buffer_desc.ByteWidth = geometry->outline.arc_count * sizeof(*geometry->outline.arcs);
+        buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
+        buffer_data.pSysMem = geometry->outline.arcs;
+
+        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
+        {
+            ERR("Failed to create arcs vertex buffer, hr %#x.\n", hr);
+            ID3D10Buffer_Release(ib);
+            goto done;
+        }
+
+        d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
+                3 * geometry->outline.arc_face_count, vb,
+                sizeof(*geometry->outline.arcs), vs_cb, ps_cb_arc, brush, NULL);
 
         ID3D10Buffer_Release(vb);
         ID3D10Buffer_Release(ib);
     }
 
 done:
-    ID3D10Buffer_Release(ps_cb);
+    ID3D10Buffer_Release(ps_cb_arc);
+    ID3D10Buffer_Release(ps_cb_bezier);
     ID3D10Buffer_Release(vs_cb);
 }
 
@@ -2763,6 +2803,15 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
         {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
         {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
     };
+    static const D3D10_INPUT_ELEMENT_DESC il_desc_arc_outline[] =
+    {
+        {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
+        {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
+        {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
+        {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
+        {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
+        {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
+    };
     static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
     {
         {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
@@ -3049,6 +3098,137 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
         0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
         0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
     };
+    static const DWORD vs_code_arc_outline[] =
+    {
+#if 0
+        float3x2 transform_geometry;
+        float stroke_width;
+        float4 transform_rtx;
+        float4 transform_rty;
+
+        struct output
+        {
+            float2 p : WORLD_POSITION;
+            float4 b : BEZIER;
+            nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
+            float4 position : SV_POSITION;
+        };
+
+        void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
+                float2 prev : PREV, float2 next : NEXT, out struct output o)
+        {
+            float2 q_prev, q_next, v_p, q_i, p;
+            float2x2 geom, rt, p_inv;
+            float l;
+            float a;
+            float2 bc;
+
+            geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
+            rt = float2x2(transform_rtx.xy, transform_rty.xy);
+            o.stroke_transform = rt * stroke_width * 0.5f;
+
+            p = mul(geom, position);
+            p0 = mul(geom, p0);
+            p1 = mul(geom, p1);
+            p2 = mul(geom, p2);
+
+            p -= p0;
+            p1 -= p0;
+            p2 -= p0;
+
+            q_prev = normalize(mul(geom, prev));
+            q_next = normalize(mul(geom, next));
+
+            v_p = float2(-q_prev.y, q_prev.x);
+            l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
+            q_i = l * q_prev + v_p;
+            p += 0.5f * stroke_width * q_i;
+
+            p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
+            o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
+            o.b.zw = 0.0f;
+
+            o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
+            position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
+                    * float2(transform_rtx.w, transform_rty.w);
+            o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
+        }
+#endif
+        0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
+        0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
+        0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
+        0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
+        0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
+        0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
+        0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
+        0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
+        0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
+        0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
+        0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
+        0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
+        0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
+        0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
+        0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
+        0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
+        0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
+        0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
+        0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
+        0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
+        0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
+        0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
+        0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
+        0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
+        0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
+        0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
+        0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
+        0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
+        0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
+        0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
+        0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
+        0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
+        0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
+        0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
+        0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
+        0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
+        0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
+        0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
+        0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
+        0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
+        0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
+        0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
+        0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
+        0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
+        0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
+        0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
+        0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
+        0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
+        0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
+        0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
+        0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
+        0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
+        0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
+        0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
+        0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
+        0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
+        0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
+        0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
+        0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
+        0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
+        0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
+        0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
+        0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
+        0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
+        0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
+        0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
+        0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
+        0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
+        0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
+        0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
+        0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
+        0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
+        0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
+        0x0100003e,
+    };
     static const DWORD vs_code_triangle[] =
     {
 #if 0
@@ -3374,10 +3554,18 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
                 uv = i.b;
                 du = float2(ddx(uv.x), ddy(uv.x));
                 dv = float2(ddx(uv.y), ddy(uv.y));
-                df = 2.0f * uv.x * du - dv;
 
-                clip(dot(df, uv.zw));
-                clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
+                if (!is_arc) {
+                    df = 2.0f * uv.x * du - dv;
+
+                    clip(dot(df, uv.zw));
+                    clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
+                } else {
+                    df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
+
+                    clip(dot(df, uv.zw));
+                    clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
+                }
             }
             else
             {
@@ -3393,15 +3581,15 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
             return colour;
         }
 #endif
-        0x43425844, 0x9b22fd36, 0xa300dd1c, 0x99947c91, 0x774ecf4b, 0x00000001, 0x00001df4, 0x00000003,
+        0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
         0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
         0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
         0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
         0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
         0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
         0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
-        0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001cf4,
-        0x00000040, 0x0000073d, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
+        0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
+        0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
         0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
         0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
         0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
@@ -3606,33 +3794,49 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
         0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
         0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
         0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
-        0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0b000027, 0x00100032,
-        0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
-        0x00000000, 0x0500000b, 0x00100032, 0x00000001, 0x00101046, 0x00000001, 0x0500000c, 0x001000c2,
-        0x00000001, 0x00101406, 0x00000001, 0x07000000, 0x00100042, 0x00000000, 0x0010100a, 0x00000001,
-        0x0010100a, 0x00000001, 0x0a000032, 0x001000c2, 0x00000000, 0x00100aa6, 0x00000000, 0x00100806,
-        0x00000001, 0x80100d56, 0x00000041, 0x00000001, 0x0700000f, 0x00100012, 0x00000001, 0x00100ae6,
-        0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100012, 0x00000001, 0x0010000a, 0x00000001,
-        0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0010000a,
-        0x00000001, 0x0304000d, 0x0010000a, 0x00000001, 0x07000038, 0x00100032, 0x00000001, 0x00100ff6,
-        0x00000000, 0x00101046, 0x00000003, 0x09000032, 0x001000c2, 0x00000000, 0x00101406, 0x00000002,
-        0x00100aa6, 0x00000000, 0x00100406, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100ae6,
-        0x00000000, 0x00100ae6, 0x00000000, 0x0500004b, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
-        0x07000038, 0x00100032, 0x00000001, 0x00101046, 0x00000001, 0x00101046, 0x00000001, 0x0a000032,
-        0x00100082, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041,
-        0x00000001, 0x08000000, 0x00100042, 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010002a,
-        0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000,
-        0x07000001, 0x00100042, 0x00000000, 0x0010000a, 0x00000000, 0x0010002a, 0x00000000, 0x0304000d,
-        0x0010002a, 0x00000000, 0x0500003b, 0x00100052, 0x00000000, 0x00100106, 0x00000000, 0x07000001,
-        0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100082,
-        0x00000000, 0x0010003a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100082, 0x00000000,
-        0x0010003a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100052, 0x00000000, 0x00100656,
-        0x00000000, 0x00100306, 0x00000000, 0x0304000d, 0x0010002a, 0x00000000, 0x07000000, 0x00100022,
-        0x00000000, 0x0010001a, 0x00000001, 0x0010000a, 0x00000001, 0x07000000, 0x00100022, 0x00000000,
-        0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022, 0x00000000, 0x0010001a,
-        0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000, 0x0010001a, 0x00000000,
-        0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010001a,
-        0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x0100003e,
+        0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
+        0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
+        0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
+        0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
+        0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
+        0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
+        0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
+        0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
+        0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
+        0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
+        0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
+        0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
+        0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
+        0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
+        0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
+        0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
+        0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
+        0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
+        0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
+        0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
+        0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
+        0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
+        0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
+        0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
+        0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
+        0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
+        0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
+        0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
+        0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
+        0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
+        0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
+        0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
+        0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
+        0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
+        0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
+        0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
+        0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
+        0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
+        0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
+        0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
+        0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
+        0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
+        0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
     };
     static const struct shape_info
     {
@@ -3648,6 +3852,8 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
                                         vs_code_outline,        sizeof(vs_code_outline)},
         {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_bezier_outline, ARRAY_SIZE(il_desc_bezier_outline),
                                         vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
+        {D2D_SHAPE_TYPE_ARC_OUTLINE,    il_desc_arc_outline,    ARRAY_SIZE(il_desc_arc_outline),
+                                        vs_code_arc_outline,    sizeof(vs_code_arc_outline)},
         {D2D_SHAPE_TYPE_TRIANGLE,       il_desc_triangle,       ARRAY_SIZE(il_desc_triangle),
                                         vs_code_triangle,       sizeof(vs_code_triangle)},
         {D2D_SHAPE_TYPE_BEZIER,         il_desc_bezier,         ARRAY_SIZE(il_desc_bezier),
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index 2fc93bfd87..7e0792b2b0 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -174,6 +174,18 @@ static void d2d_bezier_outline_vertex_set(struct d2d_bezier_outline_vertex *b, c
     d2d_point_set(&b->next, next_x, next_y);
 }
 
+static void d2d_arc_outline_vertex_set(struct d2d_arc_outline_vertex *a, const D2D1_POINT_2F *position,
+        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)
+{
+    a->position = *position;
+    a->p0 = *p0;
+    a->p1 = *p1;
+    a->p2 = *p2;
+    d2d_point_set(&a->prev, prev_x, prev_y);
+    d2d_point_set(&a->next, next_x, next_y);
+}
+
 static void d2d_fp_two_sum(float *out, float a, float b)
 {
     float a_virt, a_round, b_virt, b_round;
@@ -2270,9 +2282,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,
         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_arc_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];
 
-    return d2d_geometry_outline_add_bezier_segment(geometry, p0, p1, p2);
+    d2d_point_subtract(&r0, p1, p0);
+    d2d_point_subtract(&r1, p2, p1);
+
+    d2d_point_normalise(&r0);
+    d2d_point_normalise(&r1);
+
+    if (d2d_point_ccw(p0, p1, p2) > 0.0f)
+    {
+        d2d_point_scale(&r0, -1.0f);
+        d2d_point_scale(&r1, -1.0f);
+    }
+
+    d2d_arc_outline_vertex_set(&a[0],  p0, p0, p1, p2,  r0.x,  r0.y,  r0.x,  r0.y);
+    d2d_arc_outline_vertex_set(&a[1],  p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y);
+    d2d_arc_outline_vertex_set(&a[2],  p1, p0, p1, p2,  r0.x,  r0.y,  r1.x,  r1.y);
+    d2d_arc_outline_vertex_set(&a[3],  p2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y);
+    d2d_arc_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,
@@ -2377,6 +2433,8 @@ static BOOL d2d_geometry_fill_add_arc_triangle(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.beziers);
     heap_free(geometry->outline.faces);
@@ -4528,6 +4586,8 @@ static ULONG STDMETHODCALLTYPE d2d_transformed_geometry_Release(ID2D1Transformed
 
     if (!refcount)
     {
+        geometry->outline.arc_faces = NULL;
+        geometry->outline.arcs = NULL;
         geometry->outline.bezier_faces = NULL;
         geometry->outline.beziers = NULL;
         geometry->outline.faces = NULL;
-- 
2.25.0




More information about the wine-devel mailing list