d2d1: Implement initial support for drawing bezier curves.
This commit is contained in:
parent
025c320145
commit
b33786ce6d
|
@ -796,20 +796,21 @@ HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_d3d_render_targe
|
|||
return hr;
|
||||
}
|
||||
|
||||
void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_d3d_render_target *render_target)
|
||||
void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_d3d_render_target *render_target,
|
||||
enum d2d_shape_type shape_type)
|
||||
{
|
||||
static const float blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
ID3D10Device *device = render_target->device;
|
||||
ID3D10PixelShader *ps;
|
||||
HRESULT hr;
|
||||
|
||||
ID3D10Device_OMSetBlendState(device, render_target->bs, blend_factor, D3D10_DEFAULT_SAMPLE_MASK);
|
||||
if (brush->type == D2D_BRUSH_TYPE_SOLID)
|
||||
if (!(ps = render_target->shape_resources[shape_type].ps[brush->type]))
|
||||
FIXME("No pixel shader for shape type %#x and brush type %#x.\n", shape_type, brush->type);
|
||||
ID3D10Device_PSSetShader(device, ps);
|
||||
|
||||
if (brush->type == D2D_BRUSH_TYPE_BITMAP)
|
||||
{
|
||||
ID3D10Device_PSSetShader(device, render_target->rect_solid_ps);
|
||||
}
|
||||
else if (brush->type == D2D_BRUSH_TYPE_BITMAP)
|
||||
{
|
||||
ID3D10Device_PSSetShader(device, render_target->rect_bitmap_ps);
|
||||
ID3D10Device_PSSetShaderResources(device, 0, 1, &brush->u.bitmap.bitmap->view);
|
||||
if (!brush->u.bitmap.sampler_state)
|
||||
{
|
||||
|
@ -838,7 +839,7 @@ void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_d3d_render_tar
|
|||
}
|
||||
ID3D10Device_PSSetSamplers(device, 0, 1, &brush->u.bitmap.sampler_state);
|
||||
}
|
||||
else
|
||||
else if (brush->type != D2D_BRUSH_TYPE_SOLID)
|
||||
{
|
||||
FIXME("Unhandled brush type %#x.\n", brush->type);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,14 @@ enum d2d_brush_type
|
|||
D2D_BRUSH_TYPE_SOLID,
|
||||
D2D_BRUSH_TYPE_LINEAR,
|
||||
D2D_BRUSH_TYPE_BITMAP,
|
||||
D2D_BRUSH_TYPE_COUNT,
|
||||
};
|
||||
|
||||
enum d2d_shape_type
|
||||
{
|
||||
D2D_SHAPE_TYPE_TRIANGLE,
|
||||
D2D_SHAPE_TYPE_BEZIER,
|
||||
D2D_SHAPE_TYPE_COUNT,
|
||||
};
|
||||
|
||||
struct d2d_clip_stack
|
||||
|
@ -44,6 +52,13 @@ struct d2d_clip_stack
|
|||
unsigned int count;
|
||||
};
|
||||
|
||||
struct d2d_shape_resources
|
||||
{
|
||||
ID3D10InputLayout *il;
|
||||
ID3D10VertexShader *vs;
|
||||
ID3D10PixelShader *ps[D2D_BRUSH_TYPE_COUNT];
|
||||
};
|
||||
|
||||
struct d2d_d3d_render_target
|
||||
{
|
||||
ID2D1RenderTarget ID2D1RenderTarget_iface;
|
||||
|
@ -54,17 +69,13 @@ struct d2d_d3d_render_target
|
|||
ID3D10Device *device;
|
||||
ID3D10RenderTargetView *view;
|
||||
ID3D10StateBlock *stateblock;
|
||||
ID3D10InputLayout *il;
|
||||
struct d2d_shape_resources shape_resources[D2D_SHAPE_TYPE_COUNT];
|
||||
ID3D10Buffer *ib;
|
||||
unsigned int vb_stride;
|
||||
ID3D10Buffer *vb;
|
||||
ID3D10VertexShader *vs;
|
||||
ID3D10RasterizerState *rs;
|
||||
ID3D10BlendState *bs;
|
||||
|
||||
ID3D10PixelShader *rect_solid_ps;
|
||||
ID3D10PixelShader *rect_bitmap_ps;
|
||||
|
||||
D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
|
||||
IDWriteRenderingParams *text_rendering_params;
|
||||
|
||||
|
@ -142,7 +153,8 @@ void d2d_linear_gradient_brush_init(struct d2d_brush *brush, ID2D1RenderTarget *
|
|||
HRESULT d2d_bitmap_brush_init(struct d2d_brush *brush, struct d2d_d3d_render_target *render_target,
|
||||
ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
|
||||
const D2D1_BRUSH_PROPERTIES *brush_desc) DECLSPEC_HIDDEN;
|
||||
void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_d3d_render_target *render_target) DECLSPEC_HIDDEN;
|
||||
void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_d3d_render_target *render_target,
|
||||
enum d2d_shape_type shape_type) DECLSPEC_HIDDEN;
|
||||
HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_d3d_render_target *render_target,
|
||||
ID3D10Buffer **ps_cb) DECLSPEC_HIDDEN;
|
||||
struct d2d_brush *unsafe_impl_from_ID2D1Brush(ID2D1Brush *iface) DECLSPEC_HIDDEN;
|
||||
|
@ -201,6 +213,18 @@ enum d2d_geometry_state
|
|||
D2D_GEOMETRY_STATE_FIGURE,
|
||||
};
|
||||
|
||||
struct d2d_bezier
|
||||
{
|
||||
struct
|
||||
{
|
||||
D2D1_POINT_2F position;
|
||||
struct
|
||||
{
|
||||
float u, v, sign;
|
||||
} texcoord;
|
||||
} v[3];
|
||||
};
|
||||
|
||||
struct d2d_face
|
||||
{
|
||||
UINT16 v[3];
|
||||
|
@ -218,6 +242,9 @@ struct d2d_geometry
|
|||
size_t faces_size;
|
||||
size_t face_count;
|
||||
|
||||
struct d2d_bezier *beziers;
|
||||
size_t bezier_count;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
|
|
|
@ -39,6 +39,10 @@ struct d2d_figure
|
|||
D2D1_POINT_2F *vertices;
|
||||
size_t vertices_size;
|
||||
size_t vertex_count;
|
||||
|
||||
struct d2d_bezier *beziers;
|
||||
size_t beziers_size;
|
||||
size_t bezier_count;
|
||||
};
|
||||
|
||||
struct d2d_cdt_edge_ref
|
||||
|
@ -71,6 +75,16 @@ static void d2d_point_subtract(D2D1_POINT_2F *out,
|
|||
out->y = a->y - b->y;
|
||||
}
|
||||
|
||||
static float d2d_point_ccw(const D2D1_POINT_2F *a, const D2D1_POINT_2F *b, const D2D1_POINT_2F *c)
|
||||
{
|
||||
D2D1_POINT_2F ab, ac;
|
||||
|
||||
d2d_point_subtract(&ab, b, a);
|
||||
d2d_point_subtract(&ac, c, a);
|
||||
|
||||
return ab.x * ac.y - ab.y * ac.x;
|
||||
}
|
||||
|
||||
static BOOL d2d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
|
||||
{
|
||||
size_t new_capacity, max_capacity;
|
||||
|
@ -133,6 +147,55 @@ static BOOL d2d_figure_add_vertex(struct d2d_figure *figure, D2D1_POINT_2F verte
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* FIXME: No inside/outside testing is done for beziers. */
|
||||
static BOOL d2d_figure_add_bezier(struct d2d_figure *figure, D2D1_POINT_2F p0, D2D1_POINT_2F p1, D2D1_POINT_2F p2)
|
||||
{
|
||||
struct d2d_bezier *b;
|
||||
unsigned int idx1, idx2;
|
||||
float sign;
|
||||
|
||||
if (!d2d_array_reserve((void **)&figure->beziers, &figure->beziers_size,
|
||||
figure->bezier_count + 1, sizeof(*figure->beziers)))
|
||||
{
|
||||
ERR("Failed to grow beziers array.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (d2d_point_ccw(&p0, &p1, &p2) > 0.0f)
|
||||
{
|
||||
sign = -1.0f;
|
||||
idx1 = 1;
|
||||
idx2 = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = 1.0f;
|
||||
idx1 = 2;
|
||||
idx2 = 1;
|
||||
}
|
||||
|
||||
b = &figure->beziers[figure->bezier_count];
|
||||
b->v[0].position = p0;
|
||||
b->v[0].texcoord.u = 0.0f;
|
||||
b->v[0].texcoord.v = 0.0f;
|
||||
b->v[0].texcoord.sign = sign;
|
||||
b->v[idx1].position = p1;
|
||||
b->v[idx1].texcoord.u = 0.5f;
|
||||
b->v[idx1].texcoord.v = 0.0f;
|
||||
b->v[idx1].texcoord.sign = sign;
|
||||
b->v[idx2].position = p2;
|
||||
b->v[idx2].texcoord.u = 1.0f;
|
||||
b->v[idx2].texcoord.v = 1.0f;
|
||||
b->v[idx2].texcoord.sign = sign;
|
||||
++figure->bezier_count;
|
||||
|
||||
if (sign > 0.0f && !d2d_figure_add_vertex(figure, p1))
|
||||
return FALSE;
|
||||
if (!d2d_figure_add_vertex(figure, p2))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void d2d_cdt_edge_rot(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
|
||||
{
|
||||
dst->idx = src->idx;
|
||||
|
@ -193,12 +256,7 @@ static void d2d_cdt_edge_set_destination(const struct d2d_cdt *cdt,
|
|||
|
||||
static float d2d_cdt_ccw(const struct d2d_cdt *cdt, size_t a, size_t b, size_t c)
|
||||
{
|
||||
D2D1_POINT_2F ab, ac;
|
||||
|
||||
d2d_point_subtract(&ab, &cdt->vertices[b], &cdt->vertices[a]);
|
||||
d2d_point_subtract(&ac, &cdt->vertices[c], &cdt->vertices[a]);
|
||||
|
||||
return ab.x * ac.y - ab.y * ac.x;
|
||||
return d2d_point_ccw(&cdt->vertices[a], &cdt->vertices[b], &cdt->vertices[c]);
|
||||
}
|
||||
|
||||
static BOOL d2d_cdt_rightof(const struct d2d_cdt *cdt, size_t p, const struct d2d_cdt_edge_ref *e)
|
||||
|
@ -773,6 +831,7 @@ static BOOL d2d_cdt_insert_segments(struct d2d_cdt *cdt, struct d2d_geometry *ge
|
|||
/* Intersect the geometry's segments with themselves. This uses the
|
||||
* straightforward approach of testing everything against everything, but
|
||||
* there certainly exist more scalable algorithms for this. */
|
||||
/* FIXME: Beziers can't currently self-intersect. */
|
||||
static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry)
|
||||
{
|
||||
D2D1_POINT_2F p0, p1, q0, q1, v_p, v_q, v_qp, intersection;
|
||||
|
@ -920,6 +979,7 @@ static BOOL d2d_path_geometry_add_figure(struct d2d_geometry *geometry)
|
|||
|
||||
static void d2d_geometry_destroy(struct d2d_geometry *geometry)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, geometry->beziers);
|
||||
HeapFree(GetProcessHeap(), 0, geometry->faces);
|
||||
HeapFree(GetProcessHeap(), 0, geometry->vertices);
|
||||
HeapFree(GetProcessHeap(), 0, geometry);
|
||||
|
@ -1048,9 +1108,11 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddBeziers(ID2D1GeometrySink *if
|
|||
const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
|
||||
{
|
||||
struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
|
||||
struct d2d_figure *figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
|
||||
D2D1_POINT_2F p;
|
||||
unsigned int i;
|
||||
|
||||
FIXME("iface %p, beziers %p, count %u stub!\n", iface, beziers, count);
|
||||
TRACE("iface %p, beziers %p, count %u.\n", iface, beziers, count);
|
||||
|
||||
if (geometry->u.path.state != D2D_GEOMETRY_STATE_FIGURE)
|
||||
{
|
||||
|
@ -1060,9 +1122,14 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddBeziers(ID2D1GeometrySink *if
|
|||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
if (!d2d_figure_add_vertex(&geometry->u.path.figures[geometry->u.path.figure_count - 1], beziers[i].point3))
|
||||
/* FIXME: This tries to approximate a cubic bezier with a quadratic one. */
|
||||
p.x = (beziers[i].point1.x + beziers[i].point2.x) * 0.75f;
|
||||
p.y = (beziers[i].point1.y + beziers[i].point2.y) * 0.75f;
|
||||
p.x -= (figure->vertices[figure->vertex_count - 1].x + beziers[i].point3.x) * 0.25f;
|
||||
p.y -= (figure->vertices[figure->vertex_count - 1].y + beziers[i].point3.y) * 0.25f;
|
||||
if (!d2d_figure_add_bezier(figure, figure->vertices[figure->vertex_count - 1], p, beziers[i].point3))
|
||||
{
|
||||
ERR("Failed to add vertex.\n");
|
||||
ERR("Failed to add bezier.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1097,6 +1164,7 @@ static void d2d_path_geometry_free_figures(struct d2d_geometry *geometry)
|
|||
|
||||
for (i = 0; i < geometry->u.path.figure_count; ++i)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, geometry->u.path.figures[i].beziers);
|
||||
HeapFree(GetProcessHeap(), 0, geometry->u.path.figures[i].vertices);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, geometry->u.path.figures);
|
||||
|
@ -1108,6 +1176,7 @@ static HRESULT STDMETHODCALLTYPE d2d_geometry_sink_Close(ID2D1GeometrySink *ifac
|
|||
{
|
||||
struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
|
||||
HRESULT hr = E_FAIL;
|
||||
size_t i, start;
|
||||
|
||||
TRACE("iface %p.\n", iface);
|
||||
|
||||
|
@ -1121,7 +1190,33 @@ static HRESULT STDMETHODCALLTYPE d2d_geometry_sink_Close(ID2D1GeometrySink *ifac
|
|||
|
||||
if (!d2d_geometry_intersect_self(geometry))
|
||||
goto done;
|
||||
hr = d2d_path_geometry_triangulate(geometry);
|
||||
if (FAILED(hr = d2d_path_geometry_triangulate(geometry)))
|
||||
goto done;
|
||||
|
||||
for (i = 0; i < geometry->u.path.figure_count; ++i)
|
||||
{
|
||||
geometry->bezier_count += geometry->u.path.figures[i].bezier_count;
|
||||
}
|
||||
|
||||
if (!(geometry->beziers = HeapAlloc(GetProcessHeap(), 0,
|
||||
geometry->bezier_count * sizeof(*geometry->beziers))))
|
||||
{
|
||||
ERR("Failed to allocate beziers array.\n");
|
||||
geometry->bezier_count = 0;
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0, start = 0; i < geometry->u.path.figure_count; ++i)
|
||||
{
|
||||
struct d2d_figure *figure = &geometry->u.path.figures[i];
|
||||
if (figure->bezier_count)
|
||||
{
|
||||
memcpy(&geometry->beziers[start], figure->beziers,
|
||||
figure->bezier_count * sizeof(*figure->beziers));
|
||||
start += figure->bezier_count;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
d2d_path_geometry_free_figures(geometry);
|
||||
|
@ -1156,9 +1251,10 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddQuadraticBeziers(ID2D1Geometr
|
|||
const D2D1_QUADRATIC_BEZIER_SEGMENT *beziers, UINT32 bezier_count)
|
||||
{
|
||||
struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
|
||||
struct d2d_figure *figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
|
||||
unsigned int i;
|
||||
|
||||
FIXME("iface %p, beziers %p, bezier_count %u stub!\n", iface, beziers, bezier_count);
|
||||
TRACE("iface %p, beziers %p, bezier_count %u.\n", iface, beziers, bezier_count);
|
||||
|
||||
if (geometry->u.path.state != D2D_GEOMETRY_STATE_FIGURE)
|
||||
{
|
||||
|
@ -1168,9 +1264,10 @@ static void STDMETHODCALLTYPE d2d_geometry_sink_AddQuadraticBeziers(ID2D1Geometr
|
|||
|
||||
for (i = 0; i < bezier_count; ++i)
|
||||
{
|
||||
if (!d2d_figure_add_vertex(&geometry->u.path.figures[geometry->u.path.figure_count - 1], beziers[i].point2))
|
||||
if (!d2d_figure_add_bezier(figure, figure->vertices[figure->vertex_count - 1],
|
||||
beziers[i].point1, beziers[i].point2))
|
||||
{
|
||||
ERR("Failed to add vertex.\n");
|
||||
ERR("Failed to add bezier.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,10 +127,11 @@ static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
|
|||
--stack->count;
|
||||
}
|
||||
|
||||
static void d2d_draw(struct d2d_d3d_render_target *render_target, ID3D10Buffer *ib, unsigned int index_count,
|
||||
ID3D10Buffer *vb, unsigned int vb_stride, ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb,
|
||||
struct d2d_brush *brush)
|
||||
static void d2d_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
|
||||
ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
|
||||
ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush)
|
||||
{
|
||||
struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
|
||||
ID3D10Device *device = render_target->device;
|
||||
unsigned int offset;
|
||||
D3D10_VIEWPORT vp;
|
||||
|
@ -151,13 +152,13 @@ static void d2d_draw(struct d2d_d3d_render_target *render_target, ID3D10Buffer *
|
|||
|
||||
ID3D10Device_ClearState(device);
|
||||
|
||||
ID3D10Device_IASetInputLayout(device, render_target->il);
|
||||
ID3D10Device_IASetInputLayout(device, shape_resources->il);
|
||||
ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
|
||||
offset = 0;
|
||||
ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
|
||||
ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
|
||||
ID3D10Device_VSSetShader(device, render_target->vs);
|
||||
ID3D10Device_VSSetShader(device, shape_resources->vs);
|
||||
ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
|
||||
ID3D10Device_RSSetViewports(device, 1, &vp);
|
||||
if (render_target->clip_stack.count)
|
||||
|
@ -175,11 +176,14 @@ static void d2d_draw(struct d2d_d3d_render_target *render_target, ID3D10Buffer *
|
|||
}
|
||||
ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
|
||||
if (brush)
|
||||
d2d_brush_bind_resources(brush, render_target);
|
||||
d2d_brush_bind_resources(brush, render_target, shape_type);
|
||||
else
|
||||
ID3D10Device_PSSetShader(device, render_target->rect_solid_ps);
|
||||
ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID]);
|
||||
|
||||
if (ib)
|
||||
ID3D10Device_DrawIndexed(device, index_count, 0, 0);
|
||||
else
|
||||
ID3D10Device_Draw(device, index_count, 0);
|
||||
|
||||
if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
|
||||
WARN("Failed to apply stateblock, hr %#x.\n", hr);
|
||||
|
@ -228,17 +232,25 @@ static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *
|
|||
|
||||
if (!refcount)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
d2d_clip_stack_cleanup(&render_target->clip_stack);
|
||||
if (render_target->text_rendering_params)
|
||||
IDWriteRenderingParams_Release(render_target->text_rendering_params);
|
||||
ID3D10PixelShader_Release(render_target->rect_bitmap_ps);
|
||||
ID3D10PixelShader_Release(render_target->rect_solid_ps);
|
||||
ID3D10BlendState_Release(render_target->bs);
|
||||
ID3D10RasterizerState_Release(render_target->rs);
|
||||
ID3D10VertexShader_Release(render_target->vs);
|
||||
ID3D10Buffer_Release(render_target->vb);
|
||||
ID3D10Buffer_Release(render_target->ib);
|
||||
ID3D10InputLayout_Release(render_target->il);
|
||||
for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
|
||||
{
|
||||
for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
|
||||
{
|
||||
if (render_target->shape_resources[i].ps[j])
|
||||
ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j]);
|
||||
}
|
||||
ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
|
||||
ID3D10InputLayout_Release(render_target->shape_resources[i].il);
|
||||
}
|
||||
render_target->stateblock->lpVtbl->Release(render_target->stateblock);
|
||||
ID3D10RenderTargetView_Release(render_target->view);
|
||||
ID3D10Device_Release(render_target->device);
|
||||
|
@ -606,33 +618,6 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarg
|
|||
|
||||
geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
|
||||
|
||||
buffer_desc.ByteWidth = geometry_impl->face_count * sizeof(*geometry_impl->faces);
|
||||
buffer_desc.Usage = D3D10_USAGE_DEFAULT;
|
||||
buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||
buffer_desc.CPUAccessFlags = 0;
|
||||
buffer_desc.MiscFlags = 0;
|
||||
|
||||
buffer_data.pSysMem = geometry_impl->faces;
|
||||
buffer_data.SysMemPitch = 0;
|
||||
buffer_data.SysMemSlicePitch = 0;
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
|
||||
{
|
||||
WARN("Failed to create index buffer, hr %#x.\n", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_desc.ByteWidth = geometry_impl->vertex_count * sizeof(*geometry_impl->vertices);
|
||||
buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
||||
buffer_data.pSysMem = geometry_impl->vertices;
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
|
||||
{
|
||||
ERR("Failed to create vertex buffer, hr %#x.\n", hr);
|
||||
ID3D10Buffer_Release(ib);
|
||||
return;
|
||||
}
|
||||
|
||||
tmp_x = (2.0f * render_target->dpi_x) / (96.0f * render_target->pixel_size.width);
|
||||
tmp_y = -(2.0f * render_target->dpi_y) / (96.0f * render_target->pixel_size.height);
|
||||
transform._11 = render_target->drawing_state.transform._11 * tmp_x;
|
||||
|
@ -645,14 +630,18 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarg
|
|||
transform.pad1 = 0.0f;
|
||||
|
||||
buffer_desc.ByteWidth = sizeof(transform);
|
||||
buffer_desc.Usage = D3D10_USAGE_DEFAULT;
|
||||
buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
|
||||
buffer_desc.CPUAccessFlags = 0;
|
||||
buffer_desc.MiscFlags = 0;
|
||||
|
||||
buffer_data.pSysMem = &transform;
|
||||
buffer_data.SysMemPitch = 0;
|
||||
buffer_data.SysMemSlicePitch = 0;
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
|
||||
{
|
||||
WARN("Failed to create constant buffer, hr %#x.\n", hr);
|
||||
ID3D10Buffer_Release(vb);
|
||||
ID3D10Buffer_Release(ib);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -660,18 +649,56 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarg
|
|||
{
|
||||
WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
|
||||
ID3D10Buffer_Release(vs_cb);
|
||||
ID3D10Buffer_Release(vb);
|
||||
ID3D10Buffer_Release(ib);
|
||||
return;
|
||||
}
|
||||
|
||||
d2d_draw(render_target, ib, 3 * geometry_impl->face_count, vb,
|
||||
buffer_desc.ByteWidth = geometry_impl->face_count * sizeof(*geometry_impl->faces);
|
||||
buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||
buffer_data.pSysMem = geometry_impl->faces;
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
|
||||
{
|
||||
WARN("Failed to create index buffer, hr %#x.\n", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
buffer_desc.ByteWidth = geometry_impl->vertex_count * sizeof(*geometry_impl->vertices);
|
||||
buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
||||
buffer_data.pSysMem = geometry_impl->vertices;
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
|
||||
{
|
||||
ERR("Failed to create vertex buffer, hr %#x.\n", hr);
|
||||
ID3D10Buffer_Release(ib);
|
||||
goto done;
|
||||
}
|
||||
|
||||
d2d_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry_impl->face_count, vb,
|
||||
sizeof(*geometry_impl->vertices), vs_cb, ps_cb, brush_impl);
|
||||
|
||||
ID3D10Buffer_Release(ps_cb);
|
||||
ID3D10Buffer_Release(vs_cb);
|
||||
ID3D10Buffer_Release(vb);
|
||||
ID3D10Buffer_Release(ib);
|
||||
|
||||
if (geometry_impl->bezier_count)
|
||||
{
|
||||
buffer_desc.ByteWidth = geometry_impl->bezier_count * sizeof(*geometry_impl->beziers);
|
||||
buffer_data.pSysMem = geometry_impl->beziers;
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
|
||||
{
|
||||
ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
d2d_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, 3 * geometry_impl->bezier_count, vb,
|
||||
sizeof(*geometry_impl->beziers->v), vs_cb, ps_cb, brush_impl);
|
||||
|
||||
ID3D10Buffer_Release(vb);
|
||||
}
|
||||
|
||||
done:
|
||||
ID3D10Buffer_Release(ps_cb);
|
||||
ID3D10Buffer_Release(vs_cb);
|
||||
}
|
||||
|
||||
static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
|
||||
|
@ -1095,7 +1122,8 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *ifa
|
|||
return;
|
||||
}
|
||||
|
||||
d2d_draw(render_target, render_target->ib, 6, render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL);
|
||||
d2d_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
|
||||
render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL);
|
||||
|
||||
ID3D10Buffer_Release(ps_cb);
|
||||
ID3D10Buffer_Release(vs_cb);
|
||||
|
@ -1408,13 +1436,19 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
|
|||
D3D10_BUFFER_DESC buffer_desc;
|
||||
D3D10_BLEND_DESC blend_desc;
|
||||
ID3D10Resource *resource;
|
||||
unsigned int i, j;
|
||||
HRESULT hr;
|
||||
|
||||
static const D3D10_INPUT_ELEMENT_DESC il_desc[] =
|
||||
static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
|
||||
{
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
|
||||
};
|
||||
static const DWORD vs_code[] =
|
||||
static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
|
||||
{
|
||||
{"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_triangle[] =
|
||||
{
|
||||
/* float3x2 transform;
|
||||
*
|
||||
|
@ -1433,7 +1467,32 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
|
|||
0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
|
||||
0x00000000, 0x0100003e,
|
||||
};
|
||||
static const DWORD rect_solid_ps_code[] =
|
||||
static const DWORD vs_code_bezier[] =
|
||||
{
|
||||
#if 0
|
||||
float3x2 transform;
|
||||
|
||||
float4 main(float4 position : POSITION,
|
||||
inout float3 texcoord : TEXCOORD0) : SV_POSITION
|
||||
{
|
||||
return float4(mul(position.xyw, transform), position.zw);
|
||||
}
|
||||
#endif
|
||||
0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
|
||||
0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
|
||||
0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
|
||||
0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
|
||||
0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
|
||||
0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
|
||||
0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
|
||||
0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
|
||||
0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
|
||||
0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
|
||||
0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
|
||||
0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
|
||||
0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
|
||||
};
|
||||
static const DWORD ps_code_triangle_solid[] =
|
||||
{
|
||||
/* float4 color;
|
||||
*
|
||||
|
@ -1449,7 +1508,7 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
|
|||
0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
|
||||
0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
|
||||
};
|
||||
static const DWORD rect_bitmap_ps_code[] =
|
||||
static const DWORD ps_code_triangle_bitmap[] =
|
||||
{
|
||||
#if 0
|
||||
float3x2 transform;
|
||||
|
@ -1487,6 +1546,32 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
|
|||
0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x05000036, 0x00102072,
|
||||
0x00000000, 0x00100246, 0x00000000, 0x0100003e,
|
||||
};
|
||||
/* The basic idea here is to evaluate the implicit form of the curve in
|
||||
* texture space. "t.z" determines which side of the curve is shaded. */
|
||||
static const DWORD ps_code_bezier_solid[] =
|
||||
{
|
||||
#if 0
|
||||
float4 color;
|
||||
|
||||
float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
|
||||
{
|
||||
clip((t.x * t.x - t.y) * t.z);
|
||||
return color;
|
||||
}
|
||||
#endif
|
||||
0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
|
||||
0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
|
||||
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
|
||||
0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
|
||||
0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
|
||||
0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
|
||||
0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
|
||||
0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
|
||||
0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
|
||||
0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
|
||||
0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
|
||||
0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
|
||||
};
|
||||
static const struct
|
||||
{
|
||||
float x, y;
|
||||
|
@ -1547,11 +1632,57 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc,
|
||||
sizeof(il_desc) / sizeof(*il_desc), vs_code, sizeof(vs_code),
|
||||
&render_target->il)))
|
||||
if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
|
||||
sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
|
||||
&render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
|
||||
{
|
||||
WARN("Failed to create clear input layout, hr %#x.\n", hr);
|
||||
WARN("Failed to create triangle input layout, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
|
||||
sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
|
||||
&render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
|
||||
{
|
||||
WARN("Failed to create bezier input layout, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
|
||||
sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
|
||||
{
|
||||
WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
|
||||
sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
|
||||
{
|
||||
WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
|
||||
ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
|
||||
&render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].ps[D2D_BRUSH_TYPE_SOLID])))
|
||||
{
|
||||
WARN("Failed to create triangle/solid pixel shader, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
|
||||
ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
|
||||
&render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].ps[D2D_BRUSH_TYPE_BITMAP])))
|
||||
{
|
||||
WARN("Failed to create triangle/bitmap pixel shader, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
|
||||
ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
|
||||
&render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].ps[D2D_BRUSH_TYPE_SOLID])))
|
||||
{
|
||||
WARN("Failed to create bezier/solid pixel shader, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -1584,13 +1715,6 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device,
|
||||
vs_code, sizeof(vs_code), &render_target->vs)))
|
||||
{
|
||||
WARN("Failed to create clear vertex shader, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rs_desc.FillMode = D3D10_FILL_SOLID;
|
||||
rs_desc.CullMode = D3D10_CULL_BACK;
|
||||
rs_desc.FrontCounterClockwise = FALSE;
|
||||
|
@ -1622,20 +1746,6 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
|
||||
rect_solid_ps_code, sizeof(rect_solid_ps_code), &render_target->rect_solid_ps)))
|
||||
{
|
||||
WARN("Failed to create pixel shader, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
|
||||
rect_bitmap_ps_code, sizeof(rect_bitmap_ps_code), &render_target->rect_bitmap_ps)))
|
||||
{
|
||||
WARN("Failed to create pixel shader, hr %#x.\n", hr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
|
||||
{
|
||||
WARN("Failed to get surface desc, hr %#x.\n", hr);
|
||||
|
@ -1665,22 +1775,26 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
|
|||
return S_OK;
|
||||
|
||||
err:
|
||||
if (render_target->rect_bitmap_ps)
|
||||
ID3D10PixelShader_Release(render_target->rect_bitmap_ps);
|
||||
if (render_target->rect_solid_ps)
|
||||
ID3D10PixelShader_Release(render_target->rect_solid_ps);
|
||||
if (render_target->bs)
|
||||
ID3D10BlendState_Release(render_target->bs);
|
||||
if (render_target->rs)
|
||||
ID3D10RasterizerState_Release(render_target->rs);
|
||||
if (render_target->vs)
|
||||
ID3D10VertexShader_Release(render_target->vs);
|
||||
if (render_target->vb)
|
||||
ID3D10Buffer_Release(render_target->vb);
|
||||
if (render_target->ib)
|
||||
ID3D10Buffer_Release(render_target->ib);
|
||||
if (render_target->il)
|
||||
ID3D10InputLayout_Release(render_target->il);
|
||||
for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
|
||||
{
|
||||
for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
|
||||
{
|
||||
if (render_target->shape_resources[i].ps[j])
|
||||
ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j]);
|
||||
}
|
||||
if (render_target->shape_resources[i].vs)
|
||||
ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
|
||||
if (render_target->shape_resources[i].il)
|
||||
ID3D10InputLayout_Release(render_target->shape_resources[i].il);
|
||||
}
|
||||
if (render_target->stateblock)
|
||||
render_target->stateblock->lpVtbl->Release(render_target->stateblock);
|
||||
if (render_target->view)
|
||||
|
|
|
@ -24,12 +24,27 @@
|
|||
#include "initguid.h"
|
||||
#include "dwrite.h"
|
||||
|
||||
struct figure
|
||||
{
|
||||
unsigned int *spans;
|
||||
unsigned int spans_size;
|
||||
unsigned int span_count;
|
||||
};
|
||||
|
||||
static void set_point(D2D1_POINT_2F *point, float x, float y)
|
||||
{
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
}
|
||||
|
||||
static void set_quadratic(D2D1_QUADRATIC_BEZIER_SEGMENT *quadratic, float x1, float y1, float x2, float y2)
|
||||
{
|
||||
quadratic->point1.x = x1;
|
||||
quadratic->point1.y = y1;
|
||||
quadratic->point2.x = x2;
|
||||
quadratic->point2.y = y2;
|
||||
}
|
||||
|
||||
static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, float bottom)
|
||||
{
|
||||
rect->left = left;
|
||||
|
@ -179,6 +194,192 @@ static BOOL compare_surface(IDXGISurface *surface, const char *ref_sha1)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void serialize_figure(struct figure *figure)
|
||||
{
|
||||
static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
unsigned int i, j, k, span;
|
||||
char output[76];
|
||||
char t[3];
|
||||
char *p;
|
||||
|
||||
for (i = 0, j = 0, k = 0, p = output; i < figure->span_count; ++i)
|
||||
{
|
||||
span = figure->spans[i];
|
||||
while (span)
|
||||
{
|
||||
t[j] = span & 0x7f;
|
||||
if (span > 0x7f)
|
||||
t[j] |= 0x80;
|
||||
span >>= 7;
|
||||
if (++j == 3)
|
||||
{
|
||||
p[0] = lookup[(t[0] & 0xfc) >> 2];
|
||||
p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
|
||||
p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
|
||||
p[3] = lookup[t[2] & 0x3f];
|
||||
p += 4;
|
||||
if (++k == 19)
|
||||
{
|
||||
trace("%.76s\n", output);
|
||||
p = output;
|
||||
k = 0;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j)
|
||||
{
|
||||
for (i = j; i < 3; ++i)
|
||||
t[i] = 0;
|
||||
p[0] = lookup[(t[0] & 0xfc) >> 2];
|
||||
p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
|
||||
p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
|
||||
p[3] = lookup[t[2] & 0x3f];
|
||||
++k;
|
||||
}
|
||||
if (k)
|
||||
trace("%.*s\n", k * 4, output);
|
||||
}
|
||||
|
||||
static void deserialize_span(struct figure *figure, unsigned int *current, unsigned int *shift, unsigned int c)
|
||||
{
|
||||
*current |= (c & 0x7f) << *shift;
|
||||
if (c & 0x80)
|
||||
{
|
||||
*shift += 7;
|
||||
return;
|
||||
}
|
||||
|
||||
if (figure->span_count == figure->spans_size)
|
||||
{
|
||||
figure->spans_size *= 2;
|
||||
figure->spans = HeapReAlloc(GetProcessHeap(), 0, figure->spans,
|
||||
figure->spans_size * sizeof(*figure->spans));
|
||||
}
|
||||
|
||||
figure->spans[figure->span_count++] = *current;
|
||||
*current = 0;
|
||||
*shift = 0;
|
||||
}
|
||||
|
||||
static void deserialize_figure(struct figure *figure, const BYTE *s)
|
||||
{
|
||||
static const BYTE lookup[] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
unsigned int current = 0, shift = 0;
|
||||
const BYTE *ptr;
|
||||
BYTE x, y;
|
||||
|
||||
figure->span_count = 0;
|
||||
figure->spans_size = 64;
|
||||
figure->spans = HeapAlloc(GetProcessHeap(), 0, figure->spans_size * sizeof(*figure->spans));
|
||||
|
||||
for (ptr = s; *ptr; ptr += 4)
|
||||
{
|
||||
x = lookup[ptr[0]];
|
||||
y = lookup[ptr[1]];
|
||||
deserialize_span(figure, ¤t, &shift, ((x & 0x3f) << 2) | ((y & 0x3f) >> 4));
|
||||
x = lookup[ptr[2]];
|
||||
deserialize_span(figure, ¤t, &shift, ((y & 0x0f) << 4) | ((x & 0x3f) >> 2));
|
||||
y = lookup[ptr[3]];
|
||||
deserialize_span(figure, ¤t, &shift, ((x & 0x03) << 6) | (y & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y,
|
||||
unsigned int w, unsigned int h, DWORD prev, unsigned int max_diff, const char *ref)
|
||||
{
|
||||
D3D10_MAPPED_TEXTURE2D mapped_texture;
|
||||
D3D10_TEXTURE2D_DESC texture_desc;
|
||||
struct figure ref_figure, figure;
|
||||
DXGI_SURFACE_DESC surface_desc;
|
||||
unsigned int i, j, span, diff;
|
||||
ID3D10Resource *src_resource;
|
||||
ID3D10Texture2D *texture;
|
||||
ID3D10Device *device;
|
||||
HRESULT hr;
|
||||
|
||||
hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
|
||||
ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
|
||||
hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
|
||||
ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
|
||||
|
||||
hr = IDXGISurface_GetDesc(surface, &surface_desc);
|
||||
ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
|
||||
texture_desc.Width = surface_desc.Width;
|
||||
texture_desc.Height = surface_desc.Height;
|
||||
texture_desc.MipLevels = 1;
|
||||
texture_desc.ArraySize = 1;
|
||||
texture_desc.Format = surface_desc.Format;
|
||||
texture_desc.SampleDesc = surface_desc.SampleDesc;
|
||||
texture_desc.Usage = D3D10_USAGE_STAGING;
|
||||
texture_desc.BindFlags = 0;
|
||||
texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
|
||||
texture_desc.MiscFlags = 0;
|
||||
hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
|
||||
ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
|
||||
|
||||
ID3D10Device_CopyResource(device, (ID3D10Resource *)texture, src_resource);
|
||||
hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &mapped_texture);
|
||||
ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
|
||||
|
||||
figure.span_count = 0;
|
||||
figure.spans_size = 64;
|
||||
figure.spans = HeapAlloc(GetProcessHeap(), 0, figure.spans_size * sizeof(*figure.spans));
|
||||
|
||||
for (i = 0, span = 0; i < h; ++i)
|
||||
{
|
||||
const DWORD *row = (DWORD *)((BYTE *)mapped_texture.pData + (y + i) * mapped_texture.RowPitch + x * 4);
|
||||
for (j = 0; j < w; ++j, ++span)
|
||||
{
|
||||
if ((i || j) && prev != row[j])
|
||||
{
|
||||
if (figure.span_count == figure.spans_size)
|
||||
{
|
||||
figure.spans_size *= 2;
|
||||
figure.spans = HeapReAlloc(GetProcessHeap(), 0, figure.spans,
|
||||
figure.spans_size * sizeof(*figure.spans));
|
||||
}
|
||||
figure.spans[figure.span_count++] = span;
|
||||
prev = row[j];
|
||||
span = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserialize_figure(&ref_figure, (BYTE *)ref);
|
||||
|
||||
j = min(figure.span_count, ref_figure.span_count);
|
||||
for (i = 0, diff = 0; i < j; ++i)
|
||||
diff += abs(figure.spans[i] - ref_figure.spans[i]);
|
||||
for (i = j; j < figure.span_count; ++j)
|
||||
diff += figure.spans[i];
|
||||
for (i = j; j < ref_figure.span_count; ++j)
|
||||
diff += ref_figure.spans[i];
|
||||
if (diff > max_diff)
|
||||
serialize_figure(&figure);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, ref_figure.spans);
|
||||
HeapFree(GetProcessHeap(), 0, figure.spans);
|
||||
ID3D10Texture2D_Unmap(texture, 0);
|
||||
|
||||
ID3D10Texture2D_Release(texture);
|
||||
ID3D10Resource_Release(src_resource);
|
||||
ID3D10Device_Release(device);
|
||||
|
||||
return diff <= max_diff;
|
||||
}
|
||||
|
||||
static ID3D10Device1 *create_device(void)
|
||||
{
|
||||
ID3D10Device1 *device;
|
||||
|
@ -982,6 +1183,36 @@ static void fill_geometry_sink(ID2D1GeometrySink *sink)
|
|||
ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
|
||||
}
|
||||
|
||||
static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink)
|
||||
{
|
||||
D2D1_QUADRATIC_BEZIER_SEGMENT quadratic;
|
||||
D2D1_POINT_2F point;
|
||||
|
||||
set_point(&point, 5.0f, 160.0f);
|
||||
ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
|
||||
set_quadratic(&quadratic, 40.0f, 160.0f, 40.0f, 20.0f);
|
||||
ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
|
||||
set_quadratic(&quadratic, 40.0f, 160.0f, 75.0f, 160.0f);
|
||||
ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
|
||||
set_quadratic(&quadratic, 40.0f, 160.0f, 40.0f, 300.0f);
|
||||
ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
|
||||
set_quadratic(&quadratic, 40.0f, 160.0f, 5.0f, 160.0f);
|
||||
ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
|
||||
ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
|
||||
|
||||
set_point(&point, 20.0f, 160.0f);
|
||||
ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
|
||||
set_quadratic(&quadratic, 20.0f, 80.0f, 40.0f, 80.0f);
|
||||
ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
|
||||
set_quadratic(&quadratic, 60.0f, 80.0f, 60.0f, 160.0f);
|
||||
ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
|
||||
set_quadratic(&quadratic, 60.0f, 240.0f, 40.0f, 240.0f);
|
||||
ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
|
||||
set_quadratic(&quadratic, 20.0f, 240.0f, 20.0f, 160.0f);
|
||||
ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
|
||||
ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
|
||||
}
|
||||
|
||||
static void test_path_geometry(void)
|
||||
{
|
||||
ID2D1GeometrySink *sink, *tmp_sink;
|
||||
|
@ -1227,6 +1458,68 @@ static void test_path_geometry(void)
|
|||
ok(match, "Surface does not match.\n");
|
||||
ID2D1PathGeometry_Release(geometry);
|
||||
|
||||
hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
|
||||
ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
|
||||
hr = ID2D1PathGeometry_Open(geometry, &sink);
|
||||
ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
|
||||
fill_geometry_sink_bezier(sink);
|
||||
hr = ID2D1GeometrySink_Close(sink);
|
||||
ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
|
||||
hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
|
||||
ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
|
||||
ok(count == 2, "Got unexpected figure count %u.\n", count);
|
||||
hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
|
||||
ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
|
||||
ok(count == 10, "Got unexpected segment count %u.\n", count);
|
||||
ID2D1GeometrySink_Release(sink);
|
||||
|
||||
ID2D1RenderTarget_BeginDraw(rt);
|
||||
ID2D1RenderTarget_Clear(rt, &color);
|
||||
ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
|
||||
hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
|
||||
ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
|
||||
match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
|
||||
"7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
|
||||
"lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
|
||||
"FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
|
||||
"EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
|
||||
"PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
|
||||
"EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
|
||||
"EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
|
||||
"BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
|
||||
todo_wine ok(match, "Figure does not match.\n");
|
||||
ID2D1PathGeometry_Release(geometry);
|
||||
|
||||
hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
|
||||
ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
|
||||
hr = ID2D1PathGeometry_Open(geometry, &sink);
|
||||
ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
|
||||
fill_geometry_sink_bezier(sink);
|
||||
ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
|
||||
hr = ID2D1GeometrySink_Close(sink);
|
||||
ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
|
||||
hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
|
||||
ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
|
||||
ok(count == 2, "Got unexpected figure count %u.\n", count);
|
||||
hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
|
||||
ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
|
||||
ok(count == 10, "Got unexpected segment count %u.\n", count);
|
||||
ID2D1GeometrySink_Release(sink);
|
||||
|
||||
ID2D1RenderTarget_BeginDraw(rt);
|
||||
ID2D1RenderTarget_Clear(rt, &color);
|
||||
ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
|
||||
hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
|
||||
ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
|
||||
match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
|
||||
"7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
|
||||
"lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
|
||||
"U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
|
||||
"TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
|
||||
"mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
|
||||
ok(match, "Figure does not match.\n");
|
||||
ID2D1PathGeometry_Release(geometry);
|
||||
|
||||
ID2D1SolidColorBrush_Release(brush);
|
||||
ID2D1RenderTarget_Release(rt);
|
||||
refcount = ID2D1Factory_Release(factory);
|
||||
|
|
Loading…
Reference in New Issue