d2d1: Implement ellipse and rounded rectangle stroking with arcs.

Signed-off-by: Giovanni Mascellani <gio@debian.org>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Giovanni Mascellani 2020-03-03 18:59:47 +01:00 committed by Alexandre Julliard
parent a6bf2c429e
commit 873e3d0691
3 changed files with 345 additions and 63 deletions

View File

@ -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_CURVE,
D2D_SHAPE_TYPE_COUNT,
@ -415,7 +416,7 @@ struct d2d_outline_vertex
D2D1_POINT_2F next;
};
struct d2d_bezier_outline_vertex
struct d2d_curve_outline_vertex
{
D2D1_POINT_2F position;
D2D1_POINT_2F p0, p1, p2;
@ -459,13 +460,21 @@ struct d2d_geometry
size_t faces_size;
size_t face_count;
struct d2d_bezier_outline_vertex *beziers;
struct d2d_curve_outline_vertex *beziers;
size_t beziers_size;
size_t bezier_count;
struct d2d_face *bezier_faces;
size_t bezier_faces_size;
size_t bezier_face_count;
struct d2d_curve_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

View File

@ -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);
}
@ -2756,7 +2796,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
{"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
{"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
};
static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier_outline[] =
static const D3D10_INPUT_ELEMENT_DESC il_desc_curve_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},
@ -3046,6 +3086,154 @@ 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,
};
/* ⎡p0.x p0.y 1⎤
* A = p1.x p1.y 1
* p2.x p2.y 1
*
* 1 0
* B = 1 1
* 0 1
*
* A' = p1.x-p0.x p1.y-p0.y
* p2.x-p0.x p2.y-p0.y
*
* B' = 0 1
* -1 1
*
* A'T = B'
* T = A'¹B' = (B'¹A')¹
*/
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
@ -3305,22 +3493,41 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
float2 du, dv, df;
float4 uv;
/* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
* using the screen-space partial derivatives to convert the calculated
* distance to object space.
/* Evaluate the implicit form of the curve (u² - v = 0
* for Béziers, u² + v² - 1 = 0 for arcs) in texture
* space, using the screen-space partial derivatives
* to convert the calculated distance to object space.
*
* d(x, y) = |f(x, y)| / f(x, y)
* = |f(x, y)| / ((f/x)² + (f/y)²)
*
* For Béziers:
* f(x, y) = u(x, y)² - v(x, y)
* f/x = 2u · u/x - v/x
* f/y = 2u · u/y - v/y */
* f/y = 2u · u/y - v/y
*
* For arcs:
* f(x, y) = u(x, y)² + v(x, y)² - 1
* f/x = 2u · u/x + 2v · v/x
* f/y = 2u · u/y + 2v · v/y */
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
{
@ -3339,15 +3546,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,
@ -3552,33 +3759,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
{
@ -3592,8 +3815,10 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
{
{D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
vs_code_outline, sizeof(vs_code_outline)},
{D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_bezier_outline, ARRAY_SIZE(il_desc_bezier_outline),
{D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
{D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_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_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),

View File

@ -153,16 +153,16 @@ static void d2d_outline_vertex_set(struct d2d_outline_vertex *v, float x, float
d2d_point_set(&v->next, next_x, next_y);
}
static void d2d_bezier_outline_vertex_set(struct d2d_bezier_outline_vertex *b, const D2D1_POINT_2F *position,
static void d2d_curve_outline_vertex_set(struct d2d_curve_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)
{
b->position = *position;
b->p0 = *p0;
b->p1 = *p1;
b->p2 = *p2;
d2d_point_set(&b->prev, prev_x, prev_y);
d2d_point_set(&b->next, next_x, 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)
@ -2197,7 +2197,7 @@ static BOOL d2d_geometry_outline_add_line_segment(struct d2d_geometry *geometry,
static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometry,
const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
{
struct d2d_bezier_outline_vertex *b;
struct d2d_curve_outline_vertex *b;
D2D1_POINT_2F r0, r1, r2;
D2D1_POINT_2F q0, q1, q2;
struct d2d_face *f;
@ -2239,13 +2239,13 @@ static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometr
d2d_point_scale(&r2, -1.0f);
}
d2d_bezier_outline_vertex_set(&b[0], p0, p0, p1, p2, r0.x, r0.y, r0.x, r0.y);
d2d_bezier_outline_vertex_set(&b[1], p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y);
d2d_bezier_outline_vertex_set(&b[2], &q0, p0, p1, p2, r0.x, r0.y, r1.x, r1.y);
d2d_bezier_outline_vertex_set(&b[3], &q2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y);
d2d_bezier_outline_vertex_set(&b[4], &q1, p0, p1, p2, r1.x, r1.y, r2.x, r2.y);
d2d_bezier_outline_vertex_set(&b[5], p2, p0, p1, p2, -r2.x, -r2.y, -r2.x, -r2.y);
d2d_bezier_outline_vertex_set(&b[6], p2, p0, p1, p2, r2.x, r2.y, r2.x, r2.y);
d2d_curve_outline_vertex_set(&b[0], p0, p0, p1, p2, r0.x, r0.y, r0.x, r0.y);
d2d_curve_outline_vertex_set(&b[1], p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y);
d2d_curve_outline_vertex_set(&b[2], &q0, p0, p1, p2, r0.x, r0.y, r1.x, r1.y);
d2d_curve_outline_vertex_set(&b[3], &q2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y);
d2d_curve_outline_vertex_set(&b[4], &q1, p0, p1, p2, r1.x, r1.y, r2.x, r2.y);
d2d_curve_outline_vertex_set(&b[5], p2, p0, p1, p2, -r2.x, -r2.y, -r2.x, -r2.y);
d2d_curve_outline_vertex_set(&b[6], p2, p0, p1, p2, r2.x, r2.y, r2.x, r2.y);
geometry->outline.bezier_count += 7;
d2d_face_set(&f[0], base_idx + 0, base_idx + 1, base_idx + 2);
@ -2261,9 +2261,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_curve_outline_vertex *a;
D2D1_POINT_2F r0, r1;
struct d2d_face *f;
size_t base_idx;
return d2d_geometry_outline_add_bezier_segment(geometry, p0, p1, p2);
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];
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_curve_outline_vertex_set(&a[0], p0, p0, p1, p2, r0.x, r0.y, r0.x, r0.y);
d2d_curve_outline_vertex_set(&a[1], p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y);
d2d_curve_outline_vertex_set(&a[2], p1, p0, p1, p2, r0.x, r0.y, r1.x, r1.y);
d2d_curve_outline_vertex_set(&a[3], p2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y);
d2d_curve_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,
@ -2368,6 +2412,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);
@ -4519,6 +4565,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;