ntdll: Translate signal to trap when trap code is 0 on ARM.
[wine.git] / dlls / d2d1 / device.c
blob7c398962d6e6b8f8c6cbbb654df917bfad2f93c6
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 vp.TopLeftX = 0;
135 vp.TopLeftY = 0;
136 vp.Width = render_target->pixel_size.width;
137 vp.Height = render_target->pixel_size.height;
138 vp.MinDepth = 0.0f;
139 vp.MaxDepth = 1.0f;
141 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
143 WARN("Failed to capture stateblock, hr %#x.\n", hr);
144 return;
147 ID3D10Device_ClearState(device);
149 ID3D10Device_IASetInputLayout(device, shape_resources->il);
150 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
151 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
152 offset = 0;
153 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
154 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
155 ID3D10Device_VSSetShader(device, shape_resources->vs);
156 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
157 ID3D10Device_PSSetShader(device, render_target->ps);
158 ID3D10Device_RSSetViewports(device, 1, &vp);
159 if (render_target->clip_stack.count)
161 const D2D1_RECT_F *clip_rect;
163 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
164 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
165 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
166 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
167 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
169 else
171 scissor_rect.left = 0.0f;
172 scissor_rect.top = 0.0f;
173 scissor_rect.right = render_target->pixel_size.width;
174 scissor_rect.bottom = render_target->pixel_size.height;
176 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
177 ID3D10Device_RSSetState(device, render_target->rs);
178 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->target->rtv, NULL);
179 if (brush)
181 ID3D10Device_OMSetBlendState(device, render_target->bs, NULL, D3D10_DEFAULT_SAMPLE_MASK);
182 d2d_brush_bind_resources(brush, device, 0);
184 if (opacity_brush)
185 d2d_brush_bind_resources(opacity_brush, device, 1);
187 if (ib)
188 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
189 else
190 ID3D10Device_Draw(device, index_count, 0);
192 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
193 WARN("Failed to apply stateblock, hr %#x.\n", hr);
196 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
198 context->error.code = code;
199 context->error.tag1 = context->drawing_state.tag1;
200 context->error.tag2 = context->drawing_state.tag2;
203 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
205 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
208 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext *iface)
210 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
213 static inline struct d2d_device_context *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
215 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
218 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
220 struct d2d_device_context *context = impl_from_IUnknown(iface);
222 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
224 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext)
225 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
226 || IsEqualGUID(iid, &IID_ID2D1Resource)
227 || IsEqualGUID(iid, &IID_IUnknown))
229 ID2D1DeviceContext_AddRef(&context->ID2D1DeviceContext_iface);
230 *out = &context->ID2D1DeviceContext_iface;
231 return S_OK;
233 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
235 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
236 *out = &context->ID2D1GdiInteropRenderTarget_iface;
237 return S_OK;
240 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
242 *out = NULL;
243 return E_NOINTERFACE;
246 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
248 struct d2d_device_context *context = impl_from_IUnknown(iface);
249 ULONG refcount = InterlockedIncrement(&context->refcount);
251 TRACE("%p increasing refcount to %u.\n", iface, refcount);
253 return refcount;
256 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
258 struct d2d_device_context *context = impl_from_IUnknown(iface);
259 ULONG refcount = InterlockedDecrement(&context->refcount);
261 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
263 if (!refcount)
265 unsigned int i;
267 d2d_clip_stack_cleanup(&context->clip_stack);
268 IDWriteRenderingParams_Release(context->default_text_rendering_params);
269 if (context->text_rendering_params)
270 IDWriteRenderingParams_Release(context->text_rendering_params);
271 if (context->bs)
272 ID3D10BlendState_Release(context->bs);
273 ID3D10RasterizerState_Release(context->rs);
274 ID3D10Buffer_Release(context->vb);
275 ID3D10Buffer_Release(context->ib);
276 ID3D10PixelShader_Release(context->ps);
277 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
279 ID3D10VertexShader_Release(context->shape_resources[i].vs);
280 ID3D10InputLayout_Release(context->shape_resources[i].il);
282 context->stateblock->lpVtbl->Release(context->stateblock);
283 if (context->target)
284 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
285 ID3D10Device_Release(context->d3d_device);
286 ID2D1Factory_Release(context->factory);
287 ID2D1Device_Release(context->device);
288 heap_free(context);
291 return refcount;
294 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
296 d2d_device_context_inner_QueryInterface,
297 d2d_device_context_inner_AddRef,
298 d2d_device_context_inner_Release,
301 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out)
303 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
305 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
307 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
310 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface)
312 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
314 TRACE("iface %p.\n", iface);
316 return IUnknown_AddRef(context->outer_unknown);
319 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface)
321 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
323 TRACE("iface %p.\n", iface);
325 return IUnknown_Release(context->outer_unknown);
328 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext *iface, ID2D1Factory **factory)
330 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
332 TRACE("iface %p, factory %p.\n", iface, factory);
334 *factory = render_target->factory;
335 ID2D1Factory_AddRef(*factory);
338 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext *iface,
339 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
341 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
342 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
343 struct d2d_bitmap *object;
344 HRESULT hr;
346 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
347 iface, size.width, size.height, src_data, pitch, desc, bitmap);
349 if (desc)
351 memcpy(&bitmap_desc, desc, sizeof(*desc));
352 bitmap_desc.bitmapOptions = 0;
353 bitmap_desc.colorContext = NULL;
356 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
357 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
359 return hr;
362 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext *iface,
363 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
365 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
366 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
367 struct d2d_bitmap *object;
368 HRESULT hr;
370 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
371 iface, bitmap_source, desc, bitmap);
373 if (desc)
375 memcpy(&bitmap_desc, desc, sizeof(*desc));
376 bitmap_desc.bitmapOptions = 0;
377 bitmap_desc.colorContext = NULL;
380 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
381 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
383 return hr;
386 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext *iface,
387 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
389 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
390 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
391 struct d2d_bitmap *object;
392 HRESULT hr;
394 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
395 iface, debugstr_guid(iid), data, desc, bitmap);
397 if (desc)
399 memcpy(&bitmap_desc, desc, sizeof(*desc));
400 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
401 bitmap_desc.colorContext = NULL;
404 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
405 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
407 return hr;
410 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext *iface,
411 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
412 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
414 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
415 struct d2d_brush *object;
416 HRESULT hr;
418 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
419 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
421 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
422 brush_desc, &object)))
423 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
425 return hr;
428 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext *iface,
429 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
431 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
432 struct d2d_brush *object;
433 HRESULT hr;
435 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
437 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
438 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
440 return hr;
443 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext *iface,
444 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
445 ID2D1GradientStopCollection **gradient)
447 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
448 struct d2d_gradient *object;
449 HRESULT hr;
451 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
452 iface, stops, stop_count, gamma, extend_mode, gradient);
454 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
455 stops, stop_count, gamma, extend_mode, &object)))
456 *gradient = &object->ID2D1GradientStopCollection_iface;
458 return hr;
461 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext *iface,
462 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
463 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
465 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
466 struct d2d_brush *object;
467 HRESULT hr;
469 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
470 iface, gradient_brush_desc, brush_desc, gradient, brush);
472 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
473 gradient, &object)))
474 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
476 return hr;
479 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext *iface,
480 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
481 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
483 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
484 struct d2d_brush *object;
485 HRESULT hr;
487 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
488 iface, gradient_brush_desc, brush_desc, gradient, brush);
490 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
491 gradient_brush_desc, brush_desc, gradient, &object)))
492 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
494 return hr;
497 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext *iface,
498 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
499 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
501 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
502 struct d2d_bitmap_render_target *object;
503 HRESULT hr;
505 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
506 iface, size, pixel_size, format, options, rt);
508 if (!(object = heap_alloc_zero(sizeof(*object))))
509 return E_OUTOFMEMORY;
511 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
512 format, options)))
514 WARN("Failed to initialize render target, hr %#x.\n", hr);
515 heap_free(object);
516 return hr;
519 TRACE("Created render target %p.\n", object);
520 *rt = &object->ID2D1BitmapRenderTarget_iface;
522 return S_OK;
525 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext *iface,
526 const D2D1_SIZE_F *size, ID2D1Layer **layer)
528 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
529 struct d2d_layer *object;
530 HRESULT hr;
532 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
534 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
535 *layer = &object->ID2D1Layer_iface;
537 return hr;
540 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext *iface, ID2D1Mesh **mesh)
542 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
543 struct d2d_mesh *object;
544 HRESULT hr;
546 TRACE("iface %p, mesh %p.\n", iface, mesh);
548 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
549 *mesh = &object->ID2D1Mesh_iface;
551 return hr;
554 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext *iface,
555 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
557 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
558 ID2D1PathGeometry *geometry;
559 ID2D1GeometrySink *sink;
560 HRESULT hr;
562 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
563 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
565 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
567 WARN("Failed to create path geometry, %#x.\n", hr);
568 return;
571 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
573 WARN("Open() failed, %#x.\n", hr);
574 ID2D1PathGeometry_Release(geometry);
575 return;
578 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
579 ID2D1GeometrySink_AddLine(sink, p1);
580 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
581 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
582 WARN("Close() failed, %#x.\n", hr);
583 ID2D1GeometrySink_Release(sink);
585 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
586 ID2D1PathGeometry_Release(geometry);
589 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext *iface,
590 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
592 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
593 ID2D1RectangleGeometry *geometry;
594 HRESULT hr;
596 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
597 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
599 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
601 ERR("Failed to create geometry, hr %#x.\n", hr);
602 return;
605 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
606 ID2D1RectangleGeometry_Release(geometry);
609 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext *iface,
610 const D2D1_RECT_F *rect, ID2D1Brush *brush)
612 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
613 ID2D1RectangleGeometry *geometry;
614 HRESULT hr;
616 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
618 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
620 ERR("Failed to create geometry, hr %#x.\n", hr);
621 return;
624 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
625 ID2D1RectangleGeometry_Release(geometry);
628 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext *iface,
629 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
631 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
632 ID2D1RoundedRectangleGeometry *geometry;
633 HRESULT hr;
635 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
636 iface, rect, brush, stroke_width, stroke_style);
638 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
640 ERR("Failed to create geometry, hr %#x.\n", hr);
641 return;
644 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
645 ID2D1RoundedRectangleGeometry_Release(geometry);
648 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext *iface,
649 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
651 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
652 ID2D1RoundedRectangleGeometry *geometry;
653 HRESULT hr;
655 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
657 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
659 ERR("Failed to create geometry, hr %#x.\n", hr);
660 return;
663 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
664 ID2D1RoundedRectangleGeometry_Release(geometry);
667 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext *iface,
668 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
670 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
671 ID2D1EllipseGeometry *geometry;
672 HRESULT hr;
674 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
675 iface, ellipse, brush, stroke_width, stroke_style);
677 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
679 ERR("Failed to create geometry, hr %#x.\n", hr);
680 return;
683 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
684 ID2D1EllipseGeometry_Release(geometry);
687 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext *iface,
688 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
690 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
691 ID2D1EllipseGeometry *geometry;
692 HRESULT hr;
694 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
696 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
698 ERR("Failed to create geometry, hr %#x.\n", hr);
699 return;
702 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
703 ID2D1EllipseGeometry_Release(geometry);
706 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
707 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
709 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
710 D3D10_SUBRESOURCE_DATA buffer_data;
711 D3D10_BUFFER_DESC buffer_desc;
712 const D2D1_MATRIX_3X2_F *w;
713 float tmp_x, tmp_y;
714 HRESULT hr;
715 struct
717 struct
719 float _11, _21, _31, pad0;
720 float _12, _22, _32, stroke_width;
721 } transform_geometry;
722 struct d2d_vec4 transform_rtx;
723 struct d2d_vec4 transform_rty;
724 } vs_cb_data;
726 vs_cb_data.transform_geometry._11 = geometry->transform._11;
727 vs_cb_data.transform_geometry._21 = geometry->transform._21;
728 vs_cb_data.transform_geometry._31 = geometry->transform._31;
729 vs_cb_data.transform_geometry.pad0 = 0.0f;
730 vs_cb_data.transform_geometry._12 = geometry->transform._12;
731 vs_cb_data.transform_geometry._22 = geometry->transform._22;
732 vs_cb_data.transform_geometry._32 = geometry->transform._32;
733 vs_cb_data.transform_geometry.stroke_width = stroke_width;
735 w = &render_target->drawing_state.transform;
737 tmp_x = render_target->desc.dpiX / 96.0f;
738 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
739 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
740 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
741 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
743 tmp_y = render_target->desc.dpiY / 96.0f;
744 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
745 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
746 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
747 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
749 buffer_desc.ByteWidth = sizeof(vs_cb_data);
750 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
751 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
752 buffer_desc.CPUAccessFlags = 0;
753 buffer_desc.MiscFlags = 0;
755 buffer_data.pSysMem = &vs_cb_data;
756 buffer_data.SysMemPitch = 0;
757 buffer_data.SysMemSlicePitch = 0;
759 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
761 WARN("Failed to create constant buffer, hr %#x.\n", hr);
762 return;
765 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, render_target, &ps_cb)))
767 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
768 ID3D10Buffer_Release(vs_cb);
769 return;
772 if (geometry->outline.face_count)
774 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
775 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
776 buffer_data.pSysMem = geometry->outline.faces;
778 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
780 WARN("Failed to create index buffer, hr %#x.\n", hr);
781 goto done;
784 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
785 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
786 buffer_data.pSysMem = geometry->outline.vertices;
788 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
790 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
791 ID3D10Buffer_Release(ib);
792 goto done;
795 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
796 sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
798 ID3D10Buffer_Release(vb);
799 ID3D10Buffer_Release(ib);
802 if (geometry->outline.bezier_face_count)
804 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
805 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
806 buffer_data.pSysMem = geometry->outline.bezier_faces;
808 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
810 WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
811 goto done;
814 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
815 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
816 buffer_data.pSysMem = geometry->outline.beziers;
818 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
820 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
821 ID3D10Buffer_Release(ib);
822 goto done;
825 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
826 3 * geometry->outline.bezier_face_count, vb,
827 sizeof(*geometry->outline.beziers), vs_cb, ps_cb, brush, NULL);
829 ID3D10Buffer_Release(vb);
830 ID3D10Buffer_Release(ib);
833 done:
834 ID3D10Buffer_Release(ps_cb);
835 ID3D10Buffer_Release(vs_cb);
838 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext *iface,
839 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
841 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
842 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
843 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
845 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
846 iface, geometry, brush, stroke_width, stroke_style);
848 if (stroke_style)
849 FIXME("Ignoring stroke style %p.\n", stroke_style);
851 d2d_device_context_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
854 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
855 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
857 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
858 D3D10_SUBRESOURCE_DATA buffer_data;
859 D3D10_BUFFER_DESC buffer_desc;
860 D2D1_MATRIX_3X2_F *w;
861 float tmp_x, tmp_y;
862 HRESULT hr;
863 struct
865 struct
867 float _11, _21, _31, pad0;
868 float _12, _22, _32, pad1;
869 } transform_geometry;
870 struct d2d_vec4 transform_rtx;
871 struct d2d_vec4 transform_rty;
872 } vs_cb_data;
874 vs_cb_data.transform_geometry._11 = geometry->transform._11;
875 vs_cb_data.transform_geometry._21 = geometry->transform._21;
876 vs_cb_data.transform_geometry._31 = geometry->transform._31;
877 vs_cb_data.transform_geometry.pad0 = 0.0f;
878 vs_cb_data.transform_geometry._12 = geometry->transform._12;
879 vs_cb_data.transform_geometry._22 = geometry->transform._22;
880 vs_cb_data.transform_geometry._32 = geometry->transform._32;
881 vs_cb_data.transform_geometry.pad1 = 0.0f;
883 w = &render_target->drawing_state.transform;
885 tmp_x = render_target->desc.dpiX / 96.0f;
886 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
887 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
888 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
889 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
891 tmp_y = render_target->desc.dpiY / 96.0f;
892 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
893 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
894 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
895 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
897 buffer_desc.ByteWidth = sizeof(vs_cb_data);
898 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
899 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
900 buffer_desc.CPUAccessFlags = 0;
901 buffer_desc.MiscFlags = 0;
903 buffer_data.pSysMem = &vs_cb_data;
904 buffer_data.SysMemPitch = 0;
905 buffer_data.SysMemSlicePitch = 0;
907 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
909 WARN("Failed to create constant buffer, hr %#x.\n", hr);
910 return;
913 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, render_target, &ps_cb)))
915 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
916 ID3D10Buffer_Release(vs_cb);
917 return;
920 if (geometry->fill.face_count)
922 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
923 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
924 buffer_data.pSysMem = geometry->fill.faces;
926 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
928 WARN("Failed to create index buffer, hr %#x.\n", hr);
929 goto done;
932 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
933 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
934 buffer_data.pSysMem = geometry->fill.vertices;
936 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
938 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
939 ID3D10Buffer_Release(ib);
940 goto done;
943 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
944 sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush);
946 ID3D10Buffer_Release(vb);
947 ID3D10Buffer_Release(ib);
950 if (geometry->fill.bezier_vertex_count)
952 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
953 buffer_data.pSysMem = geometry->fill.bezier_vertices;
955 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
957 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
958 goto done;
961 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb,
962 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush);
964 ID3D10Buffer_Release(vb);
967 done:
968 ID3D10Buffer_Release(ps_cb);
969 ID3D10Buffer_Release(vs_cb);
972 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
973 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
975 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
976 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
977 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
978 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
980 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
982 if (FAILED(context->error.code))
983 return;
985 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
987 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
988 return;
991 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
994 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext *iface,
995 ID2D1Mesh *mesh, ID2D1Brush *brush)
997 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1000 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext *iface,
1001 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1002 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1004 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1005 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1008 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1009 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1010 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
1012 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1013 D2D1_BRUSH_PROPERTIES brush_desc;
1014 struct d2d_brush *brush;
1015 D2D1_RECT_F s, d;
1016 HRESULT hr;
1018 if (perspective_transform)
1019 FIXME("Perspective transform is ignored.\n");
1021 if (src_rect)
1023 s = *src_rect;
1025 else
1027 D2D1_SIZE_F size;
1029 size = ID2D1Bitmap_GetSize(bitmap);
1030 s.left = 0.0f;
1031 s.top = 0.0f;
1032 s.right = size.width;
1033 s.bottom = size.height;
1036 if (dst_rect)
1038 d = *dst_rect;
1040 else
1042 d.left = 0.0f;
1043 d.top = 0.0f;
1044 d.right = s.right - s.left;
1045 d.bottom = s.bottom - s.top;
1048 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1049 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1050 bitmap_brush_desc.interpolationMode = interpolation_mode;
1052 brush_desc.opacity = opacity;
1053 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1054 brush_desc.transform._21 = 0.0f;
1055 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1056 brush_desc.transform._12 = 0.0f;
1057 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1058 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1060 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1062 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
1063 return;
1066 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext_iface, &d, &brush->ID2D1Brush_iface);
1067 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1070 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext *iface,
1071 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1072 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1074 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1076 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1077 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1079 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1080 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1082 d2d_device_context_set_error(context, E_INVALIDARG);
1083 return;
1086 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect, NULL);
1089 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext *iface,
1090 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1091 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1093 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1094 IDWriteTextLayout *text_layout;
1095 IDWriteFactory *dwrite_factory;
1096 D2D1_POINT_2F origin;
1097 HRESULT hr;
1099 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1100 "brush %p, options %#x, measuring_mode %#x.\n",
1101 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1102 brush, options, measuring_mode);
1104 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1105 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1107 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1108 return;
1111 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1112 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1113 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
1114 else
1115 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1116 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
1117 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1118 IDWriteFactory_Release(dwrite_factory);
1119 if (FAILED(hr))
1121 ERR("Failed to create text layout, hr %#x.\n", hr);
1122 return;
1125 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
1126 ID2D1DeviceContext_DrawTextLayout(iface, origin, text_layout, brush, options);
1127 IDWriteTextLayout_Release(text_layout);
1130 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext *iface,
1131 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1133 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1134 struct d2d_draw_text_layout_ctx ctx;
1135 HRESULT hr;
1137 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1138 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1140 ctx.brush = brush;
1141 ctx.options = options;
1143 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1144 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1145 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1148 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1150 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1151 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1152 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1153 return prev_antialias_mode;
1156 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1157 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1159 D2D1_MATRIX_3X2_F *transform, prev_transform;
1160 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1161 ID2D1PathGeometry *geometry;
1162 ID2D1GeometrySink *sink;
1163 HRESULT hr;
1165 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1167 ERR("Failed to create geometry, hr %#x.\n", hr);
1168 return;
1171 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1173 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1174 ID2D1PathGeometry_Release(geometry);
1175 return;
1178 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1179 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1180 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1182 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1183 ID2D1GeometrySink_Release(sink);
1184 ID2D1PathGeometry_Release(geometry);
1185 return;
1188 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1189 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1190 ID2D1GeometrySink_Release(sink);
1192 transform = &render_target->drawing_state.transform;
1193 prev_transform = *transform;
1194 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1195 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1196 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1197 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1198 unsafe_impl_from_ID2D1Brush(brush), NULL);
1199 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1200 *transform = prev_transform;
1202 ID2D1PathGeometry_Release(geometry);
1205 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1206 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1207 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1208 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1210 ID2D1RectangleGeometry *geometry = NULL;
1211 ID2D1BitmapBrush *opacity_brush = NULL;
1212 D2D1_BITMAP_PROPERTIES bitmap_desc;
1213 ID2D1Bitmap *opacity_bitmap = NULL;
1214 IDWriteGlyphRunAnalysis *analysis;
1215 DWRITE_TEXTURE_TYPE texture_type;
1216 D2D1_BRUSH_PROPERTIES brush_desc;
1217 IDWriteFactory2 *dwrite_factory;
1218 D2D1_MATRIX_3X2_F *transform, m;
1219 void *opacity_values = NULL;
1220 size_t opacity_values_size;
1221 D2D1_SIZE_U bitmap_size;
1222 float scale_x, scale_y;
1223 D2D1_RECT_F run_rect;
1224 RECT bounds;
1225 HRESULT hr;
1227 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1228 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1230 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1231 return;
1234 transform = &render_target->drawing_state.transform;
1236 scale_x = render_target->desc.dpiX / 96.0f;
1237 m._11 = transform->_11 * scale_x;
1238 m._21 = transform->_21 * scale_x;
1239 m._31 = transform->_31 * scale_x;
1241 scale_y = render_target->desc.dpiY / 96.0f;
1242 m._12 = transform->_12 * scale_y;
1243 m._22 = transform->_22 * scale_y;
1244 m._32 = transform->_32 * scale_y;
1246 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1247 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1248 baseline_origin.x, baseline_origin.y, &analysis);
1249 IDWriteFactory2_Release(dwrite_factory);
1250 if (FAILED(hr))
1252 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1253 return;
1256 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1257 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1258 else
1259 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1261 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1263 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1264 goto done;
1267 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1268 if (!bitmap_size.width || !bitmap_size.height)
1270 /* Empty run, nothing to do. */
1271 goto done;
1274 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1275 bitmap_size.width *= 3;
1276 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1278 ERR("Failed to allocate opacity values.\n");
1279 goto done;
1281 opacity_values_size = bitmap_size.height * bitmap_size.width;
1283 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1284 texture_type, &bounds, opacity_values, opacity_values_size)))
1286 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1287 goto done;
1290 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1291 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1292 bitmap_desc.dpiX = render_target->desc.dpiX;
1293 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1294 bitmap_desc.dpiX *= 3.0f;
1295 bitmap_desc.dpiY = render_target->desc.dpiY;
1296 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext_iface,
1297 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1299 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1300 goto done;
1303 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1304 bounds.right / scale_x, bounds.bottom / scale_y);
1306 brush_desc.opacity = 1.0f;
1307 brush_desc.transform._11 = 1.0f;
1308 brush_desc.transform._12 = 0.0f;
1309 brush_desc.transform._21 = 0.0f;
1310 brush_desc.transform._22 = 1.0f;
1311 brush_desc.transform._31 = run_rect.left;
1312 brush_desc.transform._32 = run_rect.top;
1313 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext_iface,
1314 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1316 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1317 goto done;
1320 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1322 ERR("Failed to create geometry, hr %#x.\n", hr);
1323 goto done;
1326 m = *transform;
1327 *transform = identity;
1328 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1329 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1330 *transform = m;
1332 done:
1333 if (geometry)
1334 ID2D1RectangleGeometry_Release(geometry);
1335 if (opacity_brush)
1336 ID2D1BitmapBrush_Release(opacity_brush);
1337 if (opacity_bitmap)
1338 ID2D1Bitmap_Release(opacity_bitmap);
1339 heap_free(opacity_values);
1340 IDWriteGlyphRunAnalysis_Release(analysis);
1343 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext *iface,
1344 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1345 DWRITE_MEASURING_MODE measuring_mode)
1347 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1348 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1350 ID2D1DeviceContext_DrawGlyphRun(iface, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1353 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext *iface,
1354 const D2D1_MATRIX_3X2_F *transform)
1356 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1358 TRACE("iface %p, transform %p.\n", iface, transform);
1360 render_target->drawing_state.transform = *transform;
1363 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext *iface,
1364 D2D1_MATRIX_3X2_F *transform)
1366 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1368 TRACE("iface %p, transform %p.\n", iface, transform);
1370 *transform = render_target->drawing_state.transform;
1373 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext *iface,
1374 D2D1_ANTIALIAS_MODE antialias_mode)
1376 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1378 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1380 render_target->drawing_state.antialiasMode = antialias_mode;
1383 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext *iface)
1385 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1387 TRACE("iface %p.\n", iface);
1389 return render_target->drawing_state.antialiasMode;
1392 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext *iface,
1393 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1395 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1397 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1399 render_target->drawing_state.textAntialiasMode = antialias_mode;
1402 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext *iface)
1404 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1406 TRACE("iface %p.\n", iface);
1408 return render_target->drawing_state.textAntialiasMode;
1411 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext *iface,
1412 IDWriteRenderingParams *text_rendering_params)
1414 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1416 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1418 if (text_rendering_params)
1419 IDWriteRenderingParams_AddRef(text_rendering_params);
1420 if (render_target->text_rendering_params)
1421 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1422 render_target->text_rendering_params = text_rendering_params;
1425 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext *iface,
1426 IDWriteRenderingParams **text_rendering_params)
1428 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1430 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1432 if ((*text_rendering_params = render_target->text_rendering_params))
1433 IDWriteRenderingParams_AddRef(*text_rendering_params);
1436 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1438 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1440 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1442 render_target->drawing_state.tag1 = tag1;
1443 render_target->drawing_state.tag2 = tag2;
1446 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1448 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1450 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1452 *tag1 = render_target->drawing_state.tag1;
1453 *tag2 = render_target->drawing_state.tag2;
1456 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext *iface,
1457 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1459 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1462 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *iface)
1464 FIXME("iface %p stub!\n", iface);
1467 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1469 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1471 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1473 if (context->ops && context->ops->device_context_present)
1474 context->ops->device_context_present(context->outer_unknown);
1476 return E_NOTIMPL;
1479 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext *iface,
1480 ID2D1DrawingStateBlock *state_block)
1482 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1483 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1485 TRACE("iface %p, state_block %p.\n", iface, state_block);
1487 state_block_impl->drawing_state = render_target->drawing_state;
1488 if (render_target->text_rendering_params)
1489 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1490 if (state_block_impl->text_rendering_params)
1491 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1492 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1495 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext *iface,
1496 ID2D1DrawingStateBlock *state_block)
1498 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1499 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1501 TRACE("iface %p, state_block %p.\n", iface, state_block);
1503 render_target->drawing_state = state_block_impl->drawing_state;
1504 if (state_block_impl->text_rendering_params)
1505 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1506 if (render_target->text_rendering_params)
1507 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1508 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1511 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext *iface,
1512 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1514 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1515 D2D1_RECT_F transformed_rect;
1516 float x_scale, y_scale;
1517 D2D1_POINT_2F point;
1519 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1521 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1522 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1524 x_scale = render_target->desc.dpiX / 96.0f;
1525 y_scale = render_target->desc.dpiY / 96.0f;
1526 d2d_point_transform(&point, &render_target->drawing_state.transform,
1527 clip_rect->left * x_scale, clip_rect->top * y_scale);
1528 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1529 d2d_point_transform(&point, &render_target->drawing_state.transform,
1530 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1531 d2d_rect_expand(&transformed_rect, &point);
1532 d2d_point_transform(&point, &render_target->drawing_state.transform,
1533 clip_rect->right * x_scale, clip_rect->top * y_scale);
1534 d2d_rect_expand(&transformed_rect, &point);
1535 d2d_point_transform(&point, &render_target->drawing_state.transform,
1536 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1537 d2d_rect_expand(&transformed_rect, &point);
1539 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1540 WARN("Failed to push clip rect.\n");
1543 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext *iface)
1545 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1547 TRACE("iface %p.\n", iface);
1549 d2d_clip_stack_pop(&render_target->clip_stack);
1552 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface, const D2D1_COLOR_F *colour)
1554 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1555 D3D10_SUBRESOURCE_DATA buffer_data;
1556 struct d2d_ps_cb ps_cb_data = {0};
1557 D3D10_BUFFER_DESC buffer_desc;
1558 ID3D10Buffer *vs_cb, *ps_cb;
1559 D2D1_COLOR_F *c;
1560 HRESULT hr;
1562 static const struct
1564 struct
1566 float _11, _21, _31, pad0;
1567 float _12, _22, _32, pad1;
1568 } transform_geometry;
1569 struct d2d_vec4 transform_rtx;
1570 struct d2d_vec4 transform_rty;
1572 vs_cb_data =
1574 {1.0f, 0.0f, 0.0f, 0.0f,
1575 0.0f, 1.0f, 0.0f, 0.0f},
1576 {1.0f, 0.0f, 1.0f, 1.0f},
1577 {0.0f, 1.0f, 1.0f, -1.0f},
1580 TRACE("iface %p, colour %p.\n", iface, colour);
1582 buffer_desc.ByteWidth = sizeof(vs_cb_data);
1583 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1584 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1585 buffer_desc.CPUAccessFlags = 0;
1586 buffer_desc.MiscFlags = 0;
1588 buffer_data.pSysMem = &vs_cb_data;
1589 buffer_data.SysMemPitch = 0;
1590 buffer_data.SysMemSlicePitch = 0;
1592 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
1594 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1595 return;
1598 ps_cb_data.outline = FALSE;
1599 ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1600 ps_cb_data.colour_brush.opacity = 1.0f;
1601 c = &ps_cb_data.colour_brush.u.solid.colour;
1602 if (colour)
1603 *c = *colour;
1604 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1605 c->a = 1.0f;
1606 c->r *= c->a;
1607 c->g *= c->a;
1608 c->b *= c->a;
1610 ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1612 buffer_desc.ByteWidth = sizeof(ps_cb_data);
1613 buffer_data.pSysMem = &ps_cb_data;
1615 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ps_cb)))
1617 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1618 ID3D10Buffer_Release(vs_cb);
1619 return;
1622 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1623 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1625 ID3D10Buffer_Release(ps_cb);
1626 ID3D10Buffer_Release(vs_cb);
1629 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
1631 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1633 TRACE("iface %p.\n", iface);
1635 memset(&render_target->error, 0, sizeof(render_target->error));
1638 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface,
1639 D2D1_TAG *tag1, D2D1_TAG *tag2)
1641 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1642 HRESULT hr;
1644 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1646 if (tag1)
1647 *tag1 = context->error.tag1;
1648 if (tag2)
1649 *tag2 = context->error.tag2;
1651 if (context->ops && context->ops->device_context_present)
1653 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1654 context->error.code = hr;
1657 return context->error.code;
1660 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface,
1661 D2D1_PIXEL_FORMAT *format)
1663 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1665 TRACE("iface %p, format %p.\n", iface, format);
1667 *format = render_target->desc.pixelFormat;
1668 return format;
1671 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext *iface, float dpi_x, float dpi_y)
1673 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1675 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1677 if (dpi_x == 0.0f && dpi_y == 0.0f)
1679 dpi_x = 96.0f;
1680 dpi_y = 96.0f;
1682 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1683 return;
1685 render_target->desc.dpiX = dpi_x;
1686 render_target->desc.dpiY = dpi_y;
1689 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext *iface, float *dpi_x, float *dpi_y)
1691 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1693 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1695 *dpi_x = render_target->desc.dpiX;
1696 *dpi_y = render_target->desc.dpiY;
1699 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext *iface, D2D1_SIZE_F *size)
1701 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1703 TRACE("iface %p, size %p.\n", iface, size);
1705 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1706 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1707 return size;
1710 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext *iface,
1711 D2D1_SIZE_U *pixel_size)
1713 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1715 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1717 *pixel_size = render_target->pixel_size;
1718 return pixel_size;
1721 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext *iface)
1723 TRACE("iface %p.\n", iface);
1725 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1728 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext *iface,
1729 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1731 FIXME("iface %p, desc %p stub!\n", iface, desc);
1733 return FALSE;
1736 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext *iface,
1737 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
1738 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1740 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1741 struct d2d_bitmap *object;
1742 HRESULT hr;
1744 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
1745 iface, size.width, size.height, src_data, pitch, desc, bitmap);
1747 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
1748 *bitmap = &object->ID2D1Bitmap1_iface;
1750 return hr;
1753 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
1754 ID2D1DeviceContext *iface, IWICBitmapSource *bitmap_source,
1755 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1757 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1758 struct d2d_bitmap *object;
1759 HRESULT hr;
1761 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
1763 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
1764 *bitmap = &object->ID2D1Bitmap1_iface;
1766 return hr;
1769 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext *iface,
1770 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
1772 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
1773 iface, space, profile, profile_size, color_context);
1775 return E_NOTIMPL;
1778 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext *iface,
1779 const WCHAR *filename, ID2D1ColorContext **color_context)
1781 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
1783 return E_NOTIMPL;
1786 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext *iface,
1787 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
1789 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
1791 return E_NOTIMPL;
1794 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
1795 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1797 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1798 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
1799 struct d2d_bitmap *object;
1800 HRESULT hr;
1802 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
1804 if (!desc)
1806 DXGI_SURFACE_DESC surface_desc;
1808 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1810 WARN("Failed to get surface desc, hr %#x.\n", hr);
1811 return hr;
1814 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
1815 bitmap_desc.pixelFormat.format = surface_desc.Format;
1816 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1817 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
1818 desc = &bitmap_desc;
1821 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
1822 *bitmap = &object->ID2D1Bitmap1_iface;
1824 return hr;
1827 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
1828 REFCLSID effect_id, ID2D1Effect **effect)
1830 struct d2d_effect *object;
1832 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1834 if (!(object = heap_alloc_zero(sizeof(*object))))
1835 return E_OUTOFMEMORY;
1837 d2d_effect_init(object);
1839 TRACE("Created effect %p.\n", object);
1840 *effect = &object->ID2D1Effect_iface;
1842 return S_OK;
1845 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1846 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1847 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1848 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1849 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1851 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1852 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1853 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1854 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1856 return E_NOTIMPL;
1859 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1860 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1861 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1863 FIXME("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p stub!\n",
1864 iface, image, image_brush_desc, brush_desc, brush);
1866 return E_NOTIMPL;
1869 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1870 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1871 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1873 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1874 struct d2d_brush *object;
1875 HRESULT hr;
1877 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1878 brush_desc, brush);
1880 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1881 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1883 return hr;
1886 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1887 ID2D1CommandList **command_list)
1889 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1891 return E_NOTIMPL;
1894 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1896 FIXME("iface %p, format %#x stub!\n", iface, format);
1898 return FALSE;
1901 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1902 D2D1_BUFFER_PRECISION buffer_precision)
1904 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1906 return FALSE;
1909 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1910 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1912 FIXME("iface %p, image %p, local_bounds %p stub!\n", iface, image, local_bounds);
1915 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
1916 ID2D1Image *image, D2D1_RECT_F *world_bounds)
1918 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
1920 return E_NOTIMPL;
1923 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
1924 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1925 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
1927 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
1928 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
1930 return E_NOTIMPL;
1933 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
1935 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1937 TRACE("iface %p, device %p.\n", iface, device);
1939 *device = context->device;
1940 ID2D1Device_AddRef(*device);
1943 static void d2d_device_context_reset_target(struct d2d_device_context *context)
1945 if (!context->target)
1946 return;
1948 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
1949 context->target = NULL;
1951 context->desc.dpiX = 96.0f;
1952 context->desc.dpiY = 96.0f;
1954 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
1955 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
1957 ID3D10BlendState_Release(context->bs);
1958 context->bs = NULL;
1961 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
1963 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1964 struct d2d_bitmap *bitmap_impl;
1965 D3D10_BLEND_DESC blend_desc;
1966 ID2D1Bitmap *bitmap;
1967 HRESULT hr;
1969 TRACE("iface %p, target %p.\n", iface, target);
1971 if (!target)
1973 d2d_device_context_reset_target(context);
1974 return;
1977 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
1979 FIXME("Only bitmap targets are supported.\n");
1980 return;
1983 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
1985 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
1987 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
1988 return;
1991 d2d_device_context_reset_target(context);
1993 /* Set sizes and pixel format. */
1994 context->desc.dpiX = bitmap_impl->dpi_x;
1995 context->desc.dpiY = bitmap_impl->dpi_y;
1996 context->pixel_size = bitmap_impl->pixel_size;
1997 context->desc.pixelFormat = bitmap_impl->format;
1998 context->target = bitmap_impl;
2000 memset(&blend_desc, 0, sizeof(blend_desc));
2001 blend_desc.BlendEnable[0] = TRUE;
2002 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2003 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2004 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2005 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2007 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2008 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2010 else
2012 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2013 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2015 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2016 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2017 if (FAILED(hr = ID3D10Device_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2018 WARN("Failed to create blend state, hr %#x.\n", hr);
2021 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2023 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2025 TRACE("iface %p, target %p.\n", iface, target);
2027 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2028 if (*target)
2029 ID2D1Image_AddRef(*target);
2032 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2033 const D2D1_RENDERING_CONTROLS *rendering_controls)
2035 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2038 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2039 D2D1_RENDERING_CONTROLS *rendering_controls)
2041 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2044 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2045 D2D1_PRIMITIVE_BLEND primitive_blend)
2047 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2050 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2052 FIXME("iface %p stub!\n", iface);
2054 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2057 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2059 FIXME("iface %p, unit_mode %#x stub!\n", iface, unit_mode);
2062 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2064 FIXME("iface %p stub!\n", iface);
2066 return D2D1_UNIT_MODE_DIPS;
2069 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2070 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2071 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2073 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
2074 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2075 IDWriteRenderingParams *rendering_params;
2076 DWRITE_RENDERING_MODE rendering_mode;
2077 HRESULT hr;
2079 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2080 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2082 if (FAILED(context->error.code))
2083 return;
2085 rendering_params = context->text_rendering_params ? context->text_rendering_params
2086 : context->default_text_rendering_params;
2088 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
2090 switch (context->drawing_state.textAntialiasMode)
2092 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2093 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
2094 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
2095 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
2096 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
2097 d2d_device_context_set_error(context, E_INVALIDARG);
2098 break;
2100 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2101 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
2102 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2103 d2d_device_context_set_error(context, E_INVALIDARG);
2104 break;
2106 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
2107 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
2108 d2d_device_context_set_error(context, E_INVALIDARG);
2109 break;
2111 default:
2112 break;
2115 if (FAILED(context->error.code))
2116 return;
2118 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
2119 switch (context->drawing_state.textAntialiasMode)
2121 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
2122 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
2123 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2124 break;
2126 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2127 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2128 break;
2130 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2131 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
2132 break;
2134 default:
2135 break;
2138 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2140 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
2141 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
2142 measuring_mode, rendering_params, &rendering_mode)))
2144 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
2145 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
2149 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2150 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
2151 else
2152 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
2153 rendering_mode, measuring_mode, antialias_mode);
2156 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2157 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2158 D2D1_COMPOSITE_MODE composite_mode)
2160 FIXME("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x stub!\n",
2161 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2162 interpolation_mode, composite_mode);
2165 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2166 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2168 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2169 iface, metafile, debug_d2d_point_2f(target_offset));
2172 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2173 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2174 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2176 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2178 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2179 "src_rect %s, perspective_transform %p.\n",
2180 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2181 debug_d2d_rect_f(src_rect), perspective_transform);
2183 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2184 perspective_transform);
2187 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2188 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2190 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2193 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2194 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2196 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2197 iface, effect, input, debug_d2d_rect_f(input_rect));
2199 return E_NOTIMPL;
2202 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2203 ID2D1Effect *effect, UINT32 *rect_count)
2205 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2207 return E_NOTIMPL;
2210 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2211 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2213 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2215 return E_NOTIMPL;
2218 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2219 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2220 D2D1_RECT_F *input_rect, UINT32 input_count)
2222 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2223 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2225 return E_NOTIMPL;
2228 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2229 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2231 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2232 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2235 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2237 d2d_device_context_QueryInterface,
2238 d2d_device_context_AddRef,
2239 d2d_device_context_Release,
2240 d2d_device_context_GetFactory,
2241 d2d_device_context_CreateBitmap,
2242 d2d_device_context_CreateBitmapFromWicBitmap,
2243 d2d_device_context_CreateSharedBitmap,
2244 d2d_device_context_CreateBitmapBrush,
2245 d2d_device_context_CreateSolidColorBrush,
2246 d2d_device_context_CreateGradientStopCollection,
2247 d2d_device_context_CreateLinearGradientBrush,
2248 d2d_device_context_CreateRadialGradientBrush,
2249 d2d_device_context_CreateCompatibleRenderTarget,
2250 d2d_device_context_CreateLayer,
2251 d2d_device_context_CreateMesh,
2252 d2d_device_context_DrawLine,
2253 d2d_device_context_DrawRectangle,
2254 d2d_device_context_FillRectangle,
2255 d2d_device_context_DrawRoundedRectangle,
2256 d2d_device_context_FillRoundedRectangle,
2257 d2d_device_context_DrawEllipse,
2258 d2d_device_context_FillEllipse,
2259 d2d_device_context_DrawGeometry,
2260 d2d_device_context_FillGeometry,
2261 d2d_device_context_FillMesh,
2262 d2d_device_context_FillOpacityMask,
2263 d2d_device_context_DrawBitmap,
2264 d2d_device_context_DrawText,
2265 d2d_device_context_DrawTextLayout,
2266 d2d_device_context_DrawGlyphRun,
2267 d2d_device_context_SetTransform,
2268 d2d_device_context_GetTransform,
2269 d2d_device_context_SetAntialiasMode,
2270 d2d_device_context_GetAntialiasMode,
2271 d2d_device_context_SetTextAntialiasMode,
2272 d2d_device_context_GetTextAntialiasMode,
2273 d2d_device_context_SetTextRenderingParams,
2274 d2d_device_context_GetTextRenderingParams,
2275 d2d_device_context_SetTags,
2276 d2d_device_context_GetTags,
2277 d2d_device_context_PushLayer,
2278 d2d_device_context_PopLayer,
2279 d2d_device_context_Flush,
2280 d2d_device_context_SaveDrawingState,
2281 d2d_device_context_RestoreDrawingState,
2282 d2d_device_context_PushAxisAlignedClip,
2283 d2d_device_context_PopAxisAlignedClip,
2284 d2d_device_context_Clear,
2285 d2d_device_context_BeginDraw,
2286 d2d_device_context_EndDraw,
2287 d2d_device_context_GetPixelFormat,
2288 d2d_device_context_SetDpi,
2289 d2d_device_context_GetDpi,
2290 d2d_device_context_GetSize,
2291 d2d_device_context_GetPixelSize,
2292 d2d_device_context_GetMaximumBitmapSize,
2293 d2d_device_context_IsSupported,
2294 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2295 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2296 d2d_device_context_CreateColorContext,
2297 d2d_device_context_CreateColorContextFromFilename,
2298 d2d_device_context_CreateColorContextFromWicColorContext,
2299 d2d_device_context_CreateBitmapFromDxgiSurface,
2300 d2d_device_context_CreateEffect,
2301 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2302 d2d_device_context_CreateImageBrush,
2303 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2304 d2d_device_context_CreateCommandList,
2305 d2d_device_context_IsDxgiFormatSupported,
2306 d2d_device_context_IsBufferPrecisionSupported,
2307 d2d_device_context_GetImageLocalBounds,
2308 d2d_device_context_GetImageWorldBounds,
2309 d2d_device_context_GetGlyphRunWorldBounds,
2310 d2d_device_context_GetDevice,
2311 d2d_device_context_SetTarget,
2312 d2d_device_context_GetTarget,
2313 d2d_device_context_SetRenderingControls,
2314 d2d_device_context_GetRenderingControls,
2315 d2d_device_context_SetPrimitiveBlend,
2316 d2d_device_context_GetPrimitiveBlend,
2317 d2d_device_context_SetUnitMode,
2318 d2d_device_context_GetUnitMode,
2319 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2320 d2d_device_context_DrawImage,
2321 d2d_device_context_DrawGdiMetafile,
2322 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2323 d2d_device_context_ID2D1DeviceContext_PushLayer,
2324 d2d_device_context_InvalidateEffectInputRectangle,
2325 d2d_device_context_GetEffectInvalidRectangleCount,
2326 d2d_device_context_GetEffectInvalidRectangles,
2327 d2d_device_context_GetEffectRequiredInputRectangles,
2328 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2331 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2333 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2336 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2338 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2340 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2341 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2342 || IsEqualGUID(iid, &IID_IUnknown))
2344 IDWriteTextRenderer_AddRef(iface);
2345 *out = iface;
2346 return S_OK;
2349 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2351 *out = NULL;
2352 return E_NOINTERFACE;
2355 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2357 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2359 TRACE("iface %p.\n", iface);
2361 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2364 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2366 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2368 TRACE("iface %p.\n", iface);
2370 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2373 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2374 void *ctx, BOOL *disabled)
2376 struct d2d_draw_text_layout_ctx *context = ctx;
2378 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2380 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2382 return S_OK;
2385 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2386 void *ctx, DWRITE_MATRIX *transform)
2388 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2390 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2392 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2394 return S_OK;
2397 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2399 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2401 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2403 *ppd = render_target->desc.dpiY / 96.0f;
2405 return S_OK;
2408 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2409 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2410 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2412 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2413 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2414 struct d2d_draw_text_layout_ctx *context = ctx;
2415 BOOL color_font = FALSE;
2416 ID2D1Brush *brush;
2418 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2419 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2420 iface, ctx, baseline_origin_x, baseline_origin_y,
2421 measuring_mode, glyph_run, desc, effect);
2423 if (desc)
2424 WARN("Ignoring glyph run description %p.\n", desc);
2425 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2426 FIXME("Ignoring options %#x.\n", context->options);
2428 brush = d2d_draw_get_text_brush(context, effect);
2430 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2432 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2434 IDWriteFontFace2 *fontface;
2436 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2437 &IID_IDWriteFontFace2, (void **)&fontface)))
2439 color_font = IDWriteFontFace2_IsColorFont(fontface);
2440 IDWriteFontFace2_Release(fontface);
2444 if (color_font)
2446 IDWriteColorGlyphRunEnumerator *layers;
2447 IDWriteFactory2 *dwrite_factory;
2448 HRESULT hr;
2450 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2451 (IUnknown **)&dwrite_factory)))
2453 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2454 ID2D1Brush_Release(brush);
2455 return hr;
2458 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2459 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2460 IDWriteFactory2_Release(dwrite_factory);
2461 if (FAILED(hr))
2463 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
2464 ID2D1Brush_Release(brush);
2465 return hr;
2468 for (;;)
2470 const DWRITE_COLOR_GLYPH_RUN *color_run;
2471 ID2D1Brush *color_brush;
2472 D2D1_POINT_2F origin;
2473 BOOL has_run = FALSE;
2475 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2477 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
2478 break;
2481 if (!has_run)
2482 break;
2484 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2486 ERR("Failed to get current color run, hr %#x.\n", hr);
2487 break;
2490 if (color_run->paletteIndex == 0xffff)
2491 color_brush = brush;
2492 else
2494 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2495 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2497 ERR("Failed to create solid color brush, hr %#x.\n", hr);
2498 break;
2502 origin.x = color_run->baselineOriginX;
2503 origin.y = color_run->baselineOriginY;
2504 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2505 origin, &color_run->glyphRun, color_brush, measuring_mode);
2507 if (color_brush != brush)
2508 ID2D1Brush_Release(color_brush);
2511 IDWriteColorGlyphRunEnumerator_Release(layers);
2513 else
2514 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2515 baseline_origin, glyph_run, brush, measuring_mode);
2517 ID2D1Brush_Release(brush);
2519 return S_OK;
2522 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2523 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2525 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2526 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2527 struct d2d_draw_text_layout_ctx *context = ctx;
2528 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2529 D2D1_POINT_2F start, end;
2530 ID2D1Brush *brush;
2531 float thickness;
2533 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2534 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2536 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2537 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2538 underline->thickness);
2540 brush = d2d_draw_get_text_brush(context, effect);
2542 start.x = baseline_origin_x;
2543 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2544 end.x = start.x + underline->width;
2545 end.y = start.y;
2546 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2547 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2548 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2550 ID2D1Brush_Release(brush);
2552 return S_OK;
2555 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2556 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2558 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2559 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2560 struct d2d_draw_text_layout_ctx *context = ctx;
2561 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2562 D2D1_POINT_2F start, end;
2563 ID2D1Brush *brush;
2564 float thickness;
2566 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2567 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2569 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2570 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2571 strikethrough->thickness);
2573 brush = d2d_draw_get_text_brush(context, effect);
2575 start.x = baseline_origin_x;
2576 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2577 end.x = start.x + strikethrough->width;
2578 end.y = start.y;
2579 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2580 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2581 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2583 ID2D1Brush_Release(brush);
2585 return S_OK;
2588 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2589 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2591 struct d2d_draw_text_layout_ctx *context = ctx;
2592 ID2D1Brush *brush;
2593 HRESULT hr;
2595 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2596 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2598 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2599 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2600 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2601 brush is selected at Direct2D level. */
2602 brush = context->brush;
2603 context->brush = d2d_draw_get_text_brush(context, effect);
2605 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2607 ID2D1Brush_Release(context->brush);
2608 context->brush = brush;
2610 return hr;
2613 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2615 d2d_text_renderer_QueryInterface,
2616 d2d_text_renderer_AddRef,
2617 d2d_text_renderer_Release,
2618 d2d_text_renderer_IsPixelSnappingDisabled,
2619 d2d_text_renderer_GetCurrentTransform,
2620 d2d_text_renderer_GetPixelsPerDip,
2621 d2d_text_renderer_DrawGlyphRun,
2622 d2d_text_renderer_DrawUnderline,
2623 d2d_text_renderer_DrawStrikethrough,
2624 d2d_text_renderer_DrawInlineObject,
2627 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2629 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2632 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2633 REFIID iid, void **out)
2635 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2637 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2639 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2642 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2644 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2646 TRACE("iface %p.\n", iface);
2648 return IUnknown_AddRef(render_target->outer_unknown);
2651 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2653 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2655 TRACE("iface %p.\n", iface);
2657 return IUnknown_Release(render_target->outer_unknown);
2660 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2662 ID3D10Resource *resource;
2663 HRESULT hr;
2665 ID3D10RenderTargetView_GetResource(render_target->target->rtv, &resource);
2666 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2667 ID3D10Resource_Release(resource);
2668 if (FAILED(hr))
2670 *surface = NULL;
2671 WARN("Failed to get DXGI surface, %#x.\n", hr);
2672 return hr;
2675 return hr;
2678 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2679 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2681 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2682 IDXGISurface1 *surface;
2683 HRESULT hr;
2685 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2687 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2688 return hr;
2690 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2691 IDXGISurface1_Release(surface);
2693 return hr;
2696 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2697 const RECT *update)
2699 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2700 IDXGISurface1 *surface;
2701 RECT update_rect;
2702 HRESULT hr;
2704 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2706 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2707 return hr;
2709 if (update)
2710 update_rect = *update;
2711 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2712 IDXGISurface1_Release(surface);
2714 return hr;
2717 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2719 d2d_gdi_interop_render_target_QueryInterface,
2720 d2d_gdi_interop_render_target_AddRef,
2721 d2d_gdi_interop_render_target_Release,
2722 d2d_gdi_interop_render_target_GetDC,
2723 d2d_gdi_interop_render_target_ReleaseDC,
2726 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2727 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2729 D3D10_SUBRESOURCE_DATA buffer_data;
2730 D3D10_STATE_BLOCK_MASK state_mask;
2731 struct d2d_device *device_impl;
2732 IDWriteFactory *dwrite_factory;
2733 D3D10_RASTERIZER_DESC rs_desc;
2734 D3D10_BUFFER_DESC buffer_desc;
2735 unsigned int i;
2736 HRESULT hr;
2738 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2740 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2741 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2742 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2744 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier_outline[] =
2746 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2747 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2748 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2749 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2750 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2751 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2753 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2755 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2757 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
2759 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2760 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2762 static const DWORD vs_code_outline[] =
2764 #if 0
2765 float3x2 transform_geometry;
2766 float stroke_width;
2767 float4 transform_rtx;
2768 float4 transform_rty;
2770 struct output
2772 float2 p : WORLD_POSITION;
2773 float4 b : BEZIER;
2774 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2775 float4 position : SV_POSITION;
2778 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2780 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2782 * Where:
2784 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2785 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2786 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2787 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2789 float2 q_prev, q_next, v_p, q_i;
2790 float2x2 geom;
2791 float l;
2793 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2795 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2796 q_prev = normalize(mul(geom, prev));
2797 q_next = normalize(mul(geom, next));
2799 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2800 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2801 v_p = float2(-q_prev.y, q_prev.x);
2802 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2803 q_i = l * q_prev + v_p;
2805 o.b = float4(0.0, 0.0, 0.0, 0.0);
2807 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2808 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2809 * float2(transform_rtx.w, transform_rty.w);
2810 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2812 #endif
2813 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2814 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2815 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2816 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2817 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2818 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2819 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2820 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2821 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2822 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2823 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2824 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2825 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2826 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2827 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2828 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2829 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2830 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2831 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2832 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2833 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2834 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2835 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2836 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2837 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2838 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2839 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2840 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2841 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2842 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2843 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2844 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2845 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2846 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2847 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2848 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2849 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2850 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2851 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2852 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2853 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2854 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2855 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2856 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2857 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2858 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2859 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2860 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2861 0x3f800000, 0x0100003e,
2863 /* ⎡p0.x p0.y 1⎤
2864 * A = ⎢p1.x p1.y 1⎥
2865 * ⎣p2.x p2.y 1⎦
2867 * ⎡0 0⎤
2868 * B = ⎢½ 0⎥
2869 * ⎣1 1⎦
2871 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2872 * ⎣p2.x-p0.x p2.y-p0.y⎦
2874 * B' = ⎡½ 0⎤
2875 * ⎣1 1⎦
2877 * A'T = B'
2878 * T = A'⁻¹B'
2880 static const DWORD vs_code_bezier_outline[] =
2882 #if 0
2883 float3x2 transform_geometry;
2884 float stroke_width;
2885 float4 transform_rtx;
2886 float4 transform_rty;
2888 struct output
2890 float2 p : WORLD_POSITION;
2891 float4 b : BEZIER;
2892 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2893 float4 position : SV_POSITION;
2896 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2897 float2 prev : PREV, float2 next : NEXT, out struct output o)
2899 float2 q_prev, q_next, v_p, q_i, p;
2900 float2x2 geom, rt;
2901 float l;
2903 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2904 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2905 o.stroke_transform = rt * stroke_width * 0.5f;
2907 p = mul(geom, position);
2908 p0 = mul(geom, p0);
2909 p1 = mul(geom, p1);
2910 p2 = mul(geom, p2);
2912 p -= p0;
2913 p1 -= p0;
2914 p2 -= p0;
2916 q_prev = normalize(mul(geom, prev));
2917 q_next = normalize(mul(geom, next));
2919 v_p = float2(-q_prev.y, q_prev.x);
2920 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2921 q_i = l * q_prev + v_p;
2922 p += stroke_width * q_i;
2924 v_p = mul(rt, p2);
2925 v_p = normalize(float2(-v_p.y, v_p.x));
2926 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
2928 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
2929 o.b.y = dot(mul(rt, p), v_p);
2931 else
2933 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
2934 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
2935 o.b.x = dot(v_p, p1 - 0.5f * p2);
2936 o.b.y = dot(v_p, p1);
2939 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * q_i;
2940 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2941 * float2(transform_rtx.w, transform_rty.w);
2942 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2944 #endif
2945 0x43425844, 0x7ff88ce9, 0xd75cb064, 0x30396183, 0xca64489b, 0x00000001, 0x00000ae4, 0x00000003,
2946 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
2947 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
2948 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
2949 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
2950 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
2951 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
2952 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
2953 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
2954 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
2955 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
2956 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
2957 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
2958 0x52444853, 0x0000093c, 0x00010040, 0x0000024f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
2959 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
2960 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
2961 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
2962 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
2963 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
2964 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
2965 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
2966 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
2967 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
2968 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
2969 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
2970 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
2971 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
2972 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
2973 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
2974 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
2975 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
2976 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
2977 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
2978 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
2979 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
2980 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
2981 0x0a000032, 0x00100032, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000,
2982 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f,
2983 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f,
2984 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f,
2985 0x00100012, 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f,
2986 0x00100022, 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000,
2987 0x001000c2, 0x00000000, 0x00100406, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x0a000032,
2988 0x00100032, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000, 0x00100ae6,
2989 0x00000000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046,
2990 0x00000000, 0x0800000f, 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046,
2991 0x00000000, 0x0800000f, 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046,
2992 0x00000003, 0x0800000f, 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046,
2993 0x00000003, 0x08000000, 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406,
2994 0x00000004, 0x0800000f, 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6,
2995 0x00000002, 0x06000036, 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f,
2996 0x00100082, 0x00000003, 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f,
2997 0x00100082, 0x00000000, 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082,
2998 0x00000000, 0x0010003a, 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000,
2999 0x00100ea6, 0x00000003, 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6,
3000 0x00000003, 0x06000036, 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f,
3001 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3002 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3003 0x00100032, 0x00000005, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036,
3004 0x00100042, 0x00000005, 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000,
3005 0x00100a26, 0x00000005, 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6,
3006 0x00000041, 0x00000002, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046,
3007 0x00000005, 0x0800000e, 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556,
3008 0x00000000, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002,
3009 0x0700000f, 0x00100022, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f,
3010 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f,
3011 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f,
3012 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022,
3013 0x00000000, 0x00004001, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000,
3014 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a,
3015 0x00000081, 0x00000000, 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a,
3016 0x00000041, 0x00000000, 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a,
3017 0x00000000, 0x07000038, 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000,
3018 0x08000036, 0x001000d2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
3019 0x09000037, 0x001020f2, 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46,
3020 0x00000002, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3021 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3022 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3023 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3024 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3025 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3026 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3027 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3028 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3029 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3030 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3031 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3032 0x0100003e,
3034 static const DWORD vs_code_triangle[] =
3036 #if 0
3037 float3x2 transform_geometry;
3038 float4 transform_rtx;
3039 float4 transform_rty;
3041 struct output
3043 float2 p : WORLD_POSITION;
3044 float4 b : BEZIER;
3045 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3046 float4 position : SV_POSITION;
3049 void main(float2 position : POSITION, out struct output o)
3051 o.p = mul(float3(position, 1.0f), transform_geometry);
3052 o.b = float4(1.0, 0.0, 1.0, 1.0);
3053 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3054 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3055 * float2(transform_rtx.w, transform_rty.w);
3056 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3058 #endif
3059 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3060 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3061 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3062 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3063 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3064 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3065 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3066 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3067 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3068 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3069 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3070 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3071 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3072 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3073 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3074 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3075 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3076 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3077 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3078 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3079 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3080 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3081 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3082 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3083 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3084 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3085 0x00000000, 0x3f800000, 0x0100003e,
3087 static const DWORD vs_code_bezier[] =
3089 #if 0
3090 float3x2 transform_geometry;
3091 float4 transform_rtx;
3092 float4 transform_rty;
3094 struct output
3096 float2 p : WORLD_POSITION;
3097 float4 b : BEZIER;
3098 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3099 float4 position : SV_POSITION;
3102 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3104 o.p = mul(float3(position, 1.0f), transform_geometry);
3105 o.b = float4(texcoord, 1.0);
3106 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3107 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3108 * float2(transform_rtx.w, transform_rty.w);
3109 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3111 #endif
3112 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3113 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3114 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3115 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3116 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3117 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3118 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3119 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3120 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3121 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3122 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3123 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3124 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3125 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3126 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3127 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3128 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3129 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3130 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3131 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3132 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3133 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3134 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3135 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3136 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3137 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3138 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3139 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3141 static const DWORD ps_code[] =
3143 #if 0
3144 #define BRUSH_TYPE_SOLID 0
3145 #define BRUSH_TYPE_LINEAR 1
3146 #define BRUSH_TYPE_RADIAL 2
3147 #define BRUSH_TYPE_BITMAP 3
3148 #define BRUSH_TYPE_COUNT 4
3150 bool outline;
3151 struct brush
3153 uint type;
3154 float opacity;
3155 float4 data[3];
3156 } colour_brush, opacity_brush;
3158 SamplerState s0, s1;
3159 Texture2D t0, t1;
3160 Buffer<float4> b0, b1;
3162 struct input
3164 float2 p : WORLD_POSITION;
3165 float4 b : BEZIER;
3166 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3169 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3171 float4 c_low, c_high;
3172 float p_low, p_high;
3173 uint i;
3175 p_low = gradient.Load(0).x;
3176 c_low = gradient.Load(1);
3177 c_high = c_low;
3179 if (position < p_low)
3180 return c_low;
3182 for (i = 1; i < stop_count; ++i)
3184 p_high = gradient.Load(i * 2).x;
3185 c_high = gradient.Load(i * 2 + 1);
3187 if (position >= p_low && position <= p_high)
3188 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3190 p_low = p_high;
3191 c_low = c_high;
3194 return c_high;
3197 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3199 float2 start, end, v_p, v_q;
3200 uint stop_count;
3201 float p;
3203 start = brush.data[0].xy;
3204 end = brush.data[0].zw;
3205 stop_count = asuint(brush.data[1].x);
3207 v_p = position - start;
3208 v_q = end - start;
3209 p = dot(v_q, v_p) / dot(v_q, v_q);
3211 return sample_gradient(gradient, stop_count, p);
3214 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3216 float2 centre, offset, ra, rb, v_p, v_q, r;
3217 float b, c, l, t;
3218 uint stop_count;
3220 centre = brush.data[0].xy;
3221 offset = brush.data[0].zw;
3222 ra = brush.data[1].xy;
3223 rb = brush.data[1].zw;
3224 stop_count = asuint(brush.data[2].x);
3226 /* Project onto ra, rb. */
3227 r = float2(dot(ra, ra), dot(rb, rb));
3228 v_p = position - (centre + offset);
3229 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3230 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3232 /* ‖t·p̂ + q⃑‖ = 1
3233 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3234 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3236 * b = p̂·q⃑
3237 * c = q⃑·q⃑ - 1
3238 * t = -b + √(b² - c) */
3239 l = length(v_p);
3240 b = dot(v_p, v_q) / l;
3241 c = dot(v_q, v_q) - 1.0;
3242 t = -b + sqrt(b * b - c);
3244 return sample_gradient(gradient, stop_count, l / t);
3247 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3249 float3 transform[2];
3250 bool ignore_alpha;
3251 float2 texcoord;
3252 float4 colour;
3254 transform[0] = brush.data[0].xyz;
3255 transform[1] = brush.data[1].xyz;
3256 ignore_alpha = asuint(brush.data[1].w);
3258 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3259 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3260 colour = t.Sample(s, texcoord);
3261 if (ignore_alpha)
3262 colour.a = 1.0;
3263 return colour;
3266 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3268 if (brush.type == BRUSH_TYPE_SOLID)
3269 return brush.data[0] * brush.opacity;
3270 if (brush.type == BRUSH_TYPE_LINEAR)
3271 return brush_linear(brush, b, position) * brush.opacity;
3272 if (brush.type == BRUSH_TYPE_RADIAL)
3273 return brush_radial(brush, b, position) * brush.opacity;
3274 if (brush.type == BRUSH_TYPE_BITMAP)
3275 return brush_bitmap(brush, t, s, position) * brush.opacity;
3276 return float4(0.0, 0.0, 0.0, brush.opacity);
3279 float4 main(struct input i) : SV_Target
3281 float4 colour;
3283 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3284 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3285 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3287 if (outline)
3289 float2 du, dv, df;
3290 float4 uv;
3292 /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
3293 * using the screen-space partial derivatives to convert the calculated
3294 * distance to object space.
3296 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3297 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3298 * f(x, y) = u(x, y)² - v(x, y)
3299 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3300 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
3301 uv = i.b;
3302 du = float2(ddx(uv.x), ddy(uv.x));
3303 dv = float2(ddx(uv.y), ddy(uv.y));
3304 df = 2.0f * uv.x * du - dv;
3306 clip(dot(df, uv.zw));
3307 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3309 else
3311 /* Evaluate the implicit form of the curve in texture space.
3312 * "i.b.z" determines which side of the curve is shaded. */
3313 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3316 return colour;
3318 #endif
3319 0x43425844, 0xf3cbb8bd, 0x5f286454, 0x139976a7, 0x6817e876, 0x00000001, 0x00001d18, 0x00000003,
3320 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3321 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3322 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3323 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3324 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3325 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3326 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001c18,
3327 0x00000040, 0x00000706, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3328 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3329 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3330 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3331 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3332 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3333 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3334 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3335 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3336 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3337 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3338 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3339 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3340 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3341 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3342 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3343 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3344 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3345 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3346 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3347 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3348 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3349 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3350 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3351 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3352 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3353 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3354 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3355 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3356 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3357 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3358 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3359 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3360 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3361 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3362 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3363 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3364 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3365 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3366 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3367 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3368 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3369 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3370 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3371 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3372 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3373 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3374 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3375 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3376 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3377 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3378 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3379 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3380 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3381 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3382 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3383 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3384 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3385 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3386 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3387 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3388 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3389 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3390 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3391 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3392 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3393 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3394 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3395 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3396 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3397 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3398 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3399 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3400 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3401 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3402 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3403 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3404 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3405 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3406 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3407 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3408 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3409 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3410 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3411 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3412 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3413 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3414 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3415 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3416 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3417 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3418 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3419 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3420 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3421 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3422 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3423 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3424 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3425 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3426 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3427 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3428 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3429 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3430 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3431 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3432 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3433 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3434 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3435 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3436 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3437 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3438 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3439 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3440 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3441 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3442 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3443 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3444 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3445 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3446 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3447 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3448 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3449 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3450 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3451 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3452 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3453 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3454 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3455 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3456 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3457 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3458 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3459 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3460 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3461 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3462 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3463 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3464 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3465 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3466 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3467 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3468 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3469 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3470 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3471 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3472 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3473 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3474 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3475 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3476 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3477 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3478 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3479 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3480 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3481 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3482 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3483 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3484 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3485 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3486 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3487 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3488 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3489 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3490 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3491 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3492 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3493 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3494 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3495 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3496 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3497 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3498 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3499 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3500 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3501 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3502 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3503 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3504 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3505 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3506 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3507 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3508 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3509 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3510 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3511 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3512 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3513 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3514 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3515 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3516 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3517 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3518 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3519 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3520 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3521 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3522 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3523 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3524 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3525 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3526 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3527 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3528 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3529 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3530 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3531 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3532 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x08000027, 0x00100012,
3533 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022,
3534 0x00000000, 0x0010000a, 0x00000000, 0x0500000b, 0x00100032, 0x00000001, 0x00101046, 0x00000001,
3535 0x0500000c, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x07000000, 0x00100042, 0x00000000,
3536 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x001000c2, 0x00000000, 0x00100aa6,
3537 0x00000000, 0x00100806, 0x00000001, 0x80100d56, 0x00000041, 0x00000001, 0x0700000f, 0x00100012,
3538 0x00000001, 0x00100ae6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100012, 0x00000001,
3539 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000001, 0x0010000a,
3540 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010000a, 0x00000001, 0x07000038, 0x00100032,
3541 0x00000001, 0x00100ff6, 0x00000000, 0x00101046, 0x00000003, 0x09000032, 0x001000c2, 0x00000000,
3542 0x00101406, 0x00000002, 0x00100aa6, 0x00000000, 0x00100406, 0x00000001, 0x0700000f, 0x00100042,
3543 0x00000000, 0x00100ae6, 0x00000000, 0x00100ae6, 0x00000000, 0x0500004b, 0x00100042, 0x00000000,
3544 0x0010002a, 0x00000000, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a,
3545 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100042, 0x00000000, 0x8010003a,
3546 0x000000c1, 0x00000000, 0x0010002a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010002a,
3547 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000,
3548 0x0010002a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000038, 0x00100012, 0x00000000,
3549 0x0010003a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010000a,
3550 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000,
3551 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x0100003e,
3553 static const struct shape_info
3555 enum d2d_shape_type shape_type;
3556 const D3D10_INPUT_ELEMENT_DESC *il_desc;
3557 unsigned int il_element_count;
3558 const void *vs_code;
3559 size_t vs_code_size;
3561 shape_info[] =
3563 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3564 vs_code_outline, sizeof(vs_code_outline)},
3565 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_bezier_outline, ARRAY_SIZE(il_desc_bezier_outline),
3566 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3567 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3568 vs_code_triangle, sizeof(vs_code_triangle)},
3569 {D2D_SHAPE_TYPE_BEZIER, il_desc_bezier, ARRAY_SIZE(il_desc_bezier),
3570 vs_code_bezier, sizeof(vs_code_bezier)},
3572 static const struct
3574 float x, y;
3576 quad[] =
3578 {-1.0f, 1.0f},
3579 {-1.0f, -1.0f},
3580 { 1.0f, 1.0f},
3581 { 1.0f, -1.0f},
3583 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3585 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3586 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3587 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3588 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3589 render_target->refcount = 1;
3590 ID2D1Device_GetFactory(device, &render_target->factory);
3591 render_target->device = device;
3592 ID2D1Device_AddRef(render_target->device);
3594 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3595 render_target->ops = ops;
3597 device_impl = unsafe_impl_from_ID2D1Device(device);
3598 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3599 &IID_ID3D10Device, (void **)&render_target->d3d_device)))
3601 WARN("Failed to get device interface, hr %#x.\n", hr);
3602 ID2D1Factory_Release(render_target->factory);
3603 return hr;
3606 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
3608 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
3609 goto err;
3612 if (FAILED(hr = D3D10CreateStateBlock(render_target->d3d_device, &state_mask, &render_target->stateblock)))
3614 WARN("Failed to create stateblock, hr %#x.\n", hr);
3615 goto err;
3618 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3620 const struct shape_info *si = &shape_info[i];
3622 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3623 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3625 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3626 goto err;
3629 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->d3d_device, si->vs_code,
3630 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
3632 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3633 goto err;
3638 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->d3d_device,
3639 ps_code, sizeof(ps_code), &render_target->ps)))
3641 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3642 goto err;
3645 buffer_desc.ByteWidth = sizeof(indices);
3646 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
3647 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
3648 buffer_desc.CPUAccessFlags = 0;
3649 buffer_desc.MiscFlags = 0;
3651 buffer_data.pSysMem = indices;
3652 buffer_data.SysMemPitch = 0;
3653 buffer_data.SysMemSlicePitch = 0;
3655 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3656 &buffer_desc, &buffer_data, &render_target->ib)))
3658 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3659 goto err;
3662 buffer_desc.ByteWidth = sizeof(quad);
3663 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
3664 buffer_data.pSysMem = quad;
3666 render_target->vb_stride = sizeof(*quad);
3667 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3668 &buffer_desc, &buffer_data, &render_target->vb)))
3670 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3671 goto err;
3674 rs_desc.FillMode = D3D10_FILL_SOLID;
3675 rs_desc.CullMode = D3D10_CULL_NONE;
3676 rs_desc.FrontCounterClockwise = FALSE;
3677 rs_desc.DepthBias = 0;
3678 rs_desc.DepthBiasClamp = 0.0f;
3679 rs_desc.SlopeScaledDepthBias = 0.0f;
3680 rs_desc.DepthClipEnable = TRUE;
3681 rs_desc.ScissorEnable = TRUE;
3682 rs_desc.MultisampleEnable = FALSE;
3683 rs_desc.AntialiasedLineEnable = FALSE;
3684 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
3686 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3687 goto err;
3690 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3691 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3693 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3694 goto err;
3697 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3698 IDWriteFactory_Release(dwrite_factory);
3699 if (FAILED(hr))
3701 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
3702 goto err;
3705 render_target->drawing_state.transform = identity;
3707 if (!d2d_clip_stack_init(&render_target->clip_stack))
3709 WARN("Failed to initialize clip stack.\n");
3710 hr = E_FAIL;
3711 goto err;
3714 render_target->desc.dpiX = 96.0f;
3715 render_target->desc.dpiY = 96.0f;
3717 return S_OK;
3719 err:
3720 if (render_target->default_text_rendering_params)
3721 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
3722 if (render_target->rs)
3723 ID3D10RasterizerState_Release(render_target->rs);
3724 if (render_target->vb)
3725 ID3D10Buffer_Release(render_target->vb);
3726 if (render_target->ib)
3727 ID3D10Buffer_Release(render_target->ib);
3728 if (render_target->ps)
3729 ID3D10PixelShader_Release(render_target->ps);
3730 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
3732 if (render_target->shape_resources[i].vs)
3733 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
3734 if (render_target->shape_resources[i].il)
3735 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
3737 if (render_target->stateblock)
3738 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
3739 if (render_target->d3d_device)
3740 ID3D10Device_Release(render_target->d3d_device);
3741 ID2D1Device_Release(render_target->device);
3742 ID2D1Factory_Release(render_target->factory);
3743 return hr;
3746 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
3747 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
3749 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
3750 struct d2d_device_context *object;
3751 ID2D1Bitmap1 *bitmap;
3752 HRESULT hr;
3754 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
3755 WARN("Ignoring render target type %#x.\n", desc->type);
3756 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
3757 FIXME("Ignoring render target usage %#x.\n", desc->usage);
3758 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
3759 WARN("Ignoring feature level %#x.\n", desc->minLevel);
3761 bitmap_desc.dpiX = desc->dpiX;
3762 bitmap_desc.dpiY = desc->dpiY;
3764 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
3766 bitmap_desc.dpiX = 96.0f;
3767 bitmap_desc.dpiY = 96.0f;
3769 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
3770 return E_INVALIDARG;
3772 if (!(object = heap_alloc_zero(sizeof(*object))))
3773 return E_OUTOFMEMORY;
3775 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
3777 WARN("Failed to initialize render target, hr %#x.\n", hr);
3778 heap_free(object);
3779 return hr;
3782 if (surface)
3784 bitmap_desc.pixelFormat = desc->pixelFormat;
3785 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
3786 bitmap_desc.colorContext = NULL;
3788 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
3789 surface, &bitmap_desc, &bitmap)))
3791 WARN("Failed to create target bitmap, hr %#x.\n", hr);
3792 IUnknown_Release(&object->IUnknown_iface);
3793 heap_free(object);
3794 return hr;
3797 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
3798 ID2D1Bitmap1_Release(bitmap);
3800 else
3801 object->desc.pixelFormat = desc->pixelFormat;
3803 TRACE("Created render target %p.\n", object);
3804 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
3806 return S_OK;
3809 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
3811 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
3813 if (IsEqualGUID(iid, &IID_ID2D1Device)
3814 || IsEqualGUID(iid, &IID_ID2D1Resource)
3815 || IsEqualGUID(iid, &IID_IUnknown))
3817 ID2D1Device_AddRef(iface);
3818 *out = iface;
3819 return S_OK;
3822 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
3824 *out = NULL;
3825 return E_NOINTERFACE;
3828 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
3830 struct d2d_device *device = impl_from_ID2D1Device(iface);
3831 ULONG refcount = InterlockedIncrement(&device->refcount);
3833 TRACE("%p increasing refcount to %u.\n", iface, refcount);
3835 return refcount;
3838 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
3840 struct d2d_device *device = impl_from_ID2D1Device(iface);
3841 ULONG refcount = InterlockedDecrement(&device->refcount);
3843 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
3845 if (!refcount)
3847 IDXGIDevice_Release(device->dxgi_device);
3848 ID2D1Factory1_Release(device->factory);
3849 heap_free(device);
3852 return refcount;
3855 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
3857 struct d2d_device *device = impl_from_ID2D1Device(iface);
3859 TRACE("iface %p, factory %p.\n", iface, factory);
3861 *factory = (ID2D1Factory *)device->factory;
3862 ID2D1Factory1_AddRef(device->factory);
3865 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
3866 ID2D1DeviceContext **context)
3868 struct d2d_device_context *object;
3869 HRESULT hr;
3871 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
3873 if (options)
3874 FIXME("Options are ignored %#x.\n", options);
3876 if (!(object = heap_alloc_zero(sizeof(*object))))
3877 return E_OUTOFMEMORY;
3879 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
3881 WARN("Failed to initialize device context, hr %#x.\n", hr);
3882 heap_free(object);
3883 return hr;
3886 TRACE("Created device context %p.\n", object);
3887 *context = &object->ID2D1DeviceContext_iface;
3889 return S_OK;
3892 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
3893 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
3894 ID2D1PrintControl **print_control)
3896 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
3897 document_target, desc, print_control);
3899 return E_NOTIMPL;
3902 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
3904 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
3907 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
3909 FIXME("iface %p stub!\n", iface);
3911 return 0;
3914 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
3916 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
3918 return E_NOTIMPL;
3921 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
3923 d2d_device_QueryInterface,
3924 d2d_device_AddRef,
3925 d2d_device_Release,
3926 d2d_device_GetFactory,
3927 d2d_device_CreateDeviceContext,
3928 d2d_device_CreatePrintControl,
3929 d2d_device_SetMaximumTextureMemory,
3930 d2d_device_GetMaximumTextureMemory,
3931 d2d_device_ClearResources,
3934 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
3936 if (!iface)
3937 return NULL;
3938 assert(iface->lpVtbl == &d2d_device_vtbl);
3939 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
3942 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
3944 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
3945 device->refcount = 1;
3946 device->factory = iface;
3947 ID2D1Factory1_AddRef(device->factory);
3948 device->dxgi_device = dxgi_device;
3949 IDXGIDevice_AddRef(device->dxgi_device);