d2d1: Add a helper to set error state.
[wine.git] / dlls / d2d1 / device.c
blob1e420514a80c4a2182ae246f8b3b3413bdb2d32d
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 "config.h"
20 #include "wine/port.h"
22 #include "d2d1_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
26 #define INITIAL_CLIP_STACK_SIZE 4
28 static const D2D1_MATRIX_3X2_F identity =
30 1.0f, 0.0f,
31 0.0f, 1.0f,
32 0.0f, 0.0f,
35 struct d2d_draw_text_layout_ctx
37 ID2D1Brush *brush;
38 D2D1_DRAW_TEXT_OPTIONS options;
41 static inline struct d2d_device *impl_from_ID2D1Device(ID2D1Device *iface)
43 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
46 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface);
48 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
50 ID2D1Brush *brush = NULL;
52 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
53 return brush;
55 ID2D1Brush_AddRef(context->brush);
56 return context->brush;
59 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
61 if (src->left > dst->left)
62 dst->left = src->left;
63 if (src->top > dst->top)
64 dst->top = src->top;
65 if (src->right < dst->right)
66 dst->right = src->right;
67 if (src->bottom < dst->bottom)
68 dst->bottom = src->bottom;
71 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
73 dst->left = left;
74 dst->top = top;
75 dst->right = right;
76 dst->bottom = bottom;
79 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
81 dst->width = width;
82 dst->height = height;
85 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
87 if (!(stack->stack = heap_alloc(INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
88 return FALSE;
90 stack->size = INITIAL_CLIP_STACK_SIZE;
91 stack->count = 0;
93 return TRUE;
96 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
98 heap_free(stack->stack);
101 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
103 D2D1_RECT_F r;
105 if (!d2d_array_reserve((void **)&stack->stack, &stack->size, stack->count + 1, sizeof(*stack->stack)))
106 return FALSE;
108 r = *rect;
109 if (stack->count)
110 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
111 stack->stack[stack->count++] = r;
113 return TRUE;
116 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
118 if (!stack->count)
119 return;
120 --stack->count;
123 static void d2d_device_context_draw(struct d2d_device_context *render_target, enum d2d_shape_type shape_type,
124 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
125 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
127 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
128 ID3D10Device *device = render_target->d3d_device;
129 D3D10_RECT scissor_rect;
130 unsigned int offset;
131 D3D10_VIEWPORT vp;
132 HRESULT hr;
134 static const float blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f};
136 vp.TopLeftX = 0;
137 vp.TopLeftY = 0;
138 vp.Width = render_target->pixel_size.width;
139 vp.Height = render_target->pixel_size.height;
140 vp.MinDepth = 0.0f;
141 vp.MaxDepth = 1.0f;
143 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
145 WARN("Failed to capture stateblock, hr %#x.\n", hr);
146 return;
149 ID3D10Device_ClearState(device);
151 ID3D10Device_IASetInputLayout(device, shape_resources->il);
152 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
153 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
154 offset = 0;
155 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
156 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
157 ID3D10Device_VSSetShader(device, shape_resources->vs);
158 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
159 ID3D10Device_PSSetShader(device, render_target->ps);
160 ID3D10Device_RSSetViewports(device, 1, &vp);
161 if (render_target->clip_stack.count)
163 const D2D1_RECT_F *clip_rect;
165 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
166 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
167 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
168 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
169 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
171 else
173 scissor_rect.left = 0.0f;
174 scissor_rect.top = 0.0f;
175 scissor_rect.right = render_target->pixel_size.width;
176 scissor_rect.bottom = render_target->pixel_size.height;
178 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
179 ID3D10Device_RSSetState(device, render_target->rs);
180 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->target->rtv, NULL);
181 if (brush)
183 ID3D10Device_OMSetBlendState(device, render_target->bs, blend_factor, D3D10_DEFAULT_SAMPLE_MASK);
184 d2d_brush_bind_resources(brush, device, 0);
186 if (opacity_brush)
187 d2d_brush_bind_resources(opacity_brush, device, 1);
189 if (ib)
190 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
191 else
192 ID3D10Device_Draw(device, index_count, 0);
194 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
195 WARN("Failed to apply stateblock, hr %#x.\n", hr);
198 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
200 context->error.code = code;
201 context->error.tag1 = context->drawing_state.tag1;
202 context->error.tag2 = context->drawing_state.tag2;
205 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
207 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
210 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext *iface)
212 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
215 static inline struct d2d_device_context *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
217 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
220 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
222 struct d2d_device_context *context = impl_from_IUnknown(iface);
224 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
226 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext)
227 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
228 || IsEqualGUID(iid, &IID_ID2D1Resource)
229 || IsEqualGUID(iid, &IID_IUnknown))
231 ID2D1DeviceContext_AddRef(&context->ID2D1DeviceContext_iface);
232 *out = &context->ID2D1DeviceContext_iface;
233 return S_OK;
235 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
237 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
238 *out = &context->ID2D1GdiInteropRenderTarget_iface;
239 return S_OK;
242 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
244 *out = NULL;
245 return E_NOINTERFACE;
248 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
250 struct d2d_device_context *context = impl_from_IUnknown(iface);
251 ULONG refcount = InterlockedIncrement(&context->refcount);
253 TRACE("%p increasing refcount to %u.\n", iface, refcount);
255 return refcount;
258 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
260 struct d2d_device_context *context = impl_from_IUnknown(iface);
261 ULONG refcount = InterlockedDecrement(&context->refcount);
263 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
265 if (!refcount)
267 unsigned int i;
269 d2d_clip_stack_cleanup(&context->clip_stack);
270 IDWriteRenderingParams_Release(context->default_text_rendering_params);
271 if (context->text_rendering_params)
272 IDWriteRenderingParams_Release(context->text_rendering_params);
273 if (context->bs)
274 ID3D10BlendState_Release(context->bs);
275 ID3D10RasterizerState_Release(context->rs);
276 ID3D10Buffer_Release(context->vb);
277 ID3D10Buffer_Release(context->ib);
278 ID3D10PixelShader_Release(context->ps);
279 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
281 ID3D10VertexShader_Release(context->shape_resources[i].vs);
282 ID3D10InputLayout_Release(context->shape_resources[i].il);
284 context->stateblock->lpVtbl->Release(context->stateblock);
285 if (context->target)
286 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
287 ID3D10Device_Release(context->d3d_device);
288 ID2D1Factory_Release(context->factory);
289 ID2D1Device_Release(context->device);
290 heap_free(context);
293 return refcount;
296 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
298 d2d_device_context_inner_QueryInterface,
299 d2d_device_context_inner_AddRef,
300 d2d_device_context_inner_Release,
303 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out)
305 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
307 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
309 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
312 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface)
314 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
316 TRACE("iface %p.\n", iface);
318 return IUnknown_AddRef(context->outer_unknown);
321 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface)
323 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
325 TRACE("iface %p.\n", iface);
327 return IUnknown_Release(context->outer_unknown);
330 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext *iface, ID2D1Factory **factory)
332 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
334 TRACE("iface %p, factory %p.\n", iface, factory);
336 *factory = render_target->factory;
337 ID2D1Factory_AddRef(*factory);
340 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext *iface,
341 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
343 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
344 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
345 struct d2d_bitmap *object;
346 HRESULT hr;
348 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
349 iface, size.width, size.height, src_data, pitch, desc, bitmap);
351 if (desc)
353 memcpy(&bitmap_desc, desc, sizeof(*desc));
354 bitmap_desc.bitmapOptions = 0;
355 bitmap_desc.colorContext = NULL;
358 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
359 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
361 return hr;
364 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext *iface,
365 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
367 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
368 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
369 struct d2d_bitmap *object;
370 HRESULT hr;
372 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
373 iface, bitmap_source, desc, bitmap);
375 if (desc)
377 memcpy(&bitmap_desc, desc, sizeof(*desc));
378 bitmap_desc.bitmapOptions = 0;
379 bitmap_desc.colorContext = NULL;
382 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
383 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
385 return hr;
388 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext *iface,
389 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
391 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
392 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
393 struct d2d_bitmap *object;
394 HRESULT hr;
396 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
397 iface, debugstr_guid(iid), data, desc, bitmap);
399 if (desc)
401 memcpy(&bitmap_desc, desc, sizeof(*desc));
402 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
403 bitmap_desc.colorContext = NULL;
406 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
407 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
409 return hr;
412 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext *iface,
413 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
414 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
416 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
417 struct d2d_brush *object;
418 HRESULT hr;
420 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
421 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
423 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
424 brush_desc, &object)))
425 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
427 return hr;
430 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext *iface,
431 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
433 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
434 struct d2d_brush *object;
435 HRESULT hr;
437 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
439 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
440 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
442 return hr;
445 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext *iface,
446 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
447 ID2D1GradientStopCollection **gradient)
449 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
450 struct d2d_gradient *object;
451 HRESULT hr;
453 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
454 iface, stops, stop_count, gamma, extend_mode, gradient);
456 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
457 stops, stop_count, gamma, extend_mode, &object)))
458 *gradient = &object->ID2D1GradientStopCollection_iface;
460 return hr;
463 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext *iface,
464 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
465 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
467 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
468 struct d2d_brush *object;
469 HRESULT hr;
471 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
472 iface, gradient_brush_desc, brush_desc, gradient, brush);
474 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
475 gradient, &object)))
476 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
478 return hr;
481 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext *iface,
482 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
483 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
485 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
486 struct d2d_brush *object;
487 HRESULT hr;
489 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
490 iface, gradient_brush_desc, brush_desc, gradient, brush);
492 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
493 gradient_brush_desc, brush_desc, gradient, &object)))
494 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
496 return hr;
499 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext *iface,
500 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
501 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
503 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
504 struct d2d_bitmap_render_target *object;
505 HRESULT hr;
507 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
508 iface, size, pixel_size, format, options, rt);
510 if (!(object = heap_alloc_zero(sizeof(*object))))
511 return E_OUTOFMEMORY;
513 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
514 format, options)))
516 WARN("Failed to initialize render target, hr %#x.\n", hr);
517 heap_free(object);
518 return hr;
521 TRACE("Created render target %p.\n", object);
522 *rt = &object->ID2D1BitmapRenderTarget_iface;
524 return S_OK;
527 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext *iface,
528 const D2D1_SIZE_F *size, ID2D1Layer **layer)
530 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
531 struct d2d_layer *object;
532 HRESULT hr;
534 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
536 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
537 *layer = &object->ID2D1Layer_iface;
539 return hr;
542 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext *iface, ID2D1Mesh **mesh)
544 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
545 struct d2d_mesh *object;
546 HRESULT hr;
548 TRACE("iface %p, mesh %p.\n", iface, mesh);
550 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
551 *mesh = &object->ID2D1Mesh_iface;
553 return hr;
556 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext *iface,
557 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
559 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
560 ID2D1PathGeometry *geometry;
561 ID2D1GeometrySink *sink;
562 HRESULT hr;
564 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
565 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
567 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
569 WARN("Failed to create path geometry, %#x.\n", hr);
570 return;
573 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
575 WARN("Open() failed, %#x.\n", hr);
576 ID2D1PathGeometry_Release(geometry);
577 return;
580 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
581 ID2D1GeometrySink_AddLine(sink, p1);
582 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
583 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
584 WARN("Close() failed, %#x.\n", hr);
585 ID2D1GeometrySink_Release(sink);
587 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
588 ID2D1PathGeometry_Release(geometry);
591 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext *iface,
592 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
594 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
595 ID2D1RectangleGeometry *geometry;
596 HRESULT hr;
598 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
599 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
601 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
603 ERR("Failed to create geometry, hr %#x.\n", hr);
604 return;
607 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
608 ID2D1RectangleGeometry_Release(geometry);
611 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext *iface,
612 const D2D1_RECT_F *rect, ID2D1Brush *brush)
614 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
615 ID2D1RectangleGeometry *geometry;
616 HRESULT hr;
618 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
620 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
622 ERR("Failed to create geometry, hr %#x.\n", hr);
623 return;
626 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
627 ID2D1RectangleGeometry_Release(geometry);
630 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext *iface,
631 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
633 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
634 ID2D1RoundedRectangleGeometry *geometry;
635 HRESULT hr;
637 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
638 iface, rect, brush, stroke_width, stroke_style);
640 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
642 ERR("Failed to create geometry, hr %#x.\n", hr);
643 return;
646 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
647 ID2D1RoundedRectangleGeometry_Release(geometry);
650 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext *iface,
651 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
653 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
654 ID2D1RoundedRectangleGeometry *geometry;
655 HRESULT hr;
657 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
659 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
661 ERR("Failed to create geometry, hr %#x.\n", hr);
662 return;
665 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
666 ID2D1RoundedRectangleGeometry_Release(geometry);
669 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext *iface,
670 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
672 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
673 ID2D1EllipseGeometry *geometry;
674 HRESULT hr;
676 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
677 iface, ellipse, brush, stroke_width, stroke_style);
679 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
681 ERR("Failed to create geometry, hr %#x.\n", hr);
682 return;
685 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
686 ID2D1EllipseGeometry_Release(geometry);
689 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext *iface,
690 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
692 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
693 ID2D1EllipseGeometry *geometry;
694 HRESULT hr;
696 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
698 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
700 ERR("Failed to create geometry, hr %#x.\n", hr);
701 return;
704 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
705 ID2D1EllipseGeometry_Release(geometry);
708 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
709 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
711 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
712 D3D10_SUBRESOURCE_DATA buffer_data;
713 D3D10_BUFFER_DESC buffer_desc;
714 const D2D1_MATRIX_3X2_F *w;
715 float tmp_x, tmp_y;
716 HRESULT hr;
717 struct
719 struct
721 float _11, _21, _31, pad0;
722 float _12, _22, _32, stroke_width;
723 } transform_geometry;
724 struct d2d_vec4 transform_rtx;
725 struct d2d_vec4 transform_rty;
726 } vs_cb_data;
728 vs_cb_data.transform_geometry._11 = geometry->transform._11;
729 vs_cb_data.transform_geometry._21 = geometry->transform._21;
730 vs_cb_data.transform_geometry._31 = geometry->transform._31;
731 vs_cb_data.transform_geometry.pad0 = 0.0f;
732 vs_cb_data.transform_geometry._12 = geometry->transform._12;
733 vs_cb_data.transform_geometry._22 = geometry->transform._22;
734 vs_cb_data.transform_geometry._32 = geometry->transform._32;
735 vs_cb_data.transform_geometry.stroke_width = stroke_width;
737 w = &render_target->drawing_state.transform;
739 tmp_x = render_target->desc.dpiX / 96.0f;
740 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
741 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
742 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
743 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
745 tmp_y = render_target->desc.dpiY / 96.0f;
746 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
747 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
748 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
749 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
751 buffer_desc.ByteWidth = sizeof(vs_cb_data);
752 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
753 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
754 buffer_desc.CPUAccessFlags = 0;
755 buffer_desc.MiscFlags = 0;
757 buffer_data.pSysMem = &vs_cb_data;
758 buffer_data.SysMemPitch = 0;
759 buffer_data.SysMemSlicePitch = 0;
761 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
763 WARN("Failed to create constant buffer, hr %#x.\n", hr);
764 return;
767 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, render_target, &ps_cb)))
769 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
770 ID3D10Buffer_Release(vs_cb);
771 return;
774 if (geometry->outline.face_count)
776 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
777 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
778 buffer_data.pSysMem = geometry->outline.faces;
780 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
782 WARN("Failed to create index buffer, hr %#x.\n", hr);
783 goto done;
786 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
787 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
788 buffer_data.pSysMem = geometry->outline.vertices;
790 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
792 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
793 ID3D10Buffer_Release(ib);
794 goto done;
797 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
798 sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
800 ID3D10Buffer_Release(vb);
801 ID3D10Buffer_Release(ib);
804 if (geometry->outline.bezier_face_count)
806 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
807 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
808 buffer_data.pSysMem = geometry->outline.bezier_faces;
810 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
812 WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
813 goto done;
816 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
817 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
818 buffer_data.pSysMem = geometry->outline.beziers;
820 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
822 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
823 ID3D10Buffer_Release(ib);
824 goto done;
827 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
828 3 * geometry->outline.bezier_face_count, vb,
829 sizeof(*geometry->outline.beziers), vs_cb, ps_cb, brush, NULL);
831 ID3D10Buffer_Release(vb);
832 ID3D10Buffer_Release(ib);
835 done:
836 ID3D10Buffer_Release(ps_cb);
837 ID3D10Buffer_Release(vs_cb);
840 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext *iface,
841 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
843 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
844 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
845 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
847 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
848 iface, geometry, brush, stroke_width, stroke_style);
850 if (stroke_style)
851 FIXME("Ignoring stroke style %p.\n", stroke_style);
853 d2d_device_context_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
856 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
857 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
859 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
860 D3D10_SUBRESOURCE_DATA buffer_data;
861 D3D10_BUFFER_DESC buffer_desc;
862 D2D1_MATRIX_3X2_F *w;
863 float tmp_x, tmp_y;
864 HRESULT hr;
865 struct
867 struct
869 float _11, _21, _31, pad0;
870 float _12, _22, _32, pad1;
871 } transform_geometry;
872 struct d2d_vec4 transform_rtx;
873 struct d2d_vec4 transform_rty;
874 } vs_cb_data;
876 vs_cb_data.transform_geometry._11 = geometry->transform._11;
877 vs_cb_data.transform_geometry._21 = geometry->transform._21;
878 vs_cb_data.transform_geometry._31 = geometry->transform._31;
879 vs_cb_data.transform_geometry.pad0 = 0.0f;
880 vs_cb_data.transform_geometry._12 = geometry->transform._12;
881 vs_cb_data.transform_geometry._22 = geometry->transform._22;
882 vs_cb_data.transform_geometry._32 = geometry->transform._32;
883 vs_cb_data.transform_geometry.pad1 = 0.0f;
885 w = &render_target->drawing_state.transform;
887 tmp_x = render_target->desc.dpiX / 96.0f;
888 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
889 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
890 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
891 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
893 tmp_y = render_target->desc.dpiY / 96.0f;
894 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
895 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
896 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
897 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
899 buffer_desc.ByteWidth = sizeof(vs_cb_data);
900 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
901 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
902 buffer_desc.CPUAccessFlags = 0;
903 buffer_desc.MiscFlags = 0;
905 buffer_data.pSysMem = &vs_cb_data;
906 buffer_data.SysMemPitch = 0;
907 buffer_data.SysMemSlicePitch = 0;
909 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
911 WARN("Failed to create constant buffer, hr %#x.\n", hr);
912 return;
915 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, render_target, &ps_cb)))
917 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
918 ID3D10Buffer_Release(vs_cb);
919 return;
922 if (geometry->fill.face_count)
924 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
925 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
926 buffer_data.pSysMem = geometry->fill.faces;
928 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
930 WARN("Failed to create index buffer, hr %#x.\n", hr);
931 goto done;
934 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
935 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
936 buffer_data.pSysMem = geometry->fill.vertices;
938 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
940 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
941 ID3D10Buffer_Release(ib);
942 goto done;
945 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
946 sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush);
948 ID3D10Buffer_Release(vb);
949 ID3D10Buffer_Release(ib);
952 if (geometry->fill.bezier_vertex_count)
954 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
955 buffer_data.pSysMem = geometry->fill.bezier_vertices;
957 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
959 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
960 goto done;
963 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb,
964 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush);
966 ID3D10Buffer_Release(vb);
969 done:
970 ID3D10Buffer_Release(ps_cb);
971 ID3D10Buffer_Release(vs_cb);
974 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
975 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
977 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
978 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
979 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
980 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
982 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
984 if (FAILED(context->error.code))
985 return;
987 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
989 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
990 return;
993 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
996 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext *iface,
997 ID2D1Mesh *mesh, ID2D1Brush *brush)
999 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1002 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext *iface,
1003 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1004 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1006 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1007 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1010 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1011 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1012 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
1014 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1015 D2D1_BRUSH_PROPERTIES brush_desc;
1016 struct d2d_brush *brush;
1017 D2D1_RECT_F s, d;
1018 HRESULT hr;
1020 if (perspective_transform)
1021 FIXME("Perspective transform is ignored.\n");
1023 if (src_rect)
1025 s = *src_rect;
1027 else
1029 D2D1_SIZE_F size;
1031 size = ID2D1Bitmap_GetSize(bitmap);
1032 s.left = 0.0f;
1033 s.top = 0.0f;
1034 s.right = size.width;
1035 s.bottom = size.height;
1038 if (dst_rect)
1040 d = *dst_rect;
1042 else
1044 d.left = 0.0f;
1045 d.top = 0.0f;
1046 d.right = s.right - s.left;
1047 d.bottom = s.bottom - s.top;
1050 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1051 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1052 bitmap_brush_desc.interpolationMode = interpolation_mode;
1054 brush_desc.opacity = opacity;
1055 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1056 brush_desc.transform._21 = 0.0f;
1057 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1058 brush_desc.transform._12 = 0.0f;
1059 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1060 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1062 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1064 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
1065 return;
1068 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext_iface, &d, &brush->ID2D1Brush_iface);
1069 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1072 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext *iface,
1073 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1074 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1076 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1078 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1079 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1081 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1082 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1084 d2d_device_context_set_error(context, E_INVALIDARG);
1085 return;
1088 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect, NULL);
1091 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext *iface,
1092 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1093 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1095 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1096 IDWriteTextLayout *text_layout;
1097 IDWriteFactory *dwrite_factory;
1098 D2D1_POINT_2F origin;
1099 HRESULT hr;
1101 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1102 "brush %p, options %#x, measuring_mode %#x.\n",
1103 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1104 brush, options, measuring_mode);
1106 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1107 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1109 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1110 return;
1113 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1114 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1115 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
1116 else
1117 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1118 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
1119 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1120 IDWriteFactory_Release(dwrite_factory);
1121 if (FAILED(hr))
1123 ERR("Failed to create text layout, hr %#x.\n", hr);
1124 return;
1127 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
1128 ID2D1DeviceContext_DrawTextLayout(iface, origin, text_layout, brush, options);
1129 IDWriteTextLayout_Release(text_layout);
1132 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext *iface,
1133 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1135 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1136 struct d2d_draw_text_layout_ctx ctx;
1137 HRESULT hr;
1139 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1140 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1142 ctx.brush = brush;
1143 ctx.options = options;
1145 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1146 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1147 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1150 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1152 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1153 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1154 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1155 return prev_antialias_mode;
1158 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1159 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1161 D2D1_MATRIX_3X2_F *transform, prev_transform;
1162 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1163 ID2D1PathGeometry *geometry;
1164 ID2D1GeometrySink *sink;
1165 HRESULT hr;
1167 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1169 ERR("Failed to create geometry, hr %#x.\n", hr);
1170 return;
1173 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1175 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1176 ID2D1PathGeometry_Release(geometry);
1177 return;
1180 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1181 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1182 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1184 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1185 ID2D1GeometrySink_Release(sink);
1186 ID2D1PathGeometry_Release(geometry);
1187 return;
1190 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1191 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1192 ID2D1GeometrySink_Release(sink);
1194 transform = &render_target->drawing_state.transform;
1195 prev_transform = *transform;
1196 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1197 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1198 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1199 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1200 unsafe_impl_from_ID2D1Brush(brush), NULL);
1201 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1202 *transform = prev_transform;
1204 ID2D1PathGeometry_Release(geometry);
1207 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1208 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1209 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1210 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1212 ID2D1RectangleGeometry *geometry = NULL;
1213 ID2D1BitmapBrush *opacity_brush = NULL;
1214 D2D1_BITMAP_PROPERTIES bitmap_desc;
1215 ID2D1Bitmap *opacity_bitmap = NULL;
1216 IDWriteGlyphRunAnalysis *analysis;
1217 DWRITE_TEXTURE_TYPE texture_type;
1218 D2D1_BRUSH_PROPERTIES brush_desc;
1219 IDWriteFactory2 *dwrite_factory;
1220 D2D1_MATRIX_3X2_F *transform, m;
1221 void *opacity_values = NULL;
1222 size_t opacity_values_size;
1223 D2D1_SIZE_U bitmap_size;
1224 float scale_x, scale_y;
1225 D2D1_RECT_F run_rect;
1226 RECT bounds;
1227 HRESULT hr;
1229 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1230 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1232 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1233 return;
1236 transform = &render_target->drawing_state.transform;
1238 scale_x = render_target->desc.dpiX / 96.0f;
1239 m._11 = transform->_11 * scale_x;
1240 m._21 = transform->_21 * scale_x;
1241 m._31 = transform->_31 * scale_x;
1243 scale_y = render_target->desc.dpiY / 96.0f;
1244 m._12 = transform->_12 * scale_y;
1245 m._22 = transform->_22 * scale_y;
1246 m._32 = transform->_32 * scale_y;
1248 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1249 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1250 baseline_origin.x, baseline_origin.y, &analysis);
1251 IDWriteFactory2_Release(dwrite_factory);
1252 if (FAILED(hr))
1254 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1255 return;
1258 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1259 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1260 else
1261 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1263 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1265 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1266 goto done;
1269 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1270 if (!bitmap_size.width || !bitmap_size.height)
1272 /* Empty run, nothing to do. */
1273 goto done;
1276 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1277 bitmap_size.width *= 3;
1278 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1280 ERR("Failed to allocate opacity values.\n");
1281 goto done;
1283 opacity_values_size = bitmap_size.height * bitmap_size.width;
1285 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1286 texture_type, &bounds, opacity_values, opacity_values_size)))
1288 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1289 goto done;
1292 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1293 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1294 bitmap_desc.dpiX = render_target->desc.dpiX;
1295 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1296 bitmap_desc.dpiX *= 3.0f;
1297 bitmap_desc.dpiY = render_target->desc.dpiY;
1298 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext_iface,
1299 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1301 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1302 goto done;
1305 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1306 bounds.right / scale_x, bounds.bottom / scale_y);
1308 brush_desc.opacity = 1.0f;
1309 brush_desc.transform._11 = 1.0f;
1310 brush_desc.transform._12 = 0.0f;
1311 brush_desc.transform._21 = 0.0f;
1312 brush_desc.transform._22 = 1.0f;
1313 brush_desc.transform._31 = run_rect.left;
1314 brush_desc.transform._32 = run_rect.top;
1315 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext_iface,
1316 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1318 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1319 goto done;
1322 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1324 ERR("Failed to create geometry, hr %#x.\n", hr);
1325 goto done;
1328 m = *transform;
1329 *transform = identity;
1330 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1331 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1332 *transform = m;
1334 done:
1335 if (geometry)
1336 ID2D1RectangleGeometry_Release(geometry);
1337 if (opacity_brush)
1338 ID2D1BitmapBrush_Release(opacity_brush);
1339 if (opacity_bitmap)
1340 ID2D1Bitmap_Release(opacity_bitmap);
1341 heap_free(opacity_values);
1342 IDWriteGlyphRunAnalysis_Release(analysis);
1345 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext *iface,
1346 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1347 DWRITE_MEASURING_MODE measuring_mode)
1349 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1350 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
1351 IDWriteRenderingParams *rendering_params;
1352 DWRITE_RENDERING_MODE rendering_mode;
1353 HRESULT hr;
1355 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1356 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1358 rendering_params = context->text_rendering_params ? context->text_rendering_params
1359 : context->default_text_rendering_params;
1361 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
1363 switch (context->drawing_state.textAntialiasMode)
1365 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1366 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
1367 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
1368 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
1369 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
1371 d2d_device_context_set_error(context, E_INVALIDARG);
1373 break;
1374 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1375 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
1376 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1378 d2d_device_context_set_error(context, E_INVALIDARG);
1380 break;
1381 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
1382 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1383 d2d_device_context_set_error(context, E_INVALIDARG);
1384 break;
1385 default:
1389 if (FAILED(context->error.code))
1390 return;
1392 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
1393 switch (context->drawing_state.textAntialiasMode)
1395 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
1396 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
1397 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1398 break;
1399 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1400 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1401 break;
1402 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1403 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
1404 break;
1405 default:
1409 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
1411 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1412 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
1413 measuring_mode, rendering_params, &rendering_mode)))
1415 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1416 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1420 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1421 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
1422 else
1423 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
1424 rendering_mode, measuring_mode, antialias_mode);
1427 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext *iface,
1428 const D2D1_MATRIX_3X2_F *transform)
1430 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1432 TRACE("iface %p, transform %p.\n", iface, transform);
1434 render_target->drawing_state.transform = *transform;
1437 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext *iface,
1438 D2D1_MATRIX_3X2_F *transform)
1440 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1442 TRACE("iface %p, transform %p.\n", iface, transform);
1444 *transform = render_target->drawing_state.transform;
1447 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext *iface,
1448 D2D1_ANTIALIAS_MODE antialias_mode)
1450 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1452 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1454 render_target->drawing_state.antialiasMode = antialias_mode;
1457 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext *iface)
1459 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1461 TRACE("iface %p.\n", iface);
1463 return render_target->drawing_state.antialiasMode;
1466 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext *iface,
1467 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1469 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1471 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1473 render_target->drawing_state.textAntialiasMode = antialias_mode;
1476 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext *iface)
1478 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1480 TRACE("iface %p.\n", iface);
1482 return render_target->drawing_state.textAntialiasMode;
1485 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext *iface,
1486 IDWriteRenderingParams *text_rendering_params)
1488 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1490 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1492 if (text_rendering_params)
1493 IDWriteRenderingParams_AddRef(text_rendering_params);
1494 if (render_target->text_rendering_params)
1495 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1496 render_target->text_rendering_params = text_rendering_params;
1499 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext *iface,
1500 IDWriteRenderingParams **text_rendering_params)
1502 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1504 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1506 if ((*text_rendering_params = render_target->text_rendering_params))
1507 IDWriteRenderingParams_AddRef(*text_rendering_params);
1510 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1512 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1514 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1516 render_target->drawing_state.tag1 = tag1;
1517 render_target->drawing_state.tag2 = tag2;
1520 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1522 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1524 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1526 *tag1 = render_target->drawing_state.tag1;
1527 *tag2 = render_target->drawing_state.tag2;
1530 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext *iface,
1531 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1533 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1536 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *iface)
1538 FIXME("iface %p stub!\n", iface);
1541 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1543 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1545 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1547 if (context->ops && context->ops->device_context_present)
1548 context->ops->device_context_present(context->outer_unknown);
1550 return E_NOTIMPL;
1553 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext *iface,
1554 ID2D1DrawingStateBlock *state_block)
1556 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1557 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1559 TRACE("iface %p, state_block %p.\n", iface, state_block);
1561 state_block_impl->drawing_state = render_target->drawing_state;
1562 if (render_target->text_rendering_params)
1563 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1564 if (state_block_impl->text_rendering_params)
1565 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1566 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1569 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext *iface,
1570 ID2D1DrawingStateBlock *state_block)
1572 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1573 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1575 TRACE("iface %p, state_block %p.\n", iface, state_block);
1577 render_target->drawing_state = state_block_impl->drawing_state;
1578 if (state_block_impl->text_rendering_params)
1579 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1580 if (render_target->text_rendering_params)
1581 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1582 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1585 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext *iface,
1586 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1588 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1589 D2D1_RECT_F transformed_rect;
1590 float x_scale, y_scale;
1591 D2D1_POINT_2F point;
1593 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1595 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1596 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1598 x_scale = render_target->desc.dpiX / 96.0f;
1599 y_scale = render_target->desc.dpiY / 96.0f;
1600 d2d_point_transform(&point, &render_target->drawing_state.transform,
1601 clip_rect->left * x_scale, clip_rect->top * y_scale);
1602 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1603 d2d_point_transform(&point, &render_target->drawing_state.transform,
1604 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1605 d2d_rect_expand(&transformed_rect, &point);
1606 d2d_point_transform(&point, &render_target->drawing_state.transform,
1607 clip_rect->right * x_scale, clip_rect->top * y_scale);
1608 d2d_rect_expand(&transformed_rect, &point);
1609 d2d_point_transform(&point, &render_target->drawing_state.transform,
1610 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1611 d2d_rect_expand(&transformed_rect, &point);
1613 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1614 WARN("Failed to push clip rect.\n");
1617 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext *iface)
1619 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1621 TRACE("iface %p.\n", iface);
1623 d2d_clip_stack_pop(&render_target->clip_stack);
1626 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface, const D2D1_COLOR_F *colour)
1628 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1629 D3D10_SUBRESOURCE_DATA buffer_data;
1630 struct d2d_ps_cb ps_cb_data = {0};
1631 D3D10_BUFFER_DESC buffer_desc;
1632 ID3D10Buffer *vs_cb, *ps_cb;
1633 D2D1_COLOR_F *c;
1634 HRESULT hr;
1636 static const struct
1638 struct
1640 float _11, _21, _31, pad0;
1641 float _12, _22, _32, pad1;
1642 } transform_geometry;
1643 struct d2d_vec4 transform_rtx;
1644 struct d2d_vec4 transform_rty;
1646 vs_cb_data =
1648 {1.0f, 0.0f, 0.0f, 0.0f,
1649 0.0f, 1.0f, 0.0f, 0.0f},
1650 {1.0f, 0.0f, 1.0f, 1.0f},
1651 {0.0f, 1.0f, 1.0f, -1.0f},
1654 TRACE("iface %p, colour %p.\n", iface, colour);
1656 buffer_desc.ByteWidth = sizeof(vs_cb_data);
1657 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1658 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1659 buffer_desc.CPUAccessFlags = 0;
1660 buffer_desc.MiscFlags = 0;
1662 buffer_data.pSysMem = &vs_cb_data;
1663 buffer_data.SysMemPitch = 0;
1664 buffer_data.SysMemSlicePitch = 0;
1666 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
1668 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1669 return;
1672 ps_cb_data.outline = FALSE;
1673 ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1674 ps_cb_data.colour_brush.opacity = 1.0f;
1675 c = &ps_cb_data.colour_brush.u.solid.colour;
1676 if (colour)
1677 *c = *colour;
1678 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1679 c->a = 1.0f;
1680 c->r *= c->a;
1681 c->g *= c->a;
1682 c->b *= c->a;
1684 ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1686 buffer_desc.ByteWidth = sizeof(ps_cb_data);
1687 buffer_data.pSysMem = &ps_cb_data;
1689 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ps_cb)))
1691 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1692 ID3D10Buffer_Release(vs_cb);
1693 return;
1696 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1697 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1699 ID3D10Buffer_Release(ps_cb);
1700 ID3D10Buffer_Release(vs_cb);
1703 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
1705 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1707 TRACE("iface %p.\n", iface);
1709 memset(&render_target->error, 0, sizeof(render_target->error));
1712 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface,
1713 D2D1_TAG *tag1, D2D1_TAG *tag2)
1715 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1716 HRESULT hr;
1718 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1720 if (tag1)
1721 *tag1 = context->error.tag1;
1722 if (tag2)
1723 *tag2 = context->error.tag2;
1725 if (context->ops && context->ops->device_context_present)
1727 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1728 context->error.code = hr;
1731 return context->error.code;
1734 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface,
1735 D2D1_PIXEL_FORMAT *format)
1737 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1739 TRACE("iface %p, format %p.\n", iface, format);
1741 *format = render_target->desc.pixelFormat;
1742 return format;
1745 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext *iface, float dpi_x, float dpi_y)
1747 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1749 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1751 if (dpi_x == 0.0f && dpi_y == 0.0f)
1753 dpi_x = 96.0f;
1754 dpi_y = 96.0f;
1756 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1757 return;
1759 render_target->desc.dpiX = dpi_x;
1760 render_target->desc.dpiY = dpi_y;
1763 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext *iface, float *dpi_x, float *dpi_y)
1765 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1767 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1769 *dpi_x = render_target->desc.dpiX;
1770 *dpi_y = render_target->desc.dpiY;
1773 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext *iface, D2D1_SIZE_F *size)
1775 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1777 TRACE("iface %p, size %p.\n", iface, size);
1779 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1780 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1781 return size;
1784 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext *iface,
1785 D2D1_SIZE_U *pixel_size)
1787 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1789 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1791 *pixel_size = render_target->pixel_size;
1792 return pixel_size;
1795 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext *iface)
1797 FIXME("iface %p stub!\n", iface);
1799 return 0;
1802 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext *iface,
1803 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1805 FIXME("iface %p, desc %p stub!\n", iface, desc);
1807 return FALSE;
1810 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext *iface,
1811 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
1812 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1814 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1815 struct d2d_bitmap *object;
1816 HRESULT hr;
1818 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
1819 iface, size.width, size.height, src_data, pitch, desc, bitmap);
1821 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
1822 *bitmap = &object->ID2D1Bitmap1_iface;
1824 return hr;
1827 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
1828 ID2D1DeviceContext *iface, IWICBitmapSource *bitmap_source,
1829 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1831 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1832 struct d2d_bitmap *object;
1833 HRESULT hr;
1835 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
1837 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
1838 *bitmap = &object->ID2D1Bitmap1_iface;
1840 return hr;
1843 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext *iface,
1844 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
1846 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
1847 iface, space, profile, profile_size, color_context);
1849 return E_NOTIMPL;
1852 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext *iface,
1853 const WCHAR *filename, ID2D1ColorContext **color_context)
1855 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
1857 return E_NOTIMPL;
1860 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext *iface,
1861 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
1863 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
1865 return E_NOTIMPL;
1868 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
1869 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1871 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1872 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
1873 struct d2d_bitmap *object;
1874 HRESULT hr;
1876 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
1878 if (!desc)
1880 DXGI_SURFACE_DESC surface_desc;
1882 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1884 WARN("Failed to get surface desc, hr %#x.\n", hr);
1885 return hr;
1888 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
1889 bitmap_desc.pixelFormat.format = surface_desc.Format;
1890 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1891 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
1892 desc = &bitmap_desc;
1895 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
1896 *bitmap = &object->ID2D1Bitmap1_iface;
1898 return hr;
1901 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
1902 REFCLSID effect_id, ID2D1Effect **effect)
1904 struct d2d_effect *object;
1906 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1908 if (!(object = heap_alloc_zero(sizeof(*object))))
1909 return E_OUTOFMEMORY;
1911 d2d_effect_init(object);
1913 TRACE("Created effect %p.\n", object);
1914 *effect = &object->ID2D1Effect_iface;
1916 return S_OK;
1919 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1920 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1921 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1922 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1923 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1925 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1926 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1927 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1928 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1930 return E_NOTIMPL;
1933 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1934 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1935 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1937 FIXME("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p stub!\n",
1938 iface, image, image_brush_desc, brush_desc, brush);
1940 return E_NOTIMPL;
1943 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1944 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1945 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1947 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1948 struct d2d_brush *object;
1949 HRESULT hr;
1951 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1952 brush_desc, brush);
1954 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1955 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1957 return hr;
1960 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1961 ID2D1CommandList **command_list)
1963 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1965 return E_NOTIMPL;
1968 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1970 FIXME("iface %p, format %#x stub!\n", iface, format);
1972 return FALSE;
1975 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1976 D2D1_BUFFER_PRECISION buffer_precision)
1978 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1980 return FALSE;
1983 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1984 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1986 FIXME("iface %p, image %p, local_bounds %p stub!\n", iface, image, local_bounds);
1989 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
1990 ID2D1Image *image, D2D1_RECT_F *world_bounds)
1992 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
1994 return E_NOTIMPL;
1997 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
1998 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1999 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
2001 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
2002 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
2004 return E_NOTIMPL;
2007 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
2009 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2011 TRACE("iface %p, device %p.\n", iface, device);
2013 *device = context->device;
2014 ID2D1Device_AddRef(*device);
2017 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2019 if (!context->target)
2020 return;
2022 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
2023 context->target = NULL;
2025 context->desc.dpiX = 96.0f;
2026 context->desc.dpiY = 96.0f;
2028 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2029 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2031 ID3D10BlendState_Release(context->bs);
2032 context->bs = NULL;
2035 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
2037 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2038 struct d2d_bitmap *bitmap_impl;
2039 D3D10_BLEND_DESC blend_desc;
2040 ID2D1Bitmap *bitmap;
2041 HRESULT hr;
2043 TRACE("iface %p, target %p.\n", iface, target);
2045 if (!target)
2047 d2d_device_context_reset_target(context);
2048 return;
2051 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2053 FIXME("Only bitmap targets are supported.\n");
2054 return;
2057 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2059 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2061 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2062 return;
2065 d2d_device_context_reset_target(context);
2067 /* Set sizes and pixel format. */
2068 context->desc.dpiX = bitmap_impl->dpi_x;
2069 context->desc.dpiY = bitmap_impl->dpi_y;
2070 context->pixel_size = bitmap_impl->pixel_size;
2071 context->desc.pixelFormat = bitmap_impl->format;
2072 context->target = bitmap_impl;
2074 memset(&blend_desc, 0, sizeof(blend_desc));
2075 blend_desc.BlendEnable[0] = TRUE;
2076 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2077 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2078 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2079 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2081 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2082 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2084 else
2086 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2087 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2089 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2090 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2091 if (FAILED(hr = ID3D10Device_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2092 WARN("Failed to create blend state, hr %#x.\n", hr);
2095 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2097 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2099 TRACE("iface %p, target %p.\n", iface, target);
2101 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2102 if (*target)
2103 ID2D1Image_AddRef(*target);
2106 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2107 const D2D1_RENDERING_CONTROLS *rendering_controls)
2109 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2112 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2113 D2D1_RENDERING_CONTROLS *rendering_controls)
2115 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2118 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2119 D2D1_PRIMITIVE_BLEND primitive_blend)
2121 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2124 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2126 FIXME("iface %p stub!\n", iface);
2128 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2131 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2133 FIXME("iface %p, unit_mode %#x stub!\n", iface, unit_mode);
2136 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2138 FIXME("iface %p stub!\n", iface);
2140 return D2D1_UNIT_MODE_DIPS;
2143 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2144 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2145 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2147 FIXME("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x stub!\n",
2148 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2151 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2152 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2153 D2D1_COMPOSITE_MODE composite_mode)
2155 FIXME("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x stub!\n",
2156 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2157 interpolation_mode, composite_mode);
2160 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2161 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2163 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2164 iface, metafile, debug_d2d_point_2f(target_offset));
2167 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2168 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2169 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2171 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2173 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2174 "src_rect %s, perspective_transform %p.\n",
2175 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2176 debug_d2d_rect_f(src_rect), perspective_transform);
2178 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2179 perspective_transform);
2182 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2183 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2185 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2188 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2189 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2191 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2192 iface, effect, input, debug_d2d_rect_f(input_rect));
2194 return E_NOTIMPL;
2197 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2198 ID2D1Effect *effect, UINT32 *rect_count)
2200 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2202 return E_NOTIMPL;
2205 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2206 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2208 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2210 return E_NOTIMPL;
2213 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2214 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2215 D2D1_RECT_F *input_rect, UINT32 input_count)
2217 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2218 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2220 return E_NOTIMPL;
2223 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2224 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2226 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2227 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2230 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2232 d2d_device_context_QueryInterface,
2233 d2d_device_context_AddRef,
2234 d2d_device_context_Release,
2235 d2d_device_context_GetFactory,
2236 d2d_device_context_CreateBitmap,
2237 d2d_device_context_CreateBitmapFromWicBitmap,
2238 d2d_device_context_CreateSharedBitmap,
2239 d2d_device_context_CreateBitmapBrush,
2240 d2d_device_context_CreateSolidColorBrush,
2241 d2d_device_context_CreateGradientStopCollection,
2242 d2d_device_context_CreateLinearGradientBrush,
2243 d2d_device_context_CreateRadialGradientBrush,
2244 d2d_device_context_CreateCompatibleRenderTarget,
2245 d2d_device_context_CreateLayer,
2246 d2d_device_context_CreateMesh,
2247 d2d_device_context_DrawLine,
2248 d2d_device_context_DrawRectangle,
2249 d2d_device_context_FillRectangle,
2250 d2d_device_context_DrawRoundedRectangle,
2251 d2d_device_context_FillRoundedRectangle,
2252 d2d_device_context_DrawEllipse,
2253 d2d_device_context_FillEllipse,
2254 d2d_device_context_DrawGeometry,
2255 d2d_device_context_FillGeometry,
2256 d2d_device_context_FillMesh,
2257 d2d_device_context_FillOpacityMask,
2258 d2d_device_context_DrawBitmap,
2259 d2d_device_context_DrawText,
2260 d2d_device_context_DrawTextLayout,
2261 d2d_device_context_DrawGlyphRun,
2262 d2d_device_context_SetTransform,
2263 d2d_device_context_GetTransform,
2264 d2d_device_context_SetAntialiasMode,
2265 d2d_device_context_GetAntialiasMode,
2266 d2d_device_context_SetTextAntialiasMode,
2267 d2d_device_context_GetTextAntialiasMode,
2268 d2d_device_context_SetTextRenderingParams,
2269 d2d_device_context_GetTextRenderingParams,
2270 d2d_device_context_SetTags,
2271 d2d_device_context_GetTags,
2272 d2d_device_context_PushLayer,
2273 d2d_device_context_PopLayer,
2274 d2d_device_context_Flush,
2275 d2d_device_context_SaveDrawingState,
2276 d2d_device_context_RestoreDrawingState,
2277 d2d_device_context_PushAxisAlignedClip,
2278 d2d_device_context_PopAxisAlignedClip,
2279 d2d_device_context_Clear,
2280 d2d_device_context_BeginDraw,
2281 d2d_device_context_EndDraw,
2282 d2d_device_context_GetPixelFormat,
2283 d2d_device_context_SetDpi,
2284 d2d_device_context_GetDpi,
2285 d2d_device_context_GetSize,
2286 d2d_device_context_GetPixelSize,
2287 d2d_device_context_GetMaximumBitmapSize,
2288 d2d_device_context_IsSupported,
2289 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2290 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2291 d2d_device_context_CreateColorContext,
2292 d2d_device_context_CreateColorContextFromFilename,
2293 d2d_device_context_CreateColorContextFromWicColorContext,
2294 d2d_device_context_CreateBitmapFromDxgiSurface,
2295 d2d_device_context_CreateEffect,
2296 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2297 d2d_device_context_CreateImageBrush,
2298 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2299 d2d_device_context_CreateCommandList,
2300 d2d_device_context_IsDxgiFormatSupported,
2301 d2d_device_context_IsBufferPrecisionSupported,
2302 d2d_device_context_GetImageLocalBounds,
2303 d2d_device_context_GetImageWorldBounds,
2304 d2d_device_context_GetGlyphRunWorldBounds,
2305 d2d_device_context_GetDevice,
2306 d2d_device_context_SetTarget,
2307 d2d_device_context_GetTarget,
2308 d2d_device_context_SetRenderingControls,
2309 d2d_device_context_GetRenderingControls,
2310 d2d_device_context_SetPrimitiveBlend,
2311 d2d_device_context_GetPrimitiveBlend,
2312 d2d_device_context_SetUnitMode,
2313 d2d_device_context_GetUnitMode,
2314 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2315 d2d_device_context_DrawImage,
2316 d2d_device_context_DrawGdiMetafile,
2317 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2318 d2d_device_context_ID2D1DeviceContext_PushLayer,
2319 d2d_device_context_InvalidateEffectInputRectangle,
2320 d2d_device_context_GetEffectInvalidRectangleCount,
2321 d2d_device_context_GetEffectInvalidRectangles,
2322 d2d_device_context_GetEffectRequiredInputRectangles,
2323 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2326 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2328 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2331 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2333 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2335 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2336 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2337 || IsEqualGUID(iid, &IID_IUnknown))
2339 IDWriteTextRenderer_AddRef(iface);
2340 *out = iface;
2341 return S_OK;
2344 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2346 *out = NULL;
2347 return E_NOINTERFACE;
2350 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2352 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2354 TRACE("iface %p.\n", iface);
2356 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2359 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2361 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2363 TRACE("iface %p.\n", iface);
2365 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2368 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2369 void *ctx, BOOL *disabled)
2371 struct d2d_draw_text_layout_ctx *context = ctx;
2373 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2375 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2377 return S_OK;
2380 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2381 void *ctx, DWRITE_MATRIX *transform)
2383 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2385 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2387 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2389 return S_OK;
2392 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2394 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2396 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2398 *ppd = render_target->desc.dpiY / 96.0f;
2400 return S_OK;
2403 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2404 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2405 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2407 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2408 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2409 struct d2d_draw_text_layout_ctx *context = ctx;
2410 BOOL color_font = FALSE;
2411 ID2D1Brush *brush;
2413 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2414 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2415 iface, ctx, baseline_origin_x, baseline_origin_y,
2416 measuring_mode, glyph_run, desc, effect);
2418 if (desc)
2419 WARN("Ignoring glyph run description %p.\n", desc);
2420 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2421 FIXME("Ignoring options %#x.\n", context->options);
2423 brush = d2d_draw_get_text_brush(context, effect);
2425 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2427 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2429 IDWriteFontFace2 *fontface;
2431 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2432 &IID_IDWriteFontFace2, (void **)&fontface)))
2434 color_font = IDWriteFontFace2_IsColorFont(fontface);
2435 IDWriteFontFace2_Release(fontface);
2439 if (color_font)
2441 IDWriteColorGlyphRunEnumerator *layers;
2442 IDWriteFactory2 *dwrite_factory;
2443 HRESULT hr;
2445 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2446 (IUnknown **)&dwrite_factory)))
2448 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2449 ID2D1Brush_Release(brush);
2450 return hr;
2453 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2454 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2455 IDWriteFactory2_Release(dwrite_factory);
2456 if (FAILED(hr))
2458 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
2459 ID2D1Brush_Release(brush);
2460 return hr;
2463 for (;;)
2465 const DWRITE_COLOR_GLYPH_RUN *color_run;
2466 ID2D1Brush *color_brush;
2467 D2D1_POINT_2F origin;
2468 BOOL has_run = FALSE;
2470 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2472 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
2473 break;
2476 if (!has_run)
2477 break;
2479 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2481 ERR("Failed to get current color run, hr %#x.\n", hr);
2482 break;
2485 if (color_run->paletteIndex == 0xffff)
2486 color_brush = brush;
2487 else
2489 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2490 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2492 ERR("Failed to create solid color brush, hr %#x.\n", hr);
2493 break;
2497 origin.x = color_run->baselineOriginX;
2498 origin.y = color_run->baselineOriginY;
2499 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2500 origin, &color_run->glyphRun, color_brush, measuring_mode);
2502 if (color_brush != brush)
2503 ID2D1Brush_Release(color_brush);
2506 IDWriteColorGlyphRunEnumerator_Release(layers);
2508 else
2509 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2510 baseline_origin, glyph_run, brush, measuring_mode);
2512 ID2D1Brush_Release(brush);
2514 return S_OK;
2517 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2518 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2520 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2521 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2522 struct d2d_draw_text_layout_ctx *context = ctx;
2523 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2524 D2D1_POINT_2F start, end;
2525 ID2D1Brush *brush;
2526 float thickness;
2528 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2529 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2531 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2532 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2533 underline->thickness);
2535 brush = d2d_draw_get_text_brush(context, effect);
2537 start.x = baseline_origin_x;
2538 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2539 end.x = start.x + underline->width;
2540 end.y = start.y;
2541 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2542 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2543 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2545 ID2D1Brush_Release(brush);
2547 return S_OK;
2550 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2551 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2553 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2554 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2555 struct d2d_draw_text_layout_ctx *context = ctx;
2556 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2557 D2D1_POINT_2F start, end;
2558 ID2D1Brush *brush;
2559 float thickness;
2561 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2562 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2564 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2565 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2566 strikethrough->thickness);
2568 brush = d2d_draw_get_text_brush(context, effect);
2570 start.x = baseline_origin_x;
2571 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2572 end.x = start.x + strikethrough->width;
2573 end.y = start.y;
2574 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2575 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2576 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2578 ID2D1Brush_Release(brush);
2580 return S_OK;
2583 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2584 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2586 struct d2d_draw_text_layout_ctx *context = ctx;
2587 ID2D1Brush *brush;
2588 HRESULT hr;
2590 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2591 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2593 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2594 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2595 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2596 brush is selected at Direct2D level. */
2597 brush = context->brush;
2598 context->brush = d2d_draw_get_text_brush(context, effect);
2600 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2602 ID2D1Brush_Release(context->brush);
2603 context->brush = brush;
2605 return hr;
2608 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2610 d2d_text_renderer_QueryInterface,
2611 d2d_text_renderer_AddRef,
2612 d2d_text_renderer_Release,
2613 d2d_text_renderer_IsPixelSnappingDisabled,
2614 d2d_text_renderer_GetCurrentTransform,
2615 d2d_text_renderer_GetPixelsPerDip,
2616 d2d_text_renderer_DrawGlyphRun,
2617 d2d_text_renderer_DrawUnderline,
2618 d2d_text_renderer_DrawStrikethrough,
2619 d2d_text_renderer_DrawInlineObject,
2622 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2624 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2627 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2628 REFIID iid, void **out)
2630 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2632 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2634 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2637 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2639 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2641 TRACE("iface %p.\n", iface);
2643 return IUnknown_AddRef(render_target->outer_unknown);
2646 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2648 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2650 TRACE("iface %p.\n", iface);
2652 return IUnknown_Release(render_target->outer_unknown);
2655 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2657 ID3D10Resource *resource;
2658 HRESULT hr;
2660 ID3D10RenderTargetView_GetResource(render_target->target->rtv, &resource);
2661 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2662 ID3D10Resource_Release(resource);
2663 if (FAILED(hr))
2665 *surface = NULL;
2666 WARN("Failed to get DXGI surface, %#x.\n", hr);
2667 return hr;
2670 return hr;
2673 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2674 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2676 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2677 IDXGISurface1 *surface;
2678 HRESULT hr;
2680 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2682 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2683 return hr;
2685 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2686 IDXGISurface1_Release(surface);
2688 return hr;
2691 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2692 const RECT *update)
2694 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2695 IDXGISurface1 *surface;
2696 RECT update_rect;
2697 HRESULT hr;
2699 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2701 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2702 return hr;
2704 if (update)
2705 update_rect = *update;
2706 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2707 IDXGISurface1_Release(surface);
2709 return hr;
2712 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2714 d2d_gdi_interop_render_target_QueryInterface,
2715 d2d_gdi_interop_render_target_AddRef,
2716 d2d_gdi_interop_render_target_Release,
2717 d2d_gdi_interop_render_target_GetDC,
2718 d2d_gdi_interop_render_target_ReleaseDC,
2721 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2722 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2724 D3D10_SUBRESOURCE_DATA buffer_data;
2725 D3D10_STATE_BLOCK_MASK state_mask;
2726 struct d2d_device *device_impl;
2727 IDWriteFactory *dwrite_factory;
2728 D3D10_RASTERIZER_DESC rs_desc;
2729 D3D10_BUFFER_DESC buffer_desc;
2730 unsigned int i;
2731 HRESULT hr;
2733 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2735 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2736 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2737 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2739 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier_outline[] =
2741 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2742 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2743 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2744 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2745 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2746 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2748 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2750 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2752 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
2754 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2755 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2757 static const DWORD vs_code_outline[] =
2759 #if 0
2760 float3x2 transform_geometry;
2761 float stroke_width;
2762 float4 transform_rtx;
2763 float4 transform_rty;
2765 struct output
2767 float2 p : WORLD_POSITION;
2768 float4 b : BEZIER;
2769 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2770 float4 position : SV_POSITION;
2773 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2775 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2777 * Where:
2779 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2780 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2781 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2782 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2784 float2 q_prev, q_next, v_p, q_i;
2785 float2x2 geom;
2786 float l;
2788 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2790 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2791 q_prev = normalize(mul(geom, prev));
2792 q_next = normalize(mul(geom, next));
2794 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2795 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2796 v_p = float2(-q_prev.y, q_prev.x);
2797 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2798 q_i = l * q_prev + v_p;
2800 o.b = float4(0.0, 0.0, 0.0, 0.0);
2802 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2803 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2804 * float2(transform_rtx.w, transform_rty.w);
2805 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2807 #endif
2808 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2809 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2810 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2811 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2812 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2813 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2814 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2815 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2816 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2817 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2818 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2819 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2820 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2821 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2822 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2823 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2824 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2825 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2826 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2827 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2828 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2829 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2830 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2831 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2832 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2833 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2834 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2835 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2836 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2837 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2838 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2839 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2840 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2841 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2842 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2843 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2844 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2845 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2846 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2847 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2848 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2849 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2850 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2851 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2852 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2853 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2854 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2855 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2856 0x3f800000, 0x0100003e,
2858 /* ⎡p0.x p0.y 1⎤
2859 * A = ⎢p1.x p1.y 1⎥
2860 * ⎣p2.x p2.y 1⎦
2862 * ⎡0 0⎤
2863 * B = ⎢½ 0⎥
2864 * ⎣1 1⎦
2866 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2867 * ⎣p2.x-p0.x p2.y-p0.y⎦
2869 * B' = ⎡½ 0⎤
2870 * ⎣1 1⎦
2872 * A'T = B'
2873 * T = A'⁻¹B'
2875 static const DWORD vs_code_bezier_outline[] =
2877 #if 0
2878 float3x2 transform_geometry;
2879 float stroke_width;
2880 float4 transform_rtx;
2881 float4 transform_rty;
2883 struct output
2885 float2 p : WORLD_POSITION;
2886 float4 b : BEZIER;
2887 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2888 float4 position : SV_POSITION;
2891 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2892 float2 prev : PREV, float2 next : NEXT, out struct output o)
2894 float2 q_prev, q_next, v_p, q_i, p;
2895 float2x2 geom, rt;
2896 float l;
2898 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2899 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2900 o.stroke_transform = rt * stroke_width * 0.5f;
2902 p = mul(geom, position);
2903 p0 = mul(geom, p0);
2904 p1 = mul(geom, p1);
2905 p2 = mul(geom, p2);
2907 p -= p0;
2908 p1 -= p0;
2909 p2 -= p0;
2911 q_prev = normalize(mul(geom, prev));
2912 q_next = normalize(mul(geom, next));
2914 v_p = float2(-q_prev.y, q_prev.x);
2915 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2916 q_i = l * q_prev + v_p;
2917 p += stroke_width * q_i;
2919 v_p = mul(rt, p2);
2920 v_p = normalize(float2(-v_p.y, v_p.x));
2921 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
2923 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
2924 o.b.y = dot(mul(rt, p), v_p);
2926 else
2928 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
2929 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
2930 o.b.x = dot(v_p, p1 - 0.5f * p2);
2931 o.b.y = dot(v_p, p1);
2934 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * q_i;
2935 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2936 * float2(transform_rtx.w, transform_rty.w);
2937 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2939 #endif
2940 0x43425844, 0x7ff88ce9, 0xd75cb064, 0x30396183, 0xca64489b, 0x00000001, 0x00000ae4, 0x00000003,
2941 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
2942 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
2943 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
2944 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
2945 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
2946 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
2947 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
2948 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
2949 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
2950 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
2951 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
2952 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
2953 0x52444853, 0x0000093c, 0x00010040, 0x0000024f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
2954 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
2955 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
2956 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
2957 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
2958 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
2959 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
2960 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
2961 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
2962 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
2963 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
2964 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
2965 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
2966 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
2967 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
2968 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
2969 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
2970 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
2971 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
2972 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
2973 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
2974 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
2975 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
2976 0x0a000032, 0x00100032, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000,
2977 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f,
2978 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f,
2979 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f,
2980 0x00100012, 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f,
2981 0x00100022, 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000,
2982 0x001000c2, 0x00000000, 0x00100406, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x0a000032,
2983 0x00100032, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000, 0x00100ae6,
2984 0x00000000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046,
2985 0x00000000, 0x0800000f, 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046,
2986 0x00000000, 0x0800000f, 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046,
2987 0x00000003, 0x0800000f, 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046,
2988 0x00000003, 0x08000000, 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406,
2989 0x00000004, 0x0800000f, 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6,
2990 0x00000002, 0x06000036, 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f,
2991 0x00100082, 0x00000003, 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f,
2992 0x00100082, 0x00000000, 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082,
2993 0x00000000, 0x0010003a, 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000,
2994 0x00100ea6, 0x00000003, 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6,
2995 0x00000003, 0x06000036, 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f,
2996 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
2997 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
2998 0x00100032, 0x00000005, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036,
2999 0x00100042, 0x00000005, 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000,
3000 0x00100a26, 0x00000005, 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6,
3001 0x00000041, 0x00000002, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046,
3002 0x00000005, 0x0800000e, 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556,
3003 0x00000000, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002,
3004 0x0700000f, 0x00100022, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f,
3005 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f,
3006 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f,
3007 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022,
3008 0x00000000, 0x00004001, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000,
3009 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a,
3010 0x00000081, 0x00000000, 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a,
3011 0x00000041, 0x00000000, 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a,
3012 0x00000000, 0x07000038, 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000,
3013 0x08000036, 0x001000d2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
3014 0x09000037, 0x001020f2, 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46,
3015 0x00000002, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3016 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3017 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3018 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3019 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3020 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3021 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3022 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3023 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3024 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3025 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3026 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3027 0x0100003e,
3029 static const DWORD vs_code_triangle[] =
3031 #if 0
3032 float3x2 transform_geometry;
3033 float4 transform_rtx;
3034 float4 transform_rty;
3036 struct output
3038 float2 p : WORLD_POSITION;
3039 float4 b : BEZIER;
3040 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3041 float4 position : SV_POSITION;
3044 void main(float2 position : POSITION, out struct output o)
3046 o.p = mul(float3(position, 1.0f), transform_geometry);
3047 o.b = float4(1.0, 0.0, 1.0, 1.0);
3048 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3049 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3050 * float2(transform_rtx.w, transform_rty.w);
3051 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3053 #endif
3054 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3055 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3056 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3057 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3058 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3059 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3060 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3061 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3062 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3063 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3064 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3065 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3066 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3067 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3068 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3069 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3070 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3071 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3072 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3073 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3074 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3075 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3076 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3077 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3078 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3079 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3080 0x00000000, 0x3f800000, 0x0100003e,
3082 static const DWORD vs_code_bezier[] =
3084 #if 0
3085 float3x2 transform_geometry;
3086 float4 transform_rtx;
3087 float4 transform_rty;
3089 struct output
3091 float2 p : WORLD_POSITION;
3092 float4 b : BEZIER;
3093 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3094 float4 position : SV_POSITION;
3097 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3099 o.p = mul(float3(position, 1.0f), transform_geometry);
3100 o.b = float4(texcoord, 1.0);
3101 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3102 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3103 * float2(transform_rtx.w, transform_rty.w);
3104 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3106 #endif
3107 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3108 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3109 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3110 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3111 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3112 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3113 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3114 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3115 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3116 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3117 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3118 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3119 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3120 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3121 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3122 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3123 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3124 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3125 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3126 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3127 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3128 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3129 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3130 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3131 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3132 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3133 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3134 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3136 static const DWORD ps_code[] =
3138 #if 0
3139 #define BRUSH_TYPE_SOLID 0
3140 #define BRUSH_TYPE_LINEAR 1
3141 #define BRUSH_TYPE_RADIAL 2
3142 #define BRUSH_TYPE_BITMAP 3
3143 #define BRUSH_TYPE_COUNT 4
3145 bool outline;
3146 struct brush
3148 uint type;
3149 float opacity;
3150 float4 data[3];
3151 } colour_brush, opacity_brush;
3153 SamplerState s0, s1;
3154 Texture2D t0, t1;
3155 Buffer<float4> b0, b1;
3157 struct input
3159 float2 p : WORLD_POSITION;
3160 float4 b : BEZIER;
3161 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3164 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3166 float4 c_low, c_high;
3167 float p_low, p_high;
3168 uint i;
3170 p_low = gradient.Load(0).x;
3171 c_low = gradient.Load(1);
3172 c_high = c_low;
3174 if (position < p_low)
3175 return c_low;
3177 for (i = 1; i < stop_count; ++i)
3179 p_high = gradient.Load(i * 2).x;
3180 c_high = gradient.Load(i * 2 + 1);
3182 if (position >= p_low && position <= p_high)
3183 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3185 p_low = p_high;
3186 c_low = c_high;
3189 return c_high;
3192 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3194 float2 start, end, v_p, v_q;
3195 uint stop_count;
3196 float p;
3198 start = brush.data[0].xy;
3199 end = brush.data[0].zw;
3200 stop_count = asuint(brush.data[1].x);
3202 v_p = position - start;
3203 v_q = end - start;
3204 p = dot(v_q, v_p) / dot(v_q, v_q);
3206 return sample_gradient(gradient, stop_count, p);
3209 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3211 float2 centre, offset, ra, rb, v_p, v_q, r;
3212 float b, c, l, t;
3213 uint stop_count;
3215 centre = brush.data[0].xy;
3216 offset = brush.data[0].zw;
3217 ra = brush.data[1].xy;
3218 rb = brush.data[1].zw;
3219 stop_count = asuint(brush.data[2].x);
3221 /* Project onto ra, rb. */
3222 r = float2(dot(ra, ra), dot(rb, rb));
3223 v_p = position - (centre + offset);
3224 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3225 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3227 /* ‖t·p̂ + q⃑‖ = 1
3228 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3229 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3231 * b = p̂·q⃑
3232 * c = q⃑·q⃑ - 1
3233 * t = -b + √(b² - c) */
3234 l = length(v_p);
3235 b = dot(v_p, v_q) / l;
3236 c = dot(v_q, v_q) - 1.0;
3237 t = -b + sqrt(b * b - c);
3239 return sample_gradient(gradient, stop_count, l / t);
3242 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3244 float3 transform[2];
3245 bool ignore_alpha;
3246 float2 texcoord;
3247 float4 colour;
3249 transform[0] = brush.data[0].xyz;
3250 transform[1] = brush.data[1].xyz;
3251 ignore_alpha = asuint(brush.data[1].w);
3253 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3254 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3255 colour = t.Sample(s, texcoord);
3256 if (ignore_alpha)
3257 colour.a = 1.0;
3258 return colour;
3261 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3263 if (brush.type == BRUSH_TYPE_SOLID)
3264 return brush.data[0] * brush.opacity;
3265 if (brush.type == BRUSH_TYPE_LINEAR)
3266 return brush_linear(brush, b, position) * brush.opacity;
3267 if (brush.type == BRUSH_TYPE_RADIAL)
3268 return brush_radial(brush, b, position) * brush.opacity;
3269 if (brush.type == BRUSH_TYPE_BITMAP)
3270 return brush_bitmap(brush, t, s, position) * brush.opacity;
3271 return float4(0.0, 0.0, 0.0, brush.opacity);
3274 float4 main(struct input i) : SV_Target
3276 float4 colour;
3278 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3279 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3280 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3282 if (outline)
3284 float2 du, dv, df;
3285 float4 uv;
3287 /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
3288 * using the screen-space partial derivatives to convert the calculated
3289 * distance to object space.
3291 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3292 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3293 * f(x, y) = u(x, y)² - v(x, y)
3294 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3295 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
3296 uv = i.b;
3297 du = float2(ddx(uv.x), ddy(uv.x));
3298 dv = float2(ddx(uv.y), ddy(uv.y));
3299 df = 2.0f * uv.x * du - dv;
3301 clip(dot(df, uv.zw));
3302 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3304 else
3306 /* Evaluate the implicit form of the curve in texture space.
3307 * "i.b.z" determines which side of the curve is shaded. */
3308 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3311 return colour;
3313 #endif
3314 0x43425844, 0xf3cbb8bd, 0x5f286454, 0x139976a7, 0x6817e876, 0x00000001, 0x00001d18, 0x00000003,
3315 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3316 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3317 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3318 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3319 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3320 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3321 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001c18,
3322 0x00000040, 0x00000706, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3323 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3324 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3325 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3326 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3327 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3328 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3329 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3330 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3331 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3332 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3333 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3334 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3335 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3336 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3337 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3338 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3339 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3340 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3341 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3342 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3343 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3344 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3345 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3346 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3347 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3348 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3349 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3350 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3351 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3352 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3353 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3354 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3355 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3356 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3357 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3358 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3359 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3360 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3361 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3362 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3363 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3364 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3365 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3366 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3367 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3368 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3369 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3370 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3371 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3372 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3373 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3374 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3375 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3376 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3377 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3378 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3379 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3380 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3381 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3382 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3383 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3384 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3385 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3386 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3387 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3388 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3389 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3390 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3391 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3392 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3393 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3394 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3395 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3396 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3397 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3398 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3399 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3400 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3401 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3402 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3403 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3404 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3405 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3406 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3407 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3408 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3409 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3410 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3411 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3412 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3413 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3414 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3415 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3416 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3417 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3418 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3419 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3420 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3421 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3422 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3423 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3424 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3425 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3426 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3427 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3428 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3429 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3430 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3431 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3432 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3433 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3434 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3435 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3436 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3437 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3438 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3439 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3440 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3441 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3442 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3443 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3444 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3445 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3446 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3447 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3448 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3449 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3450 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3451 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3452 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3453 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3454 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3455 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3456 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3457 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3458 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3459 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3460 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3461 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3462 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3463 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3464 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3465 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3466 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3467 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3468 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3469 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3470 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3471 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3472 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3473 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3474 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3475 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3476 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3477 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3478 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3479 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3480 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3481 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3482 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3483 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3484 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3485 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3486 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3487 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3488 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3489 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3490 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3491 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3492 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3493 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3494 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3495 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3496 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3497 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3498 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3499 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3500 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3501 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3502 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3503 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3504 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3505 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3506 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3507 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3508 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3509 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3510 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3511 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3512 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3513 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3514 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3515 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3516 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3517 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3518 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3519 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3520 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3521 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3522 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3523 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3524 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3525 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3526 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3527 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x08000027, 0x00100012,
3528 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022,
3529 0x00000000, 0x0010000a, 0x00000000, 0x0500000b, 0x00100032, 0x00000001, 0x00101046, 0x00000001,
3530 0x0500000c, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x07000000, 0x00100042, 0x00000000,
3531 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x001000c2, 0x00000000, 0x00100aa6,
3532 0x00000000, 0x00100806, 0x00000001, 0x80100d56, 0x00000041, 0x00000001, 0x0700000f, 0x00100012,
3533 0x00000001, 0x00100ae6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100012, 0x00000001,
3534 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000001, 0x0010000a,
3535 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010000a, 0x00000001, 0x07000038, 0x00100032,
3536 0x00000001, 0x00100ff6, 0x00000000, 0x00101046, 0x00000003, 0x09000032, 0x001000c2, 0x00000000,
3537 0x00101406, 0x00000002, 0x00100aa6, 0x00000000, 0x00100406, 0x00000001, 0x0700000f, 0x00100042,
3538 0x00000000, 0x00100ae6, 0x00000000, 0x00100ae6, 0x00000000, 0x0500004b, 0x00100042, 0x00000000,
3539 0x0010002a, 0x00000000, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a,
3540 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100042, 0x00000000, 0x8010003a,
3541 0x000000c1, 0x00000000, 0x0010002a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010002a,
3542 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000,
3543 0x0010002a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000038, 0x00100012, 0x00000000,
3544 0x0010003a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010000a,
3545 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000,
3546 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x0100003e,
3548 static const struct shape_info
3550 enum d2d_shape_type shape_type;
3551 const D3D10_INPUT_ELEMENT_DESC *il_desc;
3552 unsigned int il_element_count;
3553 const void *vs_code;
3554 size_t vs_code_size;
3556 shape_info[] =
3558 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3559 vs_code_outline, sizeof(vs_code_outline)},
3560 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_bezier_outline, ARRAY_SIZE(il_desc_bezier_outline),
3561 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3562 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3563 vs_code_triangle, sizeof(vs_code_triangle)},
3564 {D2D_SHAPE_TYPE_BEZIER, il_desc_bezier, ARRAY_SIZE(il_desc_bezier),
3565 vs_code_bezier, sizeof(vs_code_bezier)},
3567 static const struct
3569 float x, y;
3571 quad[] =
3573 {-1.0f, 1.0f},
3574 {-1.0f, -1.0f},
3575 { 1.0f, 1.0f},
3576 { 1.0f, -1.0f},
3578 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3580 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3581 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3582 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3583 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3584 render_target->refcount = 1;
3585 ID2D1Device_GetFactory(device, &render_target->factory);
3586 render_target->device = device;
3587 ID2D1Device_AddRef(render_target->device);
3589 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3590 render_target->ops = ops;
3592 device_impl = unsafe_impl_from_ID2D1Device(device);
3593 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3594 &IID_ID3D10Device, (void **)&render_target->d3d_device)))
3596 WARN("Failed to get device interface, hr %#x.\n", hr);
3597 ID2D1Factory_Release(render_target->factory);
3598 return hr;
3601 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
3603 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
3604 goto err;
3607 if (FAILED(hr = D3D10CreateStateBlock(render_target->d3d_device, &state_mask, &render_target->stateblock)))
3609 WARN("Failed to create stateblock, hr %#x.\n", hr);
3610 goto err;
3613 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3615 const struct shape_info *si = &shape_info[i];
3617 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3618 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3620 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3621 goto err;
3624 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->d3d_device, si->vs_code,
3625 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
3627 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3628 goto err;
3633 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->d3d_device,
3634 ps_code, sizeof(ps_code), &render_target->ps)))
3636 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3637 goto err;
3640 buffer_desc.ByteWidth = sizeof(indices);
3641 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
3642 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
3643 buffer_desc.CPUAccessFlags = 0;
3644 buffer_desc.MiscFlags = 0;
3646 buffer_data.pSysMem = indices;
3647 buffer_data.SysMemPitch = 0;
3648 buffer_data.SysMemSlicePitch = 0;
3650 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3651 &buffer_desc, &buffer_data, &render_target->ib)))
3653 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3654 goto err;
3657 buffer_desc.ByteWidth = sizeof(quad);
3658 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
3659 buffer_data.pSysMem = quad;
3661 render_target->vb_stride = sizeof(*quad);
3662 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3663 &buffer_desc, &buffer_data, &render_target->vb)))
3665 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3666 goto err;
3669 rs_desc.FillMode = D3D10_FILL_SOLID;
3670 rs_desc.CullMode = D3D10_CULL_NONE;
3671 rs_desc.FrontCounterClockwise = FALSE;
3672 rs_desc.DepthBias = 0;
3673 rs_desc.DepthBiasClamp = 0.0f;
3674 rs_desc.SlopeScaledDepthBias = 0.0f;
3675 rs_desc.DepthClipEnable = TRUE;
3676 rs_desc.ScissorEnable = TRUE;
3677 rs_desc.MultisampleEnable = FALSE;
3678 rs_desc.AntialiasedLineEnable = FALSE;
3679 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
3681 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3682 goto err;
3685 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3686 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3688 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3689 goto err;
3692 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3693 IDWriteFactory_Release(dwrite_factory);
3694 if (FAILED(hr))
3696 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
3697 goto err;
3700 render_target->drawing_state.transform = identity;
3702 if (!d2d_clip_stack_init(&render_target->clip_stack))
3704 WARN("Failed to initialize clip stack.\n");
3705 hr = E_FAIL;
3706 goto err;
3709 render_target->desc.dpiX = 96.0f;
3710 render_target->desc.dpiY = 96.0f;
3712 return S_OK;
3714 err:
3715 if (render_target->default_text_rendering_params)
3716 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
3717 if (render_target->rs)
3718 ID3D10RasterizerState_Release(render_target->rs);
3719 if (render_target->vb)
3720 ID3D10Buffer_Release(render_target->vb);
3721 if (render_target->ib)
3722 ID3D10Buffer_Release(render_target->ib);
3723 if (render_target->ps)
3724 ID3D10PixelShader_Release(render_target->ps);
3725 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
3727 if (render_target->shape_resources[i].vs)
3728 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
3729 if (render_target->shape_resources[i].il)
3730 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
3732 if (render_target->stateblock)
3733 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
3734 if (render_target->d3d_device)
3735 ID3D10Device_Release(render_target->d3d_device);
3736 ID2D1Device_Release(render_target->device);
3737 ID2D1Factory_Release(render_target->factory);
3738 return hr;
3741 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
3742 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
3744 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
3745 struct d2d_device_context *object;
3746 ID2D1Bitmap1 *bitmap;
3747 HRESULT hr;
3749 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
3750 WARN("Ignoring render target type %#x.\n", desc->type);
3751 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
3752 FIXME("Ignoring render target usage %#x.\n", desc->usage);
3753 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
3754 WARN("Ignoring feature level %#x.\n", desc->minLevel);
3756 bitmap_desc.dpiX = desc->dpiX;
3757 bitmap_desc.dpiY = desc->dpiY;
3759 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
3761 bitmap_desc.dpiX = 96.0f;
3762 bitmap_desc.dpiY = 96.0f;
3764 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
3765 return E_INVALIDARG;
3767 if (!(object = heap_alloc_zero(sizeof(*object))))
3768 return E_OUTOFMEMORY;
3770 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
3772 WARN("Failed to initialize render target, hr %#x.\n", hr);
3773 heap_free(object);
3774 return hr;
3777 if (surface)
3779 bitmap_desc.pixelFormat = desc->pixelFormat;
3780 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
3781 bitmap_desc.colorContext = NULL;
3783 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
3784 surface, &bitmap_desc, &bitmap)))
3786 WARN("Failed to create target bitmap, hr %#x.\n", hr);
3787 IUnknown_Release(&object->IUnknown_iface);
3788 heap_free(object);
3789 return hr;
3792 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
3793 ID2D1Bitmap1_Release(bitmap);
3795 else
3796 object->desc.pixelFormat = desc->pixelFormat;
3798 TRACE("Created render target %p.\n", object);
3799 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
3801 return S_OK;
3804 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
3806 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
3808 if (IsEqualGUID(iid, &IID_ID2D1Device)
3809 || IsEqualGUID(iid, &IID_ID2D1Resource)
3810 || IsEqualGUID(iid, &IID_IUnknown))
3812 ID2D1Device_AddRef(iface);
3813 *out = iface;
3814 return S_OK;
3817 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
3819 *out = NULL;
3820 return E_NOINTERFACE;
3823 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
3825 struct d2d_device *device = impl_from_ID2D1Device(iface);
3826 ULONG refcount = InterlockedIncrement(&device->refcount);
3828 TRACE("%p increasing refcount to %u.\n", iface, refcount);
3830 return refcount;
3833 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
3835 struct d2d_device *device = impl_from_ID2D1Device(iface);
3836 ULONG refcount = InterlockedDecrement(&device->refcount);
3838 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
3840 if (!refcount)
3842 IDXGIDevice_Release(device->dxgi_device);
3843 ID2D1Factory1_Release(device->factory);
3844 heap_free(device);
3847 return refcount;
3850 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
3852 struct d2d_device *device = impl_from_ID2D1Device(iface);
3854 TRACE("iface %p, factory %p.\n", iface, factory);
3856 *factory = (ID2D1Factory *)device->factory;
3857 ID2D1Factory1_AddRef(device->factory);
3860 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
3861 ID2D1DeviceContext **context)
3863 struct d2d_device_context *object;
3864 HRESULT hr;
3866 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
3868 if (options)
3869 FIXME("Options are ignored %#x.\n", options);
3871 if (!(object = heap_alloc_zero(sizeof(*object))))
3872 return E_OUTOFMEMORY;
3874 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
3876 WARN("Failed to initialize device context, hr %#x.\n", hr);
3877 heap_free(object);
3878 return hr;
3881 TRACE("Created device context %p.\n", object);
3882 *context = &object->ID2D1DeviceContext_iface;
3884 return S_OK;
3887 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
3888 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
3889 ID2D1PrintControl **print_control)
3891 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
3892 document_target, desc, print_control);
3894 return E_NOTIMPL;
3897 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
3899 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
3902 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
3904 FIXME("iface %p stub!\n", iface);
3906 return 0;
3909 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
3911 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
3913 return E_NOTIMPL;
3916 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
3918 d2d_device_QueryInterface,
3919 d2d_device_AddRef,
3920 d2d_device_Release,
3921 d2d_device_GetFactory,
3922 d2d_device_CreateDeviceContext,
3923 d2d_device_CreatePrintControl,
3924 d2d_device_SetMaximumTextureMemory,
3925 d2d_device_GetMaximumTextureMemory,
3926 d2d_device_ClearResources,
3929 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
3931 if (!iface)
3932 return NULL;
3933 assert(iface->lpVtbl == &d2d_device_vtbl);
3934 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
3937 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
3939 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
3940 device->refcount = 1;
3941 device->factory = iface;
3942 ID2D1Factory1_AddRef(device->factory);
3943 device->dxgi_device = dxgi_device;
3944 IDXGIDevice_AddRef(device->dxgi_device);