d2d1: Add D2D1Crop.
[wine.git] / dlls / d2d1 / device.c
blobc6ef2e286901a9fe3603be496c147c6546ee836e
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 if (opacity_brush)
179 d2d_brush_bind_resources(opacity_brush, render_target, 1);
181 if (ib)
182 ID3D11DeviceContext1_DrawIndexed(context, index_count, 0, 0);
183 else
184 ID3D11DeviceContext1_Draw(context, index_count, 0);
186 ID3D11DeviceContext1_SwapDeviceContextState(context, prev_state, NULL);
187 ID3D11DeviceContext1_Release(context);
188 ID3DDeviceContextState_Release(prev_state);
191 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
193 context->error.code = code;
194 context->error.tag1 = context->drawing_state.tag1;
195 context->error.tag2 = context->drawing_state.tag2;
198 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
200 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
203 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext *iface)
205 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
208 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
210 struct d2d_device_context *context = impl_from_IUnknown(iface);
212 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
214 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext)
215 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
216 || IsEqualGUID(iid, &IID_ID2D1Resource)
217 || IsEqualGUID(iid, &IID_IUnknown))
219 ID2D1DeviceContext_AddRef(&context->ID2D1DeviceContext_iface);
220 *out = &context->ID2D1DeviceContext_iface;
221 return S_OK;
223 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
225 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
226 *out = &context->ID2D1GdiInteropRenderTarget_iface;
227 return S_OK;
230 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
232 *out = NULL;
233 return E_NOINTERFACE;
236 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
238 struct d2d_device_context *context = impl_from_IUnknown(iface);
239 ULONG refcount = InterlockedIncrement(&context->refcount);
241 TRACE("%p increasing refcount to %u.\n", iface, refcount);
243 return refcount;
246 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
248 struct d2d_device_context *context = impl_from_IUnknown(iface);
249 ULONG refcount = InterlockedDecrement(&context->refcount);
251 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
253 if (!refcount)
255 unsigned int i, j, k;
257 d2d_clip_stack_cleanup(&context->clip_stack);
258 IDWriteRenderingParams_Release(context->default_text_rendering_params);
259 if (context->text_rendering_params)
260 IDWriteRenderingParams_Release(context->text_rendering_params);
261 if (context->bs)
262 ID3D11BlendState_Release(context->bs);
263 ID3D11RasterizerState_Release(context->rs);
264 ID3D11Buffer_Release(context->vb);
265 ID3D11Buffer_Release(context->ib);
266 ID3D11Buffer_Release(context->ps_cb);
267 ID3D11PixelShader_Release(context->ps);
268 ID3D11Buffer_Release(context->vs_cb);
269 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
271 ID3D11VertexShader_Release(context->shape_resources[i].vs);
272 ID3D11InputLayout_Release(context->shape_resources[i].il);
274 for (i = 0; i < D2D_SAMPLER_INTERPOLATION_MODE_COUNT; ++i)
276 for (j = 0; j < D2D_SAMPLER_EXTEND_MODE_COUNT; ++j)
278 for (k = 0; k < D2D_SAMPLER_EXTEND_MODE_COUNT; ++k)
280 if (context->sampler_states[i][j][k])
281 ID3D11SamplerState_Release(context->sampler_states[i][j][k]);
285 if (context->d3d_state)
286 ID3DDeviceContextState_Release(context->d3d_state);
287 if (context->target)
288 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
289 ID3D11Device1_Release(context->d3d_device);
290 ID2D1Factory_Release(context->factory);
291 ID2D1Device_Release(context->device);
292 heap_free(context);
295 return refcount;
298 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
300 d2d_device_context_inner_QueryInterface,
301 d2d_device_context_inner_AddRef,
302 d2d_device_context_inner_Release,
305 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out)
307 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
309 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
311 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
314 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface)
316 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
318 TRACE("iface %p.\n", iface);
320 return IUnknown_AddRef(context->outer_unknown);
323 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface)
325 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
327 TRACE("iface %p.\n", iface);
329 return IUnknown_Release(context->outer_unknown);
332 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext *iface, ID2D1Factory **factory)
334 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
336 TRACE("iface %p, factory %p.\n", iface, factory);
338 *factory = render_target->factory;
339 ID2D1Factory_AddRef(*factory);
342 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext *iface,
343 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
345 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
346 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
347 struct d2d_bitmap *object;
348 HRESULT hr;
350 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
351 iface, size.width, size.height, src_data, pitch, desc, bitmap);
353 if (desc)
355 memcpy(&bitmap_desc, desc, sizeof(*desc));
356 bitmap_desc.bitmapOptions = 0;
357 bitmap_desc.colorContext = NULL;
360 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
361 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
363 return hr;
366 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext *iface,
367 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
369 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
370 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
371 struct d2d_bitmap *object;
372 HRESULT hr;
374 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
375 iface, bitmap_source, desc, bitmap);
377 if (desc)
379 memcpy(&bitmap_desc, desc, sizeof(*desc));
380 bitmap_desc.bitmapOptions = 0;
381 bitmap_desc.colorContext = NULL;
384 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
385 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
387 return hr;
390 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext *iface,
391 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
393 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
394 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
395 struct d2d_bitmap *object;
396 HRESULT hr;
398 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
399 iface, debugstr_guid(iid), data, desc, bitmap);
401 if (desc)
403 memcpy(&bitmap_desc, desc, sizeof(*desc));
404 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
405 bitmap_desc.colorContext = NULL;
408 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
409 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
411 return hr;
414 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext *iface,
415 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
416 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
418 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
419 struct d2d_brush *object;
420 HRESULT hr;
422 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
423 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
425 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
426 brush_desc, &object)))
427 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
429 return hr;
432 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext *iface,
433 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
435 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
436 struct d2d_brush *object;
437 HRESULT hr;
439 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
441 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
442 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
444 return hr;
447 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext *iface,
448 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
449 ID2D1GradientStopCollection **gradient)
451 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
452 struct d2d_gradient *object;
453 HRESULT hr;
455 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
456 iface, stops, stop_count, gamma, extend_mode, gradient);
458 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
459 stops, stop_count, gamma, extend_mode, &object)))
460 *gradient = &object->ID2D1GradientStopCollection_iface;
462 return hr;
465 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext *iface,
466 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
467 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
469 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
470 struct d2d_brush *object;
471 HRESULT hr;
473 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
474 iface, gradient_brush_desc, brush_desc, gradient, brush);
476 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
477 gradient, &object)))
478 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
480 return hr;
483 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext *iface,
484 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
485 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
487 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
488 struct d2d_brush *object;
489 HRESULT hr;
491 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
492 iface, gradient_brush_desc, brush_desc, gradient, brush);
494 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
495 gradient_brush_desc, brush_desc, gradient, &object)))
496 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
498 return hr;
501 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext *iface,
502 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
503 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
505 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
506 struct d2d_bitmap_render_target *object;
507 HRESULT hr;
509 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
510 iface, size, pixel_size, format, options, rt);
512 if (!(object = heap_alloc_zero(sizeof(*object))))
513 return E_OUTOFMEMORY;
515 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
516 format, options)))
518 WARN("Failed to initialize render target, hr %#x.\n", hr);
519 heap_free(object);
520 return hr;
523 TRACE("Created render target %p.\n", object);
524 *rt = &object->ID2D1BitmapRenderTarget_iface;
526 return S_OK;
529 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext *iface,
530 const D2D1_SIZE_F *size, ID2D1Layer **layer)
532 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
533 struct d2d_layer *object;
534 HRESULT hr;
536 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
538 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
539 *layer = &object->ID2D1Layer_iface;
541 return hr;
544 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext *iface, ID2D1Mesh **mesh)
546 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
547 struct d2d_mesh *object;
548 HRESULT hr;
550 TRACE("iface %p, mesh %p.\n", iface, mesh);
552 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
553 *mesh = &object->ID2D1Mesh_iface;
555 return hr;
558 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext *iface,
559 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
561 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
562 ID2D1PathGeometry *geometry;
563 ID2D1GeometrySink *sink;
564 HRESULT hr;
566 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
567 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
569 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
571 WARN("Failed to create path geometry, %#x.\n", hr);
572 return;
575 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
577 WARN("Open() failed, %#x.\n", hr);
578 ID2D1PathGeometry_Release(geometry);
579 return;
582 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
583 ID2D1GeometrySink_AddLine(sink, p1);
584 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
585 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
586 WARN("Close() failed, %#x.\n", hr);
587 ID2D1GeometrySink_Release(sink);
589 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
590 ID2D1PathGeometry_Release(geometry);
593 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext *iface,
594 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
596 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
597 ID2D1RectangleGeometry *geometry;
598 HRESULT hr;
600 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
601 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
603 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
605 ERR("Failed to create geometry, hr %#x.\n", hr);
606 return;
609 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
610 ID2D1RectangleGeometry_Release(geometry);
613 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext *iface,
614 const D2D1_RECT_F *rect, ID2D1Brush *brush)
616 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
617 ID2D1RectangleGeometry *geometry;
618 HRESULT hr;
620 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
622 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
624 ERR("Failed to create geometry, hr %#x.\n", hr);
625 return;
628 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
629 ID2D1RectangleGeometry_Release(geometry);
632 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext *iface,
633 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
635 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
636 ID2D1RoundedRectangleGeometry *geometry;
637 HRESULT hr;
639 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
640 iface, rect, brush, stroke_width, stroke_style);
642 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
644 ERR("Failed to create geometry, hr %#x.\n", hr);
645 return;
648 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
649 ID2D1RoundedRectangleGeometry_Release(geometry);
652 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext *iface,
653 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
655 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
656 ID2D1RoundedRectangleGeometry *geometry;
657 HRESULT hr;
659 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
661 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
663 ERR("Failed to create geometry, hr %#x.\n", hr);
664 return;
667 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
668 ID2D1RoundedRectangleGeometry_Release(geometry);
671 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext *iface,
672 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
674 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
675 ID2D1EllipseGeometry *geometry;
676 HRESULT hr;
678 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
679 iface, ellipse, brush, stroke_width, stroke_style);
681 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
683 ERR("Failed to create geometry, hr %#x.\n", hr);
684 return;
687 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
688 ID2D1EllipseGeometry_Release(geometry);
691 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext *iface,
692 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
694 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
695 ID2D1EllipseGeometry *geometry;
696 HRESULT hr;
698 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
700 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
702 ERR("Failed to create geometry, hr %#x.\n", hr);
703 return;
706 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
707 ID2D1EllipseGeometry_Release(geometry);
710 static HRESULT d2d_device_context_update_ps_cb(struct d2d_device_context *context,
711 struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, BOOL is_arc)
713 D3D11_MAPPED_SUBRESOURCE map_desc;
714 ID3D11DeviceContext *d3d_context;
715 struct d2d_ps_cb *cb_data;
716 HRESULT hr;
718 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
720 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->ps_cb,
721 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
723 WARN("Failed to map constant buffer, hr %#x.\n", hr);
724 ID3D11DeviceContext_Release(d3d_context);
725 return hr;
728 cb_data = map_desc.pData;
729 cb_data->outline = outline;
730 cb_data->is_arc = is_arc;
731 cb_data->pad[0] = 0;
732 cb_data->pad[1] = 0;
733 if (!d2d_brush_fill_cb(brush, &cb_data->colour_brush))
734 WARN("Failed to initialize colour brush buffer.\n");
735 if (!d2d_brush_fill_cb(opacity_brush, &cb_data->opacity_brush))
736 WARN("Failed to initialize opacity brush buffer.\n");
738 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->ps_cb, 0);
739 ID3D11DeviceContext_Release(d3d_context);
741 return hr;
744 static HRESULT d2d_device_context_update_vs_cb(struct d2d_device_context *context,
745 const D2D_MATRIX_3X2_F *geometry_transform, float stroke_width)
747 D3D11_MAPPED_SUBRESOURCE map_desc;
748 ID3D11DeviceContext *d3d_context;
749 const D2D1_MATRIX_3X2_F *w;
750 struct d2d_vs_cb *cb_data;
751 float tmp_x, tmp_y;
752 HRESULT hr;
754 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
756 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->vs_cb,
757 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
759 WARN("Failed to map constant buffer, hr %#x.\n", hr);
760 ID3D11DeviceContext_Release(d3d_context);
761 return hr;
764 cb_data = map_desc.pData;
765 cb_data->transform_geometry._11 = geometry_transform->_11;
766 cb_data->transform_geometry._21 = geometry_transform->_21;
767 cb_data->transform_geometry._31 = geometry_transform->_31;
768 cb_data->transform_geometry.pad0 = 0.0f;
769 cb_data->transform_geometry._12 = geometry_transform->_12;
770 cb_data->transform_geometry._22 = geometry_transform->_22;
771 cb_data->transform_geometry._32 = geometry_transform->_32;
772 cb_data->transform_geometry.stroke_width = stroke_width;
774 w = &context->drawing_state.transform;
776 tmp_x = context->desc.dpiX / 96.0f;
777 cb_data->transform_rtx.x = w->_11 * tmp_x;
778 cb_data->transform_rtx.y = w->_21 * tmp_x;
779 cb_data->transform_rtx.z = w->_31 * tmp_x;
780 cb_data->transform_rtx.w = 2.0f / context->pixel_size.width;
782 tmp_y = context->desc.dpiY / 96.0f;
783 cb_data->transform_rty.x = w->_12 * tmp_y;
784 cb_data->transform_rty.y = w->_22 * tmp_y;
785 cb_data->transform_rty.z = w->_32 * tmp_y;
786 cb_data->transform_rty.w = -2.0f / context->pixel_size.height;
788 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->vs_cb, 0);
789 ID3D11DeviceContext_Release(d3d_context);
791 return S_OK;
794 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
795 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
797 D3D11_SUBRESOURCE_DATA buffer_data;
798 D3D11_BUFFER_DESC buffer_desc;
799 ID3D11Buffer *ib, *vb;
800 HRESULT hr;
802 if (FAILED(hr = d2d_device_context_update_vs_cb(render_target, &geometry->transform, stroke_width)))
804 WARN("Failed to update vs constant buffer, hr %#x.\n", hr);
805 return;
808 if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, FALSE)))
810 WARN("Failed to update ps constant buffer, hr %#x.\n", hr);
811 return;
814 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
815 buffer_desc.CPUAccessFlags = 0;
816 buffer_desc.MiscFlags = 0;
818 buffer_data.SysMemPitch = 0;
819 buffer_data.SysMemSlicePitch = 0;
821 if (geometry->outline.face_count)
823 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
824 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
825 buffer_data.pSysMem = geometry->outline.faces;
827 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
829 WARN("Failed to create index buffer, hr %#x.\n", hr);
830 return;
833 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
834 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
835 buffer_data.pSysMem = geometry->outline.vertices;
837 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
839 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
840 ID3D11Buffer_Release(ib);
841 return;
844 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
845 sizeof(*geometry->outline.vertices), brush, NULL);
847 ID3D11Buffer_Release(vb);
848 ID3D11Buffer_Release(ib);
851 if (geometry->outline.bezier_face_count)
853 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
854 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
855 buffer_data.pSysMem = geometry->outline.bezier_faces;
857 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
859 WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
860 return;
863 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
864 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
865 buffer_data.pSysMem = geometry->outline.beziers;
867 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
869 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
870 ID3D11Buffer_Release(ib);
871 return;
874 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
875 3 * geometry->outline.bezier_face_count, vb,
876 sizeof(*geometry->outline.beziers), brush, NULL);
878 ID3D11Buffer_Release(vb);
879 ID3D11Buffer_Release(ib);
882 if (geometry->outline.arc_face_count)
884 buffer_desc.ByteWidth = geometry->outline.arc_face_count * sizeof(*geometry->outline.arc_faces);
885 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
886 buffer_data.pSysMem = geometry->outline.arc_faces;
888 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
890 WARN("Failed to create arcs index buffer, hr %#x.\n", hr);
891 return;
894 buffer_desc.ByteWidth = geometry->outline.arc_count * sizeof(*geometry->outline.arcs);
895 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
896 buffer_data.pSysMem = geometry->outline.arcs;
898 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
900 ERR("Failed to create arcs vertex buffer, hr %#x.\n", hr);
901 ID3D11Buffer_Release(ib);
902 return;
905 if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, TRUE)))
906 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
907 3 * geometry->outline.arc_face_count, vb,
908 sizeof(*geometry->outline.arcs), brush, NULL);
910 ID3D11Buffer_Release(vb);
911 ID3D11Buffer_Release(ib);
915 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext *iface,
916 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
918 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
919 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
920 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
922 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
923 iface, geometry, brush, stroke_width, stroke_style);
925 if (stroke_style)
926 FIXME("Ignoring stroke style %p.\n", stroke_style);
928 d2d_device_context_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
931 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
932 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
934 D3D11_SUBRESOURCE_DATA buffer_data;
935 D3D11_BUFFER_DESC buffer_desc;
936 ID3D11Buffer *ib, *vb;
937 HRESULT hr;
939 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
940 buffer_desc.CPUAccessFlags = 0;
941 buffer_desc.MiscFlags = 0;
943 buffer_data.SysMemPitch = 0;
944 buffer_data.SysMemSlicePitch = 0;
946 if (FAILED(hr = d2d_device_context_update_vs_cb(render_target, &geometry->transform, 0.0f)))
948 WARN("Failed to update vs constant buffer, hr %#x.\n", hr);
949 return;
952 if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, FALSE)))
954 WARN("Failed to update ps constant buffer, hr %#x.\n", hr);
955 return;
958 if (geometry->fill.face_count)
960 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
961 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
962 buffer_data.pSysMem = geometry->fill.faces;
964 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
966 WARN("Failed to create index buffer, hr %#x.\n", hr);
967 return;
970 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
971 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
972 buffer_data.pSysMem = geometry->fill.vertices;
974 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
976 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
977 ID3D11Buffer_Release(ib);
978 return;
981 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
982 sizeof(*geometry->fill.vertices), brush, opacity_brush);
984 ID3D11Buffer_Release(vb);
985 ID3D11Buffer_Release(ib);
988 if (geometry->fill.bezier_vertex_count)
990 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
991 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
992 buffer_data.pSysMem = geometry->fill.bezier_vertices;
994 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
996 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
997 return;
1000 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.bezier_vertex_count, vb,
1001 sizeof(*geometry->fill.bezier_vertices), brush, opacity_brush);
1003 ID3D11Buffer_Release(vb);
1006 if (geometry->fill.arc_vertex_count)
1008 buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices);
1009 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1010 buffer_data.pSysMem = geometry->fill.arc_vertices;
1012 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1014 ERR("Failed to create arc vertex buffer, hr %#x.\n", hr);
1015 return;
1018 if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, TRUE)))
1019 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
1020 sizeof(*geometry->fill.arc_vertices), brush, opacity_brush);
1022 ID3D11Buffer_Release(vb);
1026 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
1027 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
1029 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
1030 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
1031 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1032 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
1034 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
1036 if (FAILED(context->error.code))
1037 return;
1039 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
1041 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
1042 return;
1045 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
1048 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext *iface,
1049 ID2D1Mesh *mesh, ID2D1Brush *brush)
1051 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1054 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext *iface,
1055 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1056 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1058 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1059 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1062 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1063 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1064 const D2D1_RECT_F *src_rect, const D2D1_POINT_2F *offset,
1065 const D2D1_MATRIX_4X4_F *perspective_transform)
1067 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1068 D2D1_BRUSH_PROPERTIES brush_desc;
1069 struct d2d_brush *brush;
1070 D2D1_SIZE_F size;
1071 D2D1_RECT_F s, d;
1072 HRESULT hr;
1074 if (perspective_transform)
1075 FIXME("Perspective transform is ignored.\n");
1077 size = ID2D1Bitmap_GetSize(bitmap);
1078 d2d_rect_set(&s, 0.0f, 0.0f, size.width, size.height);
1079 if (src_rect && src_rect->left <= src_rect->right
1080 && src_rect->top <= src_rect->bottom)
1082 d2d_rect_intersect(&s, src_rect);
1085 if (s.left == s.right || s.top == s.bottom)
1086 return;
1088 if (dst_rect)
1090 d = *dst_rect;
1092 else
1094 d.left = 0.0f;
1095 d.top = 0.0f;
1096 d.right = s.right - s.left;
1097 d.bottom = s.bottom - s.top;
1100 if (offset)
1102 d.left += offset->x;
1103 d.top += offset->y;
1104 d.right += offset->x;
1105 d.bottom += offset->y;
1108 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1109 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1110 bitmap_brush_desc.interpolationMode = interpolation_mode;
1112 brush_desc.opacity = opacity;
1113 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1114 brush_desc.transform._21 = 0.0f;
1115 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1116 brush_desc.transform._12 = 0.0f;
1117 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1118 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1120 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1122 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
1123 return;
1126 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext_iface, &d, &brush->ID2D1Brush_iface);
1127 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1130 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext *iface,
1131 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1132 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1134 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1136 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1137 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1139 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1140 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1142 d2d_device_context_set_error(context, E_INVALIDARG);
1143 return;
1146 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
1147 src_rect, NULL, NULL);
1150 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext *iface,
1151 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1152 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1154 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1155 IDWriteTextLayout *text_layout;
1156 IDWriteFactory *dwrite_factory;
1157 D2D1_POINT_2F origin;
1158 float width, height;
1159 HRESULT hr;
1161 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1162 "brush %p, options %#x, measuring_mode %#x.\n",
1163 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1164 brush, options, measuring_mode);
1166 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1167 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1169 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1170 return;
1173 width = max(0.0f, layout_rect->right - layout_rect->left);
1174 height = max(0.0f, layout_rect->bottom - layout_rect->top);
1175 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1176 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1177 width, height, &text_layout);
1178 else
1179 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1180 width, height, render_target->desc.dpiX / 96.0f, (DWRITE_MATRIX *)&render_target->drawing_state.transform,
1181 measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1182 IDWriteFactory_Release(dwrite_factory);
1183 if (FAILED(hr))
1185 ERR("Failed to create text layout, hr %#x.\n", hr);
1186 return;
1189 d2d_point_set(&origin, min(layout_rect->left, layout_rect->right), min(layout_rect->top, layout_rect->bottom));
1190 ID2D1DeviceContext_DrawTextLayout(iface, origin, text_layout, brush, options);
1191 IDWriteTextLayout_Release(text_layout);
1194 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext *iface,
1195 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1197 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1198 struct d2d_draw_text_layout_ctx ctx;
1199 HRESULT hr;
1201 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1202 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1204 ctx.brush = brush;
1205 ctx.options = options;
1207 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1208 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1209 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1212 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1214 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1215 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1216 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1217 return prev_antialias_mode;
1220 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1221 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1223 D2D1_MATRIX_3X2_F *transform, prev_transform;
1224 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1225 ID2D1PathGeometry *geometry;
1226 ID2D1GeometrySink *sink;
1227 HRESULT hr;
1229 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1231 ERR("Failed to create geometry, hr %#x.\n", hr);
1232 return;
1235 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1237 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1238 ID2D1PathGeometry_Release(geometry);
1239 return;
1242 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1243 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1244 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1246 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1247 ID2D1GeometrySink_Release(sink);
1248 ID2D1PathGeometry_Release(geometry);
1249 return;
1252 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1253 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1254 ID2D1GeometrySink_Release(sink);
1256 transform = &render_target->drawing_state.transform;
1257 prev_transform = *transform;
1258 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1259 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1260 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1261 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1262 unsafe_impl_from_ID2D1Brush(brush), NULL);
1263 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1264 *transform = prev_transform;
1266 ID2D1PathGeometry_Release(geometry);
1269 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1270 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1271 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1272 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1274 ID2D1RectangleGeometry *geometry = NULL;
1275 ID2D1BitmapBrush *opacity_brush = NULL;
1276 D2D1_BITMAP_PROPERTIES bitmap_desc;
1277 ID2D1Bitmap *opacity_bitmap = NULL;
1278 IDWriteGlyphRunAnalysis *analysis;
1279 DWRITE_TEXTURE_TYPE texture_type;
1280 D2D1_BRUSH_PROPERTIES brush_desc;
1281 IDWriteFactory2 *dwrite_factory;
1282 D2D1_MATRIX_3X2_F *transform, m;
1283 void *opacity_values = NULL;
1284 size_t opacity_values_size;
1285 D2D1_SIZE_U bitmap_size;
1286 float scale_x, scale_y;
1287 D2D1_RECT_F run_rect;
1288 RECT bounds;
1289 HRESULT hr;
1291 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1292 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1294 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1295 return;
1298 transform = &render_target->drawing_state.transform;
1300 scale_x = render_target->desc.dpiX / 96.0f;
1301 m._11 = transform->_11 * scale_x;
1302 m._21 = transform->_21 * scale_x;
1303 m._31 = transform->_31 * scale_x;
1305 scale_y = render_target->desc.dpiY / 96.0f;
1306 m._12 = transform->_12 * scale_y;
1307 m._22 = transform->_22 * scale_y;
1308 m._32 = transform->_32 * scale_y;
1310 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1311 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1312 baseline_origin.x, baseline_origin.y, &analysis);
1313 IDWriteFactory2_Release(dwrite_factory);
1314 if (FAILED(hr))
1316 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1317 return;
1320 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1321 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1322 else
1323 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1325 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1327 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1328 goto done;
1331 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1332 if (!bitmap_size.width || !bitmap_size.height)
1334 /* Empty run, nothing to do. */
1335 goto done;
1338 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1339 bitmap_size.width *= 3;
1340 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1342 ERR("Failed to allocate opacity values.\n");
1343 goto done;
1345 opacity_values_size = bitmap_size.height * bitmap_size.width;
1347 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1348 texture_type, &bounds, opacity_values, opacity_values_size)))
1350 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1351 goto done;
1354 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1355 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1356 bitmap_desc.dpiX = render_target->desc.dpiX;
1357 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1358 bitmap_desc.dpiX *= 3.0f;
1359 bitmap_desc.dpiY = render_target->desc.dpiY;
1360 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext_iface,
1361 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1363 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1364 goto done;
1367 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1368 bounds.right / scale_x, bounds.bottom / scale_y);
1370 brush_desc.opacity = 1.0f;
1371 brush_desc.transform._11 = 1.0f;
1372 brush_desc.transform._12 = 0.0f;
1373 brush_desc.transform._21 = 0.0f;
1374 brush_desc.transform._22 = 1.0f;
1375 brush_desc.transform._31 = run_rect.left;
1376 brush_desc.transform._32 = run_rect.top;
1377 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext_iface,
1378 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1380 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1381 goto done;
1384 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1386 ERR("Failed to create geometry, hr %#x.\n", hr);
1387 goto done;
1390 m = *transform;
1391 *transform = identity;
1392 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1393 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1394 *transform = m;
1396 done:
1397 if (geometry)
1398 ID2D1RectangleGeometry_Release(geometry);
1399 if (opacity_brush)
1400 ID2D1BitmapBrush_Release(opacity_brush);
1401 if (opacity_bitmap)
1402 ID2D1Bitmap_Release(opacity_bitmap);
1403 heap_free(opacity_values);
1404 IDWriteGlyphRunAnalysis_Release(analysis);
1407 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext *iface,
1408 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1409 DWRITE_MEASURING_MODE measuring_mode)
1411 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1412 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1414 ID2D1DeviceContext_DrawGlyphRun(iface, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1417 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext *iface,
1418 const D2D1_MATRIX_3X2_F *transform)
1420 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1422 TRACE("iface %p, transform %p.\n", iface, transform);
1424 render_target->drawing_state.transform = *transform;
1427 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext *iface,
1428 D2D1_MATRIX_3X2_F *transform)
1430 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1432 TRACE("iface %p, transform %p.\n", iface, transform);
1434 *transform = render_target->drawing_state.transform;
1437 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext *iface,
1438 D2D1_ANTIALIAS_MODE antialias_mode)
1440 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1442 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1444 render_target->drawing_state.antialiasMode = antialias_mode;
1447 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext *iface)
1449 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1451 TRACE("iface %p.\n", iface);
1453 return render_target->drawing_state.antialiasMode;
1456 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext *iface,
1457 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1459 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1461 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1463 render_target->drawing_state.textAntialiasMode = antialias_mode;
1466 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext *iface)
1468 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1470 TRACE("iface %p.\n", iface);
1472 return render_target->drawing_state.textAntialiasMode;
1475 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext *iface,
1476 IDWriteRenderingParams *text_rendering_params)
1478 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1480 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1482 if (text_rendering_params)
1483 IDWriteRenderingParams_AddRef(text_rendering_params);
1484 if (render_target->text_rendering_params)
1485 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1486 render_target->text_rendering_params = text_rendering_params;
1489 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext *iface,
1490 IDWriteRenderingParams **text_rendering_params)
1492 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1494 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1496 if ((*text_rendering_params = render_target->text_rendering_params))
1497 IDWriteRenderingParams_AddRef(*text_rendering_params);
1500 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1502 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1504 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1506 render_target->drawing_state.tag1 = tag1;
1507 render_target->drawing_state.tag2 = tag2;
1510 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1512 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1514 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1516 *tag1 = render_target->drawing_state.tag1;
1517 *tag2 = render_target->drawing_state.tag2;
1520 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext *iface,
1521 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1523 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1526 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *iface)
1528 FIXME("iface %p stub!\n", iface);
1531 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1533 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1535 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1537 if (context->ops && context->ops->device_context_present)
1538 context->ops->device_context_present(context->outer_unknown);
1540 return E_NOTIMPL;
1543 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext *iface,
1544 ID2D1DrawingStateBlock *state_block)
1546 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1547 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1549 TRACE("iface %p, state_block %p.\n", iface, state_block);
1551 state_block_impl->drawing_state = render_target->drawing_state;
1552 if (render_target->text_rendering_params)
1553 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1554 if (state_block_impl->text_rendering_params)
1555 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1556 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1559 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext *iface,
1560 ID2D1DrawingStateBlock *state_block)
1562 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1563 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1565 TRACE("iface %p, state_block %p.\n", iface, state_block);
1567 render_target->drawing_state = state_block_impl->drawing_state;
1568 if (state_block_impl->text_rendering_params)
1569 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1570 if (render_target->text_rendering_params)
1571 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1572 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1575 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext *iface,
1576 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1578 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1579 D2D1_RECT_F transformed_rect;
1580 float x_scale, y_scale;
1581 D2D1_POINT_2F point;
1583 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1585 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1586 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1588 x_scale = render_target->desc.dpiX / 96.0f;
1589 y_scale = render_target->desc.dpiY / 96.0f;
1590 d2d_point_transform(&point, &render_target->drawing_state.transform,
1591 clip_rect->left * x_scale, clip_rect->top * y_scale);
1592 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1593 d2d_point_transform(&point, &render_target->drawing_state.transform,
1594 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1595 d2d_rect_expand(&transformed_rect, &point);
1596 d2d_point_transform(&point, &render_target->drawing_state.transform,
1597 clip_rect->right * x_scale, clip_rect->top * y_scale);
1598 d2d_rect_expand(&transformed_rect, &point);
1599 d2d_point_transform(&point, &render_target->drawing_state.transform,
1600 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1601 d2d_rect_expand(&transformed_rect, &point);
1603 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1604 WARN("Failed to push clip rect.\n");
1607 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext *iface)
1609 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1611 TRACE("iface %p.\n", iface);
1613 d2d_clip_stack_pop(&render_target->clip_stack);
1616 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface, const D2D1_COLOR_F *colour)
1618 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1619 D3D11_MAPPED_SUBRESOURCE map_desc;
1620 ID3D11DeviceContext *d3d_context;
1621 struct d2d_ps_cb *ps_cb_data;
1622 struct d2d_vs_cb *vs_cb_data;
1623 D2D1_COLOR_F *c;
1624 HRESULT hr;
1626 TRACE("iface %p, colour %p.\n", iface, colour);
1628 ID3D11Device1_GetImmediateContext(render_target->d3d_device, &d3d_context);
1630 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)render_target->vs_cb,
1631 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
1633 WARN("Failed to map vs constant buffer, hr %#x.\n", hr);
1634 ID3D11DeviceContext_Release(d3d_context);
1635 return;
1638 vs_cb_data = map_desc.pData;
1639 vs_cb_data->transform_geometry._11 = 1.0f;
1640 vs_cb_data->transform_geometry._21 = 0.0f;
1641 vs_cb_data->transform_geometry._31 = 0.0f;
1642 vs_cb_data->transform_geometry.pad0 = 0.0f;
1643 vs_cb_data->transform_geometry._12 = 0.0f;
1644 vs_cb_data->transform_geometry._22 = 1.0f;
1645 vs_cb_data->transform_geometry._32 = 0.0f;
1646 vs_cb_data->transform_geometry.stroke_width = 0.0f;
1647 vs_cb_data->transform_rtx.x = 1.0f;
1648 vs_cb_data->transform_rtx.y = 0.0f;
1649 vs_cb_data->transform_rtx.z = 1.0f;
1650 vs_cb_data->transform_rtx.w = 1.0f;
1651 vs_cb_data->transform_rty.x = 0.0f;
1652 vs_cb_data->transform_rty.y = 1.0f;
1653 vs_cb_data->transform_rty.z = 1.0f;
1654 vs_cb_data->transform_rty.w = -1.0f;
1656 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)render_target->vs_cb, 0);
1658 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)render_target->ps_cb,
1659 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
1661 WARN("Failed to map ps constant buffer, hr %#x.\n", hr);
1662 ID3D11DeviceContext_Release(d3d_context);
1663 return;
1666 ps_cb_data = map_desc.pData;
1667 memset(ps_cb_data, 0, sizeof(*ps_cb_data));
1668 ps_cb_data->colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1669 ps_cb_data->colour_brush.opacity = 1.0f;
1670 ps_cb_data->opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1671 c = &ps_cb_data->colour_brush.u.solid.colour;
1672 if (colour)
1673 *c = *colour;
1674 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1675 c->a = 1.0f;
1676 c->r *= c->a;
1677 c->g *= c->a;
1678 c->b *= c->a;
1680 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)render_target->ps_cb, 0);
1681 ID3D11DeviceContext_Release(d3d_context);
1683 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1684 render_target->vb, render_target->vb_stride, NULL, NULL);
1687 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
1689 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1691 TRACE("iface %p.\n", iface);
1693 memset(&render_target->error, 0, sizeof(render_target->error));
1696 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface,
1697 D2D1_TAG *tag1, D2D1_TAG *tag2)
1699 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1700 HRESULT hr;
1702 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1704 if (tag1)
1705 *tag1 = context->error.tag1;
1706 if (tag2)
1707 *tag2 = context->error.tag2;
1709 if (context->ops && context->ops->device_context_present)
1711 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1712 context->error.code = hr;
1715 return context->error.code;
1718 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface,
1719 D2D1_PIXEL_FORMAT *format)
1721 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1723 TRACE("iface %p, format %p.\n", iface, format);
1725 *format = render_target->desc.pixelFormat;
1726 return format;
1729 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext *iface, float dpi_x, float dpi_y)
1731 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1733 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1735 if (dpi_x == 0.0f && dpi_y == 0.0f)
1737 dpi_x = 96.0f;
1738 dpi_y = 96.0f;
1740 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1741 return;
1743 render_target->desc.dpiX = dpi_x;
1744 render_target->desc.dpiY = dpi_y;
1747 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext *iface, float *dpi_x, float *dpi_y)
1749 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1751 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1753 *dpi_x = render_target->desc.dpiX;
1754 *dpi_y = render_target->desc.dpiY;
1757 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext *iface, D2D1_SIZE_F *size)
1759 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1761 TRACE("iface %p, size %p.\n", iface, size);
1763 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1764 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1765 return size;
1768 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext *iface,
1769 D2D1_SIZE_U *pixel_size)
1771 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1773 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1775 *pixel_size = render_target->pixel_size;
1776 return pixel_size;
1779 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext *iface)
1781 TRACE("iface %p.\n", iface);
1783 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1786 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext *iface,
1787 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1789 FIXME("iface %p, desc %p stub!\n", iface, desc);
1791 return FALSE;
1794 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext *iface,
1795 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
1796 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1798 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1799 struct d2d_bitmap *object;
1800 HRESULT hr;
1802 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
1803 iface, size.width, size.height, src_data, pitch, desc, bitmap);
1805 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
1806 *bitmap = &object->ID2D1Bitmap1_iface;
1808 return hr;
1811 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
1812 ID2D1DeviceContext *iface, IWICBitmapSource *bitmap_source,
1813 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1815 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1816 struct d2d_bitmap *object;
1817 HRESULT hr;
1819 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
1821 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
1822 *bitmap = &object->ID2D1Bitmap1_iface;
1824 return hr;
1827 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext *iface,
1828 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
1830 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
1831 iface, space, profile, profile_size, color_context);
1833 return E_NOTIMPL;
1836 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext *iface,
1837 const WCHAR *filename, ID2D1ColorContext **color_context)
1839 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
1841 return E_NOTIMPL;
1844 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext *iface,
1845 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
1847 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
1849 return E_NOTIMPL;
1852 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
1853 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1855 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1856 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
1857 struct d2d_bitmap *object;
1858 HRESULT hr;
1860 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
1862 if (!desc)
1864 DXGI_SURFACE_DESC surface_desc;
1866 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1868 WARN("Failed to get surface desc, hr %#x.\n", hr);
1869 return hr;
1872 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
1873 bitmap_desc.pixelFormat.format = surface_desc.Format;
1874 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1875 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
1876 desc = &bitmap_desc;
1879 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
1880 *bitmap = &object->ID2D1Bitmap1_iface;
1882 return hr;
1885 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
1886 REFCLSID effect_id, ID2D1Effect **effect)
1888 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1889 struct d2d_effect *object;
1890 HRESULT hr;
1892 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1894 if (!(object = heap_alloc_zero(sizeof(*object))))
1895 return E_OUTOFMEMORY;
1897 if (FAILED(hr = d2d_effect_init(object, context->factory, effect_id)))
1899 WARN("Failed to initialize effect, hr %#x.\n", hr);
1900 heap_free(object);
1901 return hr;
1904 TRACE("Created effect %p.\n", object);
1905 *effect = &object->ID2D1Effect_iface;
1907 return S_OK;
1910 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1911 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1912 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1913 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1914 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1916 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1917 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1918 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1919 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1921 return E_NOTIMPL;
1924 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1925 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1926 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1928 FIXME("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p stub!\n",
1929 iface, image, image_brush_desc, brush_desc, brush);
1931 return E_NOTIMPL;
1934 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1935 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1936 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1938 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1939 struct d2d_brush *object;
1940 HRESULT hr;
1942 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1943 brush_desc, brush);
1945 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1946 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1948 return hr;
1951 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1952 ID2D1CommandList **command_list)
1954 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1956 return E_NOTIMPL;
1959 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1961 FIXME("iface %p, format %#x stub!\n", iface, format);
1963 return FALSE;
1966 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1967 D2D1_BUFFER_PRECISION buffer_precision)
1969 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1971 return FALSE;
1974 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1975 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1977 FIXME("iface %p, image %p, local_bounds %p stub!\n", iface, image, local_bounds);
1980 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
1981 ID2D1Image *image, D2D1_RECT_F *world_bounds)
1983 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
1985 return E_NOTIMPL;
1988 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
1989 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1990 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
1992 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
1993 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
1995 return E_NOTIMPL;
1998 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
2000 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2002 TRACE("iface %p, device %p.\n", iface, device);
2004 *device = context->device;
2005 ID2D1Device_AddRef(*device);
2008 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2010 if (!context->target)
2011 return;
2013 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
2014 context->target = NULL;
2016 /* Note that DPI settings are kept. */
2017 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2018 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2020 ID3D11BlendState_Release(context->bs);
2021 context->bs = NULL;
2024 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
2026 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2027 struct d2d_bitmap *bitmap_impl;
2028 D3D11_BLEND_DESC blend_desc;
2029 ID2D1Bitmap *bitmap;
2030 HRESULT hr;
2032 TRACE("iface %p, target %p.\n", iface, target);
2034 if (!target)
2036 d2d_device_context_reset_target(context);
2037 return;
2040 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2042 FIXME("Only bitmap targets are supported.\n");
2043 return;
2046 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2048 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2050 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2051 return;
2054 d2d_device_context_reset_target(context);
2056 /* Set sizes and pixel format. */
2057 context->pixel_size = bitmap_impl->pixel_size;
2058 context->desc.pixelFormat = bitmap_impl->format;
2059 context->target = bitmap_impl;
2061 memset(&blend_desc, 0, sizeof(blend_desc));
2062 blend_desc.IndependentBlendEnable = FALSE;
2063 blend_desc.RenderTarget[0].BlendEnable = TRUE;
2064 blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
2065 blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
2066 blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
2067 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2069 blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
2070 blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
2072 else
2074 blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
2075 blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
2077 blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
2078 blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
2079 if (FAILED(hr = ID3D11Device1_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2080 WARN("Failed to create blend state, hr %#x.\n", hr);
2083 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2085 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2087 TRACE("iface %p, target %p.\n", iface, target);
2089 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2090 if (*target)
2091 ID2D1Image_AddRef(*target);
2094 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2095 const D2D1_RENDERING_CONTROLS *rendering_controls)
2097 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2100 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2101 D2D1_RENDERING_CONTROLS *rendering_controls)
2103 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2106 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2107 D2D1_PRIMITIVE_BLEND primitive_blend)
2109 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2112 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2114 FIXME("iface %p stub!\n", iface);
2116 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2119 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2121 FIXME("iface %p, unit_mode %#x stub!\n", iface, unit_mode);
2124 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2126 FIXME("iface %p stub!\n", iface);
2128 return D2D1_UNIT_MODE_DIPS;
2131 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2132 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2133 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2135 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
2136 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2137 IDWriteRenderingParams *rendering_params;
2138 DWRITE_RENDERING_MODE rendering_mode;
2139 HRESULT hr;
2141 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2142 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2144 if (FAILED(context->error.code))
2145 return;
2147 rendering_params = context->text_rendering_params ? context->text_rendering_params
2148 : context->default_text_rendering_params;
2150 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
2152 switch (context->drawing_state.textAntialiasMode)
2154 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2155 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
2156 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
2157 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
2158 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
2159 d2d_device_context_set_error(context, E_INVALIDARG);
2160 break;
2162 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2163 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
2164 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2165 d2d_device_context_set_error(context, E_INVALIDARG);
2166 break;
2168 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
2169 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
2170 d2d_device_context_set_error(context, E_INVALIDARG);
2171 break;
2173 default:
2174 break;
2177 if (FAILED(context->error.code))
2178 return;
2180 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
2181 switch (context->drawing_state.textAntialiasMode)
2183 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
2184 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
2185 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2186 break;
2188 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2189 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2190 break;
2192 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2193 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
2194 break;
2196 default:
2197 break;
2200 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2202 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
2203 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
2204 measuring_mode, rendering_params, &rendering_mode)))
2206 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
2207 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
2211 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2212 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
2213 else
2214 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
2215 rendering_mode, measuring_mode, antialias_mode);
2218 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2219 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2220 D2D1_COMPOSITE_MODE composite_mode)
2222 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2223 ID2D1Bitmap *bitmap;
2225 TRACE("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x.\n",
2226 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2227 interpolation_mode, composite_mode);
2229 if (composite_mode != D2D1_COMPOSITE_MODE_SOURCE_OVER)
2230 FIXME("Unhandled composite mode %#x.\n", composite_mode);
2232 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
2234 d2d_device_context_draw_bitmap(context, bitmap, NULL, 1.0f, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
2235 image_rect, target_offset, NULL);
2237 ID2D1Bitmap_Release(bitmap);
2238 return;
2241 FIXME("Unhandled image %p.\n", image);
2244 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2245 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2247 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2248 iface, metafile, debug_d2d_point_2f(target_offset));
2251 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2252 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2253 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2255 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2257 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2258 "src_rect %s, perspective_transform %p.\n",
2259 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2260 debug_d2d_rect_f(src_rect), perspective_transform);
2262 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2263 NULL, perspective_transform);
2266 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2267 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2269 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2272 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2273 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2275 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2276 iface, effect, input, debug_d2d_rect_f(input_rect));
2278 return E_NOTIMPL;
2281 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2282 ID2D1Effect *effect, UINT32 *rect_count)
2284 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2286 return E_NOTIMPL;
2289 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2290 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2292 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2294 return E_NOTIMPL;
2297 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2298 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2299 D2D1_RECT_F *input_rect, UINT32 input_count)
2301 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2302 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2304 return E_NOTIMPL;
2307 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2308 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2310 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2311 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2314 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2316 d2d_device_context_QueryInterface,
2317 d2d_device_context_AddRef,
2318 d2d_device_context_Release,
2319 d2d_device_context_GetFactory,
2320 d2d_device_context_CreateBitmap,
2321 d2d_device_context_CreateBitmapFromWicBitmap,
2322 d2d_device_context_CreateSharedBitmap,
2323 d2d_device_context_CreateBitmapBrush,
2324 d2d_device_context_CreateSolidColorBrush,
2325 d2d_device_context_CreateGradientStopCollection,
2326 d2d_device_context_CreateLinearGradientBrush,
2327 d2d_device_context_CreateRadialGradientBrush,
2328 d2d_device_context_CreateCompatibleRenderTarget,
2329 d2d_device_context_CreateLayer,
2330 d2d_device_context_CreateMesh,
2331 d2d_device_context_DrawLine,
2332 d2d_device_context_DrawRectangle,
2333 d2d_device_context_FillRectangle,
2334 d2d_device_context_DrawRoundedRectangle,
2335 d2d_device_context_FillRoundedRectangle,
2336 d2d_device_context_DrawEllipse,
2337 d2d_device_context_FillEllipse,
2338 d2d_device_context_DrawGeometry,
2339 d2d_device_context_FillGeometry,
2340 d2d_device_context_FillMesh,
2341 d2d_device_context_FillOpacityMask,
2342 d2d_device_context_DrawBitmap,
2343 d2d_device_context_DrawText,
2344 d2d_device_context_DrawTextLayout,
2345 d2d_device_context_DrawGlyphRun,
2346 d2d_device_context_SetTransform,
2347 d2d_device_context_GetTransform,
2348 d2d_device_context_SetAntialiasMode,
2349 d2d_device_context_GetAntialiasMode,
2350 d2d_device_context_SetTextAntialiasMode,
2351 d2d_device_context_GetTextAntialiasMode,
2352 d2d_device_context_SetTextRenderingParams,
2353 d2d_device_context_GetTextRenderingParams,
2354 d2d_device_context_SetTags,
2355 d2d_device_context_GetTags,
2356 d2d_device_context_PushLayer,
2357 d2d_device_context_PopLayer,
2358 d2d_device_context_Flush,
2359 d2d_device_context_SaveDrawingState,
2360 d2d_device_context_RestoreDrawingState,
2361 d2d_device_context_PushAxisAlignedClip,
2362 d2d_device_context_PopAxisAlignedClip,
2363 d2d_device_context_Clear,
2364 d2d_device_context_BeginDraw,
2365 d2d_device_context_EndDraw,
2366 d2d_device_context_GetPixelFormat,
2367 d2d_device_context_SetDpi,
2368 d2d_device_context_GetDpi,
2369 d2d_device_context_GetSize,
2370 d2d_device_context_GetPixelSize,
2371 d2d_device_context_GetMaximumBitmapSize,
2372 d2d_device_context_IsSupported,
2373 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2374 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2375 d2d_device_context_CreateColorContext,
2376 d2d_device_context_CreateColorContextFromFilename,
2377 d2d_device_context_CreateColorContextFromWicColorContext,
2378 d2d_device_context_CreateBitmapFromDxgiSurface,
2379 d2d_device_context_CreateEffect,
2380 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2381 d2d_device_context_CreateImageBrush,
2382 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2383 d2d_device_context_CreateCommandList,
2384 d2d_device_context_IsDxgiFormatSupported,
2385 d2d_device_context_IsBufferPrecisionSupported,
2386 d2d_device_context_GetImageLocalBounds,
2387 d2d_device_context_GetImageWorldBounds,
2388 d2d_device_context_GetGlyphRunWorldBounds,
2389 d2d_device_context_GetDevice,
2390 d2d_device_context_SetTarget,
2391 d2d_device_context_GetTarget,
2392 d2d_device_context_SetRenderingControls,
2393 d2d_device_context_GetRenderingControls,
2394 d2d_device_context_SetPrimitiveBlend,
2395 d2d_device_context_GetPrimitiveBlend,
2396 d2d_device_context_SetUnitMode,
2397 d2d_device_context_GetUnitMode,
2398 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2399 d2d_device_context_DrawImage,
2400 d2d_device_context_DrawGdiMetafile,
2401 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2402 d2d_device_context_ID2D1DeviceContext_PushLayer,
2403 d2d_device_context_InvalidateEffectInputRectangle,
2404 d2d_device_context_GetEffectInvalidRectangleCount,
2405 d2d_device_context_GetEffectInvalidRectangles,
2406 d2d_device_context_GetEffectRequiredInputRectangles,
2407 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2410 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2412 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2415 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2417 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2419 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2420 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2421 || IsEqualGUID(iid, &IID_IUnknown))
2423 IDWriteTextRenderer_AddRef(iface);
2424 *out = iface;
2425 return S_OK;
2428 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2430 *out = NULL;
2431 return E_NOINTERFACE;
2434 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2436 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2438 TRACE("iface %p.\n", iface);
2440 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2443 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2445 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2447 TRACE("iface %p.\n", iface);
2449 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2452 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2453 void *ctx, BOOL *disabled)
2455 struct d2d_draw_text_layout_ctx *context = ctx;
2457 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2459 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2461 return S_OK;
2464 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2465 void *ctx, DWRITE_MATRIX *transform)
2467 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2469 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2471 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2473 return S_OK;
2476 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2478 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2480 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2482 *ppd = render_target->desc.dpiY / 96.0f;
2484 return S_OK;
2487 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2488 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2489 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2491 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2492 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2493 struct d2d_draw_text_layout_ctx *context = ctx;
2494 BOOL color_font = FALSE;
2495 ID2D1Brush *brush;
2497 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2498 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2499 iface, ctx, baseline_origin_x, baseline_origin_y,
2500 measuring_mode, glyph_run, desc, effect);
2502 if (desc)
2503 WARN("Ignoring glyph run description %p.\n", desc);
2504 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2505 FIXME("Ignoring options %#x.\n", context->options);
2507 brush = d2d_draw_get_text_brush(context, effect);
2509 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2511 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2513 IDWriteFontFace2 *fontface;
2515 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2516 &IID_IDWriteFontFace2, (void **)&fontface)))
2518 color_font = IDWriteFontFace2_IsColorFont(fontface);
2519 IDWriteFontFace2_Release(fontface);
2523 if (color_font)
2525 IDWriteColorGlyphRunEnumerator *layers;
2526 IDWriteFactory2 *dwrite_factory;
2527 HRESULT hr;
2529 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2530 (IUnknown **)&dwrite_factory)))
2532 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2533 ID2D1Brush_Release(brush);
2534 return hr;
2537 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2538 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2539 IDWriteFactory2_Release(dwrite_factory);
2540 if (FAILED(hr))
2542 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
2543 ID2D1Brush_Release(brush);
2544 return hr;
2547 for (;;)
2549 const DWRITE_COLOR_GLYPH_RUN *color_run;
2550 ID2D1Brush *color_brush;
2551 D2D1_POINT_2F origin;
2552 BOOL has_run = FALSE;
2554 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2556 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
2557 break;
2560 if (!has_run)
2561 break;
2563 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2565 ERR("Failed to get current color run, hr %#x.\n", hr);
2566 break;
2569 if (color_run->paletteIndex == 0xffff)
2570 color_brush = brush;
2571 else
2573 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2574 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2576 ERR("Failed to create solid color brush, hr %#x.\n", hr);
2577 break;
2581 origin.x = color_run->baselineOriginX;
2582 origin.y = color_run->baselineOriginY;
2583 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2584 origin, &color_run->glyphRun, color_brush, measuring_mode);
2586 if (color_brush != brush)
2587 ID2D1Brush_Release(color_brush);
2590 IDWriteColorGlyphRunEnumerator_Release(layers);
2592 else
2593 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2594 baseline_origin, glyph_run, brush, measuring_mode);
2596 ID2D1Brush_Release(brush);
2598 return S_OK;
2601 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2602 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2604 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2605 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2606 struct d2d_draw_text_layout_ctx *context = ctx;
2607 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2608 D2D1_POINT_2F start, end;
2609 ID2D1Brush *brush;
2610 float thickness;
2612 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2613 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2615 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2616 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2617 underline->thickness);
2619 brush = d2d_draw_get_text_brush(context, effect);
2621 start.x = baseline_origin_x;
2622 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2623 end.x = start.x + underline->width;
2624 end.y = start.y;
2625 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2626 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2627 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2629 ID2D1Brush_Release(brush);
2631 return S_OK;
2634 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2635 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2637 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2638 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2639 struct d2d_draw_text_layout_ctx *context = ctx;
2640 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2641 D2D1_POINT_2F start, end;
2642 ID2D1Brush *brush;
2643 float thickness;
2645 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2646 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2648 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2649 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2650 strikethrough->thickness);
2652 brush = d2d_draw_get_text_brush(context, effect);
2654 start.x = baseline_origin_x;
2655 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2656 end.x = start.x + strikethrough->width;
2657 end.y = start.y;
2658 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2659 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2660 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2662 ID2D1Brush_Release(brush);
2664 return S_OK;
2667 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2668 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2670 struct d2d_draw_text_layout_ctx *context = ctx;
2671 ID2D1Brush *brush;
2672 HRESULT hr;
2674 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2675 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2677 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2678 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2679 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2680 brush is selected at Direct2D level. */
2681 brush = context->brush;
2682 context->brush = d2d_draw_get_text_brush(context, effect);
2684 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2686 ID2D1Brush_Release(context->brush);
2687 context->brush = brush;
2689 return hr;
2692 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2694 d2d_text_renderer_QueryInterface,
2695 d2d_text_renderer_AddRef,
2696 d2d_text_renderer_Release,
2697 d2d_text_renderer_IsPixelSnappingDisabled,
2698 d2d_text_renderer_GetCurrentTransform,
2699 d2d_text_renderer_GetPixelsPerDip,
2700 d2d_text_renderer_DrawGlyphRun,
2701 d2d_text_renderer_DrawUnderline,
2702 d2d_text_renderer_DrawStrikethrough,
2703 d2d_text_renderer_DrawInlineObject,
2706 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2708 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2711 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2712 REFIID iid, void **out)
2714 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2716 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2718 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2721 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2723 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2725 TRACE("iface %p.\n", iface);
2727 return IUnknown_AddRef(render_target->outer_unknown);
2730 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2732 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2734 TRACE("iface %p.\n", iface);
2736 return IUnknown_Release(render_target->outer_unknown);
2739 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2741 ID3D11Resource *resource;
2742 HRESULT hr;
2744 ID3D11RenderTargetView_GetResource(render_target->target->rtv, &resource);
2745 hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2746 ID3D11Resource_Release(resource);
2747 if (FAILED(hr))
2749 *surface = NULL;
2750 WARN("Failed to get DXGI surface, %#x.\n", hr);
2751 return hr;
2754 return hr;
2757 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2758 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2760 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2761 IDXGISurface1 *surface;
2762 HRESULT hr;
2764 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2766 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2767 return hr;
2769 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2770 IDXGISurface1_Release(surface);
2772 return hr;
2775 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2776 const RECT *update)
2778 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2779 IDXGISurface1 *surface;
2780 RECT update_rect;
2781 HRESULT hr;
2783 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2785 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2786 return hr;
2788 if (update)
2789 update_rect = *update;
2790 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2791 IDXGISurface1_Release(surface);
2793 return hr;
2796 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2798 d2d_gdi_interop_render_target_QueryInterface,
2799 d2d_gdi_interop_render_target_AddRef,
2800 d2d_gdi_interop_render_target_Release,
2801 d2d_gdi_interop_render_target_GetDC,
2802 d2d_gdi_interop_render_target_ReleaseDC,
2805 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2806 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2808 D3D11_SUBRESOURCE_DATA buffer_data;
2809 struct d2d_device *device_impl;
2810 IDWriteFactory *dwrite_factory;
2811 D3D11_RASTERIZER_DESC rs_desc;
2812 D3D11_BUFFER_DESC buffer_desc;
2813 unsigned int i;
2814 HRESULT hr;
2816 static const D3D11_INPUT_ELEMENT_DESC il_desc_outline[] =
2818 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2819 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2820 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
2822 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
2824 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2825 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2826 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
2827 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
2828 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
2829 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0},
2831 static const D3D11_INPUT_ELEMENT_DESC il_desc_triangle[] =
2833 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2835 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve[] =
2837 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
2838 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
2840 static const DWORD vs_code_outline[] =
2842 #if 0
2843 float3x2 transform_geometry;
2844 float stroke_width;
2845 float4 transform_rtx;
2846 float4 transform_rty;
2848 struct output
2850 float2 p : WORLD_POSITION;
2851 float4 b : BEZIER;
2852 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2853 float4 position : SV_POSITION;
2856 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2858 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2860 * Where:
2862 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2863 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2864 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2865 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2867 float2 q_prev, q_next, v_p, q_i;
2868 float2x2 geom;
2869 float l;
2871 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2873 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2874 q_prev = normalize(mul(geom, prev));
2875 q_next = normalize(mul(geom, next));
2877 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2878 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2879 v_p = float2(-q_prev.y, q_prev.x);
2880 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2881 q_i = l * q_prev + v_p;
2883 o.b = float4(0.0, 0.0, 0.0, 0.0);
2885 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2886 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2887 * float2(transform_rtx.w, transform_rty.w);
2888 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2890 #endif
2891 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2892 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2893 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2894 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2895 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2896 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2897 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2898 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2899 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2900 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2901 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2902 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2903 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2904 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2905 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2906 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2907 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2908 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2909 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2910 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2911 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2912 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2913 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2914 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2915 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2916 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2917 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2918 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2919 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2920 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2921 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2922 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2923 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2924 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2925 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2926 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2927 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2928 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2929 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2930 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2931 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2932 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2933 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2934 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2935 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2936 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2937 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2938 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2939 0x3f800000, 0x0100003e,
2941 /* ⎡p0.x p0.y 1⎤
2942 * A = ⎢p1.x p1.y 1⎥
2943 * ⎣p2.x p2.y 1⎦
2945 * ⎡0 0⎤
2946 * B = ⎢½ 0⎥
2947 * ⎣1 1⎦
2949 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2950 * ⎣p2.x-p0.x p2.y-p0.y⎦
2952 * B' = ⎡½ 0⎤
2953 * ⎣1 1⎦
2955 * A'T = B'
2956 * T = A'⁻¹B'
2958 static const DWORD vs_code_bezier_outline[] =
2960 #if 0
2961 float3x2 transform_geometry;
2962 float stroke_width;
2963 float4 transform_rtx;
2964 float4 transform_rty;
2966 struct output
2968 float2 p : WORLD_POSITION;
2969 float4 b : BEZIER;
2970 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2971 float4 position : SV_POSITION;
2974 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2975 float2 prev : PREV, float2 next : NEXT, out struct output o)
2977 float2 q_prev, q_next, v_p, q_i, p;
2978 float2x2 geom, rt;
2979 float l;
2981 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2982 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2983 o.stroke_transform = rt * stroke_width * 0.5f;
2985 p = mul(geom, position);
2986 p0 = mul(geom, p0);
2987 p1 = mul(geom, p1);
2988 p2 = mul(geom, p2);
2990 p -= p0;
2991 p1 -= p0;
2992 p2 -= p0;
2994 q_prev = normalize(mul(geom, prev));
2995 q_next = normalize(mul(geom, next));
2997 v_p = float2(-q_prev.y, q_prev.x);
2998 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2999 q_i = l * q_prev + v_p;
3000 p += 0.5f * stroke_width * q_i;
3002 v_p = mul(rt, p2);
3003 v_p = normalize(float2(-v_p.y, v_p.x));
3004 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
3006 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
3007 o.b.y = dot(mul(rt, p), v_p);
3009 else
3011 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
3012 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
3013 o.b.x = dot(v_p, p1 - 0.5f * p2);
3014 o.b.y = dot(v_p, p1);
3017 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3018 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3019 * float2(transform_rtx.w, transform_rty.w);
3020 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3022 #endif
3023 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3024 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3025 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3026 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3027 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3028 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3029 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3030 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3031 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3032 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3033 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3034 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3035 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3036 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3037 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3038 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3039 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3040 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3041 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3042 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3043 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3044 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3045 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3046 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3047 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3048 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3049 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3050 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3051 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3052 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3053 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3054 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3055 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3056 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3057 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3058 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3059 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3060 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3061 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3062 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3063 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3064 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3065 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3066 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3067 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3068 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3069 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3070 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3071 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3072 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3073 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3074 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3075 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3076 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3077 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3078 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3079 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3080 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3081 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3082 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3083 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3084 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3085 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3086 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3087 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3088 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3089 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3090 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3091 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3092 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3093 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3094 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3095 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3096 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3097 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3098 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3099 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3100 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3101 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3102 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3103 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3104 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3105 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3106 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3107 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3108 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3109 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3110 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3112 /* ⎡p0.x p0.y 1⎤
3113 * A = ⎢p1.x p1.y 1⎥
3114 * ⎣p2.x p2.y 1⎦
3116 * ⎡1 0⎤
3117 * B = ⎢1 1⎥
3118 * ⎣0 1⎦
3120 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3121 * ⎣p2.x-p0.x p2.y-p0.y⎦
3123 * B' = ⎡ 0 1⎤
3124 * ⎣-1 1⎦
3126 * A'T = B'
3127 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3129 static const DWORD vs_code_arc_outline[] =
3131 #if 0
3132 float3x2 transform_geometry;
3133 float stroke_width;
3134 float4 transform_rtx;
3135 float4 transform_rty;
3137 struct output
3139 float2 p : WORLD_POSITION;
3140 float4 b : BEZIER;
3141 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3142 float4 position : SV_POSITION;
3145 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3146 float2 prev : PREV, float2 next : NEXT, out struct output o)
3148 float2 q_prev, q_next, v_p, q_i, p;
3149 float2x2 geom, rt, p_inv;
3150 float l;
3151 float a;
3152 float2 bc;
3154 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3155 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3156 o.stroke_transform = rt * stroke_width * 0.5f;
3158 p = mul(geom, position);
3159 p0 = mul(geom, p0);
3160 p1 = mul(geom, p1);
3161 p2 = mul(geom, p2);
3163 p -= p0;
3164 p1 -= p0;
3165 p2 -= p0;
3167 q_prev = normalize(mul(geom, prev));
3168 q_next = normalize(mul(geom, next));
3170 v_p = float2(-q_prev.y, q_prev.x);
3171 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3172 q_i = l * q_prev + v_p;
3173 p += 0.5f * stroke_width * q_i;
3175 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3176 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3177 o.b.zw = 0.0f;
3179 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3180 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3181 * float2(transform_rtx.w, transform_rty.w);
3182 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3184 #endif
3185 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3186 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3187 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3188 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3189 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3190 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3191 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3192 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3193 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3194 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3195 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3196 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3197 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3198 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3199 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3200 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3201 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3202 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3203 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3204 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3205 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3206 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3207 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3208 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3209 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3210 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3211 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3212 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3213 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3214 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3215 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3216 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3217 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3218 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3219 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3220 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3221 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3222 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3223 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3224 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3225 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3226 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3227 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3228 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3229 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3230 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3231 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3232 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3233 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3234 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3235 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3236 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3237 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3238 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3239 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3240 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3241 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3242 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3243 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3244 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3245 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3246 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3247 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3248 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3249 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3250 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3251 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3252 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3253 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3254 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3255 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3256 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3257 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3258 0x0100003e,
3260 static const DWORD vs_code_triangle[] =
3262 #if 0
3263 float3x2 transform_geometry;
3264 float4 transform_rtx;
3265 float4 transform_rty;
3267 struct output
3269 float2 p : WORLD_POSITION;
3270 float4 b : BEZIER;
3271 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3272 float4 position : SV_POSITION;
3275 void main(float2 position : POSITION, out struct output o)
3277 o.p = mul(float3(position, 1.0f), transform_geometry);
3278 o.b = float4(1.0, 0.0, 1.0, 1.0);
3279 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3280 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3281 * float2(transform_rtx.w, transform_rty.w);
3282 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3284 #endif
3285 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3286 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3287 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3288 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3289 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3290 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3291 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3292 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3293 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3294 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3295 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3296 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3297 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3298 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3299 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3300 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3301 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3302 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3303 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3304 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3305 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3306 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3307 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3308 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3309 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3310 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3311 0x00000000, 0x3f800000, 0x0100003e,
3313 static const DWORD vs_code_curve[] =
3315 #if 0
3316 float3x2 transform_geometry;
3317 float4 transform_rtx;
3318 float4 transform_rty;
3320 struct output
3322 float2 p : WORLD_POSITION;
3323 float4 b : BEZIER;
3324 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3325 float4 position : SV_POSITION;
3328 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3330 o.p = mul(float3(position, 1.0f), transform_geometry);
3331 o.b = float4(texcoord, 1.0);
3332 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3333 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3334 * float2(transform_rtx.w, transform_rty.w);
3335 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3337 #endif
3338 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3339 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3340 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3341 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3342 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3343 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3344 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3345 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3346 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3347 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3348 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3349 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3350 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3351 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3352 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3353 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3354 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3355 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3356 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3357 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3358 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3359 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3360 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3361 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3362 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3363 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3364 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3365 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3367 static const DWORD ps_code[] =
3369 #if 0
3370 #define BRUSH_TYPE_SOLID 0
3371 #define BRUSH_TYPE_LINEAR 1
3372 #define BRUSH_TYPE_RADIAL 2
3373 #define BRUSH_TYPE_BITMAP 3
3374 #define BRUSH_TYPE_COUNT 4
3376 bool outline;
3377 bool is_arc;
3378 struct brush
3380 uint type;
3381 float opacity;
3382 float4 data[3];
3383 } colour_brush, opacity_brush;
3385 SamplerState s0, s1;
3386 Texture2D t0, t1;
3387 Buffer<float4> b0, b1;
3389 struct input
3391 float2 p : WORLD_POSITION;
3392 float4 b : BEZIER;
3393 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3396 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3398 float4 c_low, c_high;
3399 float p_low, p_high;
3400 uint i;
3402 p_low = gradient.Load(0).x;
3403 c_low = gradient.Load(1);
3404 c_high = c_low;
3406 if (position < p_low)
3407 return c_low;
3409 for (i = 1; i < stop_count; ++i)
3411 p_high = gradient.Load(i * 2).x;
3412 c_high = gradient.Load(i * 2 + 1);
3414 if (position >= p_low && position <= p_high)
3415 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3417 p_low = p_high;
3418 c_low = c_high;
3421 return c_high;
3424 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3426 float2 start, end, v_p, v_q;
3427 uint stop_count;
3428 float p;
3430 start = brush.data[0].xy;
3431 end = brush.data[0].zw;
3432 stop_count = asuint(brush.data[1].x);
3434 v_p = position - start;
3435 v_q = end - start;
3436 p = dot(v_q, v_p) / dot(v_q, v_q);
3438 return sample_gradient(gradient, stop_count, p);
3441 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3443 float2 centre, offset, ra, rb, v_p, v_q, r;
3444 float b, c, l, t;
3445 uint stop_count;
3447 centre = brush.data[0].xy;
3448 offset = brush.data[0].zw;
3449 ra = brush.data[1].xy;
3450 rb = brush.data[1].zw;
3451 stop_count = asuint(brush.data[2].x);
3453 /* Project onto ra, rb. */
3454 r = float2(dot(ra, ra), dot(rb, rb));
3455 v_p = position - (centre + offset);
3456 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3457 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3459 /* ‖t·p̂ + q⃑‖ = 1
3460 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3461 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3463 * b = p̂·q⃑
3464 * c = q⃑·q⃑ - 1
3465 * t = -b + √(b² - c) */
3466 l = length(v_p);
3467 b = dot(v_p, v_q) / l;
3468 c = dot(v_q, v_q) - 1.0;
3469 t = -b + sqrt(b * b - c);
3471 return sample_gradient(gradient, stop_count, l / t);
3474 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3476 float3 transform[2];
3477 bool ignore_alpha;
3478 float2 texcoord;
3479 float4 colour;
3481 transform[0] = brush.data[0].xyz;
3482 transform[1] = brush.data[1].xyz;
3483 ignore_alpha = asuint(brush.data[1].w);
3485 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3486 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3487 colour = t.Sample(s, texcoord);
3488 if (ignore_alpha)
3489 colour.a = 1.0;
3490 return colour;
3493 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3495 if (brush.type == BRUSH_TYPE_SOLID)
3496 return brush.data[0] * brush.opacity;
3497 if (brush.type == BRUSH_TYPE_LINEAR)
3498 return brush_linear(brush, b, position) * brush.opacity;
3499 if (brush.type == BRUSH_TYPE_RADIAL)
3500 return brush_radial(brush, b, position) * brush.opacity;
3501 if (brush.type == BRUSH_TYPE_BITMAP)
3502 return brush_bitmap(brush, t, s, position) * brush.opacity;
3503 return float4(0.0, 0.0, 0.0, brush.opacity);
3506 float4 main(struct input i) : SV_Target
3508 float4 colour;
3510 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3511 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3512 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3514 if (outline)
3516 float2 du, dv, df;
3517 float4 uv;
3519 /* Evaluate the implicit form of the curve (u² - v = 0
3520 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3521 * space, using the screen-space partial derivatives
3522 * to convert the calculated distance to object space.
3524 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3525 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3527 * For Béziers:
3528 * f(x, y) = u(x, y)² - v(x, y)
3529 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3530 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3532 * For arcs:
3533 * f(x, y) = u(x, y)² + v(x, y)² - 1
3534 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3535 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3536 uv = i.b;
3537 du = float2(ddx(uv.x), ddy(uv.x));
3538 dv = float2(ddx(uv.y), ddy(uv.y));
3540 if (!is_arc)
3542 df = 2.0f * uv.x * du - dv;
3544 clip(dot(df, uv.zw));
3545 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3547 else
3549 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3551 clip(dot(df, uv.zw));
3552 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3555 else
3557 /* Evaluate the implicit form of the curve in texture space.
3558 * "i.b.z" determines which side of the curve is shaded. */
3559 if (!is_arc)
3561 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3563 else
3565 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3569 return colour;
3571 #endif
3572 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3573 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3574 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3575 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3576 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3577 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3578 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3579 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3580 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3581 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3582 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3583 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3584 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3585 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3586 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3587 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3588 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3589 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3590 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3591 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3592 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3593 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3594 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3595 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3596 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3597 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3598 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3599 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3600 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3601 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3602 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3603 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3604 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3605 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3606 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3607 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3608 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3609 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3610 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3611 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3612 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3613 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3614 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3615 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3616 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3617 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3618 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3619 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3620 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3621 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3622 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3623 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3624 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3625 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3626 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3627 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3628 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3629 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3630 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3631 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3632 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3633 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3634 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3635 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3636 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3637 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3638 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3639 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3640 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3641 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3642 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3643 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3644 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3645 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3646 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3647 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3648 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3649 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3650 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3651 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3652 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3653 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3654 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3655 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3656 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3657 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3658 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3659 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3660 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3661 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3662 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3663 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3664 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3665 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3666 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3667 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3668 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3669 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3670 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3671 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3672 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3673 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3674 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3675 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3676 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3677 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3678 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3679 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3680 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3681 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3682 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3683 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3684 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3685 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3686 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3687 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3688 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3689 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3690 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3691 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3692 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3693 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3694 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3695 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3696 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3697 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3698 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3699 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3700 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3701 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3702 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3703 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3704 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3705 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3706 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3707 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3708 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3709 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3710 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3711 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3712 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3713 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3714 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3715 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3716 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3717 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3718 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3719 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3720 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3721 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3722 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3723 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3724 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3725 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3726 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3727 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3728 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3729 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3730 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3731 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3732 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3733 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3734 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3735 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3736 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3737 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3738 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3739 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3740 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3741 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3742 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3743 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3744 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3745 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3746 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3747 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3748 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3749 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3750 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3751 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3752 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3753 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3754 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3755 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3756 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3757 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3758 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3759 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3760 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3761 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3762 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3763 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3764 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3765 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3766 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3767 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3768 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3769 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3770 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3771 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3772 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3773 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3774 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3775 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3776 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3777 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3778 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3779 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3780 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3781 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3782 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3783 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3784 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3785 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
3786 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
3787 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
3788 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
3789 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
3790 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
3791 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
3792 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
3793 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3794 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
3795 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
3796 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
3797 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
3798 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
3799 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
3800 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
3801 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
3802 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
3803 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
3804 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
3805 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
3806 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
3807 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
3808 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
3809 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
3810 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
3811 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
3812 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
3813 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
3814 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3815 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
3816 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
3817 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
3818 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
3819 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
3820 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
3821 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
3822 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
3823 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
3824 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
3825 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
3826 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
3827 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
3829 static const struct shape_info
3831 enum d2d_shape_type shape_type;
3832 const D3D11_INPUT_ELEMENT_DESC *il_desc;
3833 unsigned int il_element_count;
3834 const void *vs_code;
3835 size_t vs_code_size;
3837 shape_info[] =
3839 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3840 vs_code_outline, sizeof(vs_code_outline)},
3841 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3842 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3843 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3844 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
3845 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3846 vs_code_triangle, sizeof(vs_code_triangle)},
3847 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
3848 vs_code_curve, sizeof(vs_code_curve)},
3850 static const struct
3852 float x, y;
3854 quad[] =
3856 {-1.0f, 1.0f},
3857 {-1.0f, -1.0f},
3858 { 1.0f, 1.0f},
3859 { 1.0f, -1.0f},
3861 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3862 static const D3D_FEATURE_LEVEL feature_levels = D3D_FEATURE_LEVEL_11_0;
3864 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3865 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3866 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3867 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3868 render_target->refcount = 1;
3869 ID2D1Device_GetFactory(device, &render_target->factory);
3870 render_target->device = device;
3871 ID2D1Device_AddRef(render_target->device);
3873 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3874 render_target->ops = ops;
3876 device_impl = unsafe_impl_from_ID2D1Device(device);
3877 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3878 &IID_ID3D11Device1, (void **)&render_target->d3d_device)))
3880 WARN("Failed to query ID3D11Device1 interface, hr %#x.\n", hr);
3881 goto err;
3884 if (FAILED(hr = ID3D11Device1_CreateDeviceContextState(render_target->d3d_device,
3885 0, &feature_levels, 1, D3D11_SDK_VERSION, &IID_ID3D11Device1, NULL,
3886 &render_target->d3d_state)))
3888 WARN("Failed to create device context state, hr %#x.\n", hr);
3889 goto err;
3892 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3894 const struct shape_info *si = &shape_info[i];
3896 if (FAILED(hr = ID3D11Device1_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3897 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3899 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3900 goto err;
3903 if (FAILED(hr = ID3D11Device1_CreateVertexShader(render_target->d3d_device, si->vs_code,
3904 si->vs_code_size, NULL, &render_target->shape_resources[si->shape_type].vs)))
3906 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3907 goto err;
3912 buffer_desc.ByteWidth = sizeof(struct d2d_vs_cb);
3913 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
3914 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
3915 buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
3916 buffer_desc.MiscFlags = 0;
3918 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
3919 &render_target->vs_cb)))
3921 WARN("Failed to create constant buffer, hr %#x.\n", hr);
3922 goto err;
3925 if (FAILED(hr = ID3D11Device1_CreatePixelShader(render_target->d3d_device,
3926 ps_code, sizeof(ps_code), NULL, &render_target->ps)))
3928 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3929 goto err;
3932 buffer_desc.ByteWidth = sizeof(struct d2d_ps_cb);
3933 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
3934 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
3935 buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
3936 buffer_desc.MiscFlags = 0;
3938 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
3939 &render_target->ps_cb)))
3941 WARN("Failed to create constant buffer, hr %#x.\n", hr);
3942 goto err;
3945 buffer_desc.ByteWidth = sizeof(indices);
3946 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
3947 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
3948 buffer_desc.CPUAccessFlags = 0;
3949 buffer_desc.MiscFlags = 0;
3951 buffer_data.pSysMem = indices;
3952 buffer_data.SysMemPitch = 0;
3953 buffer_data.SysMemSlicePitch = 0;
3955 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
3956 &buffer_desc, &buffer_data, &render_target->ib)))
3958 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3959 goto err;
3962 buffer_desc.ByteWidth = sizeof(quad);
3963 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
3964 buffer_data.pSysMem = quad;
3966 render_target->vb_stride = sizeof(*quad);
3967 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
3968 &buffer_desc, &buffer_data, &render_target->vb)))
3970 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3971 goto err;
3974 rs_desc.FillMode = D3D11_FILL_SOLID;
3975 rs_desc.CullMode = D3D11_CULL_NONE;
3976 rs_desc.FrontCounterClockwise = FALSE;
3977 rs_desc.DepthBias = 0;
3978 rs_desc.DepthBiasClamp = 0.0f;
3979 rs_desc.SlopeScaledDepthBias = 0.0f;
3980 rs_desc.DepthClipEnable = TRUE;
3981 rs_desc.ScissorEnable = TRUE;
3982 rs_desc.MultisampleEnable = FALSE;
3983 rs_desc.AntialiasedLineEnable = FALSE;
3984 if (FAILED(hr = ID3D11Device1_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
3986 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3987 goto err;
3990 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3991 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3993 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3994 goto err;
3997 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3998 IDWriteFactory_Release(dwrite_factory);
3999 if (FAILED(hr))
4001 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
4002 goto err;
4005 render_target->drawing_state.transform = identity;
4007 if (!d2d_clip_stack_init(&render_target->clip_stack))
4009 WARN("Failed to initialize clip stack.\n");
4010 hr = E_FAIL;
4011 goto err;
4014 render_target->desc.dpiX = 96.0f;
4015 render_target->desc.dpiY = 96.0f;
4017 return S_OK;
4019 err:
4020 if (render_target->default_text_rendering_params)
4021 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
4022 if (render_target->rs)
4023 ID3D11RasterizerState_Release(render_target->rs);
4024 if (render_target->vb)
4025 ID3D11Buffer_Release(render_target->vb);
4026 if (render_target->ib)
4027 ID3D11Buffer_Release(render_target->ib);
4028 if (render_target->ps_cb)
4029 ID3D11Buffer_Release(render_target->ps_cb);
4030 if (render_target->ps)
4031 ID3D11PixelShader_Release(render_target->ps);
4032 if (render_target->vs_cb)
4033 ID3D11Buffer_Release(render_target->vs_cb);
4034 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
4036 if (render_target->shape_resources[i].vs)
4037 ID3D11VertexShader_Release(render_target->shape_resources[i].vs);
4038 if (render_target->shape_resources[i].il)
4039 ID3D11InputLayout_Release(render_target->shape_resources[i].il);
4041 if (render_target->d3d_state)
4042 ID3DDeviceContextState_Release(render_target->d3d_state);
4043 if (render_target->d3d_device)
4044 ID3D11Device1_Release(render_target->d3d_device);
4045 ID2D1Device_Release(render_target->device);
4046 ID2D1Factory_Release(render_target->factory);
4047 return hr;
4050 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4051 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4053 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4054 struct d2d_device_context *object;
4055 ID2D1Bitmap1 *bitmap;
4056 HRESULT hr;
4058 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4059 WARN("Ignoring render target type %#x.\n", desc->type);
4060 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4061 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4062 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4063 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4065 bitmap_desc.dpiX = desc->dpiX;
4066 bitmap_desc.dpiY = desc->dpiY;
4068 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4070 bitmap_desc.dpiX = 96.0f;
4071 bitmap_desc.dpiY = 96.0f;
4073 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4074 return E_INVALIDARG;
4076 if (!(object = heap_alloc_zero(sizeof(*object))))
4077 return E_OUTOFMEMORY;
4079 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4081 WARN("Failed to initialize render target, hr %#x.\n", hr);
4082 heap_free(object);
4083 return hr;
4086 ID2D1DeviceContext_SetDpi(&object->ID2D1DeviceContext_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4088 if (surface)
4090 bitmap_desc.pixelFormat = desc->pixelFormat;
4091 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4092 bitmap_desc.colorContext = NULL;
4094 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
4095 surface, &bitmap_desc, &bitmap)))
4097 WARN("Failed to create target bitmap, hr %#x.\n", hr);
4098 IUnknown_Release(&object->IUnknown_iface);
4099 heap_free(object);
4100 return hr;
4103 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
4104 ID2D1Bitmap1_Release(bitmap);
4106 else
4107 object->desc.pixelFormat = desc->pixelFormat;
4109 TRACE("Created render target %p.\n", object);
4110 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
4112 return S_OK;
4115 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
4117 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4119 if (IsEqualGUID(iid, &IID_ID2D1Device)
4120 || IsEqualGUID(iid, &IID_ID2D1Resource)
4121 || IsEqualGUID(iid, &IID_IUnknown))
4123 ID2D1Device_AddRef(iface);
4124 *out = iface;
4125 return S_OK;
4128 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4130 *out = NULL;
4131 return E_NOINTERFACE;
4134 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
4136 struct d2d_device *device = impl_from_ID2D1Device(iface);
4137 ULONG refcount = InterlockedIncrement(&device->refcount);
4139 TRACE("%p increasing refcount to %u.\n", iface, refcount);
4141 return refcount;
4144 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
4146 struct d2d_device *device = impl_from_ID2D1Device(iface);
4147 ULONG refcount = InterlockedDecrement(&device->refcount);
4149 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
4151 if (!refcount)
4153 IDXGIDevice_Release(device->dxgi_device);
4154 ID2D1Factory1_Release(device->factory);
4155 heap_free(device);
4158 return refcount;
4161 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
4163 struct d2d_device *device = impl_from_ID2D1Device(iface);
4165 TRACE("iface %p, factory %p.\n", iface, factory);
4167 *factory = (ID2D1Factory *)device->factory;
4168 ID2D1Factory1_AddRef(device->factory);
4171 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4172 ID2D1DeviceContext **context)
4174 struct d2d_device_context *object;
4175 HRESULT hr;
4177 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4179 if (options)
4180 FIXME("Options are ignored %#x.\n", options);
4182 if (!(object = heap_alloc_zero(sizeof(*object))))
4183 return E_OUTOFMEMORY;
4185 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
4187 WARN("Failed to initialize device context, hr %#x.\n", hr);
4188 heap_free(object);
4189 return hr;
4192 TRACE("Created device context %p.\n", object);
4193 *context = &object->ID2D1DeviceContext_iface;
4195 return S_OK;
4198 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
4199 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4200 ID2D1PrintControl **print_control)
4202 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4203 document_target, desc, print_control);
4205 return E_NOTIMPL;
4208 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
4210 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4213 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
4215 FIXME("iface %p stub!\n", iface);
4217 return 0;
4220 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
4222 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4224 return E_NOTIMPL;
4227 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
4229 d2d_device_QueryInterface,
4230 d2d_device_AddRef,
4231 d2d_device_Release,
4232 d2d_device_GetFactory,
4233 d2d_device_CreateDeviceContext,
4234 d2d_device_CreatePrintControl,
4235 d2d_device_SetMaximumTextureMemory,
4236 d2d_device_GetMaximumTextureMemory,
4237 d2d_device_ClearResources,
4240 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
4242 if (!iface)
4243 return NULL;
4244 assert(iface->lpVtbl == &d2d_device_vtbl);
4245 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
4248 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4250 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
4251 device->refcount = 1;
4252 device->factory = iface;
4253 ID2D1Factory1_AddRef(device->factory);
4254 device->dxgi_device = dxgi_device;
4255 IDXGIDevice_AddRef(device->dxgi_device);