d2d1: Implement ID2D1DeviceContext::CreateImageBrush().
[wine.git] / dlls / d2d1 / device.c
blobeb0c1935ebbd13a3bf1f4d34fcf77f02431fbe48
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "d2d1_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
23 #define INITIAL_CLIP_STACK_SIZE 4
25 static const D2D1_MATRIX_3X2_F identity =
26 {{{
27 1.0f, 0.0f,
28 0.0f, 1.0f,
29 0.0f, 0.0f,
30 }}};
32 struct d2d_draw_text_layout_ctx
34 ID2D1Brush *brush;
35 D2D1_DRAW_TEXT_OPTIONS options;
38 static inline struct d2d_device *impl_from_ID2D1Device(ID2D1Device *iface)
40 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
43 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface);
45 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
47 ID2D1Brush *brush = NULL;
49 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
50 return brush;
52 ID2D1Brush_AddRef(context->brush);
53 return context->brush;
56 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
58 if (src->left > dst->left)
59 dst->left = src->left;
60 if (src->top > dst->top)
61 dst->top = src->top;
62 if (src->right < dst->right)
63 dst->right = src->right;
64 if (src->bottom < dst->bottom)
65 dst->bottom = src->bottom;
68 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
70 dst->left = left;
71 dst->top = top;
72 dst->right = right;
73 dst->bottom = bottom;
76 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
78 dst->width = width;
79 dst->height = height;
82 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
84 if (!(stack->stack = heap_alloc(INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
85 return FALSE;
87 stack->size = INITIAL_CLIP_STACK_SIZE;
88 stack->count = 0;
90 return TRUE;
93 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
95 heap_free(stack->stack);
98 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
100 D2D1_RECT_F r;
102 if (!d2d_array_reserve((void **)&stack->stack, &stack->size, stack->count + 1, sizeof(*stack->stack)))
103 return FALSE;
105 r = *rect;
106 if (stack->count)
107 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
108 stack->stack[stack->count++] = r;
110 return TRUE;
113 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
115 if (!stack->count)
116 return;
117 --stack->count;
120 static void d2d_device_context_draw(struct d2d_device_context *render_target, enum d2d_shape_type shape_type,
121 ID3D11Buffer *ib, unsigned int index_count, ID3D11Buffer *vb, unsigned int vb_stride,
122 struct d2d_brush *brush, struct d2d_brush *opacity_brush)
124 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
125 ID3DDeviceContextState *prev_state;
126 ID3D11Device1 *device = render_target->d3d_device;
127 ID3D11DeviceContext1 *context;
128 ID3D11Buffer *vs_cb = render_target->vs_cb, *ps_cb = render_target->ps_cb;
129 D3D11_RECT scissor_rect;
130 unsigned int offset;
131 D3D11_VIEWPORT vp;
133 vp.TopLeftX = 0;
134 vp.TopLeftY = 0;
135 vp.Width = render_target->pixel_size.width;
136 vp.Height = render_target->pixel_size.height;
137 vp.MinDepth = 0.0f;
138 vp.MaxDepth = 1.0f;
140 ID3D11Device1_GetImmediateContext1(device, &context);
141 ID3D11DeviceContext1_SwapDeviceContextState(context, render_target->d3d_state, &prev_state);
143 ID3D11DeviceContext1_IASetInputLayout(context, shape_resources->il);
144 ID3D11DeviceContext1_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
145 ID3D11DeviceContext1_IASetIndexBuffer(context, ib, DXGI_FORMAT_R16_UINT, 0);
146 offset = 0;
147 ID3D11DeviceContext1_IASetVertexBuffers(context, 0, 1, &vb, &vb_stride, &offset);
148 ID3D11DeviceContext1_VSSetConstantBuffers(context, 0, 1, &vs_cb);
149 ID3D11DeviceContext1_VSSetShader(context, shape_resources->vs, NULL, 0);
150 ID3D11DeviceContext1_PSSetConstantBuffers(context, 0, 1, &ps_cb);
151 ID3D11DeviceContext1_PSSetShader(context, render_target->ps, NULL, 0);
152 ID3D11DeviceContext1_RSSetViewports(context, 1, &vp);
153 if (render_target->clip_stack.count)
155 const D2D1_RECT_F *clip_rect;
157 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
158 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
159 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
160 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
161 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
163 else
165 scissor_rect.left = 0.0f;
166 scissor_rect.top = 0.0f;
167 scissor_rect.right = render_target->pixel_size.width;
168 scissor_rect.bottom = render_target->pixel_size.height;
170 ID3D11DeviceContext1_RSSetScissorRects(context, 1, &scissor_rect);
171 ID3D11DeviceContext1_RSSetState(context, render_target->rs);
172 ID3D11DeviceContext1_OMSetRenderTargets(context, 1, &render_target->target->rtv, NULL);
173 if (brush)
175 ID3D11DeviceContext1_OMSetBlendState(context, render_target->bs, NULL, D3D11_DEFAULT_SAMPLE_MASK);
176 d2d_brush_bind_resources(brush, render_target, 0);
178 else
180 ID3D11DeviceContext1_OMSetBlendState(context, NULL, NULL, D3D11_DEFAULT_SAMPLE_MASK);
182 if (opacity_brush)
183 d2d_brush_bind_resources(opacity_brush, render_target, 1);
185 if (ib)
186 ID3D11DeviceContext1_DrawIndexed(context, index_count, 0, 0);
187 else
188 ID3D11DeviceContext1_Draw(context, index_count, 0);
190 ID3D11DeviceContext1_SwapDeviceContextState(context, prev_state, NULL);
191 ID3D11DeviceContext1_Release(context);
192 ID3DDeviceContextState_Release(prev_state);
195 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
197 context->error.code = code;
198 context->error.tag1 = context->drawing_state.tag1;
199 context->error.tag2 = context->drawing_state.tag2;
202 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
204 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
207 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext *iface)
209 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
212 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
214 struct d2d_device_context *context = impl_from_IUnknown(iface);
216 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
218 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext)
219 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
220 || IsEqualGUID(iid, &IID_ID2D1Resource)
221 || IsEqualGUID(iid, &IID_IUnknown))
223 ID2D1DeviceContext_AddRef(&context->ID2D1DeviceContext_iface);
224 *out = &context->ID2D1DeviceContext_iface;
225 return S_OK;
227 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
229 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
230 *out = &context->ID2D1GdiInteropRenderTarget_iface;
231 return S_OK;
234 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
236 *out = NULL;
237 return E_NOINTERFACE;
240 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
242 struct d2d_device_context *context = impl_from_IUnknown(iface);
243 ULONG refcount = InterlockedIncrement(&context->refcount);
245 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
247 return refcount;
250 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
252 struct d2d_device_context *context = impl_from_IUnknown(iface);
253 ULONG refcount = InterlockedDecrement(&context->refcount);
255 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
257 if (!refcount)
259 unsigned int i, j, k;
261 d2d_clip_stack_cleanup(&context->clip_stack);
262 IDWriteRenderingParams_Release(context->default_text_rendering_params);
263 if (context->text_rendering_params)
264 IDWriteRenderingParams_Release(context->text_rendering_params);
265 if (context->bs)
266 ID3D11BlendState_Release(context->bs);
267 ID3D11RasterizerState_Release(context->rs);
268 ID3D11Buffer_Release(context->vb);
269 ID3D11Buffer_Release(context->ib);
270 ID3D11Buffer_Release(context->ps_cb);
271 ID3D11PixelShader_Release(context->ps);
272 ID3D11Buffer_Release(context->vs_cb);
273 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
275 ID3D11VertexShader_Release(context->shape_resources[i].vs);
276 ID3D11InputLayout_Release(context->shape_resources[i].il);
278 for (i = 0; i < D2D_SAMPLER_INTERPOLATION_MODE_COUNT; ++i)
280 for (j = 0; j < D2D_SAMPLER_EXTEND_MODE_COUNT; ++j)
282 for (k = 0; k < D2D_SAMPLER_EXTEND_MODE_COUNT; ++k)
284 if (context->sampler_states[i][j][k])
285 ID3D11SamplerState_Release(context->sampler_states[i][j][k]);
289 if (context->d3d_state)
290 ID3DDeviceContextState_Release(context->d3d_state);
291 if (context->target)
292 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
293 ID3D11Device1_Release(context->d3d_device);
294 ID2D1Factory_Release(context->factory);
295 ID2D1Device_Release(context->device);
296 heap_free(context);
299 return refcount;
302 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
304 d2d_device_context_inner_QueryInterface,
305 d2d_device_context_inner_AddRef,
306 d2d_device_context_inner_Release,
309 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out)
311 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
313 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
315 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
318 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface)
320 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
322 TRACE("iface %p.\n", iface);
324 return IUnknown_AddRef(context->outer_unknown);
327 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface)
329 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
331 TRACE("iface %p.\n", iface);
333 return IUnknown_Release(context->outer_unknown);
336 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext *iface, ID2D1Factory **factory)
338 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
340 TRACE("iface %p, factory %p.\n", iface, factory);
342 *factory = render_target->factory;
343 ID2D1Factory_AddRef(*factory);
346 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext *iface,
347 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
349 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
350 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
351 struct d2d_bitmap *object;
352 HRESULT hr;
354 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
355 iface, size.width, size.height, src_data, pitch, desc, bitmap);
357 if (desc)
359 memcpy(&bitmap_desc, desc, sizeof(*desc));
360 bitmap_desc.bitmapOptions = 0;
361 bitmap_desc.colorContext = NULL;
364 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
365 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
367 return hr;
370 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext *iface,
371 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
373 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
374 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
375 struct d2d_bitmap *object;
376 HRESULT hr;
378 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
379 iface, bitmap_source, desc, bitmap);
381 if (desc)
383 memcpy(&bitmap_desc, desc, sizeof(*desc));
384 bitmap_desc.bitmapOptions = 0;
385 bitmap_desc.colorContext = NULL;
388 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
389 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
391 return hr;
394 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext *iface,
395 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
397 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
398 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
399 struct d2d_bitmap *object;
400 HRESULT hr;
402 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
403 iface, debugstr_guid(iid), data, desc, bitmap);
405 if (desc)
407 memcpy(&bitmap_desc, desc, sizeof(*desc));
408 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
409 bitmap_desc.colorContext = NULL;
412 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
413 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
415 return hr;
418 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext *iface,
419 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
420 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
422 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
423 struct d2d_brush *object;
424 HRESULT hr;
426 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
427 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
429 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
430 brush_desc, &object)))
431 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
433 return hr;
436 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext *iface,
437 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
439 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
440 struct d2d_brush *object;
441 HRESULT hr;
443 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
445 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
446 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
448 return hr;
451 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext *iface,
452 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
453 ID2D1GradientStopCollection **gradient)
455 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
456 struct d2d_gradient *object;
457 HRESULT hr;
459 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
460 iface, stops, stop_count, gamma, extend_mode, gradient);
462 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
463 stops, stop_count, gamma, extend_mode, &object)))
464 *gradient = &object->ID2D1GradientStopCollection_iface;
466 return hr;
469 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext *iface,
470 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
471 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
473 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
474 struct d2d_brush *object;
475 HRESULT hr;
477 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
478 iface, gradient_brush_desc, brush_desc, gradient, brush);
480 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
481 gradient, &object)))
482 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
484 return hr;
487 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext *iface,
488 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
489 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
491 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
492 struct d2d_brush *object;
493 HRESULT hr;
495 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
496 iface, gradient_brush_desc, brush_desc, gradient, brush);
498 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
499 gradient_brush_desc, brush_desc, gradient, &object)))
500 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
502 return hr;
505 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext *iface,
506 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
507 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
509 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
510 struct d2d_bitmap_render_target *object;
511 HRESULT hr;
513 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
514 iface, size, pixel_size, format, options, rt);
516 if (!(object = heap_alloc_zero(sizeof(*object))))
517 return E_OUTOFMEMORY;
519 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
520 format, options)))
522 WARN("Failed to initialise render target, hr %#lx.\n", hr);
523 heap_free(object);
524 return hr;
527 TRACE("Created render target %p.\n", object);
528 *rt = &object->ID2D1BitmapRenderTarget_iface;
530 return S_OK;
533 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext *iface,
534 const D2D1_SIZE_F *size, ID2D1Layer **layer)
536 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
537 struct d2d_layer *object;
538 HRESULT hr;
540 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
542 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
543 *layer = &object->ID2D1Layer_iface;
545 return hr;
548 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext *iface, ID2D1Mesh **mesh)
550 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
551 struct d2d_mesh *object;
552 HRESULT hr;
554 TRACE("iface %p, mesh %p.\n", iface, mesh);
556 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
557 *mesh = &object->ID2D1Mesh_iface;
559 return hr;
562 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext *iface,
563 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
565 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
566 ID2D1PathGeometry *geometry;
567 ID2D1GeometrySink *sink;
568 HRESULT hr;
570 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
571 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
573 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
575 WARN("Failed to create path geometry, hr %#lx.\n", hr);
576 return;
579 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
581 WARN("Failed to open geometry sink, hr %#lx.\n", hr);
582 ID2D1PathGeometry_Release(geometry);
583 return;
586 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
587 ID2D1GeometrySink_AddLine(sink, p1);
588 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
589 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
590 WARN("Failed to close geometry sink, hr %#lx.\n", hr);
591 ID2D1GeometrySink_Release(sink);
593 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
594 ID2D1PathGeometry_Release(geometry);
597 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext *iface,
598 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
600 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
601 ID2D1RectangleGeometry *geometry;
602 HRESULT hr;
604 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
605 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
607 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
609 ERR("Failed to create geometry, hr %#lx.\n", hr);
610 return;
613 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
614 ID2D1RectangleGeometry_Release(geometry);
617 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext *iface,
618 const D2D1_RECT_F *rect, ID2D1Brush *brush)
620 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
621 ID2D1RectangleGeometry *geometry;
622 HRESULT hr;
624 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
626 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
628 ERR("Failed to create geometry, hr %#lx.\n", hr);
629 return;
632 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
633 ID2D1RectangleGeometry_Release(geometry);
636 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext *iface,
637 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
639 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
640 ID2D1RoundedRectangleGeometry *geometry;
641 HRESULT hr;
643 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
644 iface, rect, brush, stroke_width, stroke_style);
646 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
648 ERR("Failed to create geometry, hr %#lx.\n", hr);
649 return;
652 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
653 ID2D1RoundedRectangleGeometry_Release(geometry);
656 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext *iface,
657 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
659 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
660 ID2D1RoundedRectangleGeometry *geometry;
661 HRESULT hr;
663 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
665 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
667 ERR("Failed to create geometry, hr %#lx.\n", hr);
668 return;
671 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
672 ID2D1RoundedRectangleGeometry_Release(geometry);
675 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext *iface,
676 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
678 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
679 ID2D1EllipseGeometry *geometry;
680 HRESULT hr;
682 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
683 iface, ellipse, brush, stroke_width, stroke_style);
685 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
687 ERR("Failed to create geometry, hr %#lx.\n", hr);
688 return;
691 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
692 ID2D1EllipseGeometry_Release(geometry);
695 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext *iface,
696 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
698 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
699 ID2D1EllipseGeometry *geometry;
700 HRESULT hr;
702 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
704 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
706 ERR("Failed to create geometry, hr %#lx.\n", hr);
707 return;
710 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
711 ID2D1EllipseGeometry_Release(geometry);
714 static HRESULT d2d_device_context_update_ps_cb(struct d2d_device_context *context,
715 struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, BOOL is_arc)
717 D3D11_MAPPED_SUBRESOURCE map_desc;
718 ID3D11DeviceContext *d3d_context;
719 struct d2d_ps_cb *cb_data;
720 HRESULT hr;
722 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
724 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->ps_cb,
725 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
727 WARN("Failed to map constant buffer, hr %#lx.\n", hr);
728 ID3D11DeviceContext_Release(d3d_context);
729 return hr;
732 cb_data = map_desc.pData;
733 cb_data->outline = outline;
734 cb_data->is_arc = is_arc;
735 cb_data->pad[0] = 0;
736 cb_data->pad[1] = 0;
737 if (!d2d_brush_fill_cb(brush, &cb_data->colour_brush))
738 WARN("Failed to initialize colour brush buffer.\n");
739 if (!d2d_brush_fill_cb(opacity_brush, &cb_data->opacity_brush))
740 WARN("Failed to initialize opacity brush buffer.\n");
742 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->ps_cb, 0);
743 ID3D11DeviceContext_Release(d3d_context);
745 return hr;
748 static HRESULT d2d_device_context_update_vs_cb(struct d2d_device_context *context,
749 const D2D_MATRIX_3X2_F *geometry_transform, float stroke_width)
751 D3D11_MAPPED_SUBRESOURCE map_desc;
752 ID3D11DeviceContext *d3d_context;
753 const D2D1_MATRIX_3X2_F *w;
754 struct d2d_vs_cb *cb_data;
755 float tmp_x, tmp_y;
756 HRESULT hr;
758 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
760 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->vs_cb,
761 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
763 WARN("Failed to map constant buffer, hr %#lx.\n", hr);
764 ID3D11DeviceContext_Release(d3d_context);
765 return hr;
768 cb_data = map_desc.pData;
769 cb_data->transform_geometry._11 = geometry_transform->_11;
770 cb_data->transform_geometry._21 = geometry_transform->_21;
771 cb_data->transform_geometry._31 = geometry_transform->_31;
772 cb_data->transform_geometry.pad0 = 0.0f;
773 cb_data->transform_geometry._12 = geometry_transform->_12;
774 cb_data->transform_geometry._22 = geometry_transform->_22;
775 cb_data->transform_geometry._32 = geometry_transform->_32;
776 cb_data->transform_geometry.stroke_width = stroke_width;
778 w = &context->drawing_state.transform;
780 tmp_x = context->desc.dpiX / 96.0f;
781 cb_data->transform_rtx.x = w->_11 * tmp_x;
782 cb_data->transform_rtx.y = w->_21 * tmp_x;
783 cb_data->transform_rtx.z = w->_31 * tmp_x;
784 cb_data->transform_rtx.w = 2.0f / context->pixel_size.width;
786 tmp_y = context->desc.dpiY / 96.0f;
787 cb_data->transform_rty.x = w->_12 * tmp_y;
788 cb_data->transform_rty.y = w->_22 * tmp_y;
789 cb_data->transform_rty.z = w->_32 * tmp_y;
790 cb_data->transform_rty.w = -2.0f / context->pixel_size.height;
792 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->vs_cb, 0);
793 ID3D11DeviceContext_Release(d3d_context);
795 return S_OK;
798 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
799 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
801 D3D11_SUBRESOURCE_DATA buffer_data;
802 D3D11_BUFFER_DESC buffer_desc;
803 ID3D11Buffer *ib, *vb;
804 HRESULT hr;
806 if (FAILED(hr = d2d_device_context_update_vs_cb(render_target, &geometry->transform, stroke_width)))
808 WARN("Failed to update vs constant buffer, hr %#lx.\n", hr);
809 return;
812 if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, FALSE)))
814 WARN("Failed to update ps constant buffer, hr %#lx.\n", hr);
815 return;
818 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
819 buffer_desc.CPUAccessFlags = 0;
820 buffer_desc.MiscFlags = 0;
822 buffer_data.SysMemPitch = 0;
823 buffer_data.SysMemSlicePitch = 0;
825 if (geometry->outline.face_count)
827 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
828 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
829 buffer_data.pSysMem = geometry->outline.faces;
831 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
833 WARN("Failed to create index buffer, hr %#lx.\n", hr);
834 return;
837 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
838 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
839 buffer_data.pSysMem = geometry->outline.vertices;
841 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
843 ERR("Failed to create vertex buffer, hr %#lx.\n", hr);
844 ID3D11Buffer_Release(ib);
845 return;
848 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
849 sizeof(*geometry->outline.vertices), brush, NULL);
851 ID3D11Buffer_Release(vb);
852 ID3D11Buffer_Release(ib);
855 if (geometry->outline.bezier_face_count)
857 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
858 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
859 buffer_data.pSysMem = geometry->outline.bezier_faces;
861 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
863 WARN("Failed to create curves index buffer, hr %#lx.\n", hr);
864 return;
867 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
868 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
869 buffer_data.pSysMem = geometry->outline.beziers;
871 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
873 ERR("Failed to create curves vertex buffer, hr %#lx.\n", hr);
874 ID3D11Buffer_Release(ib);
875 return;
878 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
879 3 * geometry->outline.bezier_face_count, vb,
880 sizeof(*geometry->outline.beziers), brush, NULL);
882 ID3D11Buffer_Release(vb);
883 ID3D11Buffer_Release(ib);
886 if (geometry->outline.arc_face_count)
888 buffer_desc.ByteWidth = geometry->outline.arc_face_count * sizeof(*geometry->outline.arc_faces);
889 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
890 buffer_data.pSysMem = geometry->outline.arc_faces;
892 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
894 WARN("Failed to create arcs index buffer, hr %#lx.\n", hr);
895 return;
898 buffer_desc.ByteWidth = geometry->outline.arc_count * sizeof(*geometry->outline.arcs);
899 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
900 buffer_data.pSysMem = geometry->outline.arcs;
902 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
904 ERR("Failed to create arcs vertex buffer, hr %#lx.\n", hr);
905 ID3D11Buffer_Release(ib);
906 return;
909 if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, TRUE)))
910 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
911 3 * geometry->outline.arc_face_count, vb,
912 sizeof(*geometry->outline.arcs), brush, NULL);
914 ID3D11Buffer_Release(vb);
915 ID3D11Buffer_Release(ib);
919 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext *iface,
920 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
922 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
923 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
924 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
926 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
927 iface, geometry, brush, stroke_width, stroke_style);
929 if (stroke_style)
930 FIXME("Ignoring stroke style %p.\n", stroke_style);
932 d2d_device_context_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
935 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
936 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
938 D3D11_SUBRESOURCE_DATA buffer_data;
939 D3D11_BUFFER_DESC buffer_desc;
940 ID3D11Buffer *ib, *vb;
941 HRESULT hr;
943 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
944 buffer_desc.CPUAccessFlags = 0;
945 buffer_desc.MiscFlags = 0;
947 buffer_data.SysMemPitch = 0;
948 buffer_data.SysMemSlicePitch = 0;
950 if (FAILED(hr = d2d_device_context_update_vs_cb(render_target, &geometry->transform, 0.0f)))
952 WARN("Failed to update vs constant buffer, hr %#lx.\n", hr);
953 return;
956 if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, FALSE)))
958 WARN("Failed to update ps constant buffer, hr %#lx.\n", hr);
959 return;
962 if (geometry->fill.face_count)
964 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
965 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
966 buffer_data.pSysMem = geometry->fill.faces;
968 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
970 WARN("Failed to create index buffer, hr %#lx.\n", hr);
971 return;
974 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
975 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
976 buffer_data.pSysMem = geometry->fill.vertices;
978 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
980 ERR("Failed to create vertex buffer, hr %#lx.\n", hr);
981 ID3D11Buffer_Release(ib);
982 return;
985 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
986 sizeof(*geometry->fill.vertices), brush, opacity_brush);
988 ID3D11Buffer_Release(vb);
989 ID3D11Buffer_Release(ib);
992 if (geometry->fill.bezier_vertex_count)
994 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
995 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
996 buffer_data.pSysMem = geometry->fill.bezier_vertices;
998 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1000 ERR("Failed to create curves vertex buffer, hr %#lx.\n", hr);
1001 return;
1004 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.bezier_vertex_count, vb,
1005 sizeof(*geometry->fill.bezier_vertices), brush, opacity_brush);
1007 ID3D11Buffer_Release(vb);
1010 if (geometry->fill.arc_vertex_count)
1012 buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices);
1013 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1014 buffer_data.pSysMem = geometry->fill.arc_vertices;
1016 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1018 ERR("Failed to create arc vertex buffer, hr %#lx.\n", hr);
1019 return;
1022 if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, TRUE)))
1023 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
1024 sizeof(*geometry->fill.arc_vertices), brush, opacity_brush);
1026 ID3D11Buffer_Release(vb);
1030 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
1031 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
1033 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
1034 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
1035 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1036 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
1038 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
1040 if (FAILED(context->error.code))
1041 return;
1043 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
1045 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
1046 return;
1049 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
1052 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext *iface,
1053 ID2D1Mesh *mesh, ID2D1Brush *brush)
1055 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1058 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext *iface,
1059 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1060 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1062 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1063 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1066 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1067 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1068 const D2D1_RECT_F *src_rect, const D2D1_POINT_2F *offset,
1069 const D2D1_MATRIX_4X4_F *perspective_transform)
1071 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1072 D2D1_BRUSH_PROPERTIES brush_desc;
1073 struct d2d_brush *brush;
1074 D2D1_SIZE_F size;
1075 D2D1_RECT_F s, d;
1076 HRESULT hr;
1078 if (perspective_transform)
1079 FIXME("Perspective transform is ignored.\n");
1081 size = ID2D1Bitmap_GetSize(bitmap);
1082 d2d_rect_set(&s, 0.0f, 0.0f, size.width, size.height);
1083 if (src_rect && src_rect->left <= src_rect->right
1084 && src_rect->top <= src_rect->bottom)
1086 d2d_rect_intersect(&s, src_rect);
1089 if (s.left == s.right || s.top == s.bottom)
1090 return;
1092 if (dst_rect)
1094 d = *dst_rect;
1096 else
1098 d.left = 0.0f;
1099 d.top = 0.0f;
1100 d.right = s.right - s.left;
1101 d.bottom = s.bottom - s.top;
1104 if (offset)
1106 d.left += offset->x;
1107 d.top += offset->y;
1108 d.right += offset->x;
1109 d.bottom += offset->y;
1112 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1113 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1114 bitmap_brush_desc.interpolationMode = interpolation_mode;
1116 brush_desc.opacity = opacity;
1117 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1118 brush_desc.transform._21 = 0.0f;
1119 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1120 brush_desc.transform._12 = 0.0f;
1121 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1122 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1124 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1126 ERR("Failed to create bitmap brush, hr %#lx.\n", hr);
1127 return;
1130 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext_iface, &d, &brush->ID2D1Brush_iface);
1131 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1134 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext *iface,
1135 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1136 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1138 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1140 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1141 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1143 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1144 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1146 d2d_device_context_set_error(context, E_INVALIDARG);
1147 return;
1150 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
1151 src_rect, NULL, NULL);
1154 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext *iface,
1155 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1156 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1158 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1159 IDWriteTextLayout *text_layout;
1160 IDWriteFactory *dwrite_factory;
1161 D2D1_POINT_2F origin;
1162 float width, height;
1163 HRESULT hr;
1165 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1166 "brush %p, options %#x, measuring_mode %#x.\n",
1167 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1168 brush, options, measuring_mode);
1170 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1171 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1173 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
1174 return;
1177 width = max(0.0f, layout_rect->right - layout_rect->left);
1178 height = max(0.0f, layout_rect->bottom - layout_rect->top);
1179 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1180 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1181 width, height, &text_layout);
1182 else
1183 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1184 width, height, render_target->desc.dpiX / 96.0f, (DWRITE_MATRIX *)&render_target->drawing_state.transform,
1185 measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1186 IDWriteFactory_Release(dwrite_factory);
1187 if (FAILED(hr))
1189 ERR("Failed to create text layout, hr %#lx.\n", hr);
1190 return;
1193 d2d_point_set(&origin, min(layout_rect->left, layout_rect->right), min(layout_rect->top, layout_rect->bottom));
1194 ID2D1DeviceContext_DrawTextLayout(iface, origin, text_layout, brush, options);
1195 IDWriteTextLayout_Release(text_layout);
1198 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext *iface,
1199 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1201 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1202 struct d2d_draw_text_layout_ctx ctx;
1203 HRESULT hr;
1205 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1206 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1208 ctx.brush = brush;
1209 ctx.options = options;
1211 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1212 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1213 FIXME("Failed to draw text layout, hr %#lx.\n", hr);
1216 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1218 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1219 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1220 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1221 return prev_antialias_mode;
1224 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1225 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1227 D2D1_MATRIX_3X2_F *transform, prev_transform;
1228 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1229 ID2D1PathGeometry *geometry;
1230 ID2D1GeometrySink *sink;
1231 HRESULT hr;
1233 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1235 ERR("Failed to create geometry, hr %#lx.\n", hr);
1236 return;
1239 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1241 ERR("Failed to open geometry sink, hr %#lx.\n", hr);
1242 ID2D1PathGeometry_Release(geometry);
1243 return;
1246 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1247 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1248 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1250 ERR("Failed to get glyph run outline, hr %#lx.\n", hr);
1251 ID2D1GeometrySink_Release(sink);
1252 ID2D1PathGeometry_Release(geometry);
1253 return;
1256 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1257 ERR("Failed to close geometry sink, hr %#lx.\n", hr);
1258 ID2D1GeometrySink_Release(sink);
1260 transform = &render_target->drawing_state.transform;
1261 prev_transform = *transform;
1262 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1263 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1264 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1265 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1266 unsafe_impl_from_ID2D1Brush(brush), NULL);
1267 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1268 *transform = prev_transform;
1270 ID2D1PathGeometry_Release(geometry);
1273 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1274 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1275 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1276 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1278 ID2D1RectangleGeometry *geometry = NULL;
1279 ID2D1BitmapBrush *opacity_brush = NULL;
1280 D2D1_BITMAP_PROPERTIES bitmap_desc;
1281 ID2D1Bitmap *opacity_bitmap = NULL;
1282 IDWriteGlyphRunAnalysis *analysis;
1283 DWRITE_TEXTURE_TYPE texture_type;
1284 D2D1_BRUSH_PROPERTIES brush_desc;
1285 IDWriteFactory2 *dwrite_factory;
1286 D2D1_MATRIX_3X2_F *transform, m;
1287 void *opacity_values = NULL;
1288 size_t opacity_values_size;
1289 D2D1_SIZE_U bitmap_size;
1290 float scale_x, scale_y;
1291 D2D1_RECT_F run_rect;
1292 RECT bounds;
1293 HRESULT hr;
1295 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1296 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1298 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
1299 return;
1302 transform = &render_target->drawing_state.transform;
1304 scale_x = render_target->desc.dpiX / 96.0f;
1305 m._11 = transform->_11 * scale_x;
1306 m._21 = transform->_21 * scale_x;
1307 m._31 = transform->_31 * scale_x;
1309 scale_y = render_target->desc.dpiY / 96.0f;
1310 m._12 = transform->_12 * scale_y;
1311 m._22 = transform->_22 * scale_y;
1312 m._32 = transform->_32 * scale_y;
1314 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1315 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1316 baseline_origin.x, baseline_origin.y, &analysis);
1317 IDWriteFactory2_Release(dwrite_factory);
1318 if (FAILED(hr))
1320 ERR("Failed to create glyph run analysis, hr %#lx.\n", hr);
1321 return;
1324 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1325 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1326 else
1327 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1329 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1331 ERR("Failed to get alpha texture bounds, hr %#lx.\n", hr);
1332 goto done;
1335 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1336 if (!bitmap_size.width || !bitmap_size.height)
1338 /* Empty run, nothing to do. */
1339 goto done;
1342 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1343 bitmap_size.width *= 3;
1344 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1346 ERR("Failed to allocate opacity values.\n");
1347 goto done;
1349 opacity_values_size = bitmap_size.height * bitmap_size.width;
1351 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1352 texture_type, &bounds, opacity_values, opacity_values_size)))
1354 ERR("Failed to create alpha texture, hr %#lx.\n", hr);
1355 goto done;
1358 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1359 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1360 bitmap_desc.dpiX = render_target->desc.dpiX;
1361 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1362 bitmap_desc.dpiX *= 3.0f;
1363 bitmap_desc.dpiY = render_target->desc.dpiY;
1364 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext_iface,
1365 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1367 ERR("Failed to create opacity bitmap, hr %#lx.\n", hr);
1368 goto done;
1371 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1372 bounds.right / scale_x, bounds.bottom / scale_y);
1374 brush_desc.opacity = 1.0f;
1375 brush_desc.transform._11 = 1.0f;
1376 brush_desc.transform._12 = 0.0f;
1377 brush_desc.transform._21 = 0.0f;
1378 brush_desc.transform._22 = 1.0f;
1379 brush_desc.transform._31 = run_rect.left;
1380 brush_desc.transform._32 = run_rect.top;
1381 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext_iface,
1382 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1384 ERR("Failed to create opacity bitmap brush, hr %#lx.\n", hr);
1385 goto done;
1388 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1390 ERR("Failed to create geometry, hr %#lx.\n", hr);
1391 goto done;
1394 m = *transform;
1395 *transform = identity;
1396 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1397 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1398 *transform = m;
1400 done:
1401 if (geometry)
1402 ID2D1RectangleGeometry_Release(geometry);
1403 if (opacity_brush)
1404 ID2D1BitmapBrush_Release(opacity_brush);
1405 if (opacity_bitmap)
1406 ID2D1Bitmap_Release(opacity_bitmap);
1407 heap_free(opacity_values);
1408 IDWriteGlyphRunAnalysis_Release(analysis);
1411 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext *iface,
1412 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1413 DWRITE_MEASURING_MODE measuring_mode)
1415 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1416 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1418 ID2D1DeviceContext_DrawGlyphRun(iface, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1421 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext *iface,
1422 const D2D1_MATRIX_3X2_F *transform)
1424 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1426 TRACE("iface %p, transform %p.\n", iface, transform);
1428 render_target->drawing_state.transform = *transform;
1431 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext *iface,
1432 D2D1_MATRIX_3X2_F *transform)
1434 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1436 TRACE("iface %p, transform %p.\n", iface, transform);
1438 *transform = render_target->drawing_state.transform;
1441 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext *iface,
1442 D2D1_ANTIALIAS_MODE antialias_mode)
1444 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1446 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1448 render_target->drawing_state.antialiasMode = antialias_mode;
1451 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext *iface)
1453 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1455 TRACE("iface %p.\n", iface);
1457 return render_target->drawing_state.antialiasMode;
1460 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext *iface,
1461 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1463 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1465 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1467 render_target->drawing_state.textAntialiasMode = antialias_mode;
1470 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext *iface)
1472 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1474 TRACE("iface %p.\n", iface);
1476 return render_target->drawing_state.textAntialiasMode;
1479 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext *iface,
1480 IDWriteRenderingParams *text_rendering_params)
1482 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1484 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1486 if (text_rendering_params)
1487 IDWriteRenderingParams_AddRef(text_rendering_params);
1488 if (render_target->text_rendering_params)
1489 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1490 render_target->text_rendering_params = text_rendering_params;
1493 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext *iface,
1494 IDWriteRenderingParams **text_rendering_params)
1496 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1498 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1500 if ((*text_rendering_params = render_target->text_rendering_params))
1501 IDWriteRenderingParams_AddRef(*text_rendering_params);
1504 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1506 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1508 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1510 render_target->drawing_state.tag1 = tag1;
1511 render_target->drawing_state.tag2 = tag2;
1514 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1516 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1518 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1520 *tag1 = render_target->drawing_state.tag1;
1521 *tag2 = render_target->drawing_state.tag2;
1524 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext *iface,
1525 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1527 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1530 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *iface)
1532 FIXME("iface %p stub!\n", iface);
1535 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1537 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1539 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1541 if (context->ops && context->ops->device_context_present)
1542 context->ops->device_context_present(context->outer_unknown);
1544 return E_NOTIMPL;
1547 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext *iface,
1548 ID2D1DrawingStateBlock *state_block)
1550 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1551 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1553 TRACE("iface %p, state_block %p.\n", iface, state_block);
1555 state_block_impl->drawing_state = render_target->drawing_state;
1556 if (render_target->text_rendering_params)
1557 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1558 if (state_block_impl->text_rendering_params)
1559 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1560 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1563 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext *iface,
1564 ID2D1DrawingStateBlock *state_block)
1566 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1567 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1569 TRACE("iface %p, state_block %p.\n", iface, state_block);
1571 render_target->drawing_state = state_block_impl->drawing_state;
1572 if (state_block_impl->text_rendering_params)
1573 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1574 if (render_target->text_rendering_params)
1575 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1576 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1579 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext *iface,
1580 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1582 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1583 D2D1_RECT_F transformed_rect;
1584 float x_scale, y_scale;
1585 D2D1_POINT_2F point;
1587 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1589 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1590 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1592 x_scale = render_target->desc.dpiX / 96.0f;
1593 y_scale = render_target->desc.dpiY / 96.0f;
1594 d2d_point_transform(&point, &render_target->drawing_state.transform,
1595 clip_rect->left * x_scale, clip_rect->top * y_scale);
1596 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1597 d2d_point_transform(&point, &render_target->drawing_state.transform,
1598 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1599 d2d_rect_expand(&transformed_rect, &point);
1600 d2d_point_transform(&point, &render_target->drawing_state.transform,
1601 clip_rect->right * x_scale, clip_rect->top * y_scale);
1602 d2d_rect_expand(&transformed_rect, &point);
1603 d2d_point_transform(&point, &render_target->drawing_state.transform,
1604 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1605 d2d_rect_expand(&transformed_rect, &point);
1607 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1608 WARN("Failed to push clip rect.\n");
1611 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext *iface)
1613 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1615 TRACE("iface %p.\n", iface);
1617 d2d_clip_stack_pop(&render_target->clip_stack);
1620 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface, const D2D1_COLOR_F *colour)
1622 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1623 D3D11_MAPPED_SUBRESOURCE map_desc;
1624 ID3D11DeviceContext *d3d_context;
1625 struct d2d_ps_cb *ps_cb_data;
1626 struct d2d_vs_cb *vs_cb_data;
1627 D2D1_COLOR_F *c;
1628 HRESULT hr;
1630 TRACE("iface %p, colour %p.\n", iface, colour);
1632 ID3D11Device1_GetImmediateContext(render_target->d3d_device, &d3d_context);
1634 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)render_target->vs_cb,
1635 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
1637 WARN("Failed to map vs constant buffer, hr %#lx.\n", hr);
1638 ID3D11DeviceContext_Release(d3d_context);
1639 return;
1642 vs_cb_data = map_desc.pData;
1643 vs_cb_data->transform_geometry._11 = 1.0f;
1644 vs_cb_data->transform_geometry._21 = 0.0f;
1645 vs_cb_data->transform_geometry._31 = 0.0f;
1646 vs_cb_data->transform_geometry.pad0 = 0.0f;
1647 vs_cb_data->transform_geometry._12 = 0.0f;
1648 vs_cb_data->transform_geometry._22 = 1.0f;
1649 vs_cb_data->transform_geometry._32 = 0.0f;
1650 vs_cb_data->transform_geometry.stroke_width = 0.0f;
1651 vs_cb_data->transform_rtx.x = 1.0f;
1652 vs_cb_data->transform_rtx.y = 0.0f;
1653 vs_cb_data->transform_rtx.z = 1.0f;
1654 vs_cb_data->transform_rtx.w = 1.0f;
1655 vs_cb_data->transform_rty.x = 0.0f;
1656 vs_cb_data->transform_rty.y = 1.0f;
1657 vs_cb_data->transform_rty.z = 1.0f;
1658 vs_cb_data->transform_rty.w = -1.0f;
1660 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)render_target->vs_cb, 0);
1662 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)render_target->ps_cb,
1663 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
1665 WARN("Failed to map ps constant buffer, hr %#lx.\n", hr);
1666 ID3D11DeviceContext_Release(d3d_context);
1667 return;
1670 ps_cb_data = map_desc.pData;
1671 memset(ps_cb_data, 0, sizeof(*ps_cb_data));
1672 ps_cb_data->colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1673 ps_cb_data->colour_brush.opacity = 1.0f;
1674 ps_cb_data->opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1675 c = &ps_cb_data->colour_brush.u.solid.colour;
1676 if (colour)
1677 *c = *colour;
1678 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1679 c->a = 1.0f;
1680 c->r *= c->a;
1681 c->g *= c->a;
1682 c->b *= c->a;
1684 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)render_target->ps_cb, 0);
1685 ID3D11DeviceContext_Release(d3d_context);
1687 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1688 render_target->vb, render_target->vb_stride, NULL, NULL);
1691 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
1693 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1695 TRACE("iface %p.\n", iface);
1697 memset(&render_target->error, 0, sizeof(render_target->error));
1700 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface,
1701 D2D1_TAG *tag1, D2D1_TAG *tag2)
1703 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1704 HRESULT hr;
1706 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1708 if (tag1)
1709 *tag1 = context->error.tag1;
1710 if (tag2)
1711 *tag2 = context->error.tag2;
1713 if (context->ops && context->ops->device_context_present)
1715 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1716 context->error.code = hr;
1719 return context->error.code;
1722 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface,
1723 D2D1_PIXEL_FORMAT *format)
1725 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1727 TRACE("iface %p, format %p.\n", iface, format);
1729 *format = render_target->desc.pixelFormat;
1730 return format;
1733 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext *iface, float dpi_x, float dpi_y)
1735 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1737 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1739 if (dpi_x == 0.0f && dpi_y == 0.0f)
1741 dpi_x = 96.0f;
1742 dpi_y = 96.0f;
1744 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1745 return;
1747 render_target->desc.dpiX = dpi_x;
1748 render_target->desc.dpiY = dpi_y;
1751 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext *iface, float *dpi_x, float *dpi_y)
1753 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1755 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1757 *dpi_x = render_target->desc.dpiX;
1758 *dpi_y = render_target->desc.dpiY;
1761 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext *iface, D2D1_SIZE_F *size)
1763 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1765 TRACE("iface %p, size %p.\n", iface, size);
1767 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1768 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1769 return size;
1772 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext *iface,
1773 D2D1_SIZE_U *pixel_size)
1775 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1777 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1779 *pixel_size = render_target->pixel_size;
1780 return pixel_size;
1783 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext *iface)
1785 TRACE("iface %p.\n", iface);
1787 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1790 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext *iface,
1791 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1793 FIXME("iface %p, desc %p stub!\n", iface, desc);
1795 return FALSE;
1798 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext *iface,
1799 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
1800 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1802 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1803 struct d2d_bitmap *object;
1804 HRESULT hr;
1806 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
1807 iface, size.width, size.height, src_data, pitch, desc, bitmap);
1809 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
1810 *bitmap = &object->ID2D1Bitmap1_iface;
1812 return hr;
1815 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
1816 ID2D1DeviceContext *iface, IWICBitmapSource *bitmap_source,
1817 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1819 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1820 struct d2d_bitmap *object;
1821 HRESULT hr;
1823 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
1825 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
1826 *bitmap = &object->ID2D1Bitmap1_iface;
1828 return hr;
1831 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext *iface,
1832 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
1834 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
1835 iface, space, profile, profile_size, color_context);
1837 return E_NOTIMPL;
1840 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext *iface,
1841 const WCHAR *filename, ID2D1ColorContext **color_context)
1843 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
1845 return E_NOTIMPL;
1848 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext *iface,
1849 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
1851 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
1853 return E_NOTIMPL;
1856 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
1857 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1859 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1860 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
1861 struct d2d_bitmap *object;
1862 HRESULT hr;
1864 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
1866 if (!desc)
1868 DXGI_SURFACE_DESC surface_desc;
1870 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1872 WARN("Failed to get surface desc, hr %#lx.\n", hr);
1873 return hr;
1876 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
1877 bitmap_desc.pixelFormat.format = surface_desc.Format;
1878 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1879 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
1880 desc = &bitmap_desc;
1883 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
1884 *bitmap = &object->ID2D1Bitmap1_iface;
1886 return hr;
1889 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
1890 REFCLSID effect_id, ID2D1Effect **effect)
1892 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1893 struct d2d_effect_context *effect_context;
1894 HRESULT hr;
1896 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1898 if (!(effect_context = heap_alloc_zero(sizeof(*effect_context))))
1899 return E_OUTOFMEMORY;
1900 d2d_effect_context_init(effect_context, context);
1902 hr = ID2D1EffectContext_CreateEffect(&effect_context->ID2D1EffectContext_iface, effect_id, effect);
1904 ID2D1EffectContext_Release(&effect_context->ID2D1EffectContext_iface);
1905 return hr;
1908 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1909 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1910 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1911 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1912 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1914 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1915 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1916 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1917 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1919 return E_NOTIMPL;
1922 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1923 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1924 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1926 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1927 struct d2d_brush *object;
1928 HRESULT hr;
1930 TRACE("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p.\n", iface, image, image_brush_desc,
1931 brush_desc, brush);
1933 if (SUCCEEDED(hr = d2d_image_brush_create(context->factory, image, image_brush_desc,
1934 brush_desc, &object)))
1935 *brush = (ID2D1ImageBrush *)&object->ID2D1Brush_iface;
1937 return hr;
1940 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1941 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1942 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1944 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1945 struct d2d_brush *object;
1946 HRESULT hr;
1948 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1949 brush_desc, brush);
1951 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1952 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1954 return hr;
1957 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1958 ID2D1CommandList **command_list)
1960 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1962 return E_NOTIMPL;
1965 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1967 FIXME("iface %p, format %#x stub!\n", iface, format);
1969 return FALSE;
1972 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1973 D2D1_BUFFER_PRECISION buffer_precision)
1975 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1977 return FALSE;
1980 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1981 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1983 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1984 D2D_SIZE_U pixel_size;
1985 ID2D1Bitmap *bitmap;
1986 D2D_SIZE_F size;
1988 TRACE("iface %p, image %p, local_bounds %p.\n", iface, image, local_bounds);
1990 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
1992 local_bounds->left = 0.0f;
1993 local_bounds->top = 0.0f;
1994 switch (context->drawing_state.unitMode)
1996 case D2D1_UNIT_MODE_DIPS:
1997 size = ID2D1Bitmap_GetSize(bitmap);
1998 local_bounds->right = size.width;
1999 local_bounds->bottom = size.height;
2000 break;
2002 case D2D1_UNIT_MODE_PIXELS:
2003 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
2004 local_bounds->right = pixel_size.width;
2005 local_bounds->bottom = pixel_size.height;
2006 break;
2008 default:
2009 WARN("Unknown unit mode %#x.\n", context->drawing_state.unitMode);
2010 break;
2012 ID2D1Bitmap_Release(bitmap);
2014 else
2016 FIXME("Unable to get local bounds of image %p.\n", image);
2020 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
2021 ID2D1Image *image, D2D1_RECT_F *world_bounds)
2023 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
2025 return E_NOTIMPL;
2028 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
2029 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2030 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
2032 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
2033 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
2035 return E_NOTIMPL;
2038 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
2040 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2042 TRACE("iface %p, device %p.\n", iface, device);
2044 *device = context->device;
2045 ID2D1Device_AddRef(*device);
2048 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2050 if (!context->target)
2051 return;
2053 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
2054 context->target = NULL;
2056 /* Note that DPI settings are kept. */
2057 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2058 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2060 ID3D11BlendState_Release(context->bs);
2061 context->bs = NULL;
2064 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
2066 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2067 struct d2d_bitmap *bitmap_impl;
2068 D3D11_BLEND_DESC blend_desc;
2069 ID2D1Bitmap *bitmap;
2070 HRESULT hr;
2072 TRACE("iface %p, target %p.\n", iface, target);
2074 if (!target)
2076 d2d_device_context_reset_target(context);
2077 return;
2080 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2082 FIXME("Only bitmap targets are supported.\n");
2083 return;
2086 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2088 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2090 ID2D1Bitmap_Release(bitmap);
2091 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2092 return;
2095 d2d_device_context_reset_target(context);
2097 /* Set sizes and pixel format. */
2098 context->pixel_size = bitmap_impl->pixel_size;
2099 context->desc.pixelFormat = bitmap_impl->format;
2100 context->target = bitmap_impl;
2102 memset(&blend_desc, 0, sizeof(blend_desc));
2103 blend_desc.IndependentBlendEnable = FALSE;
2104 blend_desc.RenderTarget[0].BlendEnable = TRUE;
2105 blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
2106 blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
2107 blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
2108 blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
2109 blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
2110 blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
2111 blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
2112 if (FAILED(hr = ID3D11Device1_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2113 WARN("Failed to create blend state, hr %#lx.\n", hr);
2116 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2118 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2120 TRACE("iface %p, target %p.\n", iface, target);
2122 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2123 if (*target)
2124 ID2D1Image_AddRef(*target);
2127 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2128 const D2D1_RENDERING_CONTROLS *rendering_controls)
2130 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2133 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2134 D2D1_RENDERING_CONTROLS *rendering_controls)
2136 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2139 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2140 D2D1_PRIMITIVE_BLEND primitive_blend)
2142 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2145 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2147 FIXME("iface %p stub!\n", iface);
2149 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2152 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2154 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2156 TRACE("iface %p, unit_mode %#x.\n", iface, unit_mode);
2158 if (unit_mode != D2D1_UNIT_MODE_DIPS && unit_mode != D2D1_UNIT_MODE_PIXELS)
2160 WARN("Unknown unit mode %#x.\n", unit_mode);
2161 return;
2164 context->drawing_state.unitMode = unit_mode;
2167 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2169 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2171 TRACE("iface %p.\n", iface);
2173 return context->drawing_state.unitMode;
2176 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2177 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2178 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2180 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
2181 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2182 IDWriteRenderingParams *rendering_params;
2183 DWRITE_RENDERING_MODE rendering_mode;
2184 HRESULT hr;
2186 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2187 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2189 if (FAILED(context->error.code))
2190 return;
2192 rendering_params = context->text_rendering_params ? context->text_rendering_params
2193 : context->default_text_rendering_params;
2195 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
2197 switch (context->drawing_state.textAntialiasMode)
2199 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2200 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
2201 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
2202 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
2203 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
2204 d2d_device_context_set_error(context, E_INVALIDARG);
2205 break;
2207 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2208 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
2209 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2210 d2d_device_context_set_error(context, E_INVALIDARG);
2211 break;
2213 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
2214 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
2215 d2d_device_context_set_error(context, E_INVALIDARG);
2216 break;
2218 default:
2219 break;
2222 if (FAILED(context->error.code))
2223 return;
2225 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
2226 switch (context->drawing_state.textAntialiasMode)
2228 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
2229 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
2230 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2231 break;
2233 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2234 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2235 break;
2237 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2238 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
2239 break;
2241 default:
2242 break;
2245 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2247 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
2248 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
2249 measuring_mode, rendering_params, &rendering_mode)))
2251 ERR("Failed to get recommended rendering mode, hr %#lx.\n", hr);
2252 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
2256 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2257 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
2258 else
2259 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
2260 rendering_mode, measuring_mode, antialias_mode);
2263 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2264 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2265 D2D1_COMPOSITE_MODE composite_mode)
2267 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2268 ID2D1Bitmap *bitmap;
2270 TRACE("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x.\n",
2271 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2272 interpolation_mode, composite_mode);
2274 if (composite_mode != D2D1_COMPOSITE_MODE_SOURCE_OVER)
2275 FIXME("Unhandled composite mode %#x.\n", composite_mode);
2277 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
2279 d2d_device_context_draw_bitmap(context, bitmap, NULL, 1.0f, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
2280 image_rect, target_offset, NULL);
2282 ID2D1Bitmap_Release(bitmap);
2283 return;
2286 FIXME("Unhandled image %p.\n", image);
2289 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2290 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2292 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2293 iface, metafile, debug_d2d_point_2f(target_offset));
2296 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2297 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2298 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2300 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2302 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2303 "src_rect %s, perspective_transform %p.\n",
2304 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2305 debug_d2d_rect_f(src_rect), perspective_transform);
2307 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2308 NULL, perspective_transform);
2311 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2312 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2314 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2317 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2318 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2320 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2321 iface, effect, input, debug_d2d_rect_f(input_rect));
2323 return E_NOTIMPL;
2326 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2327 ID2D1Effect *effect, UINT32 *rect_count)
2329 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2331 return E_NOTIMPL;
2334 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2335 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2337 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2339 return E_NOTIMPL;
2342 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2343 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2344 D2D1_RECT_F *input_rect, UINT32 input_count)
2346 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2347 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2349 return E_NOTIMPL;
2352 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2353 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2355 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2356 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2359 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2361 d2d_device_context_QueryInterface,
2362 d2d_device_context_AddRef,
2363 d2d_device_context_Release,
2364 d2d_device_context_GetFactory,
2365 d2d_device_context_CreateBitmap,
2366 d2d_device_context_CreateBitmapFromWicBitmap,
2367 d2d_device_context_CreateSharedBitmap,
2368 d2d_device_context_CreateBitmapBrush,
2369 d2d_device_context_CreateSolidColorBrush,
2370 d2d_device_context_CreateGradientStopCollection,
2371 d2d_device_context_CreateLinearGradientBrush,
2372 d2d_device_context_CreateRadialGradientBrush,
2373 d2d_device_context_CreateCompatibleRenderTarget,
2374 d2d_device_context_CreateLayer,
2375 d2d_device_context_CreateMesh,
2376 d2d_device_context_DrawLine,
2377 d2d_device_context_DrawRectangle,
2378 d2d_device_context_FillRectangle,
2379 d2d_device_context_DrawRoundedRectangle,
2380 d2d_device_context_FillRoundedRectangle,
2381 d2d_device_context_DrawEllipse,
2382 d2d_device_context_FillEllipse,
2383 d2d_device_context_DrawGeometry,
2384 d2d_device_context_FillGeometry,
2385 d2d_device_context_FillMesh,
2386 d2d_device_context_FillOpacityMask,
2387 d2d_device_context_DrawBitmap,
2388 d2d_device_context_DrawText,
2389 d2d_device_context_DrawTextLayout,
2390 d2d_device_context_DrawGlyphRun,
2391 d2d_device_context_SetTransform,
2392 d2d_device_context_GetTransform,
2393 d2d_device_context_SetAntialiasMode,
2394 d2d_device_context_GetAntialiasMode,
2395 d2d_device_context_SetTextAntialiasMode,
2396 d2d_device_context_GetTextAntialiasMode,
2397 d2d_device_context_SetTextRenderingParams,
2398 d2d_device_context_GetTextRenderingParams,
2399 d2d_device_context_SetTags,
2400 d2d_device_context_GetTags,
2401 d2d_device_context_PushLayer,
2402 d2d_device_context_PopLayer,
2403 d2d_device_context_Flush,
2404 d2d_device_context_SaveDrawingState,
2405 d2d_device_context_RestoreDrawingState,
2406 d2d_device_context_PushAxisAlignedClip,
2407 d2d_device_context_PopAxisAlignedClip,
2408 d2d_device_context_Clear,
2409 d2d_device_context_BeginDraw,
2410 d2d_device_context_EndDraw,
2411 d2d_device_context_GetPixelFormat,
2412 d2d_device_context_SetDpi,
2413 d2d_device_context_GetDpi,
2414 d2d_device_context_GetSize,
2415 d2d_device_context_GetPixelSize,
2416 d2d_device_context_GetMaximumBitmapSize,
2417 d2d_device_context_IsSupported,
2418 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2419 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2420 d2d_device_context_CreateColorContext,
2421 d2d_device_context_CreateColorContextFromFilename,
2422 d2d_device_context_CreateColorContextFromWicColorContext,
2423 d2d_device_context_CreateBitmapFromDxgiSurface,
2424 d2d_device_context_CreateEffect,
2425 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2426 d2d_device_context_CreateImageBrush,
2427 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2428 d2d_device_context_CreateCommandList,
2429 d2d_device_context_IsDxgiFormatSupported,
2430 d2d_device_context_IsBufferPrecisionSupported,
2431 d2d_device_context_GetImageLocalBounds,
2432 d2d_device_context_GetImageWorldBounds,
2433 d2d_device_context_GetGlyphRunWorldBounds,
2434 d2d_device_context_GetDevice,
2435 d2d_device_context_SetTarget,
2436 d2d_device_context_GetTarget,
2437 d2d_device_context_SetRenderingControls,
2438 d2d_device_context_GetRenderingControls,
2439 d2d_device_context_SetPrimitiveBlend,
2440 d2d_device_context_GetPrimitiveBlend,
2441 d2d_device_context_SetUnitMode,
2442 d2d_device_context_GetUnitMode,
2443 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2444 d2d_device_context_DrawImage,
2445 d2d_device_context_DrawGdiMetafile,
2446 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2447 d2d_device_context_ID2D1DeviceContext_PushLayer,
2448 d2d_device_context_InvalidateEffectInputRectangle,
2449 d2d_device_context_GetEffectInvalidRectangleCount,
2450 d2d_device_context_GetEffectInvalidRectangles,
2451 d2d_device_context_GetEffectRequiredInputRectangles,
2452 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2455 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2457 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2460 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2462 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2464 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2465 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2466 || IsEqualGUID(iid, &IID_IUnknown))
2468 IDWriteTextRenderer_AddRef(iface);
2469 *out = iface;
2470 return S_OK;
2473 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2475 *out = NULL;
2476 return E_NOINTERFACE;
2479 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2481 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2483 TRACE("iface %p.\n", iface);
2485 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2488 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2490 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2492 TRACE("iface %p.\n", iface);
2494 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2497 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2498 void *ctx, BOOL *disabled)
2500 struct d2d_draw_text_layout_ctx *context = ctx;
2502 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2504 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2506 return S_OK;
2509 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2510 void *ctx, DWRITE_MATRIX *transform)
2512 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2514 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2516 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2518 return S_OK;
2521 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2523 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2525 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2527 *ppd = render_target->desc.dpiY / 96.0f;
2529 return S_OK;
2532 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2533 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2534 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2536 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2537 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2538 struct d2d_draw_text_layout_ctx *context = ctx;
2539 BOOL color_font = FALSE;
2540 ID2D1Brush *brush;
2542 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2543 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2544 iface, ctx, baseline_origin_x, baseline_origin_y,
2545 measuring_mode, glyph_run, desc, effect);
2547 if (desc)
2548 WARN("Ignoring glyph run description %p.\n", desc);
2549 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2550 FIXME("Ignoring options %#x.\n", context->options);
2552 brush = d2d_draw_get_text_brush(context, effect);
2554 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2556 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2558 IDWriteFontFace2 *fontface;
2560 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2561 &IID_IDWriteFontFace2, (void **)&fontface)))
2563 color_font = IDWriteFontFace2_IsColorFont(fontface);
2564 IDWriteFontFace2_Release(fontface);
2568 if (color_font)
2570 IDWriteColorGlyphRunEnumerator *layers;
2571 IDWriteFactory2 *dwrite_factory;
2572 HRESULT hr;
2574 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2575 (IUnknown **)&dwrite_factory)))
2577 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
2578 ID2D1Brush_Release(brush);
2579 return hr;
2582 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2583 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2584 IDWriteFactory2_Release(dwrite_factory);
2585 if (FAILED(hr))
2587 ERR("Failed to create colour glyph run enumerator, hr %#lx.\n", hr);
2588 ID2D1Brush_Release(brush);
2589 return hr;
2592 for (;;)
2594 const DWRITE_COLOR_GLYPH_RUN *color_run;
2595 ID2D1Brush *color_brush;
2596 D2D1_POINT_2F origin;
2597 BOOL has_run = FALSE;
2599 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2601 ERR("Failed to switch colour glyph layer, hr %#lx.\n", hr);
2602 break;
2605 if (!has_run)
2606 break;
2608 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2610 ERR("Failed to get current colour run, hr %#lx.\n", hr);
2611 break;
2614 if (color_run->paletteIndex == 0xffff)
2615 color_brush = brush;
2616 else
2618 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2619 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2621 ERR("Failed to create solid colour brush, hr %#lx.\n", hr);
2622 break;
2626 origin.x = color_run->baselineOriginX;
2627 origin.y = color_run->baselineOriginY;
2628 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2629 origin, &color_run->glyphRun, color_brush, measuring_mode);
2631 if (color_brush != brush)
2632 ID2D1Brush_Release(color_brush);
2635 IDWriteColorGlyphRunEnumerator_Release(layers);
2637 else
2638 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2639 baseline_origin, glyph_run, brush, measuring_mode);
2641 ID2D1Brush_Release(brush);
2643 return S_OK;
2646 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2647 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2649 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2650 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2651 struct d2d_draw_text_layout_ctx *context = ctx;
2652 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2653 D2D1_POINT_2F start, end;
2654 ID2D1Brush *brush;
2655 float thickness;
2657 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2658 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2660 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2661 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2662 underline->thickness);
2664 brush = d2d_draw_get_text_brush(context, effect);
2666 start.x = baseline_origin_x;
2667 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2668 end.x = start.x + underline->width;
2669 end.y = start.y;
2670 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2671 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2672 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2674 ID2D1Brush_Release(brush);
2676 return S_OK;
2679 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2680 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2682 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2683 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2684 struct d2d_draw_text_layout_ctx *context = ctx;
2685 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2686 D2D1_POINT_2F start, end;
2687 ID2D1Brush *brush;
2688 float thickness;
2690 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2691 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2693 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2694 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2695 strikethrough->thickness);
2697 brush = d2d_draw_get_text_brush(context, effect);
2699 start.x = baseline_origin_x;
2700 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2701 end.x = start.x + strikethrough->width;
2702 end.y = start.y;
2703 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2704 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2705 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2707 ID2D1Brush_Release(brush);
2709 return S_OK;
2712 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2713 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2715 struct d2d_draw_text_layout_ctx *context = ctx;
2716 ID2D1Brush *brush;
2717 HRESULT hr;
2719 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2720 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2722 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2723 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2724 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2725 brush is selected at Direct2D level. */
2726 brush = context->brush;
2727 context->brush = d2d_draw_get_text_brush(context, effect);
2729 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2731 ID2D1Brush_Release(context->brush);
2732 context->brush = brush;
2734 return hr;
2737 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2739 d2d_text_renderer_QueryInterface,
2740 d2d_text_renderer_AddRef,
2741 d2d_text_renderer_Release,
2742 d2d_text_renderer_IsPixelSnappingDisabled,
2743 d2d_text_renderer_GetCurrentTransform,
2744 d2d_text_renderer_GetPixelsPerDip,
2745 d2d_text_renderer_DrawGlyphRun,
2746 d2d_text_renderer_DrawUnderline,
2747 d2d_text_renderer_DrawStrikethrough,
2748 d2d_text_renderer_DrawInlineObject,
2751 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2753 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2756 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2757 REFIID iid, void **out)
2759 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2761 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2763 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2766 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2768 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2770 TRACE("iface %p.\n", iface);
2772 return IUnknown_AddRef(render_target->outer_unknown);
2775 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2777 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2779 TRACE("iface %p.\n", iface);
2781 return IUnknown_Release(render_target->outer_unknown);
2784 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2786 ID3D11Resource *resource;
2787 HRESULT hr;
2789 ID3D11RenderTargetView_GetResource(render_target->target->rtv, &resource);
2790 hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2791 ID3D11Resource_Release(resource);
2792 if (FAILED(hr))
2794 *surface = NULL;
2795 WARN("Failed to get DXGI surface, %#lx.\n", hr);
2796 return hr;
2799 return hr;
2802 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2803 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2805 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2806 IDXGISurface1 *surface;
2807 HRESULT hr;
2809 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2811 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2812 return hr;
2814 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2815 IDXGISurface1_Release(surface);
2817 return hr;
2820 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2821 const RECT *update)
2823 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2824 IDXGISurface1 *surface;
2825 RECT update_rect;
2826 HRESULT hr;
2828 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2830 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2831 return hr;
2833 if (update)
2834 update_rect = *update;
2835 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2836 IDXGISurface1_Release(surface);
2838 return hr;
2841 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2843 d2d_gdi_interop_render_target_QueryInterface,
2844 d2d_gdi_interop_render_target_AddRef,
2845 d2d_gdi_interop_render_target_Release,
2846 d2d_gdi_interop_render_target_GetDC,
2847 d2d_gdi_interop_render_target_ReleaseDC,
2850 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2851 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2853 D3D11_SUBRESOURCE_DATA buffer_data;
2854 struct d2d_device *device_impl;
2855 IDWriteFactory *dwrite_factory;
2856 D3D11_RASTERIZER_DESC rs_desc;
2857 D3D11_BUFFER_DESC buffer_desc;
2858 unsigned int i;
2859 HRESULT hr;
2861 static const D3D11_INPUT_ELEMENT_DESC il_desc_outline[] =
2863 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2864 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2865 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
2867 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
2869 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2870 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2871 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
2872 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
2873 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
2874 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0},
2876 static const D3D11_INPUT_ELEMENT_DESC il_desc_triangle[] =
2878 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2880 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve[] =
2882 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2883 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2885 static const DWORD vs_code_outline[] =
2887 #if 0
2888 float3x2 transform_geometry;
2889 float stroke_width;
2890 float4 transform_rtx;
2891 float4 transform_rty;
2893 struct output
2895 float2 p : WORLD_POSITION;
2896 float4 b : BEZIER;
2897 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2898 float4 position : SV_POSITION;
2901 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2903 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2905 * Where:
2907 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2908 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2909 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2910 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2912 float2 q_prev, q_next, v_p, q_i;
2913 float2x2 geom;
2914 float l;
2916 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2918 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2919 q_prev = normalize(mul(geom, prev));
2920 q_next = normalize(mul(geom, next));
2922 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2923 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2924 v_p = float2(-q_prev.y, q_prev.x);
2925 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2926 q_i = l * q_prev + v_p;
2928 o.b = float4(0.0, 0.0, 0.0, 0.0);
2930 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2931 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2932 * float2(transform_rtx.w, transform_rty.w);
2933 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2935 #endif
2936 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2937 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2938 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2939 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2940 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2941 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2942 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2943 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2944 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2945 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2946 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2947 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2948 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2949 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2950 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2951 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2952 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2953 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2954 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2955 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2956 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2957 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2958 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2959 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2960 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2961 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2962 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2963 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2964 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2965 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2966 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2967 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2968 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2969 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2970 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2971 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2972 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2973 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2974 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2975 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2976 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2977 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2978 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2979 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2980 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2981 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2982 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2983 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2984 0x3f800000, 0x0100003e,
2986 /* ⎡p0.x p0.y 1⎤
2987 * A = ⎢p1.x p1.y 1⎥
2988 * ⎣p2.x p2.y 1⎦
2990 * ⎡0 0⎤
2991 * B = ⎢½ 0⎥
2992 * ⎣1 1⎦
2994 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2995 * ⎣p2.x-p0.x p2.y-p0.y⎦
2997 * B' = ⎡½ 0⎤
2998 * ⎣1 1⎦
3000 * A'T = B'
3001 * T = A'⁻¹B'
3003 static const DWORD vs_code_bezier_outline[] =
3005 #if 0
3006 float3x2 transform_geometry;
3007 float stroke_width;
3008 float4 transform_rtx;
3009 float4 transform_rty;
3011 struct output
3013 float2 p : WORLD_POSITION;
3014 float4 b : BEZIER;
3015 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3016 float4 position : SV_POSITION;
3019 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3020 float2 prev : PREV, float2 next : NEXT, out struct output o)
3022 float2 q_prev, q_next, v_p, q_i, p;
3023 float2x2 geom, rt;
3024 float l;
3026 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3027 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3028 o.stroke_transform = rt * stroke_width * 0.5f;
3030 p = mul(geom, position);
3031 p0 = mul(geom, p0);
3032 p1 = mul(geom, p1);
3033 p2 = mul(geom, p2);
3035 p -= p0;
3036 p1 -= p0;
3037 p2 -= p0;
3039 q_prev = normalize(mul(geom, prev));
3040 q_next = normalize(mul(geom, next));
3042 v_p = float2(-q_prev.y, q_prev.x);
3043 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3044 q_i = l * q_prev + v_p;
3045 p += 0.5f * stroke_width * q_i;
3047 v_p = mul(rt, p2);
3048 v_p = normalize(float2(-v_p.y, v_p.x));
3049 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
3051 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
3052 o.b.y = dot(mul(rt, p), v_p);
3054 else
3056 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
3057 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
3058 o.b.x = dot(v_p, p1 - 0.5f * p2);
3059 o.b.y = dot(v_p, p1);
3062 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3063 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3064 * float2(transform_rtx.w, transform_rty.w);
3065 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3067 #endif
3068 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3069 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3070 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3071 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3072 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3073 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3074 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3075 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3076 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3077 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3078 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3079 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3080 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3081 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3082 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3083 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3084 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3085 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3086 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3087 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3088 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3089 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3090 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3091 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3092 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3093 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3094 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3095 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3096 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3097 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3098 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3099 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3100 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3101 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3102 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3103 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3104 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3105 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3106 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3107 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3108 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3109 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3110 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3111 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3112 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3113 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3114 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3115 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3116 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3117 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3118 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3119 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3120 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3121 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3122 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3123 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3124 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3125 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3126 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3127 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3128 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3129 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3130 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3131 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3132 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3133 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3134 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3135 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3136 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3137 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3138 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3139 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3140 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3141 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3142 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3143 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3144 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3145 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3146 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3147 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3148 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3149 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3150 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3151 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3152 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3153 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3154 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3155 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3157 /* ⎡p0.x p0.y 1⎤
3158 * A = ⎢p1.x p1.y 1⎥
3159 * ⎣p2.x p2.y 1⎦
3161 * ⎡1 0⎤
3162 * B = ⎢1 1⎥
3163 * ⎣0 1⎦
3165 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3166 * ⎣p2.x-p0.x p2.y-p0.y⎦
3168 * B' = ⎡ 0 1⎤
3169 * ⎣-1 1⎦
3171 * A'T = B'
3172 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3174 static const DWORD vs_code_arc_outline[] =
3176 #if 0
3177 float3x2 transform_geometry;
3178 float stroke_width;
3179 float4 transform_rtx;
3180 float4 transform_rty;
3182 struct output
3184 float2 p : WORLD_POSITION;
3185 float4 b : BEZIER;
3186 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3187 float4 position : SV_POSITION;
3190 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3191 float2 prev : PREV, float2 next : NEXT, out struct output o)
3193 float2 q_prev, q_next, v_p, q_i, p;
3194 float2x2 geom, rt, p_inv;
3195 float l;
3196 float a;
3197 float2 bc;
3199 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3200 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3201 o.stroke_transform = rt * stroke_width * 0.5f;
3203 p = mul(geom, position);
3204 p0 = mul(geom, p0);
3205 p1 = mul(geom, p1);
3206 p2 = mul(geom, p2);
3208 p -= p0;
3209 p1 -= p0;
3210 p2 -= p0;
3212 q_prev = normalize(mul(geom, prev));
3213 q_next = normalize(mul(geom, next));
3215 v_p = float2(-q_prev.y, q_prev.x);
3216 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3217 q_i = l * q_prev + v_p;
3218 p += 0.5f * stroke_width * q_i;
3220 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3221 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3222 o.b.zw = 0.0f;
3224 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3225 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3226 * float2(transform_rtx.w, transform_rty.w);
3227 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3229 #endif
3230 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3231 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3232 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3233 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3234 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3235 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3236 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3237 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3238 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3239 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3240 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3241 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3242 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3243 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3244 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3245 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3246 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3247 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3248 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3249 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3250 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3251 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3252 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3253 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3254 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3255 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3256 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3257 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3258 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3259 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3260 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3261 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3262 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3263 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3264 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3265 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3266 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3267 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3268 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3269 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3270 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3271 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3272 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3273 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3274 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3275 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3276 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3277 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3278 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3279 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3280 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3281 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3282 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3283 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3284 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3285 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3286 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3287 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3288 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3289 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3290 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3291 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3292 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3293 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3294 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3295 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3296 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3297 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3298 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3299 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3300 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3301 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3302 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3303 0x0100003e,
3305 static const DWORD vs_code_triangle[] =
3307 #if 0
3308 float3x2 transform_geometry;
3309 float4 transform_rtx;
3310 float4 transform_rty;
3312 struct output
3314 float2 p : WORLD_POSITION;
3315 float4 b : BEZIER;
3316 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3317 float4 position : SV_POSITION;
3320 void main(float2 position : POSITION, out struct output o)
3322 o.p = mul(float3(position, 1.0f), transform_geometry);
3323 o.b = float4(1.0, 0.0, 1.0, 1.0);
3324 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3325 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3326 * float2(transform_rtx.w, transform_rty.w);
3327 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3329 #endif
3330 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3331 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3332 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3333 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3334 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3335 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3336 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3337 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3338 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3339 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3340 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3341 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3342 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3343 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3344 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3345 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3346 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3347 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3348 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3349 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3350 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3351 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3352 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3353 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3354 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3355 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3356 0x00000000, 0x3f800000, 0x0100003e,
3358 static const DWORD vs_code_curve[] =
3360 #if 0
3361 float3x2 transform_geometry;
3362 float4 transform_rtx;
3363 float4 transform_rty;
3365 struct output
3367 float2 p : WORLD_POSITION;
3368 float4 b : BEZIER;
3369 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3370 float4 position : SV_POSITION;
3373 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3375 o.p = mul(float3(position, 1.0f), transform_geometry);
3376 o.b = float4(texcoord, 1.0);
3377 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3378 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3379 * float2(transform_rtx.w, transform_rty.w);
3380 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3382 #endif
3383 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3384 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3385 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3386 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3387 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3388 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3389 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3390 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3391 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3392 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3393 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3394 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3395 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3396 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3397 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3398 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3399 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3400 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3401 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3402 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3403 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3404 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3405 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3406 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3407 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3408 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3409 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3410 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3412 static const DWORD ps_code[] =
3414 #if 0
3415 #define BRUSH_TYPE_SOLID 0
3416 #define BRUSH_TYPE_LINEAR 1
3417 #define BRUSH_TYPE_RADIAL 2
3418 #define BRUSH_TYPE_BITMAP 3
3419 #define BRUSH_TYPE_COUNT 4
3421 bool outline;
3422 bool is_arc;
3423 struct brush
3425 uint type;
3426 float opacity;
3427 float4 data[3];
3428 } colour_brush, opacity_brush;
3430 SamplerState s0, s1;
3431 Texture2D t0, t1;
3432 Buffer<float4> b0, b1;
3434 struct input
3436 float2 p : WORLD_POSITION;
3437 float4 b : BEZIER;
3438 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3441 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3443 float4 c_low, c_high;
3444 float p_low, p_high;
3445 uint i;
3447 p_low = gradient.Load(0).x;
3448 c_low = gradient.Load(1);
3449 c_high = c_low;
3451 if (position < p_low)
3452 return c_low;
3454 for (i = 1; i < stop_count; ++i)
3456 p_high = gradient.Load(i * 2).x;
3457 c_high = gradient.Load(i * 2 + 1);
3459 if (position >= p_low && position <= p_high)
3460 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3462 p_low = p_high;
3463 c_low = c_high;
3466 return c_high;
3469 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3471 float2 start, end, v_p, v_q;
3472 uint stop_count;
3473 float p;
3475 start = brush.data[0].xy;
3476 end = brush.data[0].zw;
3477 stop_count = asuint(brush.data[1].x);
3479 v_p = position - start;
3480 v_q = end - start;
3481 p = dot(v_q, v_p) / dot(v_q, v_q);
3483 return sample_gradient(gradient, stop_count, p);
3486 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3488 float2 centre, offset, ra, rb, v_p, v_q, r;
3489 float b, c, l, t;
3490 uint stop_count;
3492 centre = brush.data[0].xy;
3493 offset = brush.data[0].zw;
3494 ra = brush.data[1].xy;
3495 rb = brush.data[1].zw;
3496 stop_count = asuint(brush.data[2].x);
3498 /* Project onto ra, rb. */
3499 r = float2(dot(ra, ra), dot(rb, rb));
3500 v_p = position - (centre + offset);
3501 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3502 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3504 /* ‖t·p̂ + q⃑‖ = 1
3505 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3506 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3508 * b = p̂·q⃑
3509 * c = q⃑·q⃑ - 1
3510 * t = -b + √(b² - c) */
3511 l = length(v_p);
3512 b = dot(v_p, v_q) / l;
3513 c = dot(v_q, v_q) - 1.0;
3514 t = -b + sqrt(b * b - c);
3516 return sample_gradient(gradient, stop_count, l / t);
3519 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3521 float3 transform[2];
3522 bool ignore_alpha;
3523 float2 texcoord;
3524 float4 colour;
3526 transform[0] = brush.data[0].xyz;
3527 transform[1] = brush.data[1].xyz;
3528 ignore_alpha = asuint(brush.data[1].w);
3530 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3531 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3532 colour = t.Sample(s, texcoord);
3533 if (ignore_alpha)
3534 colour.a = 1.0;
3535 return colour;
3538 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3540 if (brush.type == BRUSH_TYPE_SOLID)
3541 return brush.data[0] * brush.opacity;
3542 if (brush.type == BRUSH_TYPE_LINEAR)
3543 return brush_linear(brush, b, position) * brush.opacity;
3544 if (brush.type == BRUSH_TYPE_RADIAL)
3545 return brush_radial(brush, b, position) * brush.opacity;
3546 if (brush.type == BRUSH_TYPE_BITMAP)
3547 return brush_bitmap(brush, t, s, position) * brush.opacity;
3548 return float4(0.0, 0.0, 0.0, brush.opacity);
3551 float4 main(struct input i) : SV_Target
3553 float4 colour;
3555 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3556 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3557 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3559 if (outline)
3561 float2 du, dv, df;
3562 float4 uv;
3564 /* Evaluate the implicit form of the curve (u² - v = 0
3565 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3566 * space, using the screen-space partial derivatives
3567 * to convert the calculated distance to object space.
3569 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3570 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3572 * For Béziers:
3573 * f(x, y) = u(x, y)² - v(x, y)
3574 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3575 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3577 * For arcs:
3578 * f(x, y) = u(x, y)² + v(x, y)² - 1
3579 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3580 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3581 uv = i.b;
3582 du = float2(ddx(uv.x), ddy(uv.x));
3583 dv = float2(ddx(uv.y), ddy(uv.y));
3585 if (!is_arc)
3587 df = 2.0f * uv.x * du - dv;
3589 clip(dot(df, uv.zw));
3590 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3592 else
3594 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3596 clip(dot(df, uv.zw));
3597 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3600 else
3602 /* Evaluate the implicit form of the curve in texture space.
3603 * "i.b.z" determines which side of the curve is shaded. */
3604 if (!is_arc)
3606 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3608 else
3610 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3614 return colour;
3616 #endif
3617 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3618 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3619 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3620 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3621 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3622 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3623 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3624 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3625 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3626 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3627 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3628 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3629 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3630 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3631 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3632 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3633 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3634 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3635 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3636 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3637 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3638 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3639 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3640 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3641 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3642 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3643 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3644 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3645 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3646 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3647 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3648 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3649 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3650 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3651 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3652 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3653 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3654 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3655 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3656 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3657 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3658 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3659 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3660 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3661 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3662 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3663 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3664 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3665 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3666 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3667 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3668 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3669 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3670 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3671 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3672 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3673 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3674 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3675 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3676 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3677 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3678 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3679 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3680 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3681 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3682 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3683 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3684 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3685 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3686 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3687 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3688 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3689 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3690 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3691 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3692 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3693 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3694 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3695 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3696 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3697 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3698 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3699 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3700 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3701 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3702 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3703 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3704 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3705 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3706 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3707 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3708 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3709 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3710 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3711 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3712 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3713 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3714 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3715 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3716 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3717 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3718 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3719 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3720 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3721 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3722 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3723 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3724 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3725 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3726 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3727 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3728 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3729 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3730 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3731 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3732 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3733 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3734 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3735 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3736 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3737 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3738 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3739 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3740 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3741 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3742 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3743 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3744 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3745 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3746 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3747 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3748 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3749 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3750 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3751 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3752 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3753 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3754 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3755 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3756 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3757 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3758 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3759 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3760 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3761 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3762 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3763 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3764 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3765 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3766 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3767 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3768 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3769 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3770 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3771 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3772 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3773 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3774 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3775 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3776 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3777 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3778 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3779 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3780 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3781 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3782 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3783 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3784 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3785 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3786 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3787 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3788 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3789 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3790 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3791 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3792 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3793 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3794 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3795 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3796 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3797 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3798 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3799 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3800 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3801 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3802 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3803 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3804 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3805 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3806 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3807 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3808 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3809 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3810 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3811 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3812 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3813 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3814 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3815 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3816 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3817 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3818 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3819 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3820 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3821 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3822 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3823 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3824 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3825 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3826 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3827 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3828 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3829 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3830 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
3831 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
3832 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
3833 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
3834 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
3835 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
3836 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
3837 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
3838 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3839 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
3840 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
3841 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
3842 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
3843 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
3844 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
3845 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
3846 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
3847 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
3848 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
3849 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
3850 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
3851 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
3852 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
3853 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
3854 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
3855 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
3856 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
3857 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
3858 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
3859 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3860 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
3861 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
3862 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
3863 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
3864 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
3865 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
3866 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
3867 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
3868 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
3869 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
3870 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
3871 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
3872 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
3874 static const struct shape_info
3876 enum d2d_shape_type shape_type;
3877 const D3D11_INPUT_ELEMENT_DESC *il_desc;
3878 unsigned int il_element_count;
3879 const void *vs_code;
3880 size_t vs_code_size;
3882 shape_info[] =
3884 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3885 vs_code_outline, sizeof(vs_code_outline)},
3886 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3887 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3888 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3889 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
3890 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3891 vs_code_triangle, sizeof(vs_code_triangle)},
3892 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
3893 vs_code_curve, sizeof(vs_code_curve)},
3895 static const struct
3897 float x, y;
3899 quad[] =
3901 {-1.0f, 1.0f},
3902 {-1.0f, -1.0f},
3903 { 1.0f, 1.0f},
3904 { 1.0f, -1.0f},
3906 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3907 static const D3D_FEATURE_LEVEL feature_levels = D3D_FEATURE_LEVEL_10_0;
3909 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3910 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3911 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3912 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3913 render_target->refcount = 1;
3914 ID2D1Device_GetFactory(device, &render_target->factory);
3915 render_target->device = device;
3916 ID2D1Device_AddRef(render_target->device);
3918 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3919 render_target->ops = ops;
3921 device_impl = unsafe_impl_from_ID2D1Device(device);
3922 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3923 &IID_ID3D11Device1, (void **)&render_target->d3d_device)))
3925 WARN("Failed to query ID3D11Device1 interface, hr %#lx.\n", hr);
3926 goto err;
3929 if (FAILED(hr = ID3D11Device1_CreateDeviceContextState(render_target->d3d_device,
3930 0, &feature_levels, 1, D3D11_SDK_VERSION, &IID_ID3D11Device1, NULL,
3931 &render_target->d3d_state)))
3933 WARN("Failed to create device context state, hr %#lx.\n", hr);
3934 goto err;
3937 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3939 const struct shape_info *si = &shape_info[i];
3941 if (FAILED(hr = ID3D11Device1_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3942 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3944 WARN("Failed to create input layout for shape type %#x, hr %#lx.\n", si->shape_type, hr);
3945 goto err;
3948 if (FAILED(hr = ID3D11Device1_CreateVertexShader(render_target->d3d_device, si->vs_code,
3949 si->vs_code_size, NULL, &render_target->shape_resources[si->shape_type].vs)))
3951 WARN("Failed to create vertex shader for shape type %#x, hr %#lx.\n", si->shape_type, hr);
3952 goto err;
3957 buffer_desc.ByteWidth = sizeof(struct d2d_vs_cb);
3958 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
3959 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
3960 buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
3961 buffer_desc.MiscFlags = 0;
3963 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
3964 &render_target->vs_cb)))
3966 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
3967 goto err;
3970 if (FAILED(hr = ID3D11Device1_CreatePixelShader(render_target->d3d_device,
3971 ps_code, sizeof(ps_code), NULL, &render_target->ps)))
3973 WARN("Failed to create pixel shader, hr %#lx.\n", hr);
3974 goto err;
3977 buffer_desc.ByteWidth = sizeof(struct d2d_ps_cb);
3978 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
3979 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
3980 buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
3981 buffer_desc.MiscFlags = 0;
3983 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
3984 &render_target->ps_cb)))
3986 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
3987 goto err;
3990 buffer_desc.ByteWidth = sizeof(indices);
3991 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
3992 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
3993 buffer_desc.CPUAccessFlags = 0;
3994 buffer_desc.MiscFlags = 0;
3996 buffer_data.pSysMem = indices;
3997 buffer_data.SysMemPitch = 0;
3998 buffer_data.SysMemSlicePitch = 0;
4000 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4001 &buffer_desc, &buffer_data, &render_target->ib)))
4003 WARN("Failed to create clear index buffer, hr %#lx.\n", hr);
4004 goto err;
4007 buffer_desc.ByteWidth = sizeof(quad);
4008 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
4009 buffer_data.pSysMem = quad;
4011 render_target->vb_stride = sizeof(*quad);
4012 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4013 &buffer_desc, &buffer_data, &render_target->vb)))
4015 WARN("Failed to create clear vertex buffer, hr %#lx.\n", hr);
4016 goto err;
4019 rs_desc.FillMode = D3D11_FILL_SOLID;
4020 rs_desc.CullMode = D3D11_CULL_NONE;
4021 rs_desc.FrontCounterClockwise = FALSE;
4022 rs_desc.DepthBias = 0;
4023 rs_desc.DepthBiasClamp = 0.0f;
4024 rs_desc.SlopeScaledDepthBias = 0.0f;
4025 rs_desc.DepthClipEnable = TRUE;
4026 rs_desc.ScissorEnable = TRUE;
4027 rs_desc.MultisampleEnable = FALSE;
4028 rs_desc.AntialiasedLineEnable = FALSE;
4029 if (FAILED(hr = ID3D11Device1_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
4031 WARN("Failed to create clear rasteriser state, hr %#lx.\n", hr);
4032 goto err;
4035 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
4036 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
4038 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
4039 goto err;
4042 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
4043 IDWriteFactory_Release(dwrite_factory);
4044 if (FAILED(hr))
4046 ERR("Failed to create default text rendering parameters, hr %#lx.\n", hr);
4047 goto err;
4050 render_target->drawing_state.transform = identity;
4052 if (!d2d_clip_stack_init(&render_target->clip_stack))
4054 WARN("Failed to initialize clip stack.\n");
4055 hr = E_FAIL;
4056 goto err;
4059 render_target->desc.dpiX = 96.0f;
4060 render_target->desc.dpiY = 96.0f;
4062 return S_OK;
4064 err:
4065 if (render_target->default_text_rendering_params)
4066 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
4067 if (render_target->rs)
4068 ID3D11RasterizerState_Release(render_target->rs);
4069 if (render_target->vb)
4070 ID3D11Buffer_Release(render_target->vb);
4071 if (render_target->ib)
4072 ID3D11Buffer_Release(render_target->ib);
4073 if (render_target->ps_cb)
4074 ID3D11Buffer_Release(render_target->ps_cb);
4075 if (render_target->ps)
4076 ID3D11PixelShader_Release(render_target->ps);
4077 if (render_target->vs_cb)
4078 ID3D11Buffer_Release(render_target->vs_cb);
4079 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
4081 if (render_target->shape_resources[i].vs)
4082 ID3D11VertexShader_Release(render_target->shape_resources[i].vs);
4083 if (render_target->shape_resources[i].il)
4084 ID3D11InputLayout_Release(render_target->shape_resources[i].il);
4086 if (render_target->d3d_state)
4087 ID3DDeviceContextState_Release(render_target->d3d_state);
4088 if (render_target->d3d_device)
4089 ID3D11Device1_Release(render_target->d3d_device);
4090 ID2D1Device_Release(render_target->device);
4091 ID2D1Factory_Release(render_target->factory);
4092 return hr;
4095 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4096 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4098 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4099 struct d2d_device_context *object;
4100 ID2D1Bitmap1 *bitmap;
4101 HRESULT hr;
4103 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4104 WARN("Ignoring render target type %#x.\n", desc->type);
4105 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4106 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4107 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4108 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4110 bitmap_desc.dpiX = desc->dpiX;
4111 bitmap_desc.dpiY = desc->dpiY;
4113 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4115 bitmap_desc.dpiX = 96.0f;
4116 bitmap_desc.dpiY = 96.0f;
4118 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4119 return E_INVALIDARG;
4121 if (!(object = heap_alloc_zero(sizeof(*object))))
4122 return E_OUTOFMEMORY;
4124 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4126 WARN("Failed to initialise render target, hr %#lx.\n", hr);
4127 heap_free(object);
4128 return hr;
4131 ID2D1DeviceContext_SetDpi(&object->ID2D1DeviceContext_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4133 if (surface)
4135 bitmap_desc.pixelFormat = desc->pixelFormat;
4136 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4137 bitmap_desc.colorContext = NULL;
4139 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
4140 surface, &bitmap_desc, &bitmap)))
4142 WARN("Failed to create target bitmap, hr %#lx.\n", hr);
4143 IUnknown_Release(&object->IUnknown_iface);
4144 heap_free(object);
4145 return hr;
4148 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
4149 ID2D1Bitmap1_Release(bitmap);
4151 else
4152 object->desc.pixelFormat = desc->pixelFormat;
4154 TRACE("Created render target %p.\n", object);
4155 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
4157 return S_OK;
4160 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
4162 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4164 if (IsEqualGUID(iid, &IID_ID2D1Device)
4165 || IsEqualGUID(iid, &IID_ID2D1Resource)
4166 || IsEqualGUID(iid, &IID_IUnknown))
4168 ID2D1Device_AddRef(iface);
4169 *out = iface;
4170 return S_OK;
4173 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4175 *out = NULL;
4176 return E_NOINTERFACE;
4179 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
4181 struct d2d_device *device = impl_from_ID2D1Device(iface);
4182 ULONG refcount = InterlockedIncrement(&device->refcount);
4184 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4186 return refcount;
4189 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
4191 struct d2d_device *device = impl_from_ID2D1Device(iface);
4192 ULONG refcount = InterlockedDecrement(&device->refcount);
4194 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4196 if (!refcount)
4198 IDXGIDevice_Release(device->dxgi_device);
4199 ID2D1Factory1_Release(device->factory);
4200 heap_free(device);
4203 return refcount;
4206 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
4208 struct d2d_device *device = impl_from_ID2D1Device(iface);
4210 TRACE("iface %p, factory %p.\n", iface, factory);
4212 *factory = (ID2D1Factory *)device->factory;
4213 ID2D1Factory1_AddRef(device->factory);
4216 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4217 ID2D1DeviceContext **context)
4219 struct d2d_device_context *object;
4220 HRESULT hr;
4222 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4224 if (options)
4225 FIXME("Options are ignored %#x.\n", options);
4227 if (!(object = heap_alloc_zero(sizeof(*object))))
4228 return E_OUTOFMEMORY;
4230 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
4232 WARN("Failed to initialise device context, hr %#lx.\n", hr);
4233 heap_free(object);
4234 return hr;
4237 TRACE("Created device context %p.\n", object);
4238 *context = &object->ID2D1DeviceContext_iface;
4240 return S_OK;
4243 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
4244 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4245 ID2D1PrintControl **print_control)
4247 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4248 document_target, desc, print_control);
4250 return E_NOTIMPL;
4253 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
4255 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4258 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
4260 FIXME("iface %p stub!\n", iface);
4262 return 0;
4265 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
4267 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4269 return E_NOTIMPL;
4272 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
4274 d2d_device_QueryInterface,
4275 d2d_device_AddRef,
4276 d2d_device_Release,
4277 d2d_device_GetFactory,
4278 d2d_device_CreateDeviceContext,
4279 d2d_device_CreatePrintControl,
4280 d2d_device_SetMaximumTextureMemory,
4281 d2d_device_GetMaximumTextureMemory,
4282 d2d_device_ClearResources,
4285 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
4287 if (!iface)
4288 return NULL;
4289 assert(iface->lpVtbl == &d2d_device_vtbl);
4290 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
4293 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4295 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
4296 device->refcount = 1;
4297 device->factory = iface;
4298 ID2D1Factory1_AddRef(device->factory);
4299 device->dxgi_device = dxgi_device;
4300 IDXGIDevice_AddRef(device->dxgi_device);