Signed-off-by: Giovanni Mascellani gio@debian.org ---
For both this and the following patch the pixel shader needs to do different things depending on whether it is working with Bézier curves or arcs. The way I implement this is not really as clean as it could be. In case you don't like it, how would you suggest to fix it?
--- dlls/d2d1/brush.c | 3 +- dlls/d2d1/d2d1_private.h | 19 ++++- dlls/d2d1/device.c | 157 +++++++++++++++++++++++++++++++-------- dlls/d2d1/geometry.c | 29 +++++--- dlls/d2d1/tests/d2d1.c | 14 ++-- 5 files changed, 172 insertions(+), 50 deletions(-)
diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c index 80fc0f5331..cc557ea9ef 100644 --- a/dlls/d2d1/brush.c +++ b/dlls/d2d1/brush.c @@ -1262,7 +1262,7 @@ static BOOL d2d_brush_fill_cb(const struct d2d_brush *brush, }
HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush, - BOOL outline, struct d2d_device_context *render_target, ID3D10Buffer **ps_cb) + BOOL outline, BOOL is_arc, struct d2d_device_context *render_target, ID3D10Buffer **ps_cb) { D3D10_SUBRESOURCE_DATA buffer_data; struct d2d_ps_cb cb_data = {0}; @@ -1270,6 +1270,7 @@ HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_b HRESULT hr;
cb_data.outline = outline; + cb_data.is_arc = is_arc; if (!d2d_brush_fill_cb(brush, render_target, &cb_data.colour_brush)) return E_NOTIMPL; if (!d2d_brush_fill_cb(opacity_brush, render_target, &cb_data.opacity_brush)) diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 62c9d222fa..366c8418ad 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -47,6 +47,7 @@ enum d2d_shape_type D2D_SHAPE_TYPE_BEZIER_OUTLINE, D2D_SHAPE_TYPE_TRIANGLE, D2D_SHAPE_TYPE_BEZIER, + D2D_SHAPE_TYPE_ARC, D2D_SHAPE_TYPE_COUNT, };
@@ -113,7 +114,8 @@ struct d2d_brush_cb struct d2d_ps_cb { BOOL outline; - BOOL pad[3]; + BOOL is_arc; + BOOL pad[2]; struct d2d_brush_cb colour_brush; struct d2d_brush_cb opacity_brush; }; @@ -301,7 +303,7 @@ HRESULT d2d_bitmap_brush_create(ID2D1Factory *factory, ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc, struct d2d_brush **brush) DECLSPEC_HIDDEN; void d2d_brush_bind_resources(struct d2d_brush *brush, ID3D10Device *device, unsigned int brush_idx) DECLSPEC_HIDDEN; -HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, +HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, BOOL is_arc, struct d2d_device_context *render_target, ID3D10Buffer **ps_cb) DECLSPEC_HIDDEN; struct d2d_brush *unsafe_impl_from_ID2D1Brush(ID2D1Brush *iface) DECLSPEC_HIDDEN;
@@ -397,6 +399,15 @@ struct d2d_bezier_vertex } texcoord; };
+struct d2d_arc_vertex +{ + D2D1_POINT_2F position; + struct + { + float u, v, sign; + } texcoord; +}; + struct d2d_face { UINT16 v[3]; @@ -442,6 +453,10 @@ struct d2d_geometry struct d2d_bezier_vertex *bezier_vertices; size_t bezier_vertices_size; size_t bezier_vertex_count; + + struct d2d_arc_vertex *arc_vertices; + size_t arc_vertices_size; + size_t arc_vertex_count; } fill;
struct diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 0ab6e53f5f..c7960fa779 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -754,7 +754,7 @@ 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, render_target, &ps_cb))) + if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, FALSE, render_target, &ps_cb))) { WARN("Failed to get ps constant buffer, hr %#x.\n", hr); ID3D10Buffer_Release(vs_cb); @@ -846,7 +846,7 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target, const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush) { - 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; D2D1_MATRIX_3X2_F *w; @@ -902,10 +902,18 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t return; }
- if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, render_target, &ps_cb))) + if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, 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, opacity_brush, FALSE, 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; }
@@ -933,7 +941,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t }
d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb, - sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush); + sizeof(*geometry->fill.vertices), vs_cb, ps_cb_bezier, brush, opacity_brush);
ID3D10Buffer_Release(vb); ID3D10Buffer_Release(ib); @@ -952,13 +960,29 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t }
d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb, - sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush); + sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb_bezier, brush, opacity_brush); + + ID3D10Buffer_Release(vb); + } + + if (geometry->fill.arc_vertex_count) { + buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices); + buffer_data.pSysMem = geometry->fill.arc_vertices; + + if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb))) { + ERR("Failed to create arc vertex buffer, hr %#x.\n", hr); + goto done; + } + + d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC, NULL, geometry->fill.arc_vertex_count, vb, + sizeof(*geometry->fill.arc_vertices), vs_cb, ps_cb_arc, brush, opacity_brush);
ID3D10Buffer_Release(vb); }
done: - ID3D10Buffer_Release(ps_cb); + ID3D10Buffer_Release(ps_cb_arc); + ID3D10Buffer_Release(ps_cb_bezier); ID3D10Buffer_Release(vs_cb); }
@@ -2748,6 +2772,11 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0}, }; + static const D3D10_INPUT_ELEMENT_DESC il_desc_arc[] = + { + {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, + {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0}, + }; static const DWORD vs_code_outline[] = { #if 0 @@ -3127,6 +3156,60 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, }; + static const DWORD vs_code_arc[] = + { +#if 0 + float3x2 transform_geometry; + 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, float3 texcoord : TEXCOORD0, out struct output o) + { + o.p = mul(float3(position, 1.0f), transform_geometry); + o.b = float4(texcoord, 1.0); + o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0); + 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, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003, + 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, + 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000, + 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044, + 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, + 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, + 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000, + 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, + 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, + 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, + 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, + 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, + 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072, + 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000, + 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 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 ps_code[] = { #if 0 @@ -3137,6 +3220,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, #define BRUSH_TYPE_COUNT 4
bool outline; + bool is_arc; struct brush { uint type; @@ -3299,21 +3383,25 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, { /* Evaluate the implicit form of the curve in texture space. * "i.b.z" determines which side of the curve is shaded. */ - clip((i.b.x * i.b.x - i.b.y) * i.b.z); + if (!is_arc) { + clip((i.b.x * i.b.x - i.b.y) * i.b.z); + } else { + clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z); + } }
return colour; } #endif - 0x43425844, 0xf3cbb8bd, 0x5f286454, 0x139976a7, 0x6817e876, 0x00000001, 0x00001d18, 0x00000003, + 0x43425844, 0x9b22fd36, 0xa300dd1c, 0x99947c91, 0x774ecf4b, 0x00000001, 0x00001df4, 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, 0x00001c18, - 0x00000040, 0x00000706, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000, + 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001cf4, + 0x00000040, 0x0000073d, 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, @@ -3518,26 +3606,33 @@ 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, 0x08000027, 0x00100012, - 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, - 0x00000000, 0x0010000a, 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, 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, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, - 0x0010002a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000038, 0x00100012, 0x00000000, - 0x0010003a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010000a, - 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000, - 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x0100003e, + 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, }; static const struct shape_info { @@ -3557,6 +3652,8 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, vs_code_triangle, sizeof(vs_code_triangle)}, {D2D_SHAPE_TYPE_BEZIER, il_desc_bezier, ARRAY_SIZE(il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier)}, + {D2D_SHAPE_TYPE_ARC, il_desc_arc, ARRAY_SIZE(il_desc_arc), + vs_code_arc, sizeof(vs_code_arc)}, }; static const struct { diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c index e7bb809359..2fc93bfd87 100644 --- a/dlls/d2d1/geometry.c +++ b/dlls/d2d1/geometry.c @@ -138,6 +138,15 @@ static void d2d_bezier_vertex_set(struct d2d_bezier_vertex *b, b->texcoord.sign = sign; }
+static void d2d_arc_vertex_set(struct d2d_arc_vertex *a, + const D2D1_POINT_2F *p, float u, float v, float sign) +{ + a->position = *p; + a->texcoord.u = u; + a->texcoord.v = v; + a->texcoord.sign = sign; +} + static void d2d_face_set(struct d2d_face *f, UINT16 v0, UINT16 v1, UINT16 v2) { f->v[0] = v0; @@ -2351,19 +2360,17 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry, static BOOL d2d_geometry_fill_add_arc_triangle(struct d2d_geometry *geometry, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2) { - struct d2d_bezier_vertex *b; - - FIXME("Approximating arc triangle with Bezier triangle.\n"); + struct d2d_arc_vertex *a;
- if (!d2d_array_reserve((void **)&geometry->fill.bezier_vertices, &geometry->fill.bezier_vertices_size, - geometry->fill.bezier_vertex_count + 3, sizeof(*geometry->fill.bezier_vertices))) + if (!d2d_array_reserve((void **)&geometry->fill.arc_vertices, &geometry->fill.arc_vertices_size, + geometry->fill.arc_vertex_count + 3, sizeof(*geometry->fill.arc_vertices))) return FALSE;
- b = &geometry->fill.bezier_vertices[geometry->fill.bezier_vertex_count]; - d2d_bezier_vertex_set(&b[0], p0, 0.0f, 0.0f, -1.0f); - d2d_bezier_vertex_set(&b[1], p1, 0.5f, 0.0f, -1.0f); - d2d_bezier_vertex_set(&b[2], p2, 1.0f, 1.0f, -1.0f); - geometry->fill.bezier_vertex_count += 3; + a = geometry->fill.arc_vertices + geometry->fill.arc_vertex_count; + d2d_arc_vertex_set(&a[0], p0, 0.0f, 1.0f, -1.0f); + d2d_arc_vertex_set(&a[1], p1, 1.0f, 1.0f, -1.0f); + d2d_arc_vertex_set(&a[2], p2, 1.0f, 0.0f, -1.0f); + geometry->fill.arc_vertex_count += 3;
return TRUE; } @@ -2374,6 +2381,7 @@ static void d2d_geometry_cleanup(struct d2d_geometry *geometry) heap_free(geometry->outline.beziers); heap_free(geometry->outline.faces); heap_free(geometry->outline.vertices); + heap_free(geometry->fill.arc_vertices); heap_free(geometry->fill.bezier_vertices); heap_free(geometry->fill.faces); heap_free(geometry->fill.vertices); @@ -4524,6 +4532,7 @@ static ULONG STDMETHODCALLTYPE d2d_transformed_geometry_Release(ID2D1Transformed geometry->outline.beziers = NULL; geometry->outline.faces = NULL; geometry->outline.vertices = NULL; + geometry->fill.arc_vertices = NULL; geometry->fill.bezier_vertices = NULL; geometry->fill.faces = NULL; geometry->fill.vertices = NULL; diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 319246a0bc..1d4db386ab 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -6846,7 +6846,7 @@ static void test_fill_geometry(void) "yjIMjwEWhwEcggEgfiR6KHYscy5xMG40azZpOGc6ZTxjPmI+YUBfQl1EXERbRlpGWUhYSFdKVkpV" "TFRMVExTTlJOUk5STlJOUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5STlJOUk5STlNMVExUTFVK" "VkpXSFhIWUZaRltEXERdQl9AYT5iPmM8ZTpnOGk2azRuMHEucyx2KHokfiCCARyHARaPAQzKMgAA"); - todo_wine ok(match, "Figure does not match.\n"); + ok(match, "Figure does not match.\n");
ID2D1RenderTarget_BeginDraw(rt); set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f); @@ -6892,7 +6892,7 @@ static void test_fill_geometry(void) "szI6YURZSlROUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ" "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ" "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5USllEYTqzMgAA"); - todo_wine ok(match, "Figure does not match.\n"); + ok(match, "Figure does not match.\n");
match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "gMgB"); ok(match, "Figure does not match.\n"); @@ -6904,7 +6904,7 @@ static void test_fill_geometry(void) "tjI0aDxhQlxGWEpVTFNOUk5RUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ" "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ" "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFOUk5TTFVKWEZcQmA+ZzS2MgAA"); - todo_wine ok(match, "Figure does not match.\n"); + ok(match, "Figure does not match.\n");
match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "gMgB"); ok(match, "Figure does not match.\n"); @@ -6916,7 +6916,7 @@ static void test_fill_geometry(void) "sDJAWkxSUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ" "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ" "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFJMWkCwMgAA"); - todo_wine ok(match, "Figure does not match.\n"); + ok(match, "Figure does not match.\n");
ID2D1RenderTarget_BeginDraw(rt); set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f); @@ -6962,7 +6962,7 @@ static void test_fill_geometry(void) "yjIMjwEWhwEcggEgfiR6KHYscy5xMG40azZpOGc6ZTxjPmI+YUBfQl1EXERbRlpGWUhYSFdKVkpV" "TFRMVExTTlJOUk5STlJOUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5STlJOUk5STlNMVExUTFVK" "VkpXSFhIWUZaRltEXERdQl9AYT5iPmM8ZTpnOGk2azRuMHEucyx2KHokfiCCARyHARaPAQzKMgAA"); - todo_wine ok(match, "Figure does not match.\n"); + ok(match, "Figure does not match.\n");
match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "gMgB"); ok(match, "Figure does not match.\n"); @@ -6974,7 +6974,7 @@ static void test_fill_geometry(void) "uTIucDJsNmk4ZzplPGM+YUBgQF9CXkJdRFxEW0ZaRllIWEhXSlZKVkpWSlVMVExUTFRMU05STlJO" "Uk5STlJOUk9QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFPUU5STlJOUk5STlJOU0xU" "TFRMVExVSlZKVkpWSldIWEhZRlpGW0RcRF1CXkJfQGBAYT5jPGU6ZzhpNmwycC65MgAA"); - todo_wine ok(match, "Figure does not match.\n"); + ok(match, "Figure does not match.\n");
match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "gMgB"); ok(match, "Figure does not match.\n"); @@ -6986,7 +6986,7 @@ static void test_fill_geometry(void) "vzIiczhhRldMUlBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ" "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ" "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUkxXRmA6cSS+MgAA"); - todo_wine ok(match, "Figure does not match.\n"); + ok(match, "Figure does not match.\n");
hr = ID2D1Factory_CreatePathGeometry(factory, &geometry); ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
Signed-off-by: Giovanni Mascellani gio@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;
On Fri, 14 Feb 2020 at 22:11, Giovanni Mascellani gio@debian.org wrote:
+struct d2d_arc_outline_vertex +{
- D2D1_POINT_2F position;
- D2D1_POINT_2F p0, p1, p2;
- D2D1_POINT_2F prev, next;
+};
Much like for fills, I'd argue for combining this with the d2d_bezier_outline_vertex structure.
- 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},
- };
Likewise.
- 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);
}
This should just be a slightly simpler version of "vs_code_bezier_outline", but it's probably still best to include the equivalent comment.
@@ -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));
}
Likewise, please update the comment here as well. There's also a minor formatting issue.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=65233
Your paranoid android.
=== w1064v1809_ar (32 bit report) ===
d2d1: d2d1.c:9085: Test failed: Failed to create a bitmap, hr 0x8007000e. 17e8:d2d1: unhandled exception c0000005 at 0040B95A
On Fri, 14 Feb 2020 at 22:19, Giovanni Mascellani gio@debian.org wrote:
For both this and the following patch the pixel shader needs to do different things depending on whether it is working with Bézier curves or arcs. The way I implement this is not really as clean as it could be. In case you don't like it, how would you suggest to fix it?
It could be combined with the "outline" field into something similar to the "type" field in the brush structure, but I'm not sure it's really worth it. There's also the option of passing information through the vertex data, or indexed by the instance ID. We'll probably want something along those lines at some point, but not yet.
@@ -397,6 +399,15 @@ struct d2d_bezier_vertex } texcoord; };
+struct d2d_arc_vertex +{
- D2D1_POINT_2F position;
- struct
- {
float u, v, sign;
- } texcoord;
+};
I'd argue for combining this with the d2d_bezier_vertex structure into e.g. a "d2d_curve_vertex" structure.
- if (geometry->fill.arc_vertex_count) {
buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices);
buffer_data.pSysMem = geometry->fill.arc_vertices;
if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb))) {
ERR("Failed to create arc vertex buffer, hr %#x.\n", hr);
goto done;
}
d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC, NULL, geometry->fill.arc_vertex_count, vb,
sizeof(*geometry->fill.arc_vertices), vs_cb, ps_cb_arc, brush, opacity_brush);
Some formatting issues here.
@@ -2748,6 +2772,11 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0}, };
- static const D3D10_INPUT_ELEMENT_DESC il_desc_arc[] =
- {
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
- };
Similar to the d2d_arc_vertex structure, I'd argue for combining this with "il_desc_bezier".
- static const DWORD vs_code_arc[] =
- {
+#if 0
float3x2 transform_geometry;
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, float3 texcoord : TEXCOORD0, out struct output o)
{
o.p = mul(float3(position, 1.0f), transform_geometry);
o.b = float4(texcoord, 1.0);
o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
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
And then this can be combined with "vs_code_bezier".
clip((i.b.x * i.b.x - i.b.y) * i.b.z);
if (!is_arc) {
clip((i.b.x * i.b.x - i.b.y) * i.b.z);
} else {
clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
}
Formatting.
- b = &geometry->fill.bezier_vertices[geometry->fill.bezier_vertex_count];
- d2d_bezier_vertex_set(&b[0], p0, 0.0f, 0.0f, -1.0f);
- d2d_bezier_vertex_set(&b[1], p1, 0.5f, 0.0f, -1.0f);
- d2d_bezier_vertex_set(&b[2], p2, 1.0f, 1.0f, -1.0f);
- geometry->fill.bezier_vertex_count += 3;
- a = geometry->fill.arc_vertices + geometry->fill.arc_vertex_count;
- d2d_arc_vertex_set(&a[0], p0, 0.0f, 1.0f, -1.0f);
- d2d_arc_vertex_set(&a[1], p1, 1.0f, 1.0f, -1.0f);
- d2d_arc_vertex_set(&a[2], p2, 1.0f, 0.0f, -1.0f);
- geometry->fill.arc_vertex_count += 3;
It's just a style preference, but I'd prefer "a = &geometry->fill.arc_vertices[geometry->fill.arc_vertex_count];".