bcrypt: Make format_gnutls_signature() static.
[wine.git] / dlls / d2d1 / device.c
blob0d10ac3e138a9f835454c2d6294d811f3661af48
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 =
27 1.0f, 0.0f,
28 0.0f, 1.0f,
29 0.0f, 0.0f,
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 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
122 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
124 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
125 ID3D10Device *device = render_target->d3d_device;
126 D3D10_RECT scissor_rect;
127 unsigned int offset;
128 D3D10_VIEWPORT vp;
129 HRESULT hr;
131 vp.TopLeftX = 0;
132 vp.TopLeftY = 0;
133 vp.Width = render_target->pixel_size.width;
134 vp.Height = render_target->pixel_size.height;
135 vp.MinDepth = 0.0f;
136 vp.MaxDepth = 1.0f;
138 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
140 WARN("Failed to capture stateblock, hr %#x.\n", hr);
141 return;
144 ID3D10Device_ClearState(device);
146 ID3D10Device_IASetInputLayout(device, shape_resources->il);
147 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
148 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
149 offset = 0;
150 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
151 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
152 ID3D10Device_VSSetShader(device, shape_resources->vs);
153 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
154 ID3D10Device_PSSetShader(device, render_target->ps);
155 ID3D10Device_RSSetViewports(device, 1, &vp);
156 if (render_target->clip_stack.count)
158 const D2D1_RECT_F *clip_rect;
160 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
161 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
162 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
163 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
164 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
166 else
168 scissor_rect.left = 0.0f;
169 scissor_rect.top = 0.0f;
170 scissor_rect.right = render_target->pixel_size.width;
171 scissor_rect.bottom = render_target->pixel_size.height;
173 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
174 ID3D10Device_RSSetState(device, render_target->rs);
175 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->target->rtv, NULL);
176 if (brush)
178 ID3D10Device_OMSetBlendState(device, render_target->bs, NULL, D3D10_DEFAULT_SAMPLE_MASK);
179 d2d_brush_bind_resources(brush, device, 0);
181 if (opacity_brush)
182 d2d_brush_bind_resources(opacity_brush, device, 1);
184 if (ib)
185 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
186 else
187 ID3D10Device_Draw(device, index_count, 0);
189 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
190 WARN("Failed to apply stateblock, hr %#x.\n", hr);
193 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
195 context->error.code = code;
196 context->error.tag1 = context->drawing_state.tag1;
197 context->error.tag2 = context->drawing_state.tag2;
200 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
202 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
205 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext *iface)
207 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
210 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
212 struct d2d_device_context *context = impl_from_IUnknown(iface);
214 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
216 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext)
217 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
218 || IsEqualGUID(iid, &IID_ID2D1Resource)
219 || IsEqualGUID(iid, &IID_IUnknown))
221 ID2D1DeviceContext_AddRef(&context->ID2D1DeviceContext_iface);
222 *out = &context->ID2D1DeviceContext_iface;
223 return S_OK;
225 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
227 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
228 *out = &context->ID2D1GdiInteropRenderTarget_iface;
229 return S_OK;
232 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
234 *out = NULL;
235 return E_NOINTERFACE;
238 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
240 struct d2d_device_context *context = impl_from_IUnknown(iface);
241 ULONG refcount = InterlockedIncrement(&context->refcount);
243 TRACE("%p increasing refcount to %u.\n", iface, refcount);
245 return refcount;
248 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
250 struct d2d_device_context *context = impl_from_IUnknown(iface);
251 ULONG refcount = InterlockedDecrement(&context->refcount);
253 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
255 if (!refcount)
257 unsigned int i;
259 d2d_clip_stack_cleanup(&context->clip_stack);
260 IDWriteRenderingParams_Release(context->default_text_rendering_params);
261 if (context->text_rendering_params)
262 IDWriteRenderingParams_Release(context->text_rendering_params);
263 if (context->bs)
264 ID3D10BlendState_Release(context->bs);
265 ID3D10RasterizerState_Release(context->rs);
266 ID3D10Buffer_Release(context->vb);
267 ID3D10Buffer_Release(context->ib);
268 ID3D10PixelShader_Release(context->ps);
269 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
271 ID3D10VertexShader_Release(context->shape_resources[i].vs);
272 ID3D10InputLayout_Release(context->shape_resources[i].il);
274 context->stateblock->lpVtbl->Release(context->stateblock);
275 if (context->target)
276 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
277 ID3D10Device_Release(context->d3d_device);
278 ID2D1Factory_Release(context->factory);
279 ID2D1Device_Release(context->device);
280 heap_free(context);
283 return refcount;
286 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
288 d2d_device_context_inner_QueryInterface,
289 d2d_device_context_inner_AddRef,
290 d2d_device_context_inner_Release,
293 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out)
295 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
297 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
299 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
302 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface)
304 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
306 TRACE("iface %p.\n", iface);
308 return IUnknown_AddRef(context->outer_unknown);
311 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface)
313 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
315 TRACE("iface %p.\n", iface);
317 return IUnknown_Release(context->outer_unknown);
320 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext *iface, ID2D1Factory **factory)
322 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
324 TRACE("iface %p, factory %p.\n", iface, factory);
326 *factory = render_target->factory;
327 ID2D1Factory_AddRef(*factory);
330 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext *iface,
331 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
333 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
334 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
335 struct d2d_bitmap *object;
336 HRESULT hr;
338 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
339 iface, size.width, size.height, src_data, pitch, desc, bitmap);
341 if (desc)
343 memcpy(&bitmap_desc, desc, sizeof(*desc));
344 bitmap_desc.bitmapOptions = 0;
345 bitmap_desc.colorContext = NULL;
348 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
349 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
351 return hr;
354 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext *iface,
355 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
357 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
358 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
359 struct d2d_bitmap *object;
360 HRESULT hr;
362 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
363 iface, bitmap_source, desc, bitmap);
365 if (desc)
367 memcpy(&bitmap_desc, desc, sizeof(*desc));
368 bitmap_desc.bitmapOptions = 0;
369 bitmap_desc.colorContext = NULL;
372 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
373 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
375 return hr;
378 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext *iface,
379 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
381 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
382 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
383 struct d2d_bitmap *object;
384 HRESULT hr;
386 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
387 iface, debugstr_guid(iid), data, desc, bitmap);
389 if (desc)
391 memcpy(&bitmap_desc, desc, sizeof(*desc));
392 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
393 bitmap_desc.colorContext = NULL;
396 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
397 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
399 return hr;
402 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext *iface,
403 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
404 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
406 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
407 struct d2d_brush *object;
408 HRESULT hr;
410 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
411 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
413 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
414 brush_desc, &object)))
415 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
417 return hr;
420 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext *iface,
421 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
423 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
424 struct d2d_brush *object;
425 HRESULT hr;
427 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
429 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
430 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
432 return hr;
435 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext *iface,
436 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
437 ID2D1GradientStopCollection **gradient)
439 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
440 struct d2d_gradient *object;
441 HRESULT hr;
443 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
444 iface, stops, stop_count, gamma, extend_mode, gradient);
446 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
447 stops, stop_count, gamma, extend_mode, &object)))
448 *gradient = &object->ID2D1GradientStopCollection_iface;
450 return hr;
453 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext *iface,
454 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
455 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
457 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
458 struct d2d_brush *object;
459 HRESULT hr;
461 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
462 iface, gradient_brush_desc, brush_desc, gradient, brush);
464 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
465 gradient, &object)))
466 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
468 return hr;
471 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext *iface,
472 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
473 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
475 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
476 struct d2d_brush *object;
477 HRESULT hr;
479 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
480 iface, gradient_brush_desc, brush_desc, gradient, brush);
482 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
483 gradient_brush_desc, brush_desc, gradient, &object)))
484 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
486 return hr;
489 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext *iface,
490 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
491 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
493 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
494 struct d2d_bitmap_render_target *object;
495 HRESULT hr;
497 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
498 iface, size, pixel_size, format, options, rt);
500 if (!(object = heap_alloc_zero(sizeof(*object))))
501 return E_OUTOFMEMORY;
503 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
504 format, options)))
506 WARN("Failed to initialize render target, hr %#x.\n", hr);
507 heap_free(object);
508 return hr;
511 TRACE("Created render target %p.\n", object);
512 *rt = &object->ID2D1BitmapRenderTarget_iface;
514 return S_OK;
517 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext *iface,
518 const D2D1_SIZE_F *size, ID2D1Layer **layer)
520 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
521 struct d2d_layer *object;
522 HRESULT hr;
524 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
526 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
527 *layer = &object->ID2D1Layer_iface;
529 return hr;
532 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext *iface, ID2D1Mesh **mesh)
534 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
535 struct d2d_mesh *object;
536 HRESULT hr;
538 TRACE("iface %p, mesh %p.\n", iface, mesh);
540 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
541 *mesh = &object->ID2D1Mesh_iface;
543 return hr;
546 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext *iface,
547 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
549 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
550 ID2D1PathGeometry *geometry;
551 ID2D1GeometrySink *sink;
552 HRESULT hr;
554 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
555 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
557 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
559 WARN("Failed to create path geometry, %#x.\n", hr);
560 return;
563 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
565 WARN("Open() failed, %#x.\n", hr);
566 ID2D1PathGeometry_Release(geometry);
567 return;
570 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
571 ID2D1GeometrySink_AddLine(sink, p1);
572 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
573 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
574 WARN("Close() failed, %#x.\n", hr);
575 ID2D1GeometrySink_Release(sink);
577 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
578 ID2D1PathGeometry_Release(geometry);
581 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext *iface,
582 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
584 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
585 ID2D1RectangleGeometry *geometry;
586 HRESULT hr;
588 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
589 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
591 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
593 ERR("Failed to create geometry, hr %#x.\n", hr);
594 return;
597 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
598 ID2D1RectangleGeometry_Release(geometry);
601 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext *iface,
602 const D2D1_RECT_F *rect, ID2D1Brush *brush)
604 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
605 ID2D1RectangleGeometry *geometry;
606 HRESULT hr;
608 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
610 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
612 ERR("Failed to create geometry, hr %#x.\n", hr);
613 return;
616 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
617 ID2D1RectangleGeometry_Release(geometry);
620 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext *iface,
621 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
623 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
624 ID2D1RoundedRectangleGeometry *geometry;
625 HRESULT hr;
627 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
628 iface, rect, brush, stroke_width, stroke_style);
630 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
632 ERR("Failed to create geometry, hr %#x.\n", hr);
633 return;
636 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
637 ID2D1RoundedRectangleGeometry_Release(geometry);
640 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext *iface,
641 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
643 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
644 ID2D1RoundedRectangleGeometry *geometry;
645 HRESULT hr;
647 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
649 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
651 ERR("Failed to create geometry, hr %#x.\n", hr);
652 return;
655 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
656 ID2D1RoundedRectangleGeometry_Release(geometry);
659 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext *iface,
660 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
662 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
663 ID2D1EllipseGeometry *geometry;
664 HRESULT hr;
666 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
667 iface, ellipse, brush, stroke_width, stroke_style);
669 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
671 ERR("Failed to create geometry, hr %#x.\n", hr);
672 return;
675 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
676 ID2D1EllipseGeometry_Release(geometry);
679 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext *iface,
680 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
682 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
683 ID2D1EllipseGeometry *geometry;
684 HRESULT hr;
686 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
688 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
690 ERR("Failed to create geometry, hr %#x.\n", hr);
691 return;
694 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
695 ID2D1EllipseGeometry_Release(geometry);
698 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
699 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
701 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
702 D3D10_SUBRESOURCE_DATA buffer_data;
703 D3D10_BUFFER_DESC buffer_desc;
704 const D2D1_MATRIX_3X2_F *w;
705 float tmp_x, tmp_y;
706 HRESULT hr;
707 struct
709 struct
711 float _11, _21, _31, pad0;
712 float _12, _22, _32, stroke_width;
713 } transform_geometry;
714 struct d2d_vec4 transform_rtx;
715 struct d2d_vec4 transform_rty;
716 } vs_cb_data;
718 vs_cb_data.transform_geometry._11 = geometry->transform._11;
719 vs_cb_data.transform_geometry._21 = geometry->transform._21;
720 vs_cb_data.transform_geometry._31 = geometry->transform._31;
721 vs_cb_data.transform_geometry.pad0 = 0.0f;
722 vs_cb_data.transform_geometry._12 = geometry->transform._12;
723 vs_cb_data.transform_geometry._22 = geometry->transform._22;
724 vs_cb_data.transform_geometry._32 = geometry->transform._32;
725 vs_cb_data.transform_geometry.stroke_width = stroke_width;
727 w = &render_target->drawing_state.transform;
729 tmp_x = render_target->desc.dpiX / 96.0f;
730 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
731 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
732 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
733 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
735 tmp_y = render_target->desc.dpiY / 96.0f;
736 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
737 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
738 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
739 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
741 buffer_desc.ByteWidth = sizeof(vs_cb_data);
742 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
743 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
744 buffer_desc.CPUAccessFlags = 0;
745 buffer_desc.MiscFlags = 0;
747 buffer_data.pSysMem = &vs_cb_data;
748 buffer_data.SysMemPitch = 0;
749 buffer_data.SysMemSlicePitch = 0;
751 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
753 WARN("Failed to create constant buffer, hr %#x.\n", hr);
754 return;
757 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, render_target, &ps_cb)))
759 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
760 ID3D10Buffer_Release(vs_cb);
761 return;
764 if (geometry->outline.face_count)
766 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
767 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
768 buffer_data.pSysMem = geometry->outline.faces;
770 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
772 WARN("Failed to create index buffer, hr %#x.\n", hr);
773 goto done;
776 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
777 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
778 buffer_data.pSysMem = geometry->outline.vertices;
780 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
782 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
783 ID3D10Buffer_Release(ib);
784 goto done;
787 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
788 sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
790 ID3D10Buffer_Release(vb);
791 ID3D10Buffer_Release(ib);
794 if (geometry->outline.bezier_face_count)
796 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
797 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
798 buffer_data.pSysMem = geometry->outline.bezier_faces;
800 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
802 WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
803 goto done;
806 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
807 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
808 buffer_data.pSysMem = geometry->outline.beziers;
810 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
812 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
813 ID3D10Buffer_Release(ib);
814 goto done;
817 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
818 3 * geometry->outline.bezier_face_count, vb,
819 sizeof(*geometry->outline.beziers), vs_cb, ps_cb, brush, NULL);
821 ID3D10Buffer_Release(vb);
822 ID3D10Buffer_Release(ib);
825 done:
826 ID3D10Buffer_Release(ps_cb);
827 ID3D10Buffer_Release(vs_cb);
830 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext *iface,
831 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
833 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
834 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
835 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
837 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
838 iface, geometry, brush, stroke_width, stroke_style);
840 if (stroke_style)
841 FIXME("Ignoring stroke style %p.\n", stroke_style);
843 d2d_device_context_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
846 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
847 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
849 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
850 D3D10_SUBRESOURCE_DATA buffer_data;
851 D3D10_BUFFER_DESC buffer_desc;
852 D2D1_MATRIX_3X2_F *w;
853 float tmp_x, tmp_y;
854 HRESULT hr;
855 struct
857 struct
859 float _11, _21, _31, pad0;
860 float _12, _22, _32, pad1;
861 } transform_geometry;
862 struct d2d_vec4 transform_rtx;
863 struct d2d_vec4 transform_rty;
864 } vs_cb_data;
866 vs_cb_data.transform_geometry._11 = geometry->transform._11;
867 vs_cb_data.transform_geometry._21 = geometry->transform._21;
868 vs_cb_data.transform_geometry._31 = geometry->transform._31;
869 vs_cb_data.transform_geometry.pad0 = 0.0f;
870 vs_cb_data.transform_geometry._12 = geometry->transform._12;
871 vs_cb_data.transform_geometry._22 = geometry->transform._22;
872 vs_cb_data.transform_geometry._32 = geometry->transform._32;
873 vs_cb_data.transform_geometry.pad1 = 0.0f;
875 w = &render_target->drawing_state.transform;
877 tmp_x = render_target->desc.dpiX / 96.0f;
878 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
879 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
880 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
881 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
883 tmp_y = render_target->desc.dpiY / 96.0f;
884 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
885 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
886 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
887 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
889 buffer_desc.ByteWidth = sizeof(vs_cb_data);
890 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
891 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
892 buffer_desc.CPUAccessFlags = 0;
893 buffer_desc.MiscFlags = 0;
895 buffer_data.pSysMem = &vs_cb_data;
896 buffer_data.SysMemPitch = 0;
897 buffer_data.SysMemSlicePitch = 0;
899 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
901 WARN("Failed to create constant buffer, hr %#x.\n", hr);
902 return;
905 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, render_target, &ps_cb)))
907 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
908 ID3D10Buffer_Release(vs_cb);
909 return;
912 if (geometry->fill.face_count)
914 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
915 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
916 buffer_data.pSysMem = geometry->fill.faces;
918 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
920 WARN("Failed to create index buffer, hr %#x.\n", hr);
921 goto done;
924 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
925 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
926 buffer_data.pSysMem = geometry->fill.vertices;
928 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
930 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
931 ID3D10Buffer_Release(ib);
932 goto done;
935 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
936 sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush);
938 ID3D10Buffer_Release(vb);
939 ID3D10Buffer_Release(ib);
942 if (geometry->fill.bezier_vertex_count)
944 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
945 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
946 buffer_data.pSysMem = geometry->fill.bezier_vertices;
948 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
950 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
951 goto done;
954 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb,
955 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush);
957 ID3D10Buffer_Release(vb);
960 done:
961 ID3D10Buffer_Release(ps_cb);
962 ID3D10Buffer_Release(vs_cb);
965 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
966 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
968 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
969 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
970 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
971 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
973 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
975 if (FAILED(context->error.code))
976 return;
978 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
980 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
981 return;
984 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
987 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext *iface,
988 ID2D1Mesh *mesh, ID2D1Brush *brush)
990 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
993 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext *iface,
994 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
995 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
997 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
998 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1001 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1002 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1003 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
1005 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1006 D2D1_BRUSH_PROPERTIES brush_desc;
1007 struct d2d_brush *brush;
1008 D2D1_RECT_F s, d;
1009 HRESULT hr;
1011 if (perspective_transform)
1012 FIXME("Perspective transform is ignored.\n");
1014 if (src_rect)
1016 s = *src_rect;
1018 else
1020 D2D1_SIZE_F size;
1022 size = ID2D1Bitmap_GetSize(bitmap);
1023 s.left = 0.0f;
1024 s.top = 0.0f;
1025 s.right = size.width;
1026 s.bottom = size.height;
1029 if (dst_rect)
1031 d = *dst_rect;
1033 else
1035 d.left = 0.0f;
1036 d.top = 0.0f;
1037 d.right = s.right - s.left;
1038 d.bottom = s.bottom - s.top;
1041 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1042 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1043 bitmap_brush_desc.interpolationMode = interpolation_mode;
1045 brush_desc.opacity = opacity;
1046 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1047 brush_desc.transform._21 = 0.0f;
1048 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1049 brush_desc.transform._12 = 0.0f;
1050 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1051 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1053 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1055 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
1056 return;
1059 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext_iface, &d, &brush->ID2D1Brush_iface);
1060 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1063 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext *iface,
1064 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1065 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1067 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1069 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1070 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1072 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1073 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1075 d2d_device_context_set_error(context, E_INVALIDARG);
1076 return;
1079 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect, NULL);
1082 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext *iface,
1083 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1084 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1086 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1087 IDWriteTextLayout *text_layout;
1088 IDWriteFactory *dwrite_factory;
1089 D2D1_POINT_2F origin;
1090 HRESULT hr;
1092 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1093 "brush %p, options %#x, measuring_mode %#x.\n",
1094 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1095 brush, options, measuring_mode);
1097 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1098 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1100 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1101 return;
1104 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1105 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1106 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
1107 else
1108 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1109 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
1110 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1111 IDWriteFactory_Release(dwrite_factory);
1112 if (FAILED(hr))
1114 ERR("Failed to create text layout, hr %#x.\n", hr);
1115 return;
1118 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
1119 ID2D1DeviceContext_DrawTextLayout(iface, origin, text_layout, brush, options);
1120 IDWriteTextLayout_Release(text_layout);
1123 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext *iface,
1124 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1126 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1127 struct d2d_draw_text_layout_ctx ctx;
1128 HRESULT hr;
1130 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1131 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1133 ctx.brush = brush;
1134 ctx.options = options;
1136 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1137 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1138 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1141 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1143 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1144 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1145 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1146 return prev_antialias_mode;
1149 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1150 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1152 D2D1_MATRIX_3X2_F *transform, prev_transform;
1153 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1154 ID2D1PathGeometry *geometry;
1155 ID2D1GeometrySink *sink;
1156 HRESULT hr;
1158 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1160 ERR("Failed to create geometry, hr %#x.\n", hr);
1161 return;
1164 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1166 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1167 ID2D1PathGeometry_Release(geometry);
1168 return;
1171 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1172 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1173 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1175 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1176 ID2D1GeometrySink_Release(sink);
1177 ID2D1PathGeometry_Release(geometry);
1178 return;
1181 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1182 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1183 ID2D1GeometrySink_Release(sink);
1185 transform = &render_target->drawing_state.transform;
1186 prev_transform = *transform;
1187 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1188 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1189 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1190 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1191 unsafe_impl_from_ID2D1Brush(brush), NULL);
1192 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1193 *transform = prev_transform;
1195 ID2D1PathGeometry_Release(geometry);
1198 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1199 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1200 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1201 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1203 ID2D1RectangleGeometry *geometry = NULL;
1204 ID2D1BitmapBrush *opacity_brush = NULL;
1205 D2D1_BITMAP_PROPERTIES bitmap_desc;
1206 ID2D1Bitmap *opacity_bitmap = NULL;
1207 IDWriteGlyphRunAnalysis *analysis;
1208 DWRITE_TEXTURE_TYPE texture_type;
1209 D2D1_BRUSH_PROPERTIES brush_desc;
1210 IDWriteFactory2 *dwrite_factory;
1211 D2D1_MATRIX_3X2_F *transform, m;
1212 void *opacity_values = NULL;
1213 size_t opacity_values_size;
1214 D2D1_SIZE_U bitmap_size;
1215 float scale_x, scale_y;
1216 D2D1_RECT_F run_rect;
1217 RECT bounds;
1218 HRESULT hr;
1220 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1221 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1223 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1224 return;
1227 transform = &render_target->drawing_state.transform;
1229 scale_x = render_target->desc.dpiX / 96.0f;
1230 m._11 = transform->_11 * scale_x;
1231 m._21 = transform->_21 * scale_x;
1232 m._31 = transform->_31 * scale_x;
1234 scale_y = render_target->desc.dpiY / 96.0f;
1235 m._12 = transform->_12 * scale_y;
1236 m._22 = transform->_22 * scale_y;
1237 m._32 = transform->_32 * scale_y;
1239 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1240 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1241 baseline_origin.x, baseline_origin.y, &analysis);
1242 IDWriteFactory2_Release(dwrite_factory);
1243 if (FAILED(hr))
1245 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1246 return;
1249 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1250 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1251 else
1252 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1254 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1256 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1257 goto done;
1260 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1261 if (!bitmap_size.width || !bitmap_size.height)
1263 /* Empty run, nothing to do. */
1264 goto done;
1267 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1268 bitmap_size.width *= 3;
1269 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1271 ERR("Failed to allocate opacity values.\n");
1272 goto done;
1274 opacity_values_size = bitmap_size.height * bitmap_size.width;
1276 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1277 texture_type, &bounds, opacity_values, opacity_values_size)))
1279 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1280 goto done;
1283 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1284 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1285 bitmap_desc.dpiX = render_target->desc.dpiX;
1286 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1287 bitmap_desc.dpiX *= 3.0f;
1288 bitmap_desc.dpiY = render_target->desc.dpiY;
1289 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext_iface,
1290 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1292 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1293 goto done;
1296 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1297 bounds.right / scale_x, bounds.bottom / scale_y);
1299 brush_desc.opacity = 1.0f;
1300 brush_desc.transform._11 = 1.0f;
1301 brush_desc.transform._12 = 0.0f;
1302 brush_desc.transform._21 = 0.0f;
1303 brush_desc.transform._22 = 1.0f;
1304 brush_desc.transform._31 = run_rect.left;
1305 brush_desc.transform._32 = run_rect.top;
1306 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext_iface,
1307 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1309 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1310 goto done;
1313 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1315 ERR("Failed to create geometry, hr %#x.\n", hr);
1316 goto done;
1319 m = *transform;
1320 *transform = identity;
1321 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1322 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1323 *transform = m;
1325 done:
1326 if (geometry)
1327 ID2D1RectangleGeometry_Release(geometry);
1328 if (opacity_brush)
1329 ID2D1BitmapBrush_Release(opacity_brush);
1330 if (opacity_bitmap)
1331 ID2D1Bitmap_Release(opacity_bitmap);
1332 heap_free(opacity_values);
1333 IDWriteGlyphRunAnalysis_Release(analysis);
1336 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext *iface,
1337 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1338 DWRITE_MEASURING_MODE measuring_mode)
1340 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1341 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1343 ID2D1DeviceContext_DrawGlyphRun(iface, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1346 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext *iface,
1347 const D2D1_MATRIX_3X2_F *transform)
1349 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1351 TRACE("iface %p, transform %p.\n", iface, transform);
1353 render_target->drawing_state.transform = *transform;
1356 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext *iface,
1357 D2D1_MATRIX_3X2_F *transform)
1359 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1361 TRACE("iface %p, transform %p.\n", iface, transform);
1363 *transform = render_target->drawing_state.transform;
1366 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext *iface,
1367 D2D1_ANTIALIAS_MODE antialias_mode)
1369 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1371 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1373 render_target->drawing_state.antialiasMode = antialias_mode;
1376 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext *iface)
1378 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1380 TRACE("iface %p.\n", iface);
1382 return render_target->drawing_state.antialiasMode;
1385 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext *iface,
1386 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1388 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1390 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1392 render_target->drawing_state.textAntialiasMode = antialias_mode;
1395 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext *iface)
1397 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1399 TRACE("iface %p.\n", iface);
1401 return render_target->drawing_state.textAntialiasMode;
1404 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext *iface,
1405 IDWriteRenderingParams *text_rendering_params)
1407 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1409 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1411 if (text_rendering_params)
1412 IDWriteRenderingParams_AddRef(text_rendering_params);
1413 if (render_target->text_rendering_params)
1414 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1415 render_target->text_rendering_params = text_rendering_params;
1418 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext *iface,
1419 IDWriteRenderingParams **text_rendering_params)
1421 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1423 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1425 if ((*text_rendering_params = render_target->text_rendering_params))
1426 IDWriteRenderingParams_AddRef(*text_rendering_params);
1429 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1431 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1433 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1435 render_target->drawing_state.tag1 = tag1;
1436 render_target->drawing_state.tag2 = tag2;
1439 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1441 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1443 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1445 *tag1 = render_target->drawing_state.tag1;
1446 *tag2 = render_target->drawing_state.tag2;
1449 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext *iface,
1450 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1452 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1455 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *iface)
1457 FIXME("iface %p stub!\n", iface);
1460 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1462 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1464 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1466 if (context->ops && context->ops->device_context_present)
1467 context->ops->device_context_present(context->outer_unknown);
1469 return E_NOTIMPL;
1472 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext *iface,
1473 ID2D1DrawingStateBlock *state_block)
1475 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1476 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1478 TRACE("iface %p, state_block %p.\n", iface, state_block);
1480 state_block_impl->drawing_state = render_target->drawing_state;
1481 if (render_target->text_rendering_params)
1482 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1483 if (state_block_impl->text_rendering_params)
1484 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1485 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1488 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext *iface,
1489 ID2D1DrawingStateBlock *state_block)
1491 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1492 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1494 TRACE("iface %p, state_block %p.\n", iface, state_block);
1496 render_target->drawing_state = state_block_impl->drawing_state;
1497 if (state_block_impl->text_rendering_params)
1498 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1499 if (render_target->text_rendering_params)
1500 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1501 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1504 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext *iface,
1505 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1507 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1508 D2D1_RECT_F transformed_rect;
1509 float x_scale, y_scale;
1510 D2D1_POINT_2F point;
1512 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1514 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1515 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1517 x_scale = render_target->desc.dpiX / 96.0f;
1518 y_scale = render_target->desc.dpiY / 96.0f;
1519 d2d_point_transform(&point, &render_target->drawing_state.transform,
1520 clip_rect->left * x_scale, clip_rect->top * y_scale);
1521 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1522 d2d_point_transform(&point, &render_target->drawing_state.transform,
1523 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1524 d2d_rect_expand(&transformed_rect, &point);
1525 d2d_point_transform(&point, &render_target->drawing_state.transform,
1526 clip_rect->right * x_scale, clip_rect->top * y_scale);
1527 d2d_rect_expand(&transformed_rect, &point);
1528 d2d_point_transform(&point, &render_target->drawing_state.transform,
1529 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1530 d2d_rect_expand(&transformed_rect, &point);
1532 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1533 WARN("Failed to push clip rect.\n");
1536 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext *iface)
1538 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1540 TRACE("iface %p.\n", iface);
1542 d2d_clip_stack_pop(&render_target->clip_stack);
1545 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface, const D2D1_COLOR_F *colour)
1547 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1548 D3D10_SUBRESOURCE_DATA buffer_data;
1549 struct d2d_ps_cb ps_cb_data = {0};
1550 D3D10_BUFFER_DESC buffer_desc;
1551 ID3D10Buffer *vs_cb, *ps_cb;
1552 D2D1_COLOR_F *c;
1553 HRESULT hr;
1555 static const struct
1557 struct
1559 float _11, _21, _31, pad0;
1560 float _12, _22, _32, pad1;
1561 } transform_geometry;
1562 struct d2d_vec4 transform_rtx;
1563 struct d2d_vec4 transform_rty;
1565 vs_cb_data =
1567 {1.0f, 0.0f, 0.0f, 0.0f,
1568 0.0f, 1.0f, 0.0f, 0.0f},
1569 {1.0f, 0.0f, 1.0f, 1.0f},
1570 {0.0f, 1.0f, 1.0f, -1.0f},
1573 TRACE("iface %p, colour %p.\n", iface, colour);
1575 buffer_desc.ByteWidth = sizeof(vs_cb_data);
1576 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1577 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1578 buffer_desc.CPUAccessFlags = 0;
1579 buffer_desc.MiscFlags = 0;
1581 buffer_data.pSysMem = &vs_cb_data;
1582 buffer_data.SysMemPitch = 0;
1583 buffer_data.SysMemSlicePitch = 0;
1585 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
1587 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1588 return;
1591 ps_cb_data.outline = FALSE;
1592 ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1593 ps_cb_data.colour_brush.opacity = 1.0f;
1594 c = &ps_cb_data.colour_brush.u.solid.colour;
1595 if (colour)
1596 *c = *colour;
1597 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1598 c->a = 1.0f;
1599 c->r *= c->a;
1600 c->g *= c->a;
1601 c->b *= c->a;
1603 ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1605 buffer_desc.ByteWidth = sizeof(ps_cb_data);
1606 buffer_data.pSysMem = &ps_cb_data;
1608 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ps_cb)))
1610 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1611 ID3D10Buffer_Release(vs_cb);
1612 return;
1615 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1616 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1618 ID3D10Buffer_Release(ps_cb);
1619 ID3D10Buffer_Release(vs_cb);
1622 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
1624 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1626 TRACE("iface %p.\n", iface);
1628 memset(&render_target->error, 0, sizeof(render_target->error));
1631 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface,
1632 D2D1_TAG *tag1, D2D1_TAG *tag2)
1634 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1635 HRESULT hr;
1637 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1639 if (tag1)
1640 *tag1 = context->error.tag1;
1641 if (tag2)
1642 *tag2 = context->error.tag2;
1644 if (context->ops && context->ops->device_context_present)
1646 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1647 context->error.code = hr;
1650 return context->error.code;
1653 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface,
1654 D2D1_PIXEL_FORMAT *format)
1656 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1658 TRACE("iface %p, format %p.\n", iface, format);
1660 *format = render_target->desc.pixelFormat;
1661 return format;
1664 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext *iface, float dpi_x, float dpi_y)
1666 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1668 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1670 if (dpi_x == 0.0f && dpi_y == 0.0f)
1672 dpi_x = 96.0f;
1673 dpi_y = 96.0f;
1675 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1676 return;
1678 render_target->desc.dpiX = dpi_x;
1679 render_target->desc.dpiY = dpi_y;
1682 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext *iface, float *dpi_x, float *dpi_y)
1684 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1686 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1688 *dpi_x = render_target->desc.dpiX;
1689 *dpi_y = render_target->desc.dpiY;
1692 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext *iface, D2D1_SIZE_F *size)
1694 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1696 TRACE("iface %p, size %p.\n", iface, size);
1698 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1699 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1700 return size;
1703 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext *iface,
1704 D2D1_SIZE_U *pixel_size)
1706 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1708 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1710 *pixel_size = render_target->pixel_size;
1711 return pixel_size;
1714 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext *iface)
1716 TRACE("iface %p.\n", iface);
1718 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1721 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext *iface,
1722 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1724 FIXME("iface %p, desc %p stub!\n", iface, desc);
1726 return FALSE;
1729 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext *iface,
1730 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
1731 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1733 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1734 struct d2d_bitmap *object;
1735 HRESULT hr;
1737 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
1738 iface, size.width, size.height, src_data, pitch, desc, bitmap);
1740 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
1741 *bitmap = &object->ID2D1Bitmap1_iface;
1743 return hr;
1746 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
1747 ID2D1DeviceContext *iface, IWICBitmapSource *bitmap_source,
1748 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1750 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1751 struct d2d_bitmap *object;
1752 HRESULT hr;
1754 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
1756 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
1757 *bitmap = &object->ID2D1Bitmap1_iface;
1759 return hr;
1762 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext *iface,
1763 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
1765 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
1766 iface, space, profile, profile_size, color_context);
1768 return E_NOTIMPL;
1771 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext *iface,
1772 const WCHAR *filename, ID2D1ColorContext **color_context)
1774 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
1776 return E_NOTIMPL;
1779 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext *iface,
1780 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
1782 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
1784 return E_NOTIMPL;
1787 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
1788 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1790 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1791 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
1792 struct d2d_bitmap *object;
1793 HRESULT hr;
1795 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
1797 if (!desc)
1799 DXGI_SURFACE_DESC surface_desc;
1801 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1803 WARN("Failed to get surface desc, hr %#x.\n", hr);
1804 return hr;
1807 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
1808 bitmap_desc.pixelFormat.format = surface_desc.Format;
1809 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1810 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
1811 desc = &bitmap_desc;
1814 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
1815 *bitmap = &object->ID2D1Bitmap1_iface;
1817 return hr;
1820 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
1821 REFCLSID effect_id, ID2D1Effect **effect)
1823 struct d2d_effect *object;
1825 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1827 if (!(object = heap_alloc_zero(sizeof(*object))))
1828 return E_OUTOFMEMORY;
1830 d2d_effect_init(object);
1832 TRACE("Created effect %p.\n", object);
1833 *effect = &object->ID2D1Effect_iface;
1835 return S_OK;
1838 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1839 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1840 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1841 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1842 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1844 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1845 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1846 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1847 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1849 return E_NOTIMPL;
1852 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1853 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1854 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1856 FIXME("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p stub!\n",
1857 iface, image, image_brush_desc, brush_desc, brush);
1859 return E_NOTIMPL;
1862 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1863 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1864 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1866 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1867 struct d2d_brush *object;
1868 HRESULT hr;
1870 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1871 brush_desc, brush);
1873 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1874 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1876 return hr;
1879 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1880 ID2D1CommandList **command_list)
1882 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1884 return E_NOTIMPL;
1887 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1889 FIXME("iface %p, format %#x stub!\n", iface, format);
1891 return FALSE;
1894 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1895 D2D1_BUFFER_PRECISION buffer_precision)
1897 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1899 return FALSE;
1902 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1903 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1905 FIXME("iface %p, image %p, local_bounds %p stub!\n", iface, image, local_bounds);
1908 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
1909 ID2D1Image *image, D2D1_RECT_F *world_bounds)
1911 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
1913 return E_NOTIMPL;
1916 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
1917 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1918 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
1920 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
1921 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
1923 return E_NOTIMPL;
1926 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
1928 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1930 TRACE("iface %p, device %p.\n", iface, device);
1932 *device = context->device;
1933 ID2D1Device_AddRef(*device);
1936 static void d2d_device_context_reset_target(struct d2d_device_context *context)
1938 if (!context->target)
1939 return;
1941 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
1942 context->target = NULL;
1944 /* Note that DPI settings are kept. */
1945 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
1946 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
1948 ID3D10BlendState_Release(context->bs);
1949 context->bs = NULL;
1952 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
1954 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1955 struct d2d_bitmap *bitmap_impl;
1956 D3D10_BLEND_DESC blend_desc;
1957 ID2D1Bitmap *bitmap;
1958 HRESULT hr;
1960 TRACE("iface %p, target %p.\n", iface, target);
1962 if (!target)
1964 d2d_device_context_reset_target(context);
1965 return;
1968 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
1970 FIXME("Only bitmap targets are supported.\n");
1971 return;
1974 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
1976 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
1978 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
1979 return;
1982 d2d_device_context_reset_target(context);
1984 /* Set sizes and pixel format. */
1985 context->pixel_size = bitmap_impl->pixel_size;
1986 context->desc.pixelFormat = bitmap_impl->format;
1987 context->target = bitmap_impl;
1989 memset(&blend_desc, 0, sizeof(blend_desc));
1990 blend_desc.BlendEnable[0] = TRUE;
1991 blend_desc.SrcBlend = D3D10_BLEND_ONE;
1992 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
1993 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
1994 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1996 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
1997 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
1999 else
2001 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2002 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2004 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2005 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2006 if (FAILED(hr = ID3D10Device_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2007 WARN("Failed to create blend state, hr %#x.\n", hr);
2010 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2012 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2014 TRACE("iface %p, target %p.\n", iface, target);
2016 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2017 if (*target)
2018 ID2D1Image_AddRef(*target);
2021 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2022 const D2D1_RENDERING_CONTROLS *rendering_controls)
2024 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2027 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2028 D2D1_RENDERING_CONTROLS *rendering_controls)
2030 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2033 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2034 D2D1_PRIMITIVE_BLEND primitive_blend)
2036 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2039 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2041 FIXME("iface %p stub!\n", iface);
2043 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2046 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2048 FIXME("iface %p, unit_mode %#x stub!\n", iface, unit_mode);
2051 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2053 FIXME("iface %p stub!\n", iface);
2055 return D2D1_UNIT_MODE_DIPS;
2058 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2059 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2060 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2062 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
2063 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2064 IDWriteRenderingParams *rendering_params;
2065 DWRITE_RENDERING_MODE rendering_mode;
2066 HRESULT hr;
2068 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2069 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2071 if (FAILED(context->error.code))
2072 return;
2074 rendering_params = context->text_rendering_params ? context->text_rendering_params
2075 : context->default_text_rendering_params;
2077 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
2079 switch (context->drawing_state.textAntialiasMode)
2081 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2082 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
2083 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
2084 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
2085 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
2086 d2d_device_context_set_error(context, E_INVALIDARG);
2087 break;
2089 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2090 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
2091 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2092 d2d_device_context_set_error(context, E_INVALIDARG);
2093 break;
2095 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
2096 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
2097 d2d_device_context_set_error(context, E_INVALIDARG);
2098 break;
2100 default:
2101 break;
2104 if (FAILED(context->error.code))
2105 return;
2107 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
2108 switch (context->drawing_state.textAntialiasMode)
2110 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
2111 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
2112 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2113 break;
2115 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2116 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2117 break;
2119 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2120 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
2121 break;
2123 default:
2124 break;
2127 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2129 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
2130 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
2131 measuring_mode, rendering_params, &rendering_mode)))
2133 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
2134 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
2138 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2139 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
2140 else
2141 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
2142 rendering_mode, measuring_mode, antialias_mode);
2145 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2146 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2147 D2D1_COMPOSITE_MODE composite_mode)
2149 FIXME("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x stub!\n",
2150 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2151 interpolation_mode, composite_mode);
2154 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2155 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2157 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2158 iface, metafile, debug_d2d_point_2f(target_offset));
2161 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2162 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2163 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2165 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2167 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2168 "src_rect %s, perspective_transform %p.\n",
2169 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2170 debug_d2d_rect_f(src_rect), perspective_transform);
2172 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2173 perspective_transform);
2176 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2177 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2179 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2182 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2183 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2185 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2186 iface, effect, input, debug_d2d_rect_f(input_rect));
2188 return E_NOTIMPL;
2191 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2192 ID2D1Effect *effect, UINT32 *rect_count)
2194 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2196 return E_NOTIMPL;
2199 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2200 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2202 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2204 return E_NOTIMPL;
2207 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2208 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2209 D2D1_RECT_F *input_rect, UINT32 input_count)
2211 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2212 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2214 return E_NOTIMPL;
2217 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2218 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2220 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2221 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2224 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2226 d2d_device_context_QueryInterface,
2227 d2d_device_context_AddRef,
2228 d2d_device_context_Release,
2229 d2d_device_context_GetFactory,
2230 d2d_device_context_CreateBitmap,
2231 d2d_device_context_CreateBitmapFromWicBitmap,
2232 d2d_device_context_CreateSharedBitmap,
2233 d2d_device_context_CreateBitmapBrush,
2234 d2d_device_context_CreateSolidColorBrush,
2235 d2d_device_context_CreateGradientStopCollection,
2236 d2d_device_context_CreateLinearGradientBrush,
2237 d2d_device_context_CreateRadialGradientBrush,
2238 d2d_device_context_CreateCompatibleRenderTarget,
2239 d2d_device_context_CreateLayer,
2240 d2d_device_context_CreateMesh,
2241 d2d_device_context_DrawLine,
2242 d2d_device_context_DrawRectangle,
2243 d2d_device_context_FillRectangle,
2244 d2d_device_context_DrawRoundedRectangle,
2245 d2d_device_context_FillRoundedRectangle,
2246 d2d_device_context_DrawEllipse,
2247 d2d_device_context_FillEllipse,
2248 d2d_device_context_DrawGeometry,
2249 d2d_device_context_FillGeometry,
2250 d2d_device_context_FillMesh,
2251 d2d_device_context_FillOpacityMask,
2252 d2d_device_context_DrawBitmap,
2253 d2d_device_context_DrawText,
2254 d2d_device_context_DrawTextLayout,
2255 d2d_device_context_DrawGlyphRun,
2256 d2d_device_context_SetTransform,
2257 d2d_device_context_GetTransform,
2258 d2d_device_context_SetAntialiasMode,
2259 d2d_device_context_GetAntialiasMode,
2260 d2d_device_context_SetTextAntialiasMode,
2261 d2d_device_context_GetTextAntialiasMode,
2262 d2d_device_context_SetTextRenderingParams,
2263 d2d_device_context_GetTextRenderingParams,
2264 d2d_device_context_SetTags,
2265 d2d_device_context_GetTags,
2266 d2d_device_context_PushLayer,
2267 d2d_device_context_PopLayer,
2268 d2d_device_context_Flush,
2269 d2d_device_context_SaveDrawingState,
2270 d2d_device_context_RestoreDrawingState,
2271 d2d_device_context_PushAxisAlignedClip,
2272 d2d_device_context_PopAxisAlignedClip,
2273 d2d_device_context_Clear,
2274 d2d_device_context_BeginDraw,
2275 d2d_device_context_EndDraw,
2276 d2d_device_context_GetPixelFormat,
2277 d2d_device_context_SetDpi,
2278 d2d_device_context_GetDpi,
2279 d2d_device_context_GetSize,
2280 d2d_device_context_GetPixelSize,
2281 d2d_device_context_GetMaximumBitmapSize,
2282 d2d_device_context_IsSupported,
2283 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2284 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2285 d2d_device_context_CreateColorContext,
2286 d2d_device_context_CreateColorContextFromFilename,
2287 d2d_device_context_CreateColorContextFromWicColorContext,
2288 d2d_device_context_CreateBitmapFromDxgiSurface,
2289 d2d_device_context_CreateEffect,
2290 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2291 d2d_device_context_CreateImageBrush,
2292 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2293 d2d_device_context_CreateCommandList,
2294 d2d_device_context_IsDxgiFormatSupported,
2295 d2d_device_context_IsBufferPrecisionSupported,
2296 d2d_device_context_GetImageLocalBounds,
2297 d2d_device_context_GetImageWorldBounds,
2298 d2d_device_context_GetGlyphRunWorldBounds,
2299 d2d_device_context_GetDevice,
2300 d2d_device_context_SetTarget,
2301 d2d_device_context_GetTarget,
2302 d2d_device_context_SetRenderingControls,
2303 d2d_device_context_GetRenderingControls,
2304 d2d_device_context_SetPrimitiveBlend,
2305 d2d_device_context_GetPrimitiveBlend,
2306 d2d_device_context_SetUnitMode,
2307 d2d_device_context_GetUnitMode,
2308 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2309 d2d_device_context_DrawImage,
2310 d2d_device_context_DrawGdiMetafile,
2311 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2312 d2d_device_context_ID2D1DeviceContext_PushLayer,
2313 d2d_device_context_InvalidateEffectInputRectangle,
2314 d2d_device_context_GetEffectInvalidRectangleCount,
2315 d2d_device_context_GetEffectInvalidRectangles,
2316 d2d_device_context_GetEffectRequiredInputRectangles,
2317 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2320 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2322 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2325 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2327 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2329 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2330 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2331 || IsEqualGUID(iid, &IID_IUnknown))
2333 IDWriteTextRenderer_AddRef(iface);
2334 *out = iface;
2335 return S_OK;
2338 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2340 *out = NULL;
2341 return E_NOINTERFACE;
2344 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2346 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2348 TRACE("iface %p.\n", iface);
2350 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2353 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2355 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2357 TRACE("iface %p.\n", iface);
2359 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2362 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2363 void *ctx, BOOL *disabled)
2365 struct d2d_draw_text_layout_ctx *context = ctx;
2367 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2369 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2371 return S_OK;
2374 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2375 void *ctx, DWRITE_MATRIX *transform)
2377 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2379 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2381 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2383 return S_OK;
2386 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2388 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2390 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2392 *ppd = render_target->desc.dpiY / 96.0f;
2394 return S_OK;
2397 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2398 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2399 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2401 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2402 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2403 struct d2d_draw_text_layout_ctx *context = ctx;
2404 BOOL color_font = FALSE;
2405 ID2D1Brush *brush;
2407 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2408 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2409 iface, ctx, baseline_origin_x, baseline_origin_y,
2410 measuring_mode, glyph_run, desc, effect);
2412 if (desc)
2413 WARN("Ignoring glyph run description %p.\n", desc);
2414 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2415 FIXME("Ignoring options %#x.\n", context->options);
2417 brush = d2d_draw_get_text_brush(context, effect);
2419 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2421 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2423 IDWriteFontFace2 *fontface;
2425 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2426 &IID_IDWriteFontFace2, (void **)&fontface)))
2428 color_font = IDWriteFontFace2_IsColorFont(fontface);
2429 IDWriteFontFace2_Release(fontface);
2433 if (color_font)
2435 IDWriteColorGlyphRunEnumerator *layers;
2436 IDWriteFactory2 *dwrite_factory;
2437 HRESULT hr;
2439 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2440 (IUnknown **)&dwrite_factory)))
2442 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2443 ID2D1Brush_Release(brush);
2444 return hr;
2447 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2448 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2449 IDWriteFactory2_Release(dwrite_factory);
2450 if (FAILED(hr))
2452 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
2453 ID2D1Brush_Release(brush);
2454 return hr;
2457 for (;;)
2459 const DWRITE_COLOR_GLYPH_RUN *color_run;
2460 ID2D1Brush *color_brush;
2461 D2D1_POINT_2F origin;
2462 BOOL has_run = FALSE;
2464 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2466 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
2467 break;
2470 if (!has_run)
2471 break;
2473 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2475 ERR("Failed to get current color run, hr %#x.\n", hr);
2476 break;
2479 if (color_run->paletteIndex == 0xffff)
2480 color_brush = brush;
2481 else
2483 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2484 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2486 ERR("Failed to create solid color brush, hr %#x.\n", hr);
2487 break;
2491 origin.x = color_run->baselineOriginX;
2492 origin.y = color_run->baselineOriginY;
2493 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2494 origin, &color_run->glyphRun, color_brush, measuring_mode);
2496 if (color_brush != brush)
2497 ID2D1Brush_Release(color_brush);
2500 IDWriteColorGlyphRunEnumerator_Release(layers);
2502 else
2503 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2504 baseline_origin, glyph_run, brush, measuring_mode);
2506 ID2D1Brush_Release(brush);
2508 return S_OK;
2511 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2512 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2514 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2515 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2516 struct d2d_draw_text_layout_ctx *context = ctx;
2517 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2518 D2D1_POINT_2F start, end;
2519 ID2D1Brush *brush;
2520 float thickness;
2522 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2523 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2525 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2526 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2527 underline->thickness);
2529 brush = d2d_draw_get_text_brush(context, effect);
2531 start.x = baseline_origin_x;
2532 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2533 end.x = start.x + underline->width;
2534 end.y = start.y;
2535 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2536 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2537 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2539 ID2D1Brush_Release(brush);
2541 return S_OK;
2544 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2545 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2547 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2548 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2549 struct d2d_draw_text_layout_ctx *context = ctx;
2550 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2551 D2D1_POINT_2F start, end;
2552 ID2D1Brush *brush;
2553 float thickness;
2555 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2556 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2558 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2559 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2560 strikethrough->thickness);
2562 brush = d2d_draw_get_text_brush(context, effect);
2564 start.x = baseline_origin_x;
2565 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2566 end.x = start.x + strikethrough->width;
2567 end.y = start.y;
2568 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2569 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2570 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2572 ID2D1Brush_Release(brush);
2574 return S_OK;
2577 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2578 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2580 struct d2d_draw_text_layout_ctx *context = ctx;
2581 ID2D1Brush *brush;
2582 HRESULT hr;
2584 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2585 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2587 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2588 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2589 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2590 brush is selected at Direct2D level. */
2591 brush = context->brush;
2592 context->brush = d2d_draw_get_text_brush(context, effect);
2594 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2596 ID2D1Brush_Release(context->brush);
2597 context->brush = brush;
2599 return hr;
2602 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2604 d2d_text_renderer_QueryInterface,
2605 d2d_text_renderer_AddRef,
2606 d2d_text_renderer_Release,
2607 d2d_text_renderer_IsPixelSnappingDisabled,
2608 d2d_text_renderer_GetCurrentTransform,
2609 d2d_text_renderer_GetPixelsPerDip,
2610 d2d_text_renderer_DrawGlyphRun,
2611 d2d_text_renderer_DrawUnderline,
2612 d2d_text_renderer_DrawStrikethrough,
2613 d2d_text_renderer_DrawInlineObject,
2616 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2618 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2621 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2622 REFIID iid, void **out)
2624 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2626 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2628 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2631 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2633 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2635 TRACE("iface %p.\n", iface);
2637 return IUnknown_AddRef(render_target->outer_unknown);
2640 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2642 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2644 TRACE("iface %p.\n", iface);
2646 return IUnknown_Release(render_target->outer_unknown);
2649 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2651 ID3D10Resource *resource;
2652 HRESULT hr;
2654 ID3D10RenderTargetView_GetResource(render_target->target->rtv, &resource);
2655 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2656 ID3D10Resource_Release(resource);
2657 if (FAILED(hr))
2659 *surface = NULL;
2660 WARN("Failed to get DXGI surface, %#x.\n", hr);
2661 return hr;
2664 return hr;
2667 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2668 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2670 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2671 IDXGISurface1 *surface;
2672 HRESULT hr;
2674 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2676 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2677 return hr;
2679 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2680 IDXGISurface1_Release(surface);
2682 return hr;
2685 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2686 const RECT *update)
2688 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2689 IDXGISurface1 *surface;
2690 RECT update_rect;
2691 HRESULT hr;
2693 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2695 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2696 return hr;
2698 if (update)
2699 update_rect = *update;
2700 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2701 IDXGISurface1_Release(surface);
2703 return hr;
2706 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2708 d2d_gdi_interop_render_target_QueryInterface,
2709 d2d_gdi_interop_render_target_AddRef,
2710 d2d_gdi_interop_render_target_Release,
2711 d2d_gdi_interop_render_target_GetDC,
2712 d2d_gdi_interop_render_target_ReleaseDC,
2715 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2716 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2718 D3D10_SUBRESOURCE_DATA buffer_data;
2719 D3D10_STATE_BLOCK_MASK state_mask;
2720 struct d2d_device *device_impl;
2721 IDWriteFactory *dwrite_factory;
2722 D3D10_RASTERIZER_DESC rs_desc;
2723 D3D10_BUFFER_DESC buffer_desc;
2724 unsigned int i;
2725 HRESULT hr;
2727 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2729 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2730 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2731 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2733 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier_outline[] =
2735 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2736 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2737 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2738 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2739 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2740 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2742 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2744 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2746 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
2748 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2749 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2751 static const DWORD vs_code_outline[] =
2753 #if 0
2754 float3x2 transform_geometry;
2755 float stroke_width;
2756 float4 transform_rtx;
2757 float4 transform_rty;
2759 struct output
2761 float2 p : WORLD_POSITION;
2762 float4 b : BEZIER;
2763 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2764 float4 position : SV_POSITION;
2767 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2769 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2771 * Where:
2773 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2774 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2775 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2776 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2778 float2 q_prev, q_next, v_p, q_i;
2779 float2x2 geom;
2780 float l;
2782 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2784 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2785 q_prev = normalize(mul(geom, prev));
2786 q_next = normalize(mul(geom, next));
2788 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2789 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2790 v_p = float2(-q_prev.y, q_prev.x);
2791 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2792 q_i = l * q_prev + v_p;
2794 o.b = float4(0.0, 0.0, 0.0, 0.0);
2796 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2797 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2798 * float2(transform_rtx.w, transform_rty.w);
2799 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2801 #endif
2802 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2803 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2804 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2805 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2806 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2807 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2808 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2809 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2810 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2811 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2812 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2813 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2814 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2815 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2816 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2817 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2818 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2819 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2820 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2821 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2822 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2823 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2824 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2825 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2826 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2827 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2828 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2829 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2830 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2831 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2832 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2833 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2834 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2835 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2836 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2837 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2838 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2839 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2840 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2841 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2842 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2843 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2844 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2845 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2846 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2847 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2848 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2849 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2850 0x3f800000, 0x0100003e,
2852 /* ⎡p0.x p0.y 1⎤
2853 * A = ⎢p1.x p1.y 1⎥
2854 * ⎣p2.x p2.y 1⎦
2856 * ⎡0 0⎤
2857 * B = ⎢½ 0⎥
2858 * ⎣1 1⎦
2860 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2861 * ⎣p2.x-p0.x p2.y-p0.y⎦
2863 * B' = ⎡½ 0⎤
2864 * ⎣1 1⎦
2866 * A'T = B'
2867 * T = A'⁻¹B'
2869 static const DWORD vs_code_bezier_outline[] =
2871 #if 0
2872 float3x2 transform_geometry;
2873 float stroke_width;
2874 float4 transform_rtx;
2875 float4 transform_rty;
2877 struct output
2879 float2 p : WORLD_POSITION;
2880 float4 b : BEZIER;
2881 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2882 float4 position : SV_POSITION;
2885 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2886 float2 prev : PREV, float2 next : NEXT, out struct output o)
2888 float2 q_prev, q_next, v_p, q_i, p;
2889 float2x2 geom, rt;
2890 float l;
2892 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2893 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2894 o.stroke_transform = rt * stroke_width * 0.5f;
2896 p = mul(geom, position);
2897 p0 = mul(geom, p0);
2898 p1 = mul(geom, p1);
2899 p2 = mul(geom, p2);
2901 p -= p0;
2902 p1 -= p0;
2903 p2 -= p0;
2905 q_prev = normalize(mul(geom, prev));
2906 q_next = normalize(mul(geom, next));
2908 v_p = float2(-q_prev.y, q_prev.x);
2909 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2910 q_i = l * q_prev + v_p;
2911 p += stroke_width * q_i;
2913 v_p = mul(rt, p2);
2914 v_p = normalize(float2(-v_p.y, v_p.x));
2915 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
2917 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
2918 o.b.y = dot(mul(rt, p), v_p);
2920 else
2922 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
2923 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
2924 o.b.x = dot(v_p, p1 - 0.5f * p2);
2925 o.b.y = dot(v_p, p1);
2928 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * q_i;
2929 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2930 * float2(transform_rtx.w, transform_rty.w);
2931 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2933 #endif
2934 0x43425844, 0x7ff88ce9, 0xd75cb064, 0x30396183, 0xca64489b, 0x00000001, 0x00000ae4, 0x00000003,
2935 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
2936 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
2937 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
2938 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
2939 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
2940 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
2941 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
2942 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
2943 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
2944 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
2945 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
2946 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
2947 0x52444853, 0x0000093c, 0x00010040, 0x0000024f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
2948 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
2949 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
2950 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
2951 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
2952 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
2953 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
2954 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
2955 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
2956 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
2957 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
2958 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
2959 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
2960 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
2961 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
2962 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
2963 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
2964 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
2965 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
2966 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
2967 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
2968 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
2969 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
2970 0x0a000032, 0x00100032, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000,
2971 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f,
2972 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f,
2973 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f,
2974 0x00100012, 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f,
2975 0x00100022, 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000,
2976 0x001000c2, 0x00000000, 0x00100406, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x0a000032,
2977 0x00100032, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000, 0x00100ae6,
2978 0x00000000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046,
2979 0x00000000, 0x0800000f, 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046,
2980 0x00000000, 0x0800000f, 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046,
2981 0x00000003, 0x0800000f, 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046,
2982 0x00000003, 0x08000000, 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406,
2983 0x00000004, 0x0800000f, 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6,
2984 0x00000002, 0x06000036, 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f,
2985 0x00100082, 0x00000003, 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f,
2986 0x00100082, 0x00000000, 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082,
2987 0x00000000, 0x0010003a, 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000,
2988 0x00100ea6, 0x00000003, 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6,
2989 0x00000003, 0x06000036, 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f,
2990 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
2991 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
2992 0x00100032, 0x00000005, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036,
2993 0x00100042, 0x00000005, 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000,
2994 0x00100a26, 0x00000005, 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6,
2995 0x00000041, 0x00000002, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046,
2996 0x00000005, 0x0800000e, 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556,
2997 0x00000000, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002,
2998 0x0700000f, 0x00100022, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f,
2999 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f,
3000 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f,
3001 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022,
3002 0x00000000, 0x00004001, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000,
3003 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a,
3004 0x00000081, 0x00000000, 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a,
3005 0x00000041, 0x00000000, 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a,
3006 0x00000000, 0x07000038, 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000,
3007 0x08000036, 0x001000d2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
3008 0x09000037, 0x001020f2, 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46,
3009 0x00000002, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3010 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3011 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3012 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3013 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3014 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3015 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3016 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3017 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3018 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3019 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3020 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3021 0x0100003e,
3023 static const DWORD vs_code_triangle[] =
3025 #if 0
3026 float3x2 transform_geometry;
3027 float4 transform_rtx;
3028 float4 transform_rty;
3030 struct output
3032 float2 p : WORLD_POSITION;
3033 float4 b : BEZIER;
3034 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3035 float4 position : SV_POSITION;
3038 void main(float2 position : POSITION, out struct output o)
3040 o.p = mul(float3(position, 1.0f), transform_geometry);
3041 o.b = float4(1.0, 0.0, 1.0, 1.0);
3042 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3043 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3044 * float2(transform_rtx.w, transform_rty.w);
3045 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3047 #endif
3048 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3049 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3050 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3051 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3052 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3053 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3054 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3055 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3056 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3057 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3058 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3059 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3060 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3061 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3062 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3063 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3064 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3065 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3066 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3067 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3068 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3069 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3070 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3071 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3072 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3073 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3074 0x00000000, 0x3f800000, 0x0100003e,
3076 static const DWORD vs_code_bezier[] =
3078 #if 0
3079 float3x2 transform_geometry;
3080 float4 transform_rtx;
3081 float4 transform_rty;
3083 struct output
3085 float2 p : WORLD_POSITION;
3086 float4 b : BEZIER;
3087 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3088 float4 position : SV_POSITION;
3091 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3093 o.p = mul(float3(position, 1.0f), transform_geometry);
3094 o.b = float4(texcoord, 1.0);
3095 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3096 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3097 * float2(transform_rtx.w, transform_rty.w);
3098 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3100 #endif
3101 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3102 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3103 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3104 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3105 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3106 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3107 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3108 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3109 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3110 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3111 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3112 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3113 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3114 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3115 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3116 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3117 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3118 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3119 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3120 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3121 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3122 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3123 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3124 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3125 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3126 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3127 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3128 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3130 static const DWORD ps_code[] =
3132 #if 0
3133 #define BRUSH_TYPE_SOLID 0
3134 #define BRUSH_TYPE_LINEAR 1
3135 #define BRUSH_TYPE_RADIAL 2
3136 #define BRUSH_TYPE_BITMAP 3
3137 #define BRUSH_TYPE_COUNT 4
3139 bool outline;
3140 struct brush
3142 uint type;
3143 float opacity;
3144 float4 data[3];
3145 } colour_brush, opacity_brush;
3147 SamplerState s0, s1;
3148 Texture2D t0, t1;
3149 Buffer<float4> b0, b1;
3151 struct input
3153 float2 p : WORLD_POSITION;
3154 float4 b : BEZIER;
3155 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3158 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3160 float4 c_low, c_high;
3161 float p_low, p_high;
3162 uint i;
3164 p_low = gradient.Load(0).x;
3165 c_low = gradient.Load(1);
3166 c_high = c_low;
3168 if (position < p_low)
3169 return c_low;
3171 for (i = 1; i < stop_count; ++i)
3173 p_high = gradient.Load(i * 2).x;
3174 c_high = gradient.Load(i * 2 + 1);
3176 if (position >= p_low && position <= p_high)
3177 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3179 p_low = p_high;
3180 c_low = c_high;
3183 return c_high;
3186 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3188 float2 start, end, v_p, v_q;
3189 uint stop_count;
3190 float p;
3192 start = brush.data[0].xy;
3193 end = brush.data[0].zw;
3194 stop_count = asuint(brush.data[1].x);
3196 v_p = position - start;
3197 v_q = end - start;
3198 p = dot(v_q, v_p) / dot(v_q, v_q);
3200 return sample_gradient(gradient, stop_count, p);
3203 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3205 float2 centre, offset, ra, rb, v_p, v_q, r;
3206 float b, c, l, t;
3207 uint stop_count;
3209 centre = brush.data[0].xy;
3210 offset = brush.data[0].zw;
3211 ra = brush.data[1].xy;
3212 rb = brush.data[1].zw;
3213 stop_count = asuint(brush.data[2].x);
3215 /* Project onto ra, rb. */
3216 r = float2(dot(ra, ra), dot(rb, rb));
3217 v_p = position - (centre + offset);
3218 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3219 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3221 /* ‖t·p̂ + q⃑‖ = 1
3222 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3223 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3225 * b = p̂·q⃑
3226 * c = q⃑·q⃑ - 1
3227 * t = -b + √(b² - c) */
3228 l = length(v_p);
3229 b = dot(v_p, v_q) / l;
3230 c = dot(v_q, v_q) - 1.0;
3231 t = -b + sqrt(b * b - c);
3233 return sample_gradient(gradient, stop_count, l / t);
3236 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3238 float3 transform[2];
3239 bool ignore_alpha;
3240 float2 texcoord;
3241 float4 colour;
3243 transform[0] = brush.data[0].xyz;
3244 transform[1] = brush.data[1].xyz;
3245 ignore_alpha = asuint(brush.data[1].w);
3247 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3248 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3249 colour = t.Sample(s, texcoord);
3250 if (ignore_alpha)
3251 colour.a = 1.0;
3252 return colour;
3255 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3257 if (brush.type == BRUSH_TYPE_SOLID)
3258 return brush.data[0] * brush.opacity;
3259 if (brush.type == BRUSH_TYPE_LINEAR)
3260 return brush_linear(brush, b, position) * brush.opacity;
3261 if (brush.type == BRUSH_TYPE_RADIAL)
3262 return brush_radial(brush, b, position) * brush.opacity;
3263 if (brush.type == BRUSH_TYPE_BITMAP)
3264 return brush_bitmap(brush, t, s, position) * brush.opacity;
3265 return float4(0.0, 0.0, 0.0, brush.opacity);
3268 float4 main(struct input i) : SV_Target
3270 float4 colour;
3272 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3273 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3274 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3276 if (outline)
3278 float2 du, dv, df;
3279 float4 uv;
3281 /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
3282 * using the screen-space partial derivatives to convert the calculated
3283 * distance to object space.
3285 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3286 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3287 * f(x, y) = u(x, y)² - v(x, y)
3288 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3289 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
3290 uv = i.b;
3291 du = float2(ddx(uv.x), ddy(uv.x));
3292 dv = float2(ddx(uv.y), ddy(uv.y));
3293 df = 2.0f * uv.x * du - dv;
3295 clip(dot(df, uv.zw));
3296 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3298 else
3300 /* Evaluate the implicit form of the curve in texture space.
3301 * "i.b.z" determines which side of the curve is shaded. */
3302 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3305 return colour;
3307 #endif
3308 0x43425844, 0xf3cbb8bd, 0x5f286454, 0x139976a7, 0x6817e876, 0x00000001, 0x00001d18, 0x00000003,
3309 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3310 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3311 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3312 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3313 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3314 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3315 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001c18,
3316 0x00000040, 0x00000706, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3317 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3318 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3319 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3320 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3321 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3322 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3323 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3324 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3325 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3326 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3327 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3328 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3329 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3330 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3331 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3332 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3333 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3334 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3335 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3336 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3337 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3338 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3339 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3340 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3341 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3342 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3343 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3344 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3345 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3346 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3347 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3348 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3349 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3350 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3351 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3352 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3353 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3354 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3355 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3356 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3357 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3358 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3359 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3360 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3361 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3362 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3363 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3364 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3365 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3366 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3367 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3368 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3369 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3370 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3371 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3372 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3373 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3374 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3375 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3376 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3377 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3378 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3379 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3380 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3381 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3382 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3383 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3384 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3385 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3386 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3387 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3388 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3389 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3390 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3391 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3392 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3393 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3394 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3395 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3396 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3397 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3398 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3399 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3400 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3401 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3402 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3403 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3404 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3405 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3406 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3407 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3408 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3409 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3410 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3411 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3412 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3413 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3414 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3415 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3416 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3417 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3418 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3419 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3420 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3421 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3422 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3423 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3424 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3425 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3426 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3427 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3428 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3429 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3430 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3431 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3432 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3433 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3434 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3435 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3436 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3437 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3438 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3439 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3440 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3441 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3442 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3443 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3444 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3445 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3446 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3447 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3448 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3449 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3450 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3451 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3452 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3453 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3454 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3455 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3456 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3457 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3458 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3459 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3460 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3461 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3462 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3463 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3464 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3465 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3466 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3467 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3468 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3469 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3470 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3471 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3472 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3473 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3474 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3475 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3476 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3477 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3478 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3479 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3480 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3481 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3482 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3483 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3484 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3485 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3486 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3487 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3488 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3489 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3490 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3491 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3492 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3493 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3494 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3495 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3496 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3497 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3498 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3499 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3500 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3501 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3502 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3503 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3504 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3505 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3506 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3507 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3508 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3509 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3510 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3511 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3512 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3513 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3514 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3515 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3516 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3517 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3518 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3519 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3520 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3521 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x08000027, 0x00100012,
3522 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022,
3523 0x00000000, 0x0010000a, 0x00000000, 0x0500000b, 0x00100032, 0x00000001, 0x00101046, 0x00000001,
3524 0x0500000c, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x07000000, 0x00100042, 0x00000000,
3525 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x001000c2, 0x00000000, 0x00100aa6,
3526 0x00000000, 0x00100806, 0x00000001, 0x80100d56, 0x00000041, 0x00000001, 0x0700000f, 0x00100012,
3527 0x00000001, 0x00100ae6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100012, 0x00000001,
3528 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000001, 0x0010000a,
3529 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010000a, 0x00000001, 0x07000038, 0x00100032,
3530 0x00000001, 0x00100ff6, 0x00000000, 0x00101046, 0x00000003, 0x09000032, 0x001000c2, 0x00000000,
3531 0x00101406, 0x00000002, 0x00100aa6, 0x00000000, 0x00100406, 0x00000001, 0x0700000f, 0x00100042,
3532 0x00000000, 0x00100ae6, 0x00000000, 0x00100ae6, 0x00000000, 0x0500004b, 0x00100042, 0x00000000,
3533 0x0010002a, 0x00000000, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a,
3534 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100042, 0x00000000, 0x8010003a,
3535 0x000000c1, 0x00000000, 0x0010002a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010002a,
3536 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000,
3537 0x0010002a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000038, 0x00100012, 0x00000000,
3538 0x0010003a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010000a,
3539 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000,
3540 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x0100003e,
3542 static const struct shape_info
3544 enum d2d_shape_type shape_type;
3545 const D3D10_INPUT_ELEMENT_DESC *il_desc;
3546 unsigned int il_element_count;
3547 const void *vs_code;
3548 size_t vs_code_size;
3550 shape_info[] =
3552 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3553 vs_code_outline, sizeof(vs_code_outline)},
3554 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_bezier_outline, ARRAY_SIZE(il_desc_bezier_outline),
3555 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3556 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3557 vs_code_triangle, sizeof(vs_code_triangle)},
3558 {D2D_SHAPE_TYPE_BEZIER, il_desc_bezier, ARRAY_SIZE(il_desc_bezier),
3559 vs_code_bezier, sizeof(vs_code_bezier)},
3561 static const struct
3563 float x, y;
3565 quad[] =
3567 {-1.0f, 1.0f},
3568 {-1.0f, -1.0f},
3569 { 1.0f, 1.0f},
3570 { 1.0f, -1.0f},
3572 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3574 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3575 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3576 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3577 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3578 render_target->refcount = 1;
3579 ID2D1Device_GetFactory(device, &render_target->factory);
3580 render_target->device = device;
3581 ID2D1Device_AddRef(render_target->device);
3583 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3584 render_target->ops = ops;
3586 device_impl = unsafe_impl_from_ID2D1Device(device);
3587 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3588 &IID_ID3D10Device, (void **)&render_target->d3d_device)))
3590 WARN("Failed to get device interface, hr %#x.\n", hr);
3591 ID2D1Factory_Release(render_target->factory);
3592 return hr;
3595 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
3597 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
3598 goto err;
3601 if (FAILED(hr = D3D10CreateStateBlock(render_target->d3d_device, &state_mask, &render_target->stateblock)))
3603 WARN("Failed to create stateblock, hr %#x.\n", hr);
3604 goto err;
3607 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3609 const struct shape_info *si = &shape_info[i];
3611 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3612 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3614 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3615 goto err;
3618 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->d3d_device, si->vs_code,
3619 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
3621 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3622 goto err;
3627 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->d3d_device,
3628 ps_code, sizeof(ps_code), &render_target->ps)))
3630 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3631 goto err;
3634 buffer_desc.ByteWidth = sizeof(indices);
3635 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
3636 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
3637 buffer_desc.CPUAccessFlags = 0;
3638 buffer_desc.MiscFlags = 0;
3640 buffer_data.pSysMem = indices;
3641 buffer_data.SysMemPitch = 0;
3642 buffer_data.SysMemSlicePitch = 0;
3644 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3645 &buffer_desc, &buffer_data, &render_target->ib)))
3647 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3648 goto err;
3651 buffer_desc.ByteWidth = sizeof(quad);
3652 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
3653 buffer_data.pSysMem = quad;
3655 render_target->vb_stride = sizeof(*quad);
3656 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3657 &buffer_desc, &buffer_data, &render_target->vb)))
3659 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3660 goto err;
3663 rs_desc.FillMode = D3D10_FILL_SOLID;
3664 rs_desc.CullMode = D3D10_CULL_NONE;
3665 rs_desc.FrontCounterClockwise = FALSE;
3666 rs_desc.DepthBias = 0;
3667 rs_desc.DepthBiasClamp = 0.0f;
3668 rs_desc.SlopeScaledDepthBias = 0.0f;
3669 rs_desc.DepthClipEnable = TRUE;
3670 rs_desc.ScissorEnable = TRUE;
3671 rs_desc.MultisampleEnable = FALSE;
3672 rs_desc.AntialiasedLineEnable = FALSE;
3673 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
3675 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3676 goto err;
3679 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3680 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3682 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3683 goto err;
3686 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3687 IDWriteFactory_Release(dwrite_factory);
3688 if (FAILED(hr))
3690 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
3691 goto err;
3694 render_target->drawing_state.transform = identity;
3696 if (!d2d_clip_stack_init(&render_target->clip_stack))
3698 WARN("Failed to initialize clip stack.\n");
3699 hr = E_FAIL;
3700 goto err;
3703 render_target->desc.dpiX = 96.0f;
3704 render_target->desc.dpiY = 96.0f;
3706 return S_OK;
3708 err:
3709 if (render_target->default_text_rendering_params)
3710 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
3711 if (render_target->rs)
3712 ID3D10RasterizerState_Release(render_target->rs);
3713 if (render_target->vb)
3714 ID3D10Buffer_Release(render_target->vb);
3715 if (render_target->ib)
3716 ID3D10Buffer_Release(render_target->ib);
3717 if (render_target->ps)
3718 ID3D10PixelShader_Release(render_target->ps);
3719 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
3721 if (render_target->shape_resources[i].vs)
3722 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
3723 if (render_target->shape_resources[i].il)
3724 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
3726 if (render_target->stateblock)
3727 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
3728 if (render_target->d3d_device)
3729 ID3D10Device_Release(render_target->d3d_device);
3730 ID2D1Device_Release(render_target->device);
3731 ID2D1Factory_Release(render_target->factory);
3732 return hr;
3735 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
3736 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
3738 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
3739 struct d2d_device_context *object;
3740 ID2D1Bitmap1 *bitmap;
3741 HRESULT hr;
3743 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
3744 WARN("Ignoring render target type %#x.\n", desc->type);
3745 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
3746 FIXME("Ignoring render target usage %#x.\n", desc->usage);
3747 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
3748 WARN("Ignoring feature level %#x.\n", desc->minLevel);
3750 bitmap_desc.dpiX = desc->dpiX;
3751 bitmap_desc.dpiY = desc->dpiY;
3753 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
3755 bitmap_desc.dpiX = 96.0f;
3756 bitmap_desc.dpiY = 96.0f;
3758 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
3759 return E_INVALIDARG;
3761 if (!(object = heap_alloc_zero(sizeof(*object))))
3762 return E_OUTOFMEMORY;
3764 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
3766 WARN("Failed to initialize render target, hr %#x.\n", hr);
3767 heap_free(object);
3768 return hr;
3771 ID2D1DeviceContext_SetDpi(&object->ID2D1DeviceContext_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
3773 if (surface)
3775 bitmap_desc.pixelFormat = desc->pixelFormat;
3776 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
3777 bitmap_desc.colorContext = NULL;
3779 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
3780 surface, &bitmap_desc, &bitmap)))
3782 WARN("Failed to create target bitmap, hr %#x.\n", hr);
3783 IUnknown_Release(&object->IUnknown_iface);
3784 heap_free(object);
3785 return hr;
3788 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
3789 ID2D1Bitmap1_Release(bitmap);
3791 else
3792 object->desc.pixelFormat = desc->pixelFormat;
3794 TRACE("Created render target %p.\n", object);
3795 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
3797 return S_OK;
3800 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
3802 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
3804 if (IsEqualGUID(iid, &IID_ID2D1Device)
3805 || IsEqualGUID(iid, &IID_ID2D1Resource)
3806 || IsEqualGUID(iid, &IID_IUnknown))
3808 ID2D1Device_AddRef(iface);
3809 *out = iface;
3810 return S_OK;
3813 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
3815 *out = NULL;
3816 return E_NOINTERFACE;
3819 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
3821 struct d2d_device *device = impl_from_ID2D1Device(iface);
3822 ULONG refcount = InterlockedIncrement(&device->refcount);
3824 TRACE("%p increasing refcount to %u.\n", iface, refcount);
3826 return refcount;
3829 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
3831 struct d2d_device *device = impl_from_ID2D1Device(iface);
3832 ULONG refcount = InterlockedDecrement(&device->refcount);
3834 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
3836 if (!refcount)
3838 IDXGIDevice_Release(device->dxgi_device);
3839 ID2D1Factory1_Release(device->factory);
3840 heap_free(device);
3843 return refcount;
3846 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
3848 struct d2d_device *device = impl_from_ID2D1Device(iface);
3850 TRACE("iface %p, factory %p.\n", iface, factory);
3852 *factory = (ID2D1Factory *)device->factory;
3853 ID2D1Factory1_AddRef(device->factory);
3856 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
3857 ID2D1DeviceContext **context)
3859 struct d2d_device_context *object;
3860 HRESULT hr;
3862 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
3864 if (options)
3865 FIXME("Options are ignored %#x.\n", options);
3867 if (!(object = heap_alloc_zero(sizeof(*object))))
3868 return E_OUTOFMEMORY;
3870 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
3872 WARN("Failed to initialize device context, hr %#x.\n", hr);
3873 heap_free(object);
3874 return hr;
3877 TRACE("Created device context %p.\n", object);
3878 *context = &object->ID2D1DeviceContext_iface;
3880 return S_OK;
3883 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
3884 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
3885 ID2D1PrintControl **print_control)
3887 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
3888 document_target, desc, print_control);
3890 return E_NOTIMPL;
3893 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
3895 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
3898 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
3900 FIXME("iface %p stub!\n", iface);
3902 return 0;
3905 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
3907 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
3909 return E_NOTIMPL;
3912 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
3914 d2d_device_QueryInterface,
3915 d2d_device_AddRef,
3916 d2d_device_Release,
3917 d2d_device_GetFactory,
3918 d2d_device_CreateDeviceContext,
3919 d2d_device_CreatePrintControl,
3920 d2d_device_SetMaximumTextureMemory,
3921 d2d_device_GetMaximumTextureMemory,
3922 d2d_device_ClearResources,
3925 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
3927 if (!iface)
3928 return NULL;
3929 assert(iface->lpVtbl == &d2d_device_vtbl);
3930 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
3933 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
3935 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
3936 device->refcount = 1;
3937 device->factory = iface;
3938 ID2D1Factory1_AddRef(device->factory);
3939 device->dxgi_device = dxgi_device;
3940 IDXGIDevice_AddRef(device->dxgi_device);