winex11: Use NtUserBuildHwndList for has_owned_popup implementation.
[wine.git] / dlls / d2d1 / device.c
blob13c99458cfa75b8d55039b3fe6ed8840edb04acd
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 *object;
1894 HRESULT hr;
1896 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1898 if (!(object = heap_alloc_zero(sizeof(*object))))
1899 return E_OUTOFMEMORY;
1901 if (FAILED(hr = d2d_effect_init(object, context->factory, effect_id)))
1903 WARN("Failed to initialise effect, hr %#lx.\n", hr);
1904 heap_free(object);
1905 return hr;
1908 TRACE("Created effect %p.\n", object);
1909 *effect = &object->ID2D1Effect_iface;
1911 return S_OK;
1914 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1915 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1916 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1917 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1918 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1920 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1921 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1922 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1923 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1925 return E_NOTIMPL;
1928 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1929 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1930 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1932 FIXME("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p stub!\n",
1933 iface, image, image_brush_desc, brush_desc, brush);
1935 return E_NOTIMPL;
1938 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1939 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1940 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1942 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1943 struct d2d_brush *object;
1944 HRESULT hr;
1946 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1947 brush_desc, brush);
1949 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1950 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1952 return hr;
1955 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1956 ID2D1CommandList **command_list)
1958 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1960 return E_NOTIMPL;
1963 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1965 FIXME("iface %p, format %#x stub!\n", iface, format);
1967 return FALSE;
1970 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1971 D2D1_BUFFER_PRECISION buffer_precision)
1973 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1975 return FALSE;
1978 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1979 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1981 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1982 D2D_SIZE_U pixel_size;
1983 ID2D1Bitmap *bitmap;
1984 D2D_SIZE_F size;
1986 TRACE("iface %p, image %p, local_bounds %p.\n", iface, image, local_bounds);
1988 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
1990 local_bounds->left = 0.0f;
1991 local_bounds->top = 0.0f;
1992 switch (context->drawing_state.unitMode)
1994 case D2D1_UNIT_MODE_DIPS:
1995 size = ID2D1Bitmap_GetSize(bitmap);
1996 local_bounds->right = size.width;
1997 local_bounds->bottom = size.height;
1998 break;
2000 case D2D1_UNIT_MODE_PIXELS:
2001 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
2002 local_bounds->right = pixel_size.width;
2003 local_bounds->bottom = pixel_size.height;
2004 break;
2006 default:
2007 WARN("Unknown unit mode %#x.\n", context->drawing_state.unitMode);
2008 break;
2010 ID2D1Bitmap_Release(bitmap);
2012 else
2014 FIXME("Unable to get local bounds of image %p.\n", image);
2018 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
2019 ID2D1Image *image, D2D1_RECT_F *world_bounds)
2021 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
2023 return E_NOTIMPL;
2026 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
2027 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2028 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
2030 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
2031 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
2033 return E_NOTIMPL;
2036 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
2038 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2040 TRACE("iface %p, device %p.\n", iface, device);
2042 *device = context->device;
2043 ID2D1Device_AddRef(*device);
2046 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2048 if (!context->target)
2049 return;
2051 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
2052 context->target = NULL;
2054 /* Note that DPI settings are kept. */
2055 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2056 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2058 ID3D11BlendState_Release(context->bs);
2059 context->bs = NULL;
2062 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
2064 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2065 struct d2d_bitmap *bitmap_impl;
2066 D3D11_BLEND_DESC blend_desc;
2067 ID2D1Bitmap *bitmap;
2068 HRESULT hr;
2070 TRACE("iface %p, target %p.\n", iface, target);
2072 if (!target)
2074 d2d_device_context_reset_target(context);
2075 return;
2078 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2080 FIXME("Only bitmap targets are supported.\n");
2081 return;
2084 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2086 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2088 ID2D1Bitmap_Release(bitmap);
2089 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2090 return;
2093 d2d_device_context_reset_target(context);
2095 /* Set sizes and pixel format. */
2096 context->pixel_size = bitmap_impl->pixel_size;
2097 context->desc.pixelFormat = bitmap_impl->format;
2098 context->target = bitmap_impl;
2100 memset(&blend_desc, 0, sizeof(blend_desc));
2101 blend_desc.IndependentBlendEnable = FALSE;
2102 blend_desc.RenderTarget[0].BlendEnable = TRUE;
2103 blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
2104 blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
2105 blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
2106 blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
2107 blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
2108 blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
2109 blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
2110 if (FAILED(hr = ID3D11Device1_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2111 WARN("Failed to create blend state, hr %#lx.\n", hr);
2114 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2116 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2118 TRACE("iface %p, target %p.\n", iface, target);
2120 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2121 if (*target)
2122 ID2D1Image_AddRef(*target);
2125 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2126 const D2D1_RENDERING_CONTROLS *rendering_controls)
2128 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2131 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2132 D2D1_RENDERING_CONTROLS *rendering_controls)
2134 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2137 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2138 D2D1_PRIMITIVE_BLEND primitive_blend)
2140 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2143 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2145 FIXME("iface %p stub!\n", iface);
2147 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2150 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2152 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2154 TRACE("iface %p, unit_mode %#x.\n", iface, unit_mode);
2156 if (unit_mode != D2D1_UNIT_MODE_DIPS && unit_mode != D2D1_UNIT_MODE_PIXELS)
2158 WARN("Unknown unit mode %#x.\n", unit_mode);
2159 return;
2162 context->drawing_state.unitMode = unit_mode;
2165 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2167 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2169 TRACE("iface %p.\n", iface);
2171 return context->drawing_state.unitMode;
2174 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2175 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2176 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2178 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
2179 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2180 IDWriteRenderingParams *rendering_params;
2181 DWRITE_RENDERING_MODE rendering_mode;
2182 HRESULT hr;
2184 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2185 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2187 if (FAILED(context->error.code))
2188 return;
2190 rendering_params = context->text_rendering_params ? context->text_rendering_params
2191 : context->default_text_rendering_params;
2193 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
2195 switch (context->drawing_state.textAntialiasMode)
2197 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2198 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
2199 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
2200 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
2201 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
2202 d2d_device_context_set_error(context, E_INVALIDARG);
2203 break;
2205 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2206 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
2207 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2208 d2d_device_context_set_error(context, E_INVALIDARG);
2209 break;
2211 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
2212 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
2213 d2d_device_context_set_error(context, E_INVALIDARG);
2214 break;
2216 default:
2217 break;
2220 if (FAILED(context->error.code))
2221 return;
2223 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
2224 switch (context->drawing_state.textAntialiasMode)
2226 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
2227 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
2228 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2229 break;
2231 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2232 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2233 break;
2235 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2236 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
2237 break;
2239 default:
2240 break;
2243 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2245 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
2246 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
2247 measuring_mode, rendering_params, &rendering_mode)))
2249 ERR("Failed to get recommended rendering mode, hr %#lx.\n", hr);
2250 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
2254 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2255 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
2256 else
2257 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
2258 rendering_mode, measuring_mode, antialias_mode);
2261 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2262 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2263 D2D1_COMPOSITE_MODE composite_mode)
2265 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2266 ID2D1Bitmap *bitmap;
2268 TRACE("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x.\n",
2269 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2270 interpolation_mode, composite_mode);
2272 if (composite_mode != D2D1_COMPOSITE_MODE_SOURCE_OVER)
2273 FIXME("Unhandled composite mode %#x.\n", composite_mode);
2275 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
2277 d2d_device_context_draw_bitmap(context, bitmap, NULL, 1.0f, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
2278 image_rect, target_offset, NULL);
2280 ID2D1Bitmap_Release(bitmap);
2281 return;
2284 FIXME("Unhandled image %p.\n", image);
2287 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2288 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2290 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2291 iface, metafile, debug_d2d_point_2f(target_offset));
2294 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2295 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2296 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2298 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2300 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2301 "src_rect %s, perspective_transform %p.\n",
2302 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2303 debug_d2d_rect_f(src_rect), perspective_transform);
2305 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2306 NULL, perspective_transform);
2309 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2310 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2312 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2315 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2316 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2318 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2319 iface, effect, input, debug_d2d_rect_f(input_rect));
2321 return E_NOTIMPL;
2324 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2325 ID2D1Effect *effect, UINT32 *rect_count)
2327 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2329 return E_NOTIMPL;
2332 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2333 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2335 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2337 return E_NOTIMPL;
2340 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2341 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2342 D2D1_RECT_F *input_rect, UINT32 input_count)
2344 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2345 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2347 return E_NOTIMPL;
2350 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2351 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2353 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2354 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2357 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2359 d2d_device_context_QueryInterface,
2360 d2d_device_context_AddRef,
2361 d2d_device_context_Release,
2362 d2d_device_context_GetFactory,
2363 d2d_device_context_CreateBitmap,
2364 d2d_device_context_CreateBitmapFromWicBitmap,
2365 d2d_device_context_CreateSharedBitmap,
2366 d2d_device_context_CreateBitmapBrush,
2367 d2d_device_context_CreateSolidColorBrush,
2368 d2d_device_context_CreateGradientStopCollection,
2369 d2d_device_context_CreateLinearGradientBrush,
2370 d2d_device_context_CreateRadialGradientBrush,
2371 d2d_device_context_CreateCompatibleRenderTarget,
2372 d2d_device_context_CreateLayer,
2373 d2d_device_context_CreateMesh,
2374 d2d_device_context_DrawLine,
2375 d2d_device_context_DrawRectangle,
2376 d2d_device_context_FillRectangle,
2377 d2d_device_context_DrawRoundedRectangle,
2378 d2d_device_context_FillRoundedRectangle,
2379 d2d_device_context_DrawEllipse,
2380 d2d_device_context_FillEllipse,
2381 d2d_device_context_DrawGeometry,
2382 d2d_device_context_FillGeometry,
2383 d2d_device_context_FillMesh,
2384 d2d_device_context_FillOpacityMask,
2385 d2d_device_context_DrawBitmap,
2386 d2d_device_context_DrawText,
2387 d2d_device_context_DrawTextLayout,
2388 d2d_device_context_DrawGlyphRun,
2389 d2d_device_context_SetTransform,
2390 d2d_device_context_GetTransform,
2391 d2d_device_context_SetAntialiasMode,
2392 d2d_device_context_GetAntialiasMode,
2393 d2d_device_context_SetTextAntialiasMode,
2394 d2d_device_context_GetTextAntialiasMode,
2395 d2d_device_context_SetTextRenderingParams,
2396 d2d_device_context_GetTextRenderingParams,
2397 d2d_device_context_SetTags,
2398 d2d_device_context_GetTags,
2399 d2d_device_context_PushLayer,
2400 d2d_device_context_PopLayer,
2401 d2d_device_context_Flush,
2402 d2d_device_context_SaveDrawingState,
2403 d2d_device_context_RestoreDrawingState,
2404 d2d_device_context_PushAxisAlignedClip,
2405 d2d_device_context_PopAxisAlignedClip,
2406 d2d_device_context_Clear,
2407 d2d_device_context_BeginDraw,
2408 d2d_device_context_EndDraw,
2409 d2d_device_context_GetPixelFormat,
2410 d2d_device_context_SetDpi,
2411 d2d_device_context_GetDpi,
2412 d2d_device_context_GetSize,
2413 d2d_device_context_GetPixelSize,
2414 d2d_device_context_GetMaximumBitmapSize,
2415 d2d_device_context_IsSupported,
2416 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2417 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2418 d2d_device_context_CreateColorContext,
2419 d2d_device_context_CreateColorContextFromFilename,
2420 d2d_device_context_CreateColorContextFromWicColorContext,
2421 d2d_device_context_CreateBitmapFromDxgiSurface,
2422 d2d_device_context_CreateEffect,
2423 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2424 d2d_device_context_CreateImageBrush,
2425 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2426 d2d_device_context_CreateCommandList,
2427 d2d_device_context_IsDxgiFormatSupported,
2428 d2d_device_context_IsBufferPrecisionSupported,
2429 d2d_device_context_GetImageLocalBounds,
2430 d2d_device_context_GetImageWorldBounds,
2431 d2d_device_context_GetGlyphRunWorldBounds,
2432 d2d_device_context_GetDevice,
2433 d2d_device_context_SetTarget,
2434 d2d_device_context_GetTarget,
2435 d2d_device_context_SetRenderingControls,
2436 d2d_device_context_GetRenderingControls,
2437 d2d_device_context_SetPrimitiveBlend,
2438 d2d_device_context_GetPrimitiveBlend,
2439 d2d_device_context_SetUnitMode,
2440 d2d_device_context_GetUnitMode,
2441 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2442 d2d_device_context_DrawImage,
2443 d2d_device_context_DrawGdiMetafile,
2444 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2445 d2d_device_context_ID2D1DeviceContext_PushLayer,
2446 d2d_device_context_InvalidateEffectInputRectangle,
2447 d2d_device_context_GetEffectInvalidRectangleCount,
2448 d2d_device_context_GetEffectInvalidRectangles,
2449 d2d_device_context_GetEffectRequiredInputRectangles,
2450 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2453 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2455 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2458 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2460 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2462 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2463 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2464 || IsEqualGUID(iid, &IID_IUnknown))
2466 IDWriteTextRenderer_AddRef(iface);
2467 *out = iface;
2468 return S_OK;
2471 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2473 *out = NULL;
2474 return E_NOINTERFACE;
2477 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2479 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2481 TRACE("iface %p.\n", iface);
2483 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2486 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2488 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2490 TRACE("iface %p.\n", iface);
2492 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2495 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2496 void *ctx, BOOL *disabled)
2498 struct d2d_draw_text_layout_ctx *context = ctx;
2500 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2502 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2504 return S_OK;
2507 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2508 void *ctx, DWRITE_MATRIX *transform)
2510 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2512 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2514 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2516 return S_OK;
2519 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2521 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2523 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2525 *ppd = render_target->desc.dpiY / 96.0f;
2527 return S_OK;
2530 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2531 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2532 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2534 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2535 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2536 struct d2d_draw_text_layout_ctx *context = ctx;
2537 BOOL color_font = FALSE;
2538 ID2D1Brush *brush;
2540 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2541 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2542 iface, ctx, baseline_origin_x, baseline_origin_y,
2543 measuring_mode, glyph_run, desc, effect);
2545 if (desc)
2546 WARN("Ignoring glyph run description %p.\n", desc);
2547 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2548 FIXME("Ignoring options %#x.\n", context->options);
2550 brush = d2d_draw_get_text_brush(context, effect);
2552 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2554 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2556 IDWriteFontFace2 *fontface;
2558 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2559 &IID_IDWriteFontFace2, (void **)&fontface)))
2561 color_font = IDWriteFontFace2_IsColorFont(fontface);
2562 IDWriteFontFace2_Release(fontface);
2566 if (color_font)
2568 IDWriteColorGlyphRunEnumerator *layers;
2569 IDWriteFactory2 *dwrite_factory;
2570 HRESULT hr;
2572 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2573 (IUnknown **)&dwrite_factory)))
2575 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
2576 ID2D1Brush_Release(brush);
2577 return hr;
2580 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2581 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2582 IDWriteFactory2_Release(dwrite_factory);
2583 if (FAILED(hr))
2585 ERR("Failed to create colour glyph run enumerator, hr %#lx.\n", hr);
2586 ID2D1Brush_Release(brush);
2587 return hr;
2590 for (;;)
2592 const DWRITE_COLOR_GLYPH_RUN *color_run;
2593 ID2D1Brush *color_brush;
2594 D2D1_POINT_2F origin;
2595 BOOL has_run = FALSE;
2597 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2599 ERR("Failed to switch colour glyph layer, hr %#lx.\n", hr);
2600 break;
2603 if (!has_run)
2604 break;
2606 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2608 ERR("Failed to get current colour run, hr %#lx.\n", hr);
2609 break;
2612 if (color_run->paletteIndex == 0xffff)
2613 color_brush = brush;
2614 else
2616 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2617 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2619 ERR("Failed to create solid colour brush, hr %#lx.\n", hr);
2620 break;
2624 origin.x = color_run->baselineOriginX;
2625 origin.y = color_run->baselineOriginY;
2626 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2627 origin, &color_run->glyphRun, color_brush, measuring_mode);
2629 if (color_brush != brush)
2630 ID2D1Brush_Release(color_brush);
2633 IDWriteColorGlyphRunEnumerator_Release(layers);
2635 else
2636 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2637 baseline_origin, glyph_run, brush, measuring_mode);
2639 ID2D1Brush_Release(brush);
2641 return S_OK;
2644 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2645 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2647 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2648 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2649 struct d2d_draw_text_layout_ctx *context = ctx;
2650 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2651 D2D1_POINT_2F start, end;
2652 ID2D1Brush *brush;
2653 float thickness;
2655 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2656 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2658 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2659 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2660 underline->thickness);
2662 brush = d2d_draw_get_text_brush(context, effect);
2664 start.x = baseline_origin_x;
2665 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2666 end.x = start.x + underline->width;
2667 end.y = start.y;
2668 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2669 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2670 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2672 ID2D1Brush_Release(brush);
2674 return S_OK;
2677 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2678 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2680 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2681 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2682 struct d2d_draw_text_layout_ctx *context = ctx;
2683 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2684 D2D1_POINT_2F start, end;
2685 ID2D1Brush *brush;
2686 float thickness;
2688 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2689 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2691 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2692 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2693 strikethrough->thickness);
2695 brush = d2d_draw_get_text_brush(context, effect);
2697 start.x = baseline_origin_x;
2698 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2699 end.x = start.x + strikethrough->width;
2700 end.y = start.y;
2701 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2702 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2703 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2705 ID2D1Brush_Release(brush);
2707 return S_OK;
2710 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2711 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2713 struct d2d_draw_text_layout_ctx *context = ctx;
2714 ID2D1Brush *brush;
2715 HRESULT hr;
2717 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2718 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2720 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2721 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2722 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2723 brush is selected at Direct2D level. */
2724 brush = context->brush;
2725 context->brush = d2d_draw_get_text_brush(context, effect);
2727 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2729 ID2D1Brush_Release(context->brush);
2730 context->brush = brush;
2732 return hr;
2735 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2737 d2d_text_renderer_QueryInterface,
2738 d2d_text_renderer_AddRef,
2739 d2d_text_renderer_Release,
2740 d2d_text_renderer_IsPixelSnappingDisabled,
2741 d2d_text_renderer_GetCurrentTransform,
2742 d2d_text_renderer_GetPixelsPerDip,
2743 d2d_text_renderer_DrawGlyphRun,
2744 d2d_text_renderer_DrawUnderline,
2745 d2d_text_renderer_DrawStrikethrough,
2746 d2d_text_renderer_DrawInlineObject,
2749 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2751 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2754 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2755 REFIID iid, void **out)
2757 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2759 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2761 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2764 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2766 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2768 TRACE("iface %p.\n", iface);
2770 return IUnknown_AddRef(render_target->outer_unknown);
2773 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2775 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2777 TRACE("iface %p.\n", iface);
2779 return IUnknown_Release(render_target->outer_unknown);
2782 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2784 ID3D11Resource *resource;
2785 HRESULT hr;
2787 ID3D11RenderTargetView_GetResource(render_target->target->rtv, &resource);
2788 hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2789 ID3D11Resource_Release(resource);
2790 if (FAILED(hr))
2792 *surface = NULL;
2793 WARN("Failed to get DXGI surface, %#lx.\n", hr);
2794 return hr;
2797 return hr;
2800 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2801 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2803 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2804 IDXGISurface1 *surface;
2805 HRESULT hr;
2807 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2809 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2810 return hr;
2812 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2813 IDXGISurface1_Release(surface);
2815 return hr;
2818 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2819 const RECT *update)
2821 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2822 IDXGISurface1 *surface;
2823 RECT update_rect;
2824 HRESULT hr;
2826 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2828 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2829 return hr;
2831 if (update)
2832 update_rect = *update;
2833 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2834 IDXGISurface1_Release(surface);
2836 return hr;
2839 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2841 d2d_gdi_interop_render_target_QueryInterface,
2842 d2d_gdi_interop_render_target_AddRef,
2843 d2d_gdi_interop_render_target_Release,
2844 d2d_gdi_interop_render_target_GetDC,
2845 d2d_gdi_interop_render_target_ReleaseDC,
2848 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2849 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2851 D3D11_SUBRESOURCE_DATA buffer_data;
2852 struct d2d_device *device_impl;
2853 IDWriteFactory *dwrite_factory;
2854 D3D11_RASTERIZER_DESC rs_desc;
2855 D3D11_BUFFER_DESC buffer_desc;
2856 unsigned int i;
2857 HRESULT hr;
2859 static const D3D11_INPUT_ELEMENT_DESC il_desc_outline[] =
2861 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2862 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2863 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
2865 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
2867 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2868 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2869 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
2870 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
2871 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
2872 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0},
2874 static const D3D11_INPUT_ELEMENT_DESC il_desc_triangle[] =
2876 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2878 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve[] =
2880 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2881 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2883 static const DWORD vs_code_outline[] =
2885 #if 0
2886 float3x2 transform_geometry;
2887 float stroke_width;
2888 float4 transform_rtx;
2889 float4 transform_rty;
2891 struct output
2893 float2 p : WORLD_POSITION;
2894 float4 b : BEZIER;
2895 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2896 float4 position : SV_POSITION;
2899 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2901 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2903 * Where:
2905 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2906 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2907 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2908 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2910 float2 q_prev, q_next, v_p, q_i;
2911 float2x2 geom;
2912 float l;
2914 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2916 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2917 q_prev = normalize(mul(geom, prev));
2918 q_next = normalize(mul(geom, next));
2920 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2921 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2922 v_p = float2(-q_prev.y, q_prev.x);
2923 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2924 q_i = l * q_prev + v_p;
2926 o.b = float4(0.0, 0.0, 0.0, 0.0);
2928 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2929 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2930 * float2(transform_rtx.w, transform_rty.w);
2931 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2933 #endif
2934 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2935 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2936 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2937 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2938 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2939 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2940 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2941 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2942 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2943 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2944 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2945 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2946 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2947 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2948 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2949 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2950 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2951 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2952 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2953 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2954 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2955 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2956 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2957 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2958 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2959 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2960 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2961 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2962 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2963 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2964 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2965 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2966 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2967 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2968 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2969 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2970 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2971 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2972 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2973 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2974 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2975 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2976 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2977 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2978 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2979 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2980 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2981 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2982 0x3f800000, 0x0100003e,
2984 /* ⎡p0.x p0.y 1⎤
2985 * A = ⎢p1.x p1.y 1⎥
2986 * ⎣p2.x p2.y 1⎦
2988 * ⎡0 0⎤
2989 * B = ⎢½ 0⎥
2990 * ⎣1 1⎦
2992 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2993 * ⎣p2.x-p0.x p2.y-p0.y⎦
2995 * B' = ⎡½ 0⎤
2996 * ⎣1 1⎦
2998 * A'T = B'
2999 * T = A'⁻¹B'
3001 static const DWORD vs_code_bezier_outline[] =
3003 #if 0
3004 float3x2 transform_geometry;
3005 float stroke_width;
3006 float4 transform_rtx;
3007 float4 transform_rty;
3009 struct output
3011 float2 p : WORLD_POSITION;
3012 float4 b : BEZIER;
3013 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3014 float4 position : SV_POSITION;
3017 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3018 float2 prev : PREV, float2 next : NEXT, out struct output o)
3020 float2 q_prev, q_next, v_p, q_i, p;
3021 float2x2 geom, rt;
3022 float l;
3024 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3025 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3026 o.stroke_transform = rt * stroke_width * 0.5f;
3028 p = mul(geom, position);
3029 p0 = mul(geom, p0);
3030 p1 = mul(geom, p1);
3031 p2 = mul(geom, p2);
3033 p -= p0;
3034 p1 -= p0;
3035 p2 -= p0;
3037 q_prev = normalize(mul(geom, prev));
3038 q_next = normalize(mul(geom, next));
3040 v_p = float2(-q_prev.y, q_prev.x);
3041 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3042 q_i = l * q_prev + v_p;
3043 p += 0.5f * stroke_width * q_i;
3045 v_p = mul(rt, p2);
3046 v_p = normalize(float2(-v_p.y, v_p.x));
3047 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
3049 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
3050 o.b.y = dot(mul(rt, p), v_p);
3052 else
3054 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
3055 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
3056 o.b.x = dot(v_p, p1 - 0.5f * p2);
3057 o.b.y = dot(v_p, p1);
3060 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3061 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3062 * float2(transform_rtx.w, transform_rty.w);
3063 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3065 #endif
3066 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3067 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3068 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3069 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3070 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3071 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3072 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3073 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3074 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3075 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3076 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3077 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3078 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3079 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3080 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3081 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3082 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3083 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3084 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3085 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3086 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3087 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3088 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3089 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3090 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3091 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3092 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3093 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3094 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3095 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3096 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3097 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3098 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3099 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3100 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3101 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3102 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3103 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3104 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3105 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3106 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3107 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3108 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3109 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3110 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3111 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3112 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3113 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3114 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3115 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3116 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3117 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3118 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3119 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3120 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3121 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3122 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3123 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3124 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3125 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3126 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3127 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3128 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3129 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3130 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3131 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3132 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3133 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3134 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3135 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3136 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3137 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3138 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3139 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3140 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3141 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3142 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3143 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3144 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3145 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3146 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3147 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3148 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3149 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3150 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3151 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3152 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3153 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3155 /* ⎡p0.x p0.y 1⎤
3156 * A = ⎢p1.x p1.y 1⎥
3157 * ⎣p2.x p2.y 1⎦
3159 * ⎡1 0⎤
3160 * B = ⎢1 1⎥
3161 * ⎣0 1⎦
3163 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3164 * ⎣p2.x-p0.x p2.y-p0.y⎦
3166 * B' = ⎡ 0 1⎤
3167 * ⎣-1 1⎦
3169 * A'T = B'
3170 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3172 static const DWORD vs_code_arc_outline[] =
3174 #if 0
3175 float3x2 transform_geometry;
3176 float stroke_width;
3177 float4 transform_rtx;
3178 float4 transform_rty;
3180 struct output
3182 float2 p : WORLD_POSITION;
3183 float4 b : BEZIER;
3184 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3185 float4 position : SV_POSITION;
3188 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3189 float2 prev : PREV, float2 next : NEXT, out struct output o)
3191 float2 q_prev, q_next, v_p, q_i, p;
3192 float2x2 geom, rt, p_inv;
3193 float l;
3194 float a;
3195 float2 bc;
3197 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3198 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3199 o.stroke_transform = rt * stroke_width * 0.5f;
3201 p = mul(geom, position);
3202 p0 = mul(geom, p0);
3203 p1 = mul(geom, p1);
3204 p2 = mul(geom, p2);
3206 p -= p0;
3207 p1 -= p0;
3208 p2 -= p0;
3210 q_prev = normalize(mul(geom, prev));
3211 q_next = normalize(mul(geom, next));
3213 v_p = float2(-q_prev.y, q_prev.x);
3214 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3215 q_i = l * q_prev + v_p;
3216 p += 0.5f * stroke_width * q_i;
3218 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3219 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3220 o.b.zw = 0.0f;
3222 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3223 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3224 * float2(transform_rtx.w, transform_rty.w);
3225 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3227 #endif
3228 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3229 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3230 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3231 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3232 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3233 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3234 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3235 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3236 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3237 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3238 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3239 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3240 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3241 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3242 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3243 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3244 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3245 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3246 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3247 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3248 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3249 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3250 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3251 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3252 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3253 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3254 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3255 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3256 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3257 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3258 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3259 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3260 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3261 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3262 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3263 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3264 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3265 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3266 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3267 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3268 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3269 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3270 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3271 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3272 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3273 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3274 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3275 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3276 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3277 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3278 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3279 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3280 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3281 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3282 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3283 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3284 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3285 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3286 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3287 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3288 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3289 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3290 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3291 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3292 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3293 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3294 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3295 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3296 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3297 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3298 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3299 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3300 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3301 0x0100003e,
3303 static const DWORD vs_code_triangle[] =
3305 #if 0
3306 float3x2 transform_geometry;
3307 float4 transform_rtx;
3308 float4 transform_rty;
3310 struct output
3312 float2 p : WORLD_POSITION;
3313 float4 b : BEZIER;
3314 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3315 float4 position : SV_POSITION;
3318 void main(float2 position : POSITION, out struct output o)
3320 o.p = mul(float3(position, 1.0f), transform_geometry);
3321 o.b = float4(1.0, 0.0, 1.0, 1.0);
3322 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3323 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3324 * float2(transform_rtx.w, transform_rty.w);
3325 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3327 #endif
3328 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3329 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3330 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3331 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3332 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3333 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3334 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3335 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3336 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3337 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3338 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3339 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3340 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3341 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3342 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3343 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3344 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3345 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3346 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3347 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3348 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3349 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3350 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3351 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3352 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3353 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3354 0x00000000, 0x3f800000, 0x0100003e,
3356 static const DWORD vs_code_curve[] =
3358 #if 0
3359 float3x2 transform_geometry;
3360 float4 transform_rtx;
3361 float4 transform_rty;
3363 struct output
3365 float2 p : WORLD_POSITION;
3366 float4 b : BEZIER;
3367 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3368 float4 position : SV_POSITION;
3371 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3373 o.p = mul(float3(position, 1.0f), transform_geometry);
3374 o.b = float4(texcoord, 1.0);
3375 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3376 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3377 * float2(transform_rtx.w, transform_rty.w);
3378 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3380 #endif
3381 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3382 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3383 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3384 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3385 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3386 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3387 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3388 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3389 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3390 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3391 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3392 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3393 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3394 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3395 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3396 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3397 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3398 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3399 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3400 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3401 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3402 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3403 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3404 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3405 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3406 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3407 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3408 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3410 static const DWORD ps_code[] =
3412 #if 0
3413 #define BRUSH_TYPE_SOLID 0
3414 #define BRUSH_TYPE_LINEAR 1
3415 #define BRUSH_TYPE_RADIAL 2
3416 #define BRUSH_TYPE_BITMAP 3
3417 #define BRUSH_TYPE_COUNT 4
3419 bool outline;
3420 bool is_arc;
3421 struct brush
3423 uint type;
3424 float opacity;
3425 float4 data[3];
3426 } colour_brush, opacity_brush;
3428 SamplerState s0, s1;
3429 Texture2D t0, t1;
3430 Buffer<float4> b0, b1;
3432 struct input
3434 float2 p : WORLD_POSITION;
3435 float4 b : BEZIER;
3436 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3439 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3441 float4 c_low, c_high;
3442 float p_low, p_high;
3443 uint i;
3445 p_low = gradient.Load(0).x;
3446 c_low = gradient.Load(1);
3447 c_high = c_low;
3449 if (position < p_low)
3450 return c_low;
3452 for (i = 1; i < stop_count; ++i)
3454 p_high = gradient.Load(i * 2).x;
3455 c_high = gradient.Load(i * 2 + 1);
3457 if (position >= p_low && position <= p_high)
3458 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3460 p_low = p_high;
3461 c_low = c_high;
3464 return c_high;
3467 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3469 float2 start, end, v_p, v_q;
3470 uint stop_count;
3471 float p;
3473 start = brush.data[0].xy;
3474 end = brush.data[0].zw;
3475 stop_count = asuint(brush.data[1].x);
3477 v_p = position - start;
3478 v_q = end - start;
3479 p = dot(v_q, v_p) / dot(v_q, v_q);
3481 return sample_gradient(gradient, stop_count, p);
3484 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3486 float2 centre, offset, ra, rb, v_p, v_q, r;
3487 float b, c, l, t;
3488 uint stop_count;
3490 centre = brush.data[0].xy;
3491 offset = brush.data[0].zw;
3492 ra = brush.data[1].xy;
3493 rb = brush.data[1].zw;
3494 stop_count = asuint(brush.data[2].x);
3496 /* Project onto ra, rb. */
3497 r = float2(dot(ra, ra), dot(rb, rb));
3498 v_p = position - (centre + offset);
3499 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3500 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3502 /* ‖t·p̂ + q⃑‖ = 1
3503 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3504 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3506 * b = p̂·q⃑
3507 * c = q⃑·q⃑ - 1
3508 * t = -b + √(b² - c) */
3509 l = length(v_p);
3510 b = dot(v_p, v_q) / l;
3511 c = dot(v_q, v_q) - 1.0;
3512 t = -b + sqrt(b * b - c);
3514 return sample_gradient(gradient, stop_count, l / t);
3517 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3519 float3 transform[2];
3520 bool ignore_alpha;
3521 float2 texcoord;
3522 float4 colour;
3524 transform[0] = brush.data[0].xyz;
3525 transform[1] = brush.data[1].xyz;
3526 ignore_alpha = asuint(brush.data[1].w);
3528 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3529 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3530 colour = t.Sample(s, texcoord);
3531 if (ignore_alpha)
3532 colour.a = 1.0;
3533 return colour;
3536 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3538 if (brush.type == BRUSH_TYPE_SOLID)
3539 return brush.data[0] * brush.opacity;
3540 if (brush.type == BRUSH_TYPE_LINEAR)
3541 return brush_linear(brush, b, position) * brush.opacity;
3542 if (brush.type == BRUSH_TYPE_RADIAL)
3543 return brush_radial(brush, b, position) * brush.opacity;
3544 if (brush.type == BRUSH_TYPE_BITMAP)
3545 return brush_bitmap(brush, t, s, position) * brush.opacity;
3546 return float4(0.0, 0.0, 0.0, brush.opacity);
3549 float4 main(struct input i) : SV_Target
3551 float4 colour;
3553 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3554 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3555 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3557 if (outline)
3559 float2 du, dv, df;
3560 float4 uv;
3562 /* Evaluate the implicit form of the curve (u² - v = 0
3563 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3564 * space, using the screen-space partial derivatives
3565 * to convert the calculated distance to object space.
3567 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3568 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3570 * For Béziers:
3571 * f(x, y) = u(x, y)² - v(x, y)
3572 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3573 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3575 * For arcs:
3576 * f(x, y) = u(x, y)² + v(x, y)² - 1
3577 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3578 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3579 uv = i.b;
3580 du = float2(ddx(uv.x), ddy(uv.x));
3581 dv = float2(ddx(uv.y), ddy(uv.y));
3583 if (!is_arc)
3585 df = 2.0f * uv.x * du - dv;
3587 clip(dot(df, uv.zw));
3588 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3590 else
3592 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3594 clip(dot(df, uv.zw));
3595 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3598 else
3600 /* Evaluate the implicit form of the curve in texture space.
3601 * "i.b.z" determines which side of the curve is shaded. */
3602 if (!is_arc)
3604 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3606 else
3608 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3612 return colour;
3614 #endif
3615 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3616 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3617 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3618 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3619 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3620 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3621 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3622 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3623 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3624 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3625 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3626 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3627 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3628 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3629 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3630 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3631 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3632 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3633 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3634 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3635 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3636 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3637 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3638 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3639 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3640 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3641 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3642 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3643 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3644 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3645 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3646 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3647 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3648 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3649 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3650 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3651 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3652 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3653 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3654 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3655 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3656 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3657 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3658 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3659 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3660 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3661 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3662 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3663 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3664 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3665 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3666 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3667 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3668 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3669 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3670 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3671 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3672 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3673 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3674 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3675 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3676 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3677 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3678 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3679 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3680 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3681 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3682 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3683 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3684 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3685 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3686 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3687 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3688 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3689 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3690 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3691 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3692 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3693 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3694 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3695 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3696 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3697 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3698 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3699 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3700 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3701 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3702 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3703 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3704 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3705 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3706 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3707 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3708 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3709 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3710 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3711 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3712 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3713 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3714 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3715 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3716 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3717 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3718 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3719 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3720 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3721 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3722 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3723 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3724 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3725 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3726 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3727 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3728 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3729 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3730 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3731 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3732 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3733 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3734 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3735 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3736 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3737 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3738 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3739 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3740 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3741 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3742 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3743 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3744 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3745 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3746 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3747 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3748 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3749 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3750 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3751 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3752 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3753 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3754 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3755 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3756 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3757 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3758 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3759 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3760 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3761 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3762 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3763 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3764 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3765 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3766 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3767 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3768 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3769 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3770 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3771 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3772 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3773 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3774 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3775 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3776 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3777 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3778 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3779 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3780 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3781 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3782 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3783 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3784 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3785 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3786 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3787 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3788 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3789 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3790 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3791 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3792 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3793 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3794 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3795 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3796 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3797 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3798 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3799 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3800 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3801 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3802 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3803 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3804 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3805 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3806 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3807 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3808 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3809 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3810 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3811 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3812 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3813 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3814 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3815 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3816 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3817 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3818 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3819 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3820 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3821 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3822 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3823 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3824 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3825 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3826 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3827 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3828 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
3829 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
3830 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
3831 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
3832 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
3833 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
3834 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
3835 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
3836 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3837 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
3838 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
3839 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
3840 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
3841 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
3842 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
3843 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
3844 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
3845 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
3846 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
3847 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
3848 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
3849 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
3850 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
3851 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
3852 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
3853 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
3854 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
3855 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
3856 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
3857 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3858 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
3859 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
3860 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
3861 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
3862 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
3863 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
3864 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
3865 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
3866 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
3867 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
3868 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
3869 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
3870 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
3872 static const struct shape_info
3874 enum d2d_shape_type shape_type;
3875 const D3D11_INPUT_ELEMENT_DESC *il_desc;
3876 unsigned int il_element_count;
3877 const void *vs_code;
3878 size_t vs_code_size;
3880 shape_info[] =
3882 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3883 vs_code_outline, sizeof(vs_code_outline)},
3884 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3885 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3886 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3887 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
3888 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3889 vs_code_triangle, sizeof(vs_code_triangle)},
3890 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
3891 vs_code_curve, sizeof(vs_code_curve)},
3893 static const struct
3895 float x, y;
3897 quad[] =
3899 {-1.0f, 1.0f},
3900 {-1.0f, -1.0f},
3901 { 1.0f, 1.0f},
3902 { 1.0f, -1.0f},
3904 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3905 static const D3D_FEATURE_LEVEL feature_levels = D3D_FEATURE_LEVEL_10_0;
3907 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3908 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3909 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3910 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3911 render_target->refcount = 1;
3912 ID2D1Device_GetFactory(device, &render_target->factory);
3913 render_target->device = device;
3914 ID2D1Device_AddRef(render_target->device);
3916 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3917 render_target->ops = ops;
3919 device_impl = unsafe_impl_from_ID2D1Device(device);
3920 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3921 &IID_ID3D11Device1, (void **)&render_target->d3d_device)))
3923 WARN("Failed to query ID3D11Device1 interface, hr %#lx.\n", hr);
3924 goto err;
3927 if (FAILED(hr = ID3D11Device1_CreateDeviceContextState(render_target->d3d_device,
3928 0, &feature_levels, 1, D3D11_SDK_VERSION, &IID_ID3D11Device1, NULL,
3929 &render_target->d3d_state)))
3931 WARN("Failed to create device context state, hr %#lx.\n", hr);
3932 goto err;
3935 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3937 const struct shape_info *si = &shape_info[i];
3939 if (FAILED(hr = ID3D11Device1_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3940 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3942 WARN("Failed to create input layout for shape type %#x, hr %#lx.\n", si->shape_type, hr);
3943 goto err;
3946 if (FAILED(hr = ID3D11Device1_CreateVertexShader(render_target->d3d_device, si->vs_code,
3947 si->vs_code_size, NULL, &render_target->shape_resources[si->shape_type].vs)))
3949 WARN("Failed to create vertex shader for shape type %#x, hr %#lx.\n", si->shape_type, hr);
3950 goto err;
3955 buffer_desc.ByteWidth = sizeof(struct d2d_vs_cb);
3956 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
3957 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
3958 buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
3959 buffer_desc.MiscFlags = 0;
3961 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
3962 &render_target->vs_cb)))
3964 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
3965 goto err;
3968 if (FAILED(hr = ID3D11Device1_CreatePixelShader(render_target->d3d_device,
3969 ps_code, sizeof(ps_code), NULL, &render_target->ps)))
3971 WARN("Failed to create pixel shader, hr %#lx.\n", hr);
3972 goto err;
3975 buffer_desc.ByteWidth = sizeof(struct d2d_ps_cb);
3976 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
3977 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
3978 buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
3979 buffer_desc.MiscFlags = 0;
3981 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
3982 &render_target->ps_cb)))
3984 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
3985 goto err;
3988 buffer_desc.ByteWidth = sizeof(indices);
3989 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
3990 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
3991 buffer_desc.CPUAccessFlags = 0;
3992 buffer_desc.MiscFlags = 0;
3994 buffer_data.pSysMem = indices;
3995 buffer_data.SysMemPitch = 0;
3996 buffer_data.SysMemSlicePitch = 0;
3998 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
3999 &buffer_desc, &buffer_data, &render_target->ib)))
4001 WARN("Failed to create clear index buffer, hr %#lx.\n", hr);
4002 goto err;
4005 buffer_desc.ByteWidth = sizeof(quad);
4006 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
4007 buffer_data.pSysMem = quad;
4009 render_target->vb_stride = sizeof(*quad);
4010 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4011 &buffer_desc, &buffer_data, &render_target->vb)))
4013 WARN("Failed to create clear vertex buffer, hr %#lx.\n", hr);
4014 goto err;
4017 rs_desc.FillMode = D3D11_FILL_SOLID;
4018 rs_desc.CullMode = D3D11_CULL_NONE;
4019 rs_desc.FrontCounterClockwise = FALSE;
4020 rs_desc.DepthBias = 0;
4021 rs_desc.DepthBiasClamp = 0.0f;
4022 rs_desc.SlopeScaledDepthBias = 0.0f;
4023 rs_desc.DepthClipEnable = TRUE;
4024 rs_desc.ScissorEnable = TRUE;
4025 rs_desc.MultisampleEnable = FALSE;
4026 rs_desc.AntialiasedLineEnable = FALSE;
4027 if (FAILED(hr = ID3D11Device1_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
4029 WARN("Failed to create clear rasteriser state, hr %#lx.\n", hr);
4030 goto err;
4033 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
4034 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
4036 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
4037 goto err;
4040 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
4041 IDWriteFactory_Release(dwrite_factory);
4042 if (FAILED(hr))
4044 ERR("Failed to create default text rendering parameters, hr %#lx.\n", hr);
4045 goto err;
4048 render_target->drawing_state.transform = identity;
4050 if (!d2d_clip_stack_init(&render_target->clip_stack))
4052 WARN("Failed to initialize clip stack.\n");
4053 hr = E_FAIL;
4054 goto err;
4057 render_target->desc.dpiX = 96.0f;
4058 render_target->desc.dpiY = 96.0f;
4060 return S_OK;
4062 err:
4063 if (render_target->default_text_rendering_params)
4064 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
4065 if (render_target->rs)
4066 ID3D11RasterizerState_Release(render_target->rs);
4067 if (render_target->vb)
4068 ID3D11Buffer_Release(render_target->vb);
4069 if (render_target->ib)
4070 ID3D11Buffer_Release(render_target->ib);
4071 if (render_target->ps_cb)
4072 ID3D11Buffer_Release(render_target->ps_cb);
4073 if (render_target->ps)
4074 ID3D11PixelShader_Release(render_target->ps);
4075 if (render_target->vs_cb)
4076 ID3D11Buffer_Release(render_target->vs_cb);
4077 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
4079 if (render_target->shape_resources[i].vs)
4080 ID3D11VertexShader_Release(render_target->shape_resources[i].vs);
4081 if (render_target->shape_resources[i].il)
4082 ID3D11InputLayout_Release(render_target->shape_resources[i].il);
4084 if (render_target->d3d_state)
4085 ID3DDeviceContextState_Release(render_target->d3d_state);
4086 if (render_target->d3d_device)
4087 ID3D11Device1_Release(render_target->d3d_device);
4088 ID2D1Device_Release(render_target->device);
4089 ID2D1Factory_Release(render_target->factory);
4090 return hr;
4093 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4094 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4096 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4097 struct d2d_device_context *object;
4098 ID2D1Bitmap1 *bitmap;
4099 HRESULT hr;
4101 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4102 WARN("Ignoring render target type %#x.\n", desc->type);
4103 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4104 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4105 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4106 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4108 bitmap_desc.dpiX = desc->dpiX;
4109 bitmap_desc.dpiY = desc->dpiY;
4111 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4113 bitmap_desc.dpiX = 96.0f;
4114 bitmap_desc.dpiY = 96.0f;
4116 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4117 return E_INVALIDARG;
4119 if (!(object = heap_alloc_zero(sizeof(*object))))
4120 return E_OUTOFMEMORY;
4122 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4124 WARN("Failed to initialise render target, hr %#lx.\n", hr);
4125 heap_free(object);
4126 return hr;
4129 ID2D1DeviceContext_SetDpi(&object->ID2D1DeviceContext_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4131 if (surface)
4133 bitmap_desc.pixelFormat = desc->pixelFormat;
4134 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4135 bitmap_desc.colorContext = NULL;
4137 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
4138 surface, &bitmap_desc, &bitmap)))
4140 WARN("Failed to create target bitmap, hr %#lx.\n", hr);
4141 IUnknown_Release(&object->IUnknown_iface);
4142 heap_free(object);
4143 return hr;
4146 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
4147 ID2D1Bitmap1_Release(bitmap);
4149 else
4150 object->desc.pixelFormat = desc->pixelFormat;
4152 TRACE("Created render target %p.\n", object);
4153 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
4155 return S_OK;
4158 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
4160 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4162 if (IsEqualGUID(iid, &IID_ID2D1Device)
4163 || IsEqualGUID(iid, &IID_ID2D1Resource)
4164 || IsEqualGUID(iid, &IID_IUnknown))
4166 ID2D1Device_AddRef(iface);
4167 *out = iface;
4168 return S_OK;
4171 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4173 *out = NULL;
4174 return E_NOINTERFACE;
4177 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
4179 struct d2d_device *device = impl_from_ID2D1Device(iface);
4180 ULONG refcount = InterlockedIncrement(&device->refcount);
4182 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4184 return refcount;
4187 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
4189 struct d2d_device *device = impl_from_ID2D1Device(iface);
4190 ULONG refcount = InterlockedDecrement(&device->refcount);
4192 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4194 if (!refcount)
4196 IDXGIDevice_Release(device->dxgi_device);
4197 ID2D1Factory1_Release(device->factory);
4198 heap_free(device);
4201 return refcount;
4204 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
4206 struct d2d_device *device = impl_from_ID2D1Device(iface);
4208 TRACE("iface %p, factory %p.\n", iface, factory);
4210 *factory = (ID2D1Factory *)device->factory;
4211 ID2D1Factory1_AddRef(device->factory);
4214 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4215 ID2D1DeviceContext **context)
4217 struct d2d_device_context *object;
4218 HRESULT hr;
4220 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4222 if (options)
4223 FIXME("Options are ignored %#x.\n", options);
4225 if (!(object = heap_alloc_zero(sizeof(*object))))
4226 return E_OUTOFMEMORY;
4228 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
4230 WARN("Failed to initialise device context, hr %#lx.\n", hr);
4231 heap_free(object);
4232 return hr;
4235 TRACE("Created device context %p.\n", object);
4236 *context = &object->ID2D1DeviceContext_iface;
4238 return S_OK;
4241 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
4242 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4243 ID2D1PrintControl **print_control)
4245 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4246 document_target, desc, print_control);
4248 return E_NOTIMPL;
4251 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
4253 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4256 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
4258 FIXME("iface %p stub!\n", iface);
4260 return 0;
4263 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
4265 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4267 return E_NOTIMPL;
4270 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
4272 d2d_device_QueryInterface,
4273 d2d_device_AddRef,
4274 d2d_device_Release,
4275 d2d_device_GetFactory,
4276 d2d_device_CreateDeviceContext,
4277 d2d_device_CreatePrintControl,
4278 d2d_device_SetMaximumTextureMemory,
4279 d2d_device_GetMaximumTextureMemory,
4280 d2d_device_ClearResources,
4283 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
4285 if (!iface)
4286 return NULL;
4287 assert(iface->lpVtbl == &d2d_device_vtbl);
4288 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
4291 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4293 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
4294 device->refcount = 1;
4295 device->factory = iface;
4296 ID2D1Factory1_AddRef(device->factory);
4297 device->dxgi_device = dxgi_device;
4298 IDXGIDevice_AddRef(device->dxgi_device);