d2d1: Implement ellipse and rounded rectangle stroking with arcs.
[wine.git] / dlls / d2d1 / device.c
blobc3decf6fbdb9daf8930cb14e774a91b2ad38eeaf
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "d2d1_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
23 #define INITIAL_CLIP_STACK_SIZE 4
25 static const D2D1_MATRIX_3X2_F identity =
27 1.0f, 0.0f,
28 0.0f, 1.0f,
29 0.0f, 0.0f,
32 struct d2d_draw_text_layout_ctx
34 ID2D1Brush *brush;
35 D2D1_DRAW_TEXT_OPTIONS options;
38 static inline struct d2d_device *impl_from_ID2D1Device(ID2D1Device *iface)
40 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
43 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface);
45 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
47 ID2D1Brush *brush = NULL;
49 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
50 return brush;
52 ID2D1Brush_AddRef(context->brush);
53 return context->brush;
56 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
58 if (src->left > dst->left)
59 dst->left = src->left;
60 if (src->top > dst->top)
61 dst->top = src->top;
62 if (src->right < dst->right)
63 dst->right = src->right;
64 if (src->bottom < dst->bottom)
65 dst->bottom = src->bottom;
68 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
70 dst->left = left;
71 dst->top = top;
72 dst->right = right;
73 dst->bottom = bottom;
76 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
78 dst->width = width;
79 dst->height = height;
82 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
84 if (!(stack->stack = heap_alloc(INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
85 return FALSE;
87 stack->size = INITIAL_CLIP_STACK_SIZE;
88 stack->count = 0;
90 return TRUE;
93 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
95 heap_free(stack->stack);
98 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
100 D2D1_RECT_F r;
102 if (!d2d_array_reserve((void **)&stack->stack, &stack->size, stack->count + 1, sizeof(*stack->stack)))
103 return FALSE;
105 r = *rect;
106 if (stack->count)
107 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
108 stack->stack[stack->count++] = r;
110 return TRUE;
113 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
115 if (!stack->count)
116 return;
117 --stack->count;
120 static void d2d_device_context_draw(struct d2d_device_context *render_target, enum d2d_shape_type shape_type,
121 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
122 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
124 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
125 ID3D10Device *device = render_target->d3d_device;
126 D3D10_RECT scissor_rect;
127 unsigned int offset;
128 D3D10_VIEWPORT vp;
129 HRESULT hr;
131 vp.TopLeftX = 0;
132 vp.TopLeftY = 0;
133 vp.Width = render_target->pixel_size.width;
134 vp.Height = render_target->pixel_size.height;
135 vp.MinDepth = 0.0f;
136 vp.MaxDepth = 1.0f;
138 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
140 WARN("Failed to capture stateblock, hr %#x.\n", hr);
141 return;
144 ID3D10Device_ClearState(device);
146 ID3D10Device_IASetInputLayout(device, shape_resources->il);
147 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
148 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
149 offset = 0;
150 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
151 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
152 ID3D10Device_VSSetShader(device, shape_resources->vs);
153 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
154 ID3D10Device_PSSetShader(device, render_target->ps);
155 ID3D10Device_RSSetViewports(device, 1, &vp);
156 if (render_target->clip_stack.count)
158 const D2D1_RECT_F *clip_rect;
160 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
161 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
162 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
163 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
164 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
166 else
168 scissor_rect.left = 0.0f;
169 scissor_rect.top = 0.0f;
170 scissor_rect.right = render_target->pixel_size.width;
171 scissor_rect.bottom = render_target->pixel_size.height;
173 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
174 ID3D10Device_RSSetState(device, render_target->rs);
175 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->target->rtv, NULL);
176 if (brush)
178 ID3D10Device_OMSetBlendState(device, render_target->bs, NULL, D3D10_DEFAULT_SAMPLE_MASK);
179 d2d_brush_bind_resources(brush, device, 0);
181 if (opacity_brush)
182 d2d_brush_bind_resources(opacity_brush, device, 1);
184 if (ib)
185 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
186 else
187 ID3D10Device_Draw(device, index_count, 0);
189 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
190 WARN("Failed to apply stateblock, hr %#x.\n", hr);
193 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
195 context->error.code = code;
196 context->error.tag1 = context->drawing_state.tag1;
197 context->error.tag2 = context->drawing_state.tag2;
200 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
202 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
205 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext *iface)
207 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
210 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
212 struct d2d_device_context *context = impl_from_IUnknown(iface);
214 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
216 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext)
217 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
218 || IsEqualGUID(iid, &IID_ID2D1Resource)
219 || IsEqualGUID(iid, &IID_IUnknown))
221 ID2D1DeviceContext_AddRef(&context->ID2D1DeviceContext_iface);
222 *out = &context->ID2D1DeviceContext_iface;
223 return S_OK;
225 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
227 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
228 *out = &context->ID2D1GdiInteropRenderTarget_iface;
229 return S_OK;
232 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
234 *out = NULL;
235 return E_NOINTERFACE;
238 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
240 struct d2d_device_context *context = impl_from_IUnknown(iface);
241 ULONG refcount = InterlockedIncrement(&context->refcount);
243 TRACE("%p increasing refcount to %u.\n", iface, refcount);
245 return refcount;
248 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
250 struct d2d_device_context *context = impl_from_IUnknown(iface);
251 ULONG refcount = InterlockedDecrement(&context->refcount);
253 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
255 if (!refcount)
257 unsigned int i;
259 d2d_clip_stack_cleanup(&context->clip_stack);
260 IDWriteRenderingParams_Release(context->default_text_rendering_params);
261 if (context->text_rendering_params)
262 IDWriteRenderingParams_Release(context->text_rendering_params);
263 if (context->bs)
264 ID3D10BlendState_Release(context->bs);
265 ID3D10RasterizerState_Release(context->rs);
266 ID3D10Buffer_Release(context->vb);
267 ID3D10Buffer_Release(context->ib);
268 ID3D10PixelShader_Release(context->ps);
269 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
271 ID3D10VertexShader_Release(context->shape_resources[i].vs);
272 ID3D10InputLayout_Release(context->shape_resources[i].il);
274 context->stateblock->lpVtbl->Release(context->stateblock);
275 if (context->target)
276 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
277 ID3D10Device_Release(context->d3d_device);
278 ID2D1Factory_Release(context->factory);
279 ID2D1Device_Release(context->device);
280 heap_free(context);
283 return refcount;
286 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
288 d2d_device_context_inner_QueryInterface,
289 d2d_device_context_inner_AddRef,
290 d2d_device_context_inner_Release,
293 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out)
295 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
297 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
299 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
302 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface)
304 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
306 TRACE("iface %p.\n", iface);
308 return IUnknown_AddRef(context->outer_unknown);
311 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface)
313 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
315 TRACE("iface %p.\n", iface);
317 return IUnknown_Release(context->outer_unknown);
320 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext *iface, ID2D1Factory **factory)
322 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
324 TRACE("iface %p, factory %p.\n", iface, factory);
326 *factory = render_target->factory;
327 ID2D1Factory_AddRef(*factory);
330 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext *iface,
331 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
333 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
334 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
335 struct d2d_bitmap *object;
336 HRESULT hr;
338 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
339 iface, size.width, size.height, src_data, pitch, desc, bitmap);
341 if (desc)
343 memcpy(&bitmap_desc, desc, sizeof(*desc));
344 bitmap_desc.bitmapOptions = 0;
345 bitmap_desc.colorContext = NULL;
348 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
349 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
351 return hr;
354 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext *iface,
355 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
357 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
358 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
359 struct d2d_bitmap *object;
360 HRESULT hr;
362 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
363 iface, bitmap_source, desc, bitmap);
365 if (desc)
367 memcpy(&bitmap_desc, desc, sizeof(*desc));
368 bitmap_desc.bitmapOptions = 0;
369 bitmap_desc.colorContext = NULL;
372 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
373 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
375 return hr;
378 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext *iface,
379 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
381 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
382 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
383 struct d2d_bitmap *object;
384 HRESULT hr;
386 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
387 iface, debugstr_guid(iid), data, desc, bitmap);
389 if (desc)
391 memcpy(&bitmap_desc, desc, sizeof(*desc));
392 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
393 bitmap_desc.colorContext = NULL;
396 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
397 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
399 return hr;
402 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext *iface,
403 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
404 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
406 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
407 struct d2d_brush *object;
408 HRESULT hr;
410 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
411 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
413 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
414 brush_desc, &object)))
415 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
417 return hr;
420 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext *iface,
421 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
423 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
424 struct d2d_brush *object;
425 HRESULT hr;
427 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
429 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
430 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
432 return hr;
435 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext *iface,
436 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
437 ID2D1GradientStopCollection **gradient)
439 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
440 struct d2d_gradient *object;
441 HRESULT hr;
443 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
444 iface, stops, stop_count, gamma, extend_mode, gradient);
446 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
447 stops, stop_count, gamma, extend_mode, &object)))
448 *gradient = &object->ID2D1GradientStopCollection_iface;
450 return hr;
453 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext *iface,
454 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
455 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
457 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
458 struct d2d_brush *object;
459 HRESULT hr;
461 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
462 iface, gradient_brush_desc, brush_desc, gradient, brush);
464 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
465 gradient, &object)))
466 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
468 return hr;
471 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext *iface,
472 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
473 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
475 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
476 struct d2d_brush *object;
477 HRESULT hr;
479 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
480 iface, gradient_brush_desc, brush_desc, gradient, brush);
482 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
483 gradient_brush_desc, brush_desc, gradient, &object)))
484 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
486 return hr;
489 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext *iface,
490 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
491 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
493 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
494 struct d2d_bitmap_render_target *object;
495 HRESULT hr;
497 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
498 iface, size, pixel_size, format, options, rt);
500 if (!(object = heap_alloc_zero(sizeof(*object))))
501 return E_OUTOFMEMORY;
503 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
504 format, options)))
506 WARN("Failed to initialize render target, hr %#x.\n", hr);
507 heap_free(object);
508 return hr;
511 TRACE("Created render target %p.\n", object);
512 *rt = &object->ID2D1BitmapRenderTarget_iface;
514 return S_OK;
517 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext *iface,
518 const D2D1_SIZE_F *size, ID2D1Layer **layer)
520 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
521 struct d2d_layer *object;
522 HRESULT hr;
524 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
526 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
527 *layer = &object->ID2D1Layer_iface;
529 return hr;
532 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext *iface, ID2D1Mesh **mesh)
534 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
535 struct d2d_mesh *object;
536 HRESULT hr;
538 TRACE("iface %p, mesh %p.\n", iface, mesh);
540 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
541 *mesh = &object->ID2D1Mesh_iface;
543 return hr;
546 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext *iface,
547 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
549 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
550 ID2D1PathGeometry *geometry;
551 ID2D1GeometrySink *sink;
552 HRESULT hr;
554 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
555 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
557 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
559 WARN("Failed to create path geometry, %#x.\n", hr);
560 return;
563 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
565 WARN("Open() failed, %#x.\n", hr);
566 ID2D1PathGeometry_Release(geometry);
567 return;
570 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
571 ID2D1GeometrySink_AddLine(sink, p1);
572 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
573 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
574 WARN("Close() failed, %#x.\n", hr);
575 ID2D1GeometrySink_Release(sink);
577 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
578 ID2D1PathGeometry_Release(geometry);
581 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext *iface,
582 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
584 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
585 ID2D1RectangleGeometry *geometry;
586 HRESULT hr;
588 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
589 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
591 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
593 ERR("Failed to create geometry, hr %#x.\n", hr);
594 return;
597 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
598 ID2D1RectangleGeometry_Release(geometry);
601 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext *iface,
602 const D2D1_RECT_F *rect, ID2D1Brush *brush)
604 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
605 ID2D1RectangleGeometry *geometry;
606 HRESULT hr;
608 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
610 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
612 ERR("Failed to create geometry, hr %#x.\n", hr);
613 return;
616 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
617 ID2D1RectangleGeometry_Release(geometry);
620 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext *iface,
621 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
623 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
624 ID2D1RoundedRectangleGeometry *geometry;
625 HRESULT hr;
627 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
628 iface, rect, brush, stroke_width, stroke_style);
630 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
632 ERR("Failed to create geometry, hr %#x.\n", hr);
633 return;
636 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
637 ID2D1RoundedRectangleGeometry_Release(geometry);
640 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext *iface,
641 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
643 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
644 ID2D1RoundedRectangleGeometry *geometry;
645 HRESULT hr;
647 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
649 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
651 ERR("Failed to create geometry, hr %#x.\n", hr);
652 return;
655 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
656 ID2D1RoundedRectangleGeometry_Release(geometry);
659 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext *iface,
660 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
662 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
663 ID2D1EllipseGeometry *geometry;
664 HRESULT hr;
666 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
667 iface, ellipse, brush, stroke_width, stroke_style);
669 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
671 ERR("Failed to create geometry, hr %#x.\n", hr);
672 return;
675 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
676 ID2D1EllipseGeometry_Release(geometry);
679 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext *iface,
680 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
682 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
683 ID2D1EllipseGeometry *geometry;
684 HRESULT hr;
686 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
688 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
690 ERR("Failed to create geometry, hr %#x.\n", hr);
691 return;
694 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
695 ID2D1EllipseGeometry_Release(geometry);
698 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
699 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
701 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb_bezier, *ps_cb_arc;
702 D3D10_SUBRESOURCE_DATA buffer_data;
703 D3D10_BUFFER_DESC buffer_desc;
704 const D2D1_MATRIX_3X2_F *w;
705 float tmp_x, tmp_y;
706 HRESULT hr;
707 struct
709 struct
711 float _11, _21, _31, pad0;
712 float _12, _22, _32, stroke_width;
713 } transform_geometry;
714 struct d2d_vec4 transform_rtx;
715 struct d2d_vec4 transform_rty;
716 } vs_cb_data;
718 vs_cb_data.transform_geometry._11 = geometry->transform._11;
719 vs_cb_data.transform_geometry._21 = geometry->transform._21;
720 vs_cb_data.transform_geometry._31 = geometry->transform._31;
721 vs_cb_data.transform_geometry.pad0 = 0.0f;
722 vs_cb_data.transform_geometry._12 = geometry->transform._12;
723 vs_cb_data.transform_geometry._22 = geometry->transform._22;
724 vs_cb_data.transform_geometry._32 = geometry->transform._32;
725 vs_cb_data.transform_geometry.stroke_width = stroke_width;
727 w = &render_target->drawing_state.transform;
729 tmp_x = render_target->desc.dpiX / 96.0f;
730 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
731 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
732 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
733 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
735 tmp_y = render_target->desc.dpiY / 96.0f;
736 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
737 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
738 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
739 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
741 buffer_desc.ByteWidth = sizeof(vs_cb_data);
742 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
743 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
744 buffer_desc.CPUAccessFlags = 0;
745 buffer_desc.MiscFlags = 0;
747 buffer_data.pSysMem = &vs_cb_data;
748 buffer_data.SysMemPitch = 0;
749 buffer_data.SysMemSlicePitch = 0;
751 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
753 WARN("Failed to create constant buffer, hr %#x.\n", hr);
754 return;
757 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, FALSE, render_target, &ps_cb_bezier)))
759 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
760 ID3D10Buffer_Release(vs_cb);
761 return;
764 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, TRUE, render_target, &ps_cb_arc)))
766 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
767 ID3D10Buffer_Release(vs_cb);
768 ID3D10Buffer_Release(ps_cb_bezier);
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_bezier, 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_bezier, brush, NULL);
829 ID3D10Buffer_Release(vb);
830 ID3D10Buffer_Release(ib);
833 if (geometry->outline.arc_face_count)
835 buffer_desc.ByteWidth = geometry->outline.arc_face_count * sizeof(*geometry->outline.arc_faces);
836 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
837 buffer_data.pSysMem = geometry->outline.arc_faces;
839 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
841 WARN("Failed to create arcs index buffer, hr %#x.\n", hr);
842 goto done;
845 buffer_desc.ByteWidth = geometry->outline.arc_count * sizeof(*geometry->outline.arcs);
846 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
847 buffer_data.pSysMem = geometry->outline.arcs;
849 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
851 ERR("Failed to create arcs vertex buffer, hr %#x.\n", hr);
852 ID3D10Buffer_Release(ib);
853 goto done;
856 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
857 3 * geometry->outline.arc_face_count, vb,
858 sizeof(*geometry->outline.arcs), vs_cb, ps_cb_arc, brush, NULL);
860 ID3D10Buffer_Release(vb);
861 ID3D10Buffer_Release(ib);
864 done:
865 ID3D10Buffer_Release(ps_cb_arc);
866 ID3D10Buffer_Release(ps_cb_bezier);
867 ID3D10Buffer_Release(vs_cb);
870 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext *iface,
871 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
873 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
874 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
875 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
877 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
878 iface, geometry, brush, stroke_width, stroke_style);
880 if (stroke_style)
881 FIXME("Ignoring stroke style %p.\n", stroke_style);
883 d2d_device_context_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
886 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
887 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
889 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb_bezier, *ps_cb_arc;
890 D3D10_SUBRESOURCE_DATA buffer_data;
891 D3D10_BUFFER_DESC buffer_desc;
892 D2D1_MATRIX_3X2_F *w;
893 float tmp_x, tmp_y;
894 HRESULT hr;
895 struct
897 struct
899 float _11, _21, _31, pad0;
900 float _12, _22, _32, pad1;
901 } transform_geometry;
902 struct d2d_vec4 transform_rtx;
903 struct d2d_vec4 transform_rty;
904 } vs_cb_data;
906 vs_cb_data.transform_geometry._11 = geometry->transform._11;
907 vs_cb_data.transform_geometry._21 = geometry->transform._21;
908 vs_cb_data.transform_geometry._31 = geometry->transform._31;
909 vs_cb_data.transform_geometry.pad0 = 0.0f;
910 vs_cb_data.transform_geometry._12 = geometry->transform._12;
911 vs_cb_data.transform_geometry._22 = geometry->transform._22;
912 vs_cb_data.transform_geometry._32 = geometry->transform._32;
913 vs_cb_data.transform_geometry.pad1 = 0.0f;
915 w = &render_target->drawing_state.transform;
917 tmp_x = render_target->desc.dpiX / 96.0f;
918 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
919 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
920 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
921 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
923 tmp_y = render_target->desc.dpiY / 96.0f;
924 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
925 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
926 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
927 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
929 buffer_desc.ByteWidth = sizeof(vs_cb_data);
930 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
931 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
932 buffer_desc.CPUAccessFlags = 0;
933 buffer_desc.MiscFlags = 0;
935 buffer_data.pSysMem = &vs_cb_data;
936 buffer_data.SysMemPitch = 0;
937 buffer_data.SysMemSlicePitch = 0;
939 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
941 WARN("Failed to create constant buffer, hr %#x.\n", hr);
942 return;
945 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, FALSE, render_target, &ps_cb_bezier)))
947 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
948 ID3D10Buffer_Release(vs_cb);
949 return;
952 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, TRUE, render_target, &ps_cb_arc)))
954 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
955 ID3D10Buffer_Release(vs_cb);
956 ID3D10Buffer_Release(ps_cb_bezier);
957 return;
960 if (geometry->fill.face_count)
962 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
963 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
964 buffer_data.pSysMem = geometry->fill.faces;
966 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
968 WARN("Failed to create index buffer, hr %#x.\n", hr);
969 goto done;
972 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
973 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
974 buffer_data.pSysMem = geometry->fill.vertices;
976 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
978 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
979 ID3D10Buffer_Release(ib);
980 goto done;
983 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
984 sizeof(*geometry->fill.vertices), vs_cb, ps_cb_bezier, brush, opacity_brush);
986 ID3D10Buffer_Release(vb);
987 ID3D10Buffer_Release(ib);
990 if (geometry->fill.bezier_vertex_count)
992 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
993 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
994 buffer_data.pSysMem = geometry->fill.bezier_vertices;
996 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
998 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
999 goto done;
1002 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.bezier_vertex_count, vb,
1003 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb_bezier, brush, opacity_brush);
1005 ID3D10Buffer_Release(vb);
1008 if (geometry->fill.arc_vertex_count)
1010 buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices);
1011 buffer_data.pSysMem = geometry->fill.arc_vertices;
1013 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1015 ERR("Failed to create arc vertex buffer, hr %#x.\n", hr);
1016 goto done;
1019 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
1020 sizeof(*geometry->fill.arc_vertices), vs_cb, ps_cb_arc, brush, opacity_brush);
1022 ID3D10Buffer_Release(vb);
1025 done:
1026 ID3D10Buffer_Release(ps_cb_arc);
1027 ID3D10Buffer_Release(ps_cb_bezier);
1028 ID3D10Buffer_Release(vs_cb);
1031 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
1032 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
1034 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
1035 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
1036 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1037 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
1039 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
1041 if (FAILED(context->error.code))
1042 return;
1044 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
1046 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
1047 return;
1050 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
1053 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext *iface,
1054 ID2D1Mesh *mesh, ID2D1Brush *brush)
1056 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1059 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext *iface,
1060 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1061 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1063 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1064 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1067 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1068 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1069 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
1071 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1072 D2D1_BRUSH_PROPERTIES brush_desc;
1073 struct d2d_brush *brush;
1074 D2D1_RECT_F s, d;
1075 HRESULT hr;
1077 if (perspective_transform)
1078 FIXME("Perspective transform is ignored.\n");
1080 if (src_rect)
1082 s = *src_rect;
1084 else
1086 D2D1_SIZE_F size;
1088 size = ID2D1Bitmap_GetSize(bitmap);
1089 s.left = 0.0f;
1090 s.top = 0.0f;
1091 s.right = size.width;
1092 s.bottom = size.height;
1095 if (dst_rect)
1097 d = *dst_rect;
1099 else
1101 d.left = 0.0f;
1102 d.top = 0.0f;
1103 d.right = s.right - s.left;
1104 d.bottom = s.bottom - s.top;
1107 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1108 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1109 bitmap_brush_desc.interpolationMode = interpolation_mode;
1111 brush_desc.opacity = opacity;
1112 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1113 brush_desc.transform._21 = 0.0f;
1114 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1115 brush_desc.transform._12 = 0.0f;
1116 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1117 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1119 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1121 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
1122 return;
1125 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext_iface, &d, &brush->ID2D1Brush_iface);
1126 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1129 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext *iface,
1130 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1131 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1133 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1135 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1136 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1138 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1139 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1141 d2d_device_context_set_error(context, E_INVALIDARG);
1142 return;
1145 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect, NULL);
1148 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext *iface,
1149 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1150 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1152 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1153 IDWriteTextLayout *text_layout;
1154 IDWriteFactory *dwrite_factory;
1155 D2D1_POINT_2F origin;
1156 HRESULT hr;
1158 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1159 "brush %p, options %#x, measuring_mode %#x.\n",
1160 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1161 brush, options, measuring_mode);
1163 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1164 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1166 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1167 return;
1170 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1171 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1172 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
1173 else
1174 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1175 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
1176 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1177 IDWriteFactory_Release(dwrite_factory);
1178 if (FAILED(hr))
1180 ERR("Failed to create text layout, hr %#x.\n", hr);
1181 return;
1184 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
1185 ID2D1DeviceContext_DrawTextLayout(iface, origin, text_layout, brush, options);
1186 IDWriteTextLayout_Release(text_layout);
1189 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext *iface,
1190 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1192 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1193 struct d2d_draw_text_layout_ctx ctx;
1194 HRESULT hr;
1196 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1197 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1199 ctx.brush = brush;
1200 ctx.options = options;
1202 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1203 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1204 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1207 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1209 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1210 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1211 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1212 return prev_antialias_mode;
1215 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1216 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1218 D2D1_MATRIX_3X2_F *transform, prev_transform;
1219 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1220 ID2D1PathGeometry *geometry;
1221 ID2D1GeometrySink *sink;
1222 HRESULT hr;
1224 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1226 ERR("Failed to create geometry, hr %#x.\n", hr);
1227 return;
1230 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1232 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1233 ID2D1PathGeometry_Release(geometry);
1234 return;
1237 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1238 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1239 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1241 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1242 ID2D1GeometrySink_Release(sink);
1243 ID2D1PathGeometry_Release(geometry);
1244 return;
1247 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1248 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1249 ID2D1GeometrySink_Release(sink);
1251 transform = &render_target->drawing_state.transform;
1252 prev_transform = *transform;
1253 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1254 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1255 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1256 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1257 unsafe_impl_from_ID2D1Brush(brush), NULL);
1258 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1259 *transform = prev_transform;
1261 ID2D1PathGeometry_Release(geometry);
1264 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1265 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1266 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1267 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1269 ID2D1RectangleGeometry *geometry = NULL;
1270 ID2D1BitmapBrush *opacity_brush = NULL;
1271 D2D1_BITMAP_PROPERTIES bitmap_desc;
1272 ID2D1Bitmap *opacity_bitmap = NULL;
1273 IDWriteGlyphRunAnalysis *analysis;
1274 DWRITE_TEXTURE_TYPE texture_type;
1275 D2D1_BRUSH_PROPERTIES brush_desc;
1276 IDWriteFactory2 *dwrite_factory;
1277 D2D1_MATRIX_3X2_F *transform, m;
1278 void *opacity_values = NULL;
1279 size_t opacity_values_size;
1280 D2D1_SIZE_U bitmap_size;
1281 float scale_x, scale_y;
1282 D2D1_RECT_F run_rect;
1283 RECT bounds;
1284 HRESULT hr;
1286 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1287 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1289 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1290 return;
1293 transform = &render_target->drawing_state.transform;
1295 scale_x = render_target->desc.dpiX / 96.0f;
1296 m._11 = transform->_11 * scale_x;
1297 m._21 = transform->_21 * scale_x;
1298 m._31 = transform->_31 * scale_x;
1300 scale_y = render_target->desc.dpiY / 96.0f;
1301 m._12 = transform->_12 * scale_y;
1302 m._22 = transform->_22 * scale_y;
1303 m._32 = transform->_32 * scale_y;
1305 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1306 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1307 baseline_origin.x, baseline_origin.y, &analysis);
1308 IDWriteFactory2_Release(dwrite_factory);
1309 if (FAILED(hr))
1311 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1312 return;
1315 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1316 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1317 else
1318 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1320 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1322 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1323 goto done;
1326 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1327 if (!bitmap_size.width || !bitmap_size.height)
1329 /* Empty run, nothing to do. */
1330 goto done;
1333 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1334 bitmap_size.width *= 3;
1335 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1337 ERR("Failed to allocate opacity values.\n");
1338 goto done;
1340 opacity_values_size = bitmap_size.height * bitmap_size.width;
1342 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1343 texture_type, &bounds, opacity_values, opacity_values_size)))
1345 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1346 goto done;
1349 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1350 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1351 bitmap_desc.dpiX = render_target->desc.dpiX;
1352 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1353 bitmap_desc.dpiX *= 3.0f;
1354 bitmap_desc.dpiY = render_target->desc.dpiY;
1355 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext_iface,
1356 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1358 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1359 goto done;
1362 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1363 bounds.right / scale_x, bounds.bottom / scale_y);
1365 brush_desc.opacity = 1.0f;
1366 brush_desc.transform._11 = 1.0f;
1367 brush_desc.transform._12 = 0.0f;
1368 brush_desc.transform._21 = 0.0f;
1369 brush_desc.transform._22 = 1.0f;
1370 brush_desc.transform._31 = run_rect.left;
1371 brush_desc.transform._32 = run_rect.top;
1372 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext_iface,
1373 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1375 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1376 goto done;
1379 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1381 ERR("Failed to create geometry, hr %#x.\n", hr);
1382 goto done;
1385 m = *transform;
1386 *transform = identity;
1387 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1388 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1389 *transform = m;
1391 done:
1392 if (geometry)
1393 ID2D1RectangleGeometry_Release(geometry);
1394 if (opacity_brush)
1395 ID2D1BitmapBrush_Release(opacity_brush);
1396 if (opacity_bitmap)
1397 ID2D1Bitmap_Release(opacity_bitmap);
1398 heap_free(opacity_values);
1399 IDWriteGlyphRunAnalysis_Release(analysis);
1402 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext *iface,
1403 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1404 DWRITE_MEASURING_MODE measuring_mode)
1406 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1407 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1409 ID2D1DeviceContext_DrawGlyphRun(iface, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1412 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext *iface,
1413 const D2D1_MATRIX_3X2_F *transform)
1415 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1417 TRACE("iface %p, transform %p.\n", iface, transform);
1419 render_target->drawing_state.transform = *transform;
1422 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext *iface,
1423 D2D1_MATRIX_3X2_F *transform)
1425 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1427 TRACE("iface %p, transform %p.\n", iface, transform);
1429 *transform = render_target->drawing_state.transform;
1432 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext *iface,
1433 D2D1_ANTIALIAS_MODE antialias_mode)
1435 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1437 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1439 render_target->drawing_state.antialiasMode = antialias_mode;
1442 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext *iface)
1444 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1446 TRACE("iface %p.\n", iface);
1448 return render_target->drawing_state.antialiasMode;
1451 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext *iface,
1452 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1454 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1456 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1458 render_target->drawing_state.textAntialiasMode = antialias_mode;
1461 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext *iface)
1463 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1465 TRACE("iface %p.\n", iface);
1467 return render_target->drawing_state.textAntialiasMode;
1470 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext *iface,
1471 IDWriteRenderingParams *text_rendering_params)
1473 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1475 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1477 if (text_rendering_params)
1478 IDWriteRenderingParams_AddRef(text_rendering_params);
1479 if (render_target->text_rendering_params)
1480 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1481 render_target->text_rendering_params = text_rendering_params;
1484 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext *iface,
1485 IDWriteRenderingParams **text_rendering_params)
1487 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1489 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1491 if ((*text_rendering_params = render_target->text_rendering_params))
1492 IDWriteRenderingParams_AddRef(*text_rendering_params);
1495 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1497 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1499 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1501 render_target->drawing_state.tag1 = tag1;
1502 render_target->drawing_state.tag2 = tag2;
1505 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1507 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1509 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1511 *tag1 = render_target->drawing_state.tag1;
1512 *tag2 = render_target->drawing_state.tag2;
1515 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext *iface,
1516 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1518 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1521 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *iface)
1523 FIXME("iface %p stub!\n", iface);
1526 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1528 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1530 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1532 if (context->ops && context->ops->device_context_present)
1533 context->ops->device_context_present(context->outer_unknown);
1535 return E_NOTIMPL;
1538 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext *iface,
1539 ID2D1DrawingStateBlock *state_block)
1541 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1542 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1544 TRACE("iface %p, state_block %p.\n", iface, state_block);
1546 state_block_impl->drawing_state = render_target->drawing_state;
1547 if (render_target->text_rendering_params)
1548 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1549 if (state_block_impl->text_rendering_params)
1550 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1551 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1554 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext *iface,
1555 ID2D1DrawingStateBlock *state_block)
1557 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1558 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1560 TRACE("iface %p, state_block %p.\n", iface, state_block);
1562 render_target->drawing_state = state_block_impl->drawing_state;
1563 if (state_block_impl->text_rendering_params)
1564 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1565 if (render_target->text_rendering_params)
1566 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1567 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1570 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext *iface,
1571 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1573 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1574 D2D1_RECT_F transformed_rect;
1575 float x_scale, y_scale;
1576 D2D1_POINT_2F point;
1578 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1580 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1581 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1583 x_scale = render_target->desc.dpiX / 96.0f;
1584 y_scale = render_target->desc.dpiY / 96.0f;
1585 d2d_point_transform(&point, &render_target->drawing_state.transform,
1586 clip_rect->left * x_scale, clip_rect->top * y_scale);
1587 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1588 d2d_point_transform(&point, &render_target->drawing_state.transform,
1589 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1590 d2d_rect_expand(&transformed_rect, &point);
1591 d2d_point_transform(&point, &render_target->drawing_state.transform,
1592 clip_rect->right * x_scale, clip_rect->top * y_scale);
1593 d2d_rect_expand(&transformed_rect, &point);
1594 d2d_point_transform(&point, &render_target->drawing_state.transform,
1595 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1596 d2d_rect_expand(&transformed_rect, &point);
1598 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1599 WARN("Failed to push clip rect.\n");
1602 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext *iface)
1604 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1606 TRACE("iface %p.\n", iface);
1608 d2d_clip_stack_pop(&render_target->clip_stack);
1611 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface, const D2D1_COLOR_F *colour)
1613 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1614 D3D10_SUBRESOURCE_DATA buffer_data;
1615 struct d2d_ps_cb ps_cb_data = {0};
1616 D3D10_BUFFER_DESC buffer_desc;
1617 ID3D10Buffer *vs_cb, *ps_cb;
1618 D2D1_COLOR_F *c;
1619 HRESULT hr;
1621 static const struct
1623 struct
1625 float _11, _21, _31, pad0;
1626 float _12, _22, _32, pad1;
1627 } transform_geometry;
1628 struct d2d_vec4 transform_rtx;
1629 struct d2d_vec4 transform_rty;
1631 vs_cb_data =
1633 {1.0f, 0.0f, 0.0f, 0.0f,
1634 0.0f, 1.0f, 0.0f, 0.0f},
1635 {1.0f, 0.0f, 1.0f, 1.0f},
1636 {0.0f, 1.0f, 1.0f, -1.0f},
1639 TRACE("iface %p, colour %p.\n", iface, colour);
1641 buffer_desc.ByteWidth = sizeof(vs_cb_data);
1642 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1643 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1644 buffer_desc.CPUAccessFlags = 0;
1645 buffer_desc.MiscFlags = 0;
1647 buffer_data.pSysMem = &vs_cb_data;
1648 buffer_data.SysMemPitch = 0;
1649 buffer_data.SysMemSlicePitch = 0;
1651 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
1653 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1654 return;
1657 ps_cb_data.outline = FALSE;
1658 ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1659 ps_cb_data.colour_brush.opacity = 1.0f;
1660 c = &ps_cb_data.colour_brush.u.solid.colour;
1661 if (colour)
1662 *c = *colour;
1663 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1664 c->a = 1.0f;
1665 c->r *= c->a;
1666 c->g *= c->a;
1667 c->b *= c->a;
1669 ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1671 buffer_desc.ByteWidth = sizeof(ps_cb_data);
1672 buffer_data.pSysMem = &ps_cb_data;
1674 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ps_cb)))
1676 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1677 ID3D10Buffer_Release(vs_cb);
1678 return;
1681 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1682 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1684 ID3D10Buffer_Release(ps_cb);
1685 ID3D10Buffer_Release(vs_cb);
1688 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
1690 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1692 TRACE("iface %p.\n", iface);
1694 memset(&render_target->error, 0, sizeof(render_target->error));
1697 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface,
1698 D2D1_TAG *tag1, D2D1_TAG *tag2)
1700 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1701 HRESULT hr;
1703 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1705 if (tag1)
1706 *tag1 = context->error.tag1;
1707 if (tag2)
1708 *tag2 = context->error.tag2;
1710 if (context->ops && context->ops->device_context_present)
1712 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1713 context->error.code = hr;
1716 return context->error.code;
1719 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface,
1720 D2D1_PIXEL_FORMAT *format)
1722 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1724 TRACE("iface %p, format %p.\n", iface, format);
1726 *format = render_target->desc.pixelFormat;
1727 return format;
1730 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext *iface, float dpi_x, float dpi_y)
1732 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1734 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1736 if (dpi_x == 0.0f && dpi_y == 0.0f)
1738 dpi_x = 96.0f;
1739 dpi_y = 96.0f;
1741 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1742 return;
1744 render_target->desc.dpiX = dpi_x;
1745 render_target->desc.dpiY = dpi_y;
1748 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext *iface, float *dpi_x, float *dpi_y)
1750 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1752 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1754 *dpi_x = render_target->desc.dpiX;
1755 *dpi_y = render_target->desc.dpiY;
1758 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext *iface, D2D1_SIZE_F *size)
1760 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1762 TRACE("iface %p, size %p.\n", iface, size);
1764 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1765 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1766 return size;
1769 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext *iface,
1770 D2D1_SIZE_U *pixel_size)
1772 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1774 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1776 *pixel_size = render_target->pixel_size;
1777 return pixel_size;
1780 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext *iface)
1782 TRACE("iface %p.\n", iface);
1784 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1787 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext *iface,
1788 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1790 FIXME("iface %p, desc %p stub!\n", iface, desc);
1792 return FALSE;
1795 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext *iface,
1796 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
1797 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1799 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1800 struct d2d_bitmap *object;
1801 HRESULT hr;
1803 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
1804 iface, size.width, size.height, src_data, pitch, desc, bitmap);
1806 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
1807 *bitmap = &object->ID2D1Bitmap1_iface;
1809 return hr;
1812 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
1813 ID2D1DeviceContext *iface, IWICBitmapSource *bitmap_source,
1814 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1816 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1817 struct d2d_bitmap *object;
1818 HRESULT hr;
1820 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
1822 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
1823 *bitmap = &object->ID2D1Bitmap1_iface;
1825 return hr;
1828 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext *iface,
1829 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
1831 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
1832 iface, space, profile, profile_size, color_context);
1834 return E_NOTIMPL;
1837 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext *iface,
1838 const WCHAR *filename, ID2D1ColorContext **color_context)
1840 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
1842 return E_NOTIMPL;
1845 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext *iface,
1846 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
1848 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
1850 return E_NOTIMPL;
1853 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
1854 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1856 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1857 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
1858 struct d2d_bitmap *object;
1859 HRESULT hr;
1861 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
1863 if (!desc)
1865 DXGI_SURFACE_DESC surface_desc;
1867 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1869 WARN("Failed to get surface desc, hr %#x.\n", hr);
1870 return hr;
1873 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
1874 bitmap_desc.pixelFormat.format = surface_desc.Format;
1875 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1876 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
1877 desc = &bitmap_desc;
1880 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
1881 *bitmap = &object->ID2D1Bitmap1_iface;
1883 return hr;
1886 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
1887 REFCLSID effect_id, ID2D1Effect **effect)
1889 struct d2d_effect *object;
1891 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1893 if (!(object = heap_alloc_zero(sizeof(*object))))
1894 return E_OUTOFMEMORY;
1896 d2d_effect_init(object);
1898 TRACE("Created effect %p.\n", object);
1899 *effect = &object->ID2D1Effect_iface;
1901 return S_OK;
1904 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1905 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1906 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1907 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1908 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1910 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1911 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1912 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1913 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1915 return E_NOTIMPL;
1918 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1919 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1920 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1922 FIXME("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p stub!\n",
1923 iface, image, image_brush_desc, brush_desc, brush);
1925 return E_NOTIMPL;
1928 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1929 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1930 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1932 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1933 struct d2d_brush *object;
1934 HRESULT hr;
1936 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1937 brush_desc, brush);
1939 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1940 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1942 return hr;
1945 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1946 ID2D1CommandList **command_list)
1948 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1950 return E_NOTIMPL;
1953 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1955 FIXME("iface %p, format %#x stub!\n", iface, format);
1957 return FALSE;
1960 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1961 D2D1_BUFFER_PRECISION buffer_precision)
1963 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1965 return FALSE;
1968 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1969 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1971 FIXME("iface %p, image %p, local_bounds %p stub!\n", iface, image, local_bounds);
1974 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
1975 ID2D1Image *image, D2D1_RECT_F *world_bounds)
1977 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
1979 return E_NOTIMPL;
1982 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
1983 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1984 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
1986 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
1987 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
1989 return E_NOTIMPL;
1992 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
1994 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1996 TRACE("iface %p, device %p.\n", iface, device);
1998 *device = context->device;
1999 ID2D1Device_AddRef(*device);
2002 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2004 if (!context->target)
2005 return;
2007 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
2008 context->target = NULL;
2010 /* Note that DPI settings are kept. */
2011 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2012 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2014 ID3D10BlendState_Release(context->bs);
2015 context->bs = NULL;
2018 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
2020 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2021 struct d2d_bitmap *bitmap_impl;
2022 D3D10_BLEND_DESC blend_desc;
2023 ID2D1Bitmap *bitmap;
2024 HRESULT hr;
2026 TRACE("iface %p, target %p.\n", iface, target);
2028 if (!target)
2030 d2d_device_context_reset_target(context);
2031 return;
2034 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2036 FIXME("Only bitmap targets are supported.\n");
2037 return;
2040 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2042 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2044 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2045 return;
2048 d2d_device_context_reset_target(context);
2050 /* Set sizes and pixel format. */
2051 context->pixel_size = bitmap_impl->pixel_size;
2052 context->desc.pixelFormat = bitmap_impl->format;
2053 context->target = bitmap_impl;
2055 memset(&blend_desc, 0, sizeof(blend_desc));
2056 blend_desc.BlendEnable[0] = TRUE;
2057 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2058 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2059 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2060 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2062 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2063 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2065 else
2067 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2068 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2070 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2071 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2072 if (FAILED(hr = ID3D10Device_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2073 WARN("Failed to create blend state, hr %#x.\n", hr);
2076 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2078 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2080 TRACE("iface %p, target %p.\n", iface, target);
2082 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2083 if (*target)
2084 ID2D1Image_AddRef(*target);
2087 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2088 const D2D1_RENDERING_CONTROLS *rendering_controls)
2090 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2093 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2094 D2D1_RENDERING_CONTROLS *rendering_controls)
2096 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2099 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2100 D2D1_PRIMITIVE_BLEND primitive_blend)
2102 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2105 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2107 FIXME("iface %p stub!\n", iface);
2109 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2112 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2114 FIXME("iface %p, unit_mode %#x stub!\n", iface, unit_mode);
2117 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2119 FIXME("iface %p stub!\n", iface);
2121 return D2D1_UNIT_MODE_DIPS;
2124 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2125 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2126 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2128 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
2129 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2130 IDWriteRenderingParams *rendering_params;
2131 DWRITE_RENDERING_MODE rendering_mode;
2132 HRESULT hr;
2134 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2135 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2137 if (FAILED(context->error.code))
2138 return;
2140 rendering_params = context->text_rendering_params ? context->text_rendering_params
2141 : context->default_text_rendering_params;
2143 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
2145 switch (context->drawing_state.textAntialiasMode)
2147 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2148 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
2149 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
2150 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
2151 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
2152 d2d_device_context_set_error(context, E_INVALIDARG);
2153 break;
2155 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2156 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
2157 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2158 d2d_device_context_set_error(context, E_INVALIDARG);
2159 break;
2161 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
2162 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
2163 d2d_device_context_set_error(context, E_INVALIDARG);
2164 break;
2166 default:
2167 break;
2170 if (FAILED(context->error.code))
2171 return;
2173 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
2174 switch (context->drawing_state.textAntialiasMode)
2176 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
2177 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
2178 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2179 break;
2181 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2182 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2183 break;
2185 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2186 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
2187 break;
2189 default:
2190 break;
2193 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2195 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
2196 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
2197 measuring_mode, rendering_params, &rendering_mode)))
2199 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
2200 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
2204 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2205 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
2206 else
2207 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
2208 rendering_mode, measuring_mode, antialias_mode);
2211 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2212 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2213 D2D1_COMPOSITE_MODE composite_mode)
2215 FIXME("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x stub!\n",
2216 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2217 interpolation_mode, composite_mode);
2220 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2221 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2223 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2224 iface, metafile, debug_d2d_point_2f(target_offset));
2227 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2228 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2229 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2231 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2233 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2234 "src_rect %s, perspective_transform %p.\n",
2235 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2236 debug_d2d_rect_f(src_rect), perspective_transform);
2238 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2239 perspective_transform);
2242 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2243 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2245 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2248 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2249 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2251 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2252 iface, effect, input, debug_d2d_rect_f(input_rect));
2254 return E_NOTIMPL;
2257 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2258 ID2D1Effect *effect, UINT32 *rect_count)
2260 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2262 return E_NOTIMPL;
2265 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2266 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2268 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2270 return E_NOTIMPL;
2273 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2274 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2275 D2D1_RECT_F *input_rect, UINT32 input_count)
2277 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2278 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2280 return E_NOTIMPL;
2283 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2284 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2286 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2287 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2290 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2292 d2d_device_context_QueryInterface,
2293 d2d_device_context_AddRef,
2294 d2d_device_context_Release,
2295 d2d_device_context_GetFactory,
2296 d2d_device_context_CreateBitmap,
2297 d2d_device_context_CreateBitmapFromWicBitmap,
2298 d2d_device_context_CreateSharedBitmap,
2299 d2d_device_context_CreateBitmapBrush,
2300 d2d_device_context_CreateSolidColorBrush,
2301 d2d_device_context_CreateGradientStopCollection,
2302 d2d_device_context_CreateLinearGradientBrush,
2303 d2d_device_context_CreateRadialGradientBrush,
2304 d2d_device_context_CreateCompatibleRenderTarget,
2305 d2d_device_context_CreateLayer,
2306 d2d_device_context_CreateMesh,
2307 d2d_device_context_DrawLine,
2308 d2d_device_context_DrawRectangle,
2309 d2d_device_context_FillRectangle,
2310 d2d_device_context_DrawRoundedRectangle,
2311 d2d_device_context_FillRoundedRectangle,
2312 d2d_device_context_DrawEllipse,
2313 d2d_device_context_FillEllipse,
2314 d2d_device_context_DrawGeometry,
2315 d2d_device_context_FillGeometry,
2316 d2d_device_context_FillMesh,
2317 d2d_device_context_FillOpacityMask,
2318 d2d_device_context_DrawBitmap,
2319 d2d_device_context_DrawText,
2320 d2d_device_context_DrawTextLayout,
2321 d2d_device_context_DrawGlyphRun,
2322 d2d_device_context_SetTransform,
2323 d2d_device_context_GetTransform,
2324 d2d_device_context_SetAntialiasMode,
2325 d2d_device_context_GetAntialiasMode,
2326 d2d_device_context_SetTextAntialiasMode,
2327 d2d_device_context_GetTextAntialiasMode,
2328 d2d_device_context_SetTextRenderingParams,
2329 d2d_device_context_GetTextRenderingParams,
2330 d2d_device_context_SetTags,
2331 d2d_device_context_GetTags,
2332 d2d_device_context_PushLayer,
2333 d2d_device_context_PopLayer,
2334 d2d_device_context_Flush,
2335 d2d_device_context_SaveDrawingState,
2336 d2d_device_context_RestoreDrawingState,
2337 d2d_device_context_PushAxisAlignedClip,
2338 d2d_device_context_PopAxisAlignedClip,
2339 d2d_device_context_Clear,
2340 d2d_device_context_BeginDraw,
2341 d2d_device_context_EndDraw,
2342 d2d_device_context_GetPixelFormat,
2343 d2d_device_context_SetDpi,
2344 d2d_device_context_GetDpi,
2345 d2d_device_context_GetSize,
2346 d2d_device_context_GetPixelSize,
2347 d2d_device_context_GetMaximumBitmapSize,
2348 d2d_device_context_IsSupported,
2349 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2350 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2351 d2d_device_context_CreateColorContext,
2352 d2d_device_context_CreateColorContextFromFilename,
2353 d2d_device_context_CreateColorContextFromWicColorContext,
2354 d2d_device_context_CreateBitmapFromDxgiSurface,
2355 d2d_device_context_CreateEffect,
2356 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2357 d2d_device_context_CreateImageBrush,
2358 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2359 d2d_device_context_CreateCommandList,
2360 d2d_device_context_IsDxgiFormatSupported,
2361 d2d_device_context_IsBufferPrecisionSupported,
2362 d2d_device_context_GetImageLocalBounds,
2363 d2d_device_context_GetImageWorldBounds,
2364 d2d_device_context_GetGlyphRunWorldBounds,
2365 d2d_device_context_GetDevice,
2366 d2d_device_context_SetTarget,
2367 d2d_device_context_GetTarget,
2368 d2d_device_context_SetRenderingControls,
2369 d2d_device_context_GetRenderingControls,
2370 d2d_device_context_SetPrimitiveBlend,
2371 d2d_device_context_GetPrimitiveBlend,
2372 d2d_device_context_SetUnitMode,
2373 d2d_device_context_GetUnitMode,
2374 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2375 d2d_device_context_DrawImage,
2376 d2d_device_context_DrawGdiMetafile,
2377 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2378 d2d_device_context_ID2D1DeviceContext_PushLayer,
2379 d2d_device_context_InvalidateEffectInputRectangle,
2380 d2d_device_context_GetEffectInvalidRectangleCount,
2381 d2d_device_context_GetEffectInvalidRectangles,
2382 d2d_device_context_GetEffectRequiredInputRectangles,
2383 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2386 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2388 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2391 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2393 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2395 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2396 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2397 || IsEqualGUID(iid, &IID_IUnknown))
2399 IDWriteTextRenderer_AddRef(iface);
2400 *out = iface;
2401 return S_OK;
2404 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2406 *out = NULL;
2407 return E_NOINTERFACE;
2410 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2412 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2414 TRACE("iface %p.\n", iface);
2416 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2419 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2421 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2423 TRACE("iface %p.\n", iface);
2425 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2428 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2429 void *ctx, BOOL *disabled)
2431 struct d2d_draw_text_layout_ctx *context = ctx;
2433 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2435 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2437 return S_OK;
2440 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2441 void *ctx, DWRITE_MATRIX *transform)
2443 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2445 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2447 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2449 return S_OK;
2452 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2454 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2456 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2458 *ppd = render_target->desc.dpiY / 96.0f;
2460 return S_OK;
2463 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2464 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2465 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2467 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2468 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2469 struct d2d_draw_text_layout_ctx *context = ctx;
2470 BOOL color_font = FALSE;
2471 ID2D1Brush *brush;
2473 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2474 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2475 iface, ctx, baseline_origin_x, baseline_origin_y,
2476 measuring_mode, glyph_run, desc, effect);
2478 if (desc)
2479 WARN("Ignoring glyph run description %p.\n", desc);
2480 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2481 FIXME("Ignoring options %#x.\n", context->options);
2483 brush = d2d_draw_get_text_brush(context, effect);
2485 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2487 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2489 IDWriteFontFace2 *fontface;
2491 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2492 &IID_IDWriteFontFace2, (void **)&fontface)))
2494 color_font = IDWriteFontFace2_IsColorFont(fontface);
2495 IDWriteFontFace2_Release(fontface);
2499 if (color_font)
2501 IDWriteColorGlyphRunEnumerator *layers;
2502 IDWriteFactory2 *dwrite_factory;
2503 HRESULT hr;
2505 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2506 (IUnknown **)&dwrite_factory)))
2508 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2509 ID2D1Brush_Release(brush);
2510 return hr;
2513 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2514 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2515 IDWriteFactory2_Release(dwrite_factory);
2516 if (FAILED(hr))
2518 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
2519 ID2D1Brush_Release(brush);
2520 return hr;
2523 for (;;)
2525 const DWRITE_COLOR_GLYPH_RUN *color_run;
2526 ID2D1Brush *color_brush;
2527 D2D1_POINT_2F origin;
2528 BOOL has_run = FALSE;
2530 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2532 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
2533 break;
2536 if (!has_run)
2537 break;
2539 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2541 ERR("Failed to get current color run, hr %#x.\n", hr);
2542 break;
2545 if (color_run->paletteIndex == 0xffff)
2546 color_brush = brush;
2547 else
2549 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2550 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2552 ERR("Failed to create solid color brush, hr %#x.\n", hr);
2553 break;
2557 origin.x = color_run->baselineOriginX;
2558 origin.y = color_run->baselineOriginY;
2559 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2560 origin, &color_run->glyphRun, color_brush, measuring_mode);
2562 if (color_brush != brush)
2563 ID2D1Brush_Release(color_brush);
2566 IDWriteColorGlyphRunEnumerator_Release(layers);
2568 else
2569 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2570 baseline_origin, glyph_run, brush, measuring_mode);
2572 ID2D1Brush_Release(brush);
2574 return S_OK;
2577 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2578 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2580 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2581 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2582 struct d2d_draw_text_layout_ctx *context = ctx;
2583 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2584 D2D1_POINT_2F start, end;
2585 ID2D1Brush *brush;
2586 float thickness;
2588 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2589 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2591 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2592 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2593 underline->thickness);
2595 brush = d2d_draw_get_text_brush(context, effect);
2597 start.x = baseline_origin_x;
2598 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2599 end.x = start.x + underline->width;
2600 end.y = start.y;
2601 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2602 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2603 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2605 ID2D1Brush_Release(brush);
2607 return S_OK;
2610 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2611 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2613 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2614 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2615 struct d2d_draw_text_layout_ctx *context = ctx;
2616 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2617 D2D1_POINT_2F start, end;
2618 ID2D1Brush *brush;
2619 float thickness;
2621 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2622 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2624 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2625 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2626 strikethrough->thickness);
2628 brush = d2d_draw_get_text_brush(context, effect);
2630 start.x = baseline_origin_x;
2631 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2632 end.x = start.x + strikethrough->width;
2633 end.y = start.y;
2634 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2635 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2636 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2638 ID2D1Brush_Release(brush);
2640 return S_OK;
2643 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2644 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2646 struct d2d_draw_text_layout_ctx *context = ctx;
2647 ID2D1Brush *brush;
2648 HRESULT hr;
2650 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2651 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2653 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2654 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2655 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2656 brush is selected at Direct2D level. */
2657 brush = context->brush;
2658 context->brush = d2d_draw_get_text_brush(context, effect);
2660 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2662 ID2D1Brush_Release(context->brush);
2663 context->brush = brush;
2665 return hr;
2668 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2670 d2d_text_renderer_QueryInterface,
2671 d2d_text_renderer_AddRef,
2672 d2d_text_renderer_Release,
2673 d2d_text_renderer_IsPixelSnappingDisabled,
2674 d2d_text_renderer_GetCurrentTransform,
2675 d2d_text_renderer_GetPixelsPerDip,
2676 d2d_text_renderer_DrawGlyphRun,
2677 d2d_text_renderer_DrawUnderline,
2678 d2d_text_renderer_DrawStrikethrough,
2679 d2d_text_renderer_DrawInlineObject,
2682 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2684 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2687 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2688 REFIID iid, void **out)
2690 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2692 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2694 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2697 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2699 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2701 TRACE("iface %p.\n", iface);
2703 return IUnknown_AddRef(render_target->outer_unknown);
2706 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2708 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2710 TRACE("iface %p.\n", iface);
2712 return IUnknown_Release(render_target->outer_unknown);
2715 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2717 ID3D10Resource *resource;
2718 HRESULT hr;
2720 ID3D10RenderTargetView_GetResource(render_target->target->rtv, &resource);
2721 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2722 ID3D10Resource_Release(resource);
2723 if (FAILED(hr))
2725 *surface = NULL;
2726 WARN("Failed to get DXGI surface, %#x.\n", hr);
2727 return hr;
2730 return hr;
2733 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2734 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2736 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2737 IDXGISurface1 *surface;
2738 HRESULT hr;
2740 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2742 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2743 return hr;
2745 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2746 IDXGISurface1_Release(surface);
2748 return hr;
2751 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2752 const RECT *update)
2754 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2755 IDXGISurface1 *surface;
2756 RECT update_rect;
2757 HRESULT hr;
2759 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2761 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2762 return hr;
2764 if (update)
2765 update_rect = *update;
2766 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2767 IDXGISurface1_Release(surface);
2769 return hr;
2772 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2774 d2d_gdi_interop_render_target_QueryInterface,
2775 d2d_gdi_interop_render_target_AddRef,
2776 d2d_gdi_interop_render_target_Release,
2777 d2d_gdi_interop_render_target_GetDC,
2778 d2d_gdi_interop_render_target_ReleaseDC,
2781 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2782 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2784 D3D10_SUBRESOURCE_DATA buffer_data;
2785 D3D10_STATE_BLOCK_MASK state_mask;
2786 struct d2d_device *device_impl;
2787 IDWriteFactory *dwrite_factory;
2788 D3D10_RASTERIZER_DESC rs_desc;
2789 D3D10_BUFFER_DESC buffer_desc;
2790 unsigned int i;
2791 HRESULT hr;
2793 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2795 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2796 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2797 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2799 static const D3D10_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
2801 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2802 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2803 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2804 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2805 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2806 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2808 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2810 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2812 static const D3D10_INPUT_ELEMENT_DESC il_desc_curve[] =
2814 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2815 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2817 static const DWORD vs_code_outline[] =
2819 #if 0
2820 float3x2 transform_geometry;
2821 float stroke_width;
2822 float4 transform_rtx;
2823 float4 transform_rty;
2825 struct output
2827 float2 p : WORLD_POSITION;
2828 float4 b : BEZIER;
2829 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2830 float4 position : SV_POSITION;
2833 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2835 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2837 * Where:
2839 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2840 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2841 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2842 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2844 float2 q_prev, q_next, v_p, q_i;
2845 float2x2 geom;
2846 float l;
2848 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2850 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2851 q_prev = normalize(mul(geom, prev));
2852 q_next = normalize(mul(geom, next));
2854 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2855 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2856 v_p = float2(-q_prev.y, q_prev.x);
2857 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2858 q_i = l * q_prev + v_p;
2860 o.b = float4(0.0, 0.0, 0.0, 0.0);
2862 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2863 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2864 * float2(transform_rtx.w, transform_rty.w);
2865 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2867 #endif
2868 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2869 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2870 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2871 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2872 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2873 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2874 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2875 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2876 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2877 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2878 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2879 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2880 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2881 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2882 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2883 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2884 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2885 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2886 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2887 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2888 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2889 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2890 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2891 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2892 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2893 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2894 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2895 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2896 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2897 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2898 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2899 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2900 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2901 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2902 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2903 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2904 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2905 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2906 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2907 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2908 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2909 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2910 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2911 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2912 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2913 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2914 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2915 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2916 0x3f800000, 0x0100003e,
2918 /* ⎡p0.x p0.y 1⎤
2919 * A = ⎢p1.x p1.y 1⎥
2920 * ⎣p2.x p2.y 1⎦
2922 * ⎡0 0⎤
2923 * B = ⎢½ 0⎥
2924 * ⎣1 1⎦
2926 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2927 * ⎣p2.x-p0.x p2.y-p0.y⎦
2929 * B' = ⎡½ 0⎤
2930 * ⎣1 1⎦
2932 * A'T = B'
2933 * T = A'⁻¹B'
2935 static const DWORD vs_code_bezier_outline[] =
2937 #if 0
2938 float3x2 transform_geometry;
2939 float stroke_width;
2940 float4 transform_rtx;
2941 float4 transform_rty;
2943 struct output
2945 float2 p : WORLD_POSITION;
2946 float4 b : BEZIER;
2947 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2948 float4 position : SV_POSITION;
2951 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2952 float2 prev : PREV, float2 next : NEXT, out struct output o)
2954 float2 q_prev, q_next, v_p, q_i, p;
2955 float2x2 geom, rt;
2956 float l;
2958 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2959 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2960 o.stroke_transform = rt * stroke_width * 0.5f;
2962 p = mul(geom, position);
2963 p0 = mul(geom, p0);
2964 p1 = mul(geom, p1);
2965 p2 = mul(geom, p2);
2967 p -= p0;
2968 p1 -= p0;
2969 p2 -= p0;
2971 q_prev = normalize(mul(geom, prev));
2972 q_next = normalize(mul(geom, next));
2974 v_p = float2(-q_prev.y, q_prev.x);
2975 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2976 q_i = l * q_prev + v_p;
2977 p += 0.5f * stroke_width * q_i;
2979 v_p = mul(rt, p2);
2980 v_p = normalize(float2(-v_p.y, v_p.x));
2981 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
2983 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
2984 o.b.y = dot(mul(rt, p), v_p);
2986 else
2988 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
2989 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
2990 o.b.x = dot(v_p, p1 - 0.5f * p2);
2991 o.b.y = dot(v_p, p1);
2994 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
2995 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2996 * float2(transform_rtx.w, transform_rty.w);
2997 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2999 #endif
3000 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3001 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3002 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3003 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3004 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3005 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3006 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3007 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3008 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3009 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3010 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3011 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3012 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3013 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3014 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3015 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3016 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3017 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3018 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3019 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3020 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3021 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3022 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3023 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3024 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3025 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3026 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3027 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3028 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3029 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3030 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3031 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3032 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3033 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3034 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3035 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3036 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3037 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3038 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3039 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3040 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3041 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3042 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3043 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3044 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3045 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3046 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3047 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3048 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3049 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3050 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3051 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3052 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3053 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3054 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3055 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3056 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3057 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3058 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3059 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3060 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3061 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3062 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3063 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3064 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3065 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3066 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3067 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3068 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3069 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3070 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3071 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3072 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3073 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3074 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3075 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3076 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3077 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3078 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3079 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3080 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3081 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3082 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3083 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3084 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3085 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3086 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3087 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3089 /* ⎡p0.x p0.y 1⎤
3090 * A = ⎢p1.x p1.y 1⎥
3091 * ⎣p2.x p2.y 1⎦
3093 * ⎡1 0⎤
3094 * B = ⎢1 1⎥
3095 * ⎣0 1⎦
3097 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3098 * ⎣p2.x-p0.x p2.y-p0.y⎦
3100 * B' = ⎡ 0 1⎤
3101 * ⎣-1 1⎦
3103 * A'T = B'
3104 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3106 static const DWORD vs_code_arc_outline[] =
3108 #if 0
3109 float3x2 transform_geometry;
3110 float stroke_width;
3111 float4 transform_rtx;
3112 float4 transform_rty;
3114 struct output
3116 float2 p : WORLD_POSITION;
3117 float4 b : BEZIER;
3118 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3119 float4 position : SV_POSITION;
3122 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3123 float2 prev : PREV, float2 next : NEXT, out struct output o)
3125 float2 q_prev, q_next, v_p, q_i, p;
3126 float2x2 geom, rt, p_inv;
3127 float l;
3128 float a;
3129 float2 bc;
3131 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3132 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3133 o.stroke_transform = rt * stroke_width * 0.5f;
3135 p = mul(geom, position);
3136 p0 = mul(geom, p0);
3137 p1 = mul(geom, p1);
3138 p2 = mul(geom, p2);
3140 p -= p0;
3141 p1 -= p0;
3142 p2 -= p0;
3144 q_prev = normalize(mul(geom, prev));
3145 q_next = normalize(mul(geom, next));
3147 v_p = float2(-q_prev.y, q_prev.x);
3148 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3149 q_i = l * q_prev + v_p;
3150 p += 0.5f * stroke_width * q_i;
3152 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3153 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3154 o.b.zw = 0.0f;
3156 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3157 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3158 * float2(transform_rtx.w, transform_rty.w);
3159 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3161 #endif
3162 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3163 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3164 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3165 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3166 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3167 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3168 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3169 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3170 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3171 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3172 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3173 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3174 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3175 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3176 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3177 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3178 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3179 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3180 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3181 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3182 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3183 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3184 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3185 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3186 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3187 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3188 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3189 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3190 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3191 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3192 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3193 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3194 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3195 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3196 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3197 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3198 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3199 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3200 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3201 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3202 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3203 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3204 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3205 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3206 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3207 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3208 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3209 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3210 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3211 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3212 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3213 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3214 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3215 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3216 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3217 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3218 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3219 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3220 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3221 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3222 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3223 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3224 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3225 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3226 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3227 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3228 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3229 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3230 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3231 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3232 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3233 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3234 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3235 0x0100003e,
3237 static const DWORD vs_code_triangle[] =
3239 #if 0
3240 float3x2 transform_geometry;
3241 float4 transform_rtx;
3242 float4 transform_rty;
3244 struct output
3246 float2 p : WORLD_POSITION;
3247 float4 b : BEZIER;
3248 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3249 float4 position : SV_POSITION;
3252 void main(float2 position : POSITION, out struct output o)
3254 o.p = mul(float3(position, 1.0f), transform_geometry);
3255 o.b = float4(1.0, 0.0, 1.0, 1.0);
3256 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3257 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3258 * float2(transform_rtx.w, transform_rty.w);
3259 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3261 #endif
3262 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3263 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3264 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3265 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3266 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3267 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3268 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3269 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3270 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3271 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3272 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3273 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3274 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3275 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3276 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3277 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3278 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3279 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3280 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3281 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3282 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3283 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3284 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3285 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3286 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3287 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3288 0x00000000, 0x3f800000, 0x0100003e,
3290 static const DWORD vs_code_curve[] =
3292 #if 0
3293 float3x2 transform_geometry;
3294 float4 transform_rtx;
3295 float4 transform_rty;
3297 struct output
3299 float2 p : WORLD_POSITION;
3300 float4 b : BEZIER;
3301 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3302 float4 position : SV_POSITION;
3305 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3307 o.p = mul(float3(position, 1.0f), transform_geometry);
3308 o.b = float4(texcoord, 1.0);
3309 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3310 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3311 * float2(transform_rtx.w, transform_rty.w);
3312 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3314 #endif
3315 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3316 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3317 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3318 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3319 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3320 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3321 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3322 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3323 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3324 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3325 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3326 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3327 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3328 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3329 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3330 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3331 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3332 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3333 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3334 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3335 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3336 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3337 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3338 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3339 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3340 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3341 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3342 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3344 static const DWORD ps_code[] =
3346 #if 0
3347 #define BRUSH_TYPE_SOLID 0
3348 #define BRUSH_TYPE_LINEAR 1
3349 #define BRUSH_TYPE_RADIAL 2
3350 #define BRUSH_TYPE_BITMAP 3
3351 #define BRUSH_TYPE_COUNT 4
3353 bool outline;
3354 bool is_arc;
3355 struct brush
3357 uint type;
3358 float opacity;
3359 float4 data[3];
3360 } colour_brush, opacity_brush;
3362 SamplerState s0, s1;
3363 Texture2D t0, t1;
3364 Buffer<float4> b0, b1;
3366 struct input
3368 float2 p : WORLD_POSITION;
3369 float4 b : BEZIER;
3370 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3373 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3375 float4 c_low, c_high;
3376 float p_low, p_high;
3377 uint i;
3379 p_low = gradient.Load(0).x;
3380 c_low = gradient.Load(1);
3381 c_high = c_low;
3383 if (position < p_low)
3384 return c_low;
3386 for (i = 1; i < stop_count; ++i)
3388 p_high = gradient.Load(i * 2).x;
3389 c_high = gradient.Load(i * 2 + 1);
3391 if (position >= p_low && position <= p_high)
3392 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3394 p_low = p_high;
3395 c_low = c_high;
3398 return c_high;
3401 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3403 float2 start, end, v_p, v_q;
3404 uint stop_count;
3405 float p;
3407 start = brush.data[0].xy;
3408 end = brush.data[0].zw;
3409 stop_count = asuint(brush.data[1].x);
3411 v_p = position - start;
3412 v_q = end - start;
3413 p = dot(v_q, v_p) / dot(v_q, v_q);
3415 return sample_gradient(gradient, stop_count, p);
3418 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3420 float2 centre, offset, ra, rb, v_p, v_q, r;
3421 float b, c, l, t;
3422 uint stop_count;
3424 centre = brush.data[0].xy;
3425 offset = brush.data[0].zw;
3426 ra = brush.data[1].xy;
3427 rb = brush.data[1].zw;
3428 stop_count = asuint(brush.data[2].x);
3430 /* Project onto ra, rb. */
3431 r = float2(dot(ra, ra), dot(rb, rb));
3432 v_p = position - (centre + offset);
3433 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3434 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3436 /* ‖t·p̂ + q⃑‖ = 1
3437 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3438 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3440 * b = p̂·q⃑
3441 * c = q⃑·q⃑ - 1
3442 * t = -b + √(b² - c) */
3443 l = length(v_p);
3444 b = dot(v_p, v_q) / l;
3445 c = dot(v_q, v_q) - 1.0;
3446 t = -b + sqrt(b * b - c);
3448 return sample_gradient(gradient, stop_count, l / t);
3451 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3453 float3 transform[2];
3454 bool ignore_alpha;
3455 float2 texcoord;
3456 float4 colour;
3458 transform[0] = brush.data[0].xyz;
3459 transform[1] = brush.data[1].xyz;
3460 ignore_alpha = asuint(brush.data[1].w);
3462 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3463 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3464 colour = t.Sample(s, texcoord);
3465 if (ignore_alpha)
3466 colour.a = 1.0;
3467 return colour;
3470 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3472 if (brush.type == BRUSH_TYPE_SOLID)
3473 return brush.data[0] * brush.opacity;
3474 if (brush.type == BRUSH_TYPE_LINEAR)
3475 return brush_linear(brush, b, position) * brush.opacity;
3476 if (brush.type == BRUSH_TYPE_RADIAL)
3477 return brush_radial(brush, b, position) * brush.opacity;
3478 if (brush.type == BRUSH_TYPE_BITMAP)
3479 return brush_bitmap(brush, t, s, position) * brush.opacity;
3480 return float4(0.0, 0.0, 0.0, brush.opacity);
3483 float4 main(struct input i) : SV_Target
3485 float4 colour;
3487 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3488 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3489 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3491 if (outline)
3493 float2 du, dv, df;
3494 float4 uv;
3496 /* Evaluate the implicit form of the curve (u² - v = 0
3497 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3498 * space, using the screen-space partial derivatives
3499 * to convert the calculated distance to object space.
3501 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3502 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3504 * For Béziers:
3505 * f(x, y) = u(x, y)² - v(x, y)
3506 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3507 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3509 * For arcs:
3510 * f(x, y) = u(x, y)² + v(x, y)² - 1
3511 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3512 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3513 uv = i.b;
3514 du = float2(ddx(uv.x), ddy(uv.x));
3515 dv = float2(ddx(uv.y), ddy(uv.y));
3517 if (!is_arc)
3519 df = 2.0f * uv.x * du - dv;
3521 clip(dot(df, uv.zw));
3522 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3524 else
3526 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3528 clip(dot(df, uv.zw));
3529 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3532 else
3534 /* Evaluate the implicit form of the curve in texture space.
3535 * "i.b.z" determines which side of the curve is shaded. */
3536 if (!is_arc)
3538 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3540 else
3542 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3546 return colour;
3548 #endif
3549 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3550 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3551 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3552 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3553 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3554 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3555 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3556 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3557 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3558 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3559 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3560 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3561 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3562 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3563 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3564 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3565 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3566 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3567 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3568 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3569 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3570 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3571 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3572 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3573 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3574 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3575 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3576 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3577 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3578 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3579 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3580 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3581 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3582 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3583 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3584 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3585 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3586 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3587 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3588 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3589 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3590 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3591 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3592 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3593 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3594 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3595 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3596 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3597 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3598 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3599 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3600 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3601 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3602 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3603 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3604 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3605 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3606 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3607 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3608 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3609 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3610 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3611 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3612 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3613 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3614 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3615 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3616 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3617 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3618 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3619 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3620 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3621 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3622 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3623 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3624 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3625 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3626 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3627 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3628 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3629 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3630 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3631 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3632 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3633 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3634 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3635 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3636 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3637 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3638 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3639 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3640 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3641 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3642 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3643 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3644 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3645 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3646 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3647 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3648 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3649 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3650 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3651 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3652 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3653 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3654 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3655 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3656 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3657 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3658 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3659 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3660 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3661 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3662 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3663 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3664 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3665 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3666 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3667 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3668 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3669 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3670 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3671 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3672 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3673 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3674 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3675 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3676 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3677 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3678 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3679 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3680 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3681 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3682 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3683 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3684 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3685 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3686 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3687 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3688 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3689 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3690 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3691 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3692 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3693 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3694 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3695 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3696 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3697 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3698 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3699 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3700 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3701 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3702 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3703 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3704 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3705 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3706 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3707 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3708 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3709 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3710 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3711 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3712 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3713 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3714 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3715 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3716 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3717 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3718 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3719 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3720 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3721 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3722 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3723 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3724 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3725 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3726 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3727 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3728 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3729 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3730 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3731 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3732 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3733 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3734 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3735 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3736 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3737 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3738 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3739 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3740 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3741 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3742 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3743 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3744 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3745 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3746 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3747 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3748 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3749 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3750 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3751 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3752 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3753 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3754 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3755 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3756 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3757 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3758 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3759 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3760 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3761 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3762 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
3763 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
3764 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
3765 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
3766 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
3767 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
3768 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
3769 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
3770 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3771 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
3772 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
3773 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
3774 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
3775 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
3776 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
3777 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
3778 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
3779 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
3780 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
3781 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
3782 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
3783 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
3784 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
3785 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
3786 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
3787 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
3788 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
3789 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
3790 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
3791 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3792 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
3793 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
3794 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
3795 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
3796 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
3797 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
3798 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
3799 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
3800 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
3801 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
3802 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
3803 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
3804 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
3806 static const struct shape_info
3808 enum d2d_shape_type shape_type;
3809 const D3D10_INPUT_ELEMENT_DESC *il_desc;
3810 unsigned int il_element_count;
3811 const void *vs_code;
3812 size_t vs_code_size;
3814 shape_info[] =
3816 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3817 vs_code_outline, sizeof(vs_code_outline)},
3818 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3819 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3820 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3821 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
3822 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3823 vs_code_triangle, sizeof(vs_code_triangle)},
3824 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
3825 vs_code_curve, sizeof(vs_code_curve)},
3827 static const struct
3829 float x, y;
3831 quad[] =
3833 {-1.0f, 1.0f},
3834 {-1.0f, -1.0f},
3835 { 1.0f, 1.0f},
3836 { 1.0f, -1.0f},
3838 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3840 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3841 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3842 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3843 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3844 render_target->refcount = 1;
3845 ID2D1Device_GetFactory(device, &render_target->factory);
3846 render_target->device = device;
3847 ID2D1Device_AddRef(render_target->device);
3849 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3850 render_target->ops = ops;
3852 device_impl = unsafe_impl_from_ID2D1Device(device);
3853 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3854 &IID_ID3D10Device, (void **)&render_target->d3d_device)))
3856 WARN("Failed to get device interface, hr %#x.\n", hr);
3857 ID2D1Factory_Release(render_target->factory);
3858 return hr;
3861 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
3863 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
3864 goto err;
3867 if (FAILED(hr = D3D10CreateStateBlock(render_target->d3d_device, &state_mask, &render_target->stateblock)))
3869 WARN("Failed to create stateblock, hr %#x.\n", hr);
3870 goto err;
3873 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3875 const struct shape_info *si = &shape_info[i];
3877 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3878 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3880 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3881 goto err;
3884 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->d3d_device, si->vs_code,
3885 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
3887 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3888 goto err;
3893 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->d3d_device,
3894 ps_code, sizeof(ps_code), &render_target->ps)))
3896 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3897 goto err;
3900 buffer_desc.ByteWidth = sizeof(indices);
3901 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
3902 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
3903 buffer_desc.CPUAccessFlags = 0;
3904 buffer_desc.MiscFlags = 0;
3906 buffer_data.pSysMem = indices;
3907 buffer_data.SysMemPitch = 0;
3908 buffer_data.SysMemSlicePitch = 0;
3910 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3911 &buffer_desc, &buffer_data, &render_target->ib)))
3913 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3914 goto err;
3917 buffer_desc.ByteWidth = sizeof(quad);
3918 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
3919 buffer_data.pSysMem = quad;
3921 render_target->vb_stride = sizeof(*quad);
3922 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3923 &buffer_desc, &buffer_data, &render_target->vb)))
3925 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3926 goto err;
3929 rs_desc.FillMode = D3D10_FILL_SOLID;
3930 rs_desc.CullMode = D3D10_CULL_NONE;
3931 rs_desc.FrontCounterClockwise = FALSE;
3932 rs_desc.DepthBias = 0;
3933 rs_desc.DepthBiasClamp = 0.0f;
3934 rs_desc.SlopeScaledDepthBias = 0.0f;
3935 rs_desc.DepthClipEnable = TRUE;
3936 rs_desc.ScissorEnable = TRUE;
3937 rs_desc.MultisampleEnable = FALSE;
3938 rs_desc.AntialiasedLineEnable = FALSE;
3939 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
3941 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3942 goto err;
3945 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3946 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3948 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3949 goto err;
3952 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3953 IDWriteFactory_Release(dwrite_factory);
3954 if (FAILED(hr))
3956 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
3957 goto err;
3960 render_target->drawing_state.transform = identity;
3962 if (!d2d_clip_stack_init(&render_target->clip_stack))
3964 WARN("Failed to initialize clip stack.\n");
3965 hr = E_FAIL;
3966 goto err;
3969 render_target->desc.dpiX = 96.0f;
3970 render_target->desc.dpiY = 96.0f;
3972 return S_OK;
3974 err:
3975 if (render_target->default_text_rendering_params)
3976 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
3977 if (render_target->rs)
3978 ID3D10RasterizerState_Release(render_target->rs);
3979 if (render_target->vb)
3980 ID3D10Buffer_Release(render_target->vb);
3981 if (render_target->ib)
3982 ID3D10Buffer_Release(render_target->ib);
3983 if (render_target->ps)
3984 ID3D10PixelShader_Release(render_target->ps);
3985 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
3987 if (render_target->shape_resources[i].vs)
3988 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
3989 if (render_target->shape_resources[i].il)
3990 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
3992 if (render_target->stateblock)
3993 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
3994 if (render_target->d3d_device)
3995 ID3D10Device_Release(render_target->d3d_device);
3996 ID2D1Device_Release(render_target->device);
3997 ID2D1Factory_Release(render_target->factory);
3998 return hr;
4001 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4002 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4004 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4005 struct d2d_device_context *object;
4006 ID2D1Bitmap1 *bitmap;
4007 HRESULT hr;
4009 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4010 WARN("Ignoring render target type %#x.\n", desc->type);
4011 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4012 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4013 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4014 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4016 bitmap_desc.dpiX = desc->dpiX;
4017 bitmap_desc.dpiY = desc->dpiY;
4019 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4021 bitmap_desc.dpiX = 96.0f;
4022 bitmap_desc.dpiY = 96.0f;
4024 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4025 return E_INVALIDARG;
4027 if (!(object = heap_alloc_zero(sizeof(*object))))
4028 return E_OUTOFMEMORY;
4030 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4032 WARN("Failed to initialize render target, hr %#x.\n", hr);
4033 heap_free(object);
4034 return hr;
4037 ID2D1DeviceContext_SetDpi(&object->ID2D1DeviceContext_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4039 if (surface)
4041 bitmap_desc.pixelFormat = desc->pixelFormat;
4042 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4043 bitmap_desc.colorContext = NULL;
4045 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
4046 surface, &bitmap_desc, &bitmap)))
4048 WARN("Failed to create target bitmap, hr %#x.\n", hr);
4049 IUnknown_Release(&object->IUnknown_iface);
4050 heap_free(object);
4051 return hr;
4054 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
4055 ID2D1Bitmap1_Release(bitmap);
4057 else
4058 object->desc.pixelFormat = desc->pixelFormat;
4060 TRACE("Created render target %p.\n", object);
4061 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
4063 return S_OK;
4066 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
4068 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4070 if (IsEqualGUID(iid, &IID_ID2D1Device)
4071 || IsEqualGUID(iid, &IID_ID2D1Resource)
4072 || IsEqualGUID(iid, &IID_IUnknown))
4074 ID2D1Device_AddRef(iface);
4075 *out = iface;
4076 return S_OK;
4079 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4081 *out = NULL;
4082 return E_NOINTERFACE;
4085 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
4087 struct d2d_device *device = impl_from_ID2D1Device(iface);
4088 ULONG refcount = InterlockedIncrement(&device->refcount);
4090 TRACE("%p increasing refcount to %u.\n", iface, refcount);
4092 return refcount;
4095 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
4097 struct d2d_device *device = impl_from_ID2D1Device(iface);
4098 ULONG refcount = InterlockedDecrement(&device->refcount);
4100 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
4102 if (!refcount)
4104 IDXGIDevice_Release(device->dxgi_device);
4105 ID2D1Factory1_Release(device->factory);
4106 heap_free(device);
4109 return refcount;
4112 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
4114 struct d2d_device *device = impl_from_ID2D1Device(iface);
4116 TRACE("iface %p, factory %p.\n", iface, factory);
4118 *factory = (ID2D1Factory *)device->factory;
4119 ID2D1Factory1_AddRef(device->factory);
4122 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4123 ID2D1DeviceContext **context)
4125 struct d2d_device_context *object;
4126 HRESULT hr;
4128 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4130 if (options)
4131 FIXME("Options are ignored %#x.\n", options);
4133 if (!(object = heap_alloc_zero(sizeof(*object))))
4134 return E_OUTOFMEMORY;
4136 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
4138 WARN("Failed to initialize device context, hr %#x.\n", hr);
4139 heap_free(object);
4140 return hr;
4143 TRACE("Created device context %p.\n", object);
4144 *context = &object->ID2D1DeviceContext_iface;
4146 return S_OK;
4149 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
4150 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4151 ID2D1PrintControl **print_control)
4153 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4154 document_target, desc, print_control);
4156 return E_NOTIMPL;
4159 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
4161 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4164 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
4166 FIXME("iface %p stub!\n", iface);
4168 return 0;
4171 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
4173 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4175 return E_NOTIMPL;
4178 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
4180 d2d_device_QueryInterface,
4181 d2d_device_AddRef,
4182 d2d_device_Release,
4183 d2d_device_GetFactory,
4184 d2d_device_CreateDeviceContext,
4185 d2d_device_CreatePrintControl,
4186 d2d_device_SetMaximumTextureMemory,
4187 d2d_device_GetMaximumTextureMemory,
4188 d2d_device_ClearResources,
4191 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
4193 if (!iface)
4194 return NULL;
4195 assert(iface->lpVtbl == &d2d_device_vtbl);
4196 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
4199 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4201 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
4202 device->refcount = 1;
4203 device->factory = iface;
4204 ID2D1Factory1_AddRef(device->factory);
4205 device->dxgi_device = dxgi_device;
4206 IDXGIDevice_AddRef(device->dxgi_device);