windowscodecs: Correctly set pixel format of uncompressed DDS images.
[wine.git] / dlls / d2d1 / device.c
blob3c8431ce8f44a5010764bab22e5dd7cd7e300353
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "d2d1_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
23 #define INITIAL_CLIP_STACK_SIZE 4
25 static const D2D1_MATRIX_3X2_F identity =
26 {{{
27 1.0f, 0.0f,
28 0.0f, 1.0f,
29 0.0f, 0.0f,
30 }}};
32 struct d2d_draw_text_layout_ctx
34 ID2D1Brush *brush;
35 D2D1_DRAW_TEXT_OPTIONS options;
38 static inline struct d2d_device *impl_from_ID2D1Device(ID2D1Device *iface)
40 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
43 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface);
45 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
47 ID2D1Brush *brush = NULL;
49 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
50 return brush;
52 ID2D1Brush_AddRef(context->brush);
53 return context->brush;
56 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
58 if (src->left > dst->left)
59 dst->left = src->left;
60 if (src->top > dst->top)
61 dst->top = src->top;
62 if (src->right < dst->right)
63 dst->right = src->right;
64 if (src->bottom < dst->bottom)
65 dst->bottom = src->bottom;
68 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
70 dst->left = left;
71 dst->top = top;
72 dst->right = right;
73 dst->bottom = bottom;
76 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
78 dst->width = width;
79 dst->height = height;
82 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
84 if (!(stack->stack = heap_alloc(INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
85 return FALSE;
87 stack->size = INITIAL_CLIP_STACK_SIZE;
88 stack->count = 0;
90 return TRUE;
93 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
95 heap_free(stack->stack);
98 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
100 D2D1_RECT_F r;
102 if (!d2d_array_reserve((void **)&stack->stack, &stack->size, stack->count + 1, sizeof(*stack->stack)))
103 return FALSE;
105 r = *rect;
106 if (stack->count)
107 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
108 stack->stack[stack->count++] = r;
110 return TRUE;
113 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
115 if (!stack->count)
116 return;
117 --stack->count;
120 static void d2d_device_context_draw(struct d2d_device_context *render_target, enum d2d_shape_type shape_type,
121 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_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
1012 buffer_data.pSysMem = geometry->fill.arc_vertices;
1014 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1016 ERR("Failed to create arc vertex buffer, hr %#x.\n", hr);
1017 goto done;
1020 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
1021 sizeof(*geometry->fill.arc_vertices), vs_cb, ps_cb_arc, brush, opacity_brush);
1023 ID3D10Buffer_Release(vb);
1026 done:
1027 ID3D10Buffer_Release(ps_cb_arc);
1028 ID3D10Buffer_Release(ps_cb_bezier);
1029 ID3D10Buffer_Release(vs_cb);
1032 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
1033 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
1035 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
1036 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
1037 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1038 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
1040 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
1042 if (FAILED(context->error.code))
1043 return;
1045 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
1047 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
1048 return;
1051 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
1054 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext *iface,
1055 ID2D1Mesh *mesh, ID2D1Brush *brush)
1057 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1060 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext *iface,
1061 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1062 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1064 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1065 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1068 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1069 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1070 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
1072 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1073 D2D1_BRUSH_PROPERTIES brush_desc;
1074 struct d2d_brush *brush;
1075 D2D1_RECT_F s, d;
1076 HRESULT hr;
1078 if (perspective_transform)
1079 FIXME("Perspective transform is ignored.\n");
1081 if (src_rect)
1083 s = *src_rect;
1085 else
1087 D2D1_SIZE_F size;
1089 size = ID2D1Bitmap_GetSize(bitmap);
1090 s.left = 0.0f;
1091 s.top = 0.0f;
1092 s.right = size.width;
1093 s.bottom = size.height;
1096 if (dst_rect)
1098 d = *dst_rect;
1100 else
1102 d.left = 0.0f;
1103 d.top = 0.0f;
1104 d.right = s.right - s.left;
1105 d.bottom = s.bottom - s.top;
1108 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1109 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1110 bitmap_brush_desc.interpolationMode = interpolation_mode;
1112 brush_desc.opacity = opacity;
1113 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1114 brush_desc.transform._21 = 0.0f;
1115 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1116 brush_desc.transform._12 = 0.0f;
1117 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1118 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1120 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1122 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
1123 return;
1126 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext_iface, &d, &brush->ID2D1Brush_iface);
1127 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1130 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext *iface,
1131 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1132 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1134 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1136 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1137 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1139 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1140 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1142 d2d_device_context_set_error(context, E_INVALIDARG);
1143 return;
1146 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
1147 src_rect, NULL);
1150 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext *iface,
1151 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1152 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1154 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1155 IDWriteTextLayout *text_layout;
1156 IDWriteFactory *dwrite_factory;
1157 D2D1_POINT_2F origin;
1158 HRESULT hr;
1160 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1161 "brush %p, options %#x, measuring_mode %#x.\n",
1162 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1163 brush, options, measuring_mode);
1165 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1166 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1168 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1169 return;
1172 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1173 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1174 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
1175 else
1176 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1177 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
1178 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1179 IDWriteFactory_Release(dwrite_factory);
1180 if (FAILED(hr))
1182 ERR("Failed to create text layout, hr %#x.\n", hr);
1183 return;
1186 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
1187 ID2D1DeviceContext_DrawTextLayout(iface, origin, text_layout, brush, options);
1188 IDWriteTextLayout_Release(text_layout);
1191 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext *iface,
1192 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1194 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1195 struct d2d_draw_text_layout_ctx ctx;
1196 HRESULT hr;
1198 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1199 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1201 ctx.brush = brush;
1202 ctx.options = options;
1204 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1205 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1206 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1209 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1211 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1212 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1213 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1214 return prev_antialias_mode;
1217 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1218 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1220 D2D1_MATRIX_3X2_F *transform, prev_transform;
1221 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1222 ID2D1PathGeometry *geometry;
1223 ID2D1GeometrySink *sink;
1224 HRESULT hr;
1226 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1228 ERR("Failed to create geometry, hr %#x.\n", hr);
1229 return;
1232 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1234 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1235 ID2D1PathGeometry_Release(geometry);
1236 return;
1239 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1240 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1241 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1243 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1244 ID2D1GeometrySink_Release(sink);
1245 ID2D1PathGeometry_Release(geometry);
1246 return;
1249 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1250 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1251 ID2D1GeometrySink_Release(sink);
1253 transform = &render_target->drawing_state.transform;
1254 prev_transform = *transform;
1255 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1256 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1257 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1258 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1259 unsafe_impl_from_ID2D1Brush(brush), NULL);
1260 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1261 *transform = prev_transform;
1263 ID2D1PathGeometry_Release(geometry);
1266 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1267 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1268 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1269 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1271 ID2D1RectangleGeometry *geometry = NULL;
1272 ID2D1BitmapBrush *opacity_brush = NULL;
1273 D2D1_BITMAP_PROPERTIES bitmap_desc;
1274 ID2D1Bitmap *opacity_bitmap = NULL;
1275 IDWriteGlyphRunAnalysis *analysis;
1276 DWRITE_TEXTURE_TYPE texture_type;
1277 D2D1_BRUSH_PROPERTIES brush_desc;
1278 IDWriteFactory2 *dwrite_factory;
1279 D2D1_MATRIX_3X2_F *transform, m;
1280 void *opacity_values = NULL;
1281 size_t opacity_values_size;
1282 D2D1_SIZE_U bitmap_size;
1283 float scale_x, scale_y;
1284 D2D1_RECT_F run_rect;
1285 RECT bounds;
1286 HRESULT hr;
1288 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1289 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1291 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1292 return;
1295 transform = &render_target->drawing_state.transform;
1297 scale_x = render_target->desc.dpiX / 96.0f;
1298 m._11 = transform->_11 * scale_x;
1299 m._21 = transform->_21 * scale_x;
1300 m._31 = transform->_31 * scale_x;
1302 scale_y = render_target->desc.dpiY / 96.0f;
1303 m._12 = transform->_12 * scale_y;
1304 m._22 = transform->_22 * scale_y;
1305 m._32 = transform->_32 * scale_y;
1307 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1308 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1309 baseline_origin.x, baseline_origin.y, &analysis);
1310 IDWriteFactory2_Release(dwrite_factory);
1311 if (FAILED(hr))
1313 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1314 return;
1317 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1318 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1319 else
1320 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1322 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1324 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1325 goto done;
1328 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1329 if (!bitmap_size.width || !bitmap_size.height)
1331 /* Empty run, nothing to do. */
1332 goto done;
1335 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1336 bitmap_size.width *= 3;
1337 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1339 ERR("Failed to allocate opacity values.\n");
1340 goto done;
1342 opacity_values_size = bitmap_size.height * bitmap_size.width;
1344 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1345 texture_type, &bounds, opacity_values, opacity_values_size)))
1347 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1348 goto done;
1351 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1352 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1353 bitmap_desc.dpiX = render_target->desc.dpiX;
1354 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1355 bitmap_desc.dpiX *= 3.0f;
1356 bitmap_desc.dpiY = render_target->desc.dpiY;
1357 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext_iface,
1358 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1360 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1361 goto done;
1364 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1365 bounds.right / scale_x, bounds.bottom / scale_y);
1367 brush_desc.opacity = 1.0f;
1368 brush_desc.transform._11 = 1.0f;
1369 brush_desc.transform._12 = 0.0f;
1370 brush_desc.transform._21 = 0.0f;
1371 brush_desc.transform._22 = 1.0f;
1372 brush_desc.transform._31 = run_rect.left;
1373 brush_desc.transform._32 = run_rect.top;
1374 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext_iface,
1375 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1377 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1378 goto done;
1381 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1383 ERR("Failed to create geometry, hr %#x.\n", hr);
1384 goto done;
1387 m = *transform;
1388 *transform = identity;
1389 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1390 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1391 *transform = m;
1393 done:
1394 if (geometry)
1395 ID2D1RectangleGeometry_Release(geometry);
1396 if (opacity_brush)
1397 ID2D1BitmapBrush_Release(opacity_brush);
1398 if (opacity_bitmap)
1399 ID2D1Bitmap_Release(opacity_bitmap);
1400 heap_free(opacity_values);
1401 IDWriteGlyphRunAnalysis_Release(analysis);
1404 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext *iface,
1405 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1406 DWRITE_MEASURING_MODE measuring_mode)
1408 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1409 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1411 ID2D1DeviceContext_DrawGlyphRun(iface, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1414 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext *iface,
1415 const D2D1_MATRIX_3X2_F *transform)
1417 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1419 TRACE("iface %p, transform %p.\n", iface, transform);
1421 render_target->drawing_state.transform = *transform;
1424 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext *iface,
1425 D2D1_MATRIX_3X2_F *transform)
1427 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1429 TRACE("iface %p, transform %p.\n", iface, transform);
1431 *transform = render_target->drawing_state.transform;
1434 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext *iface,
1435 D2D1_ANTIALIAS_MODE antialias_mode)
1437 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1439 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1441 render_target->drawing_state.antialiasMode = antialias_mode;
1444 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext *iface)
1446 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1448 TRACE("iface %p.\n", iface);
1450 return render_target->drawing_state.antialiasMode;
1453 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext *iface,
1454 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1456 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1458 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1460 render_target->drawing_state.textAntialiasMode = antialias_mode;
1463 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext *iface)
1465 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1467 TRACE("iface %p.\n", iface);
1469 return render_target->drawing_state.textAntialiasMode;
1472 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext *iface,
1473 IDWriteRenderingParams *text_rendering_params)
1475 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1477 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1479 if (text_rendering_params)
1480 IDWriteRenderingParams_AddRef(text_rendering_params);
1481 if (render_target->text_rendering_params)
1482 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1483 render_target->text_rendering_params = text_rendering_params;
1486 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext *iface,
1487 IDWriteRenderingParams **text_rendering_params)
1489 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1491 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1493 if ((*text_rendering_params = render_target->text_rendering_params))
1494 IDWriteRenderingParams_AddRef(*text_rendering_params);
1497 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1499 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1501 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1503 render_target->drawing_state.tag1 = tag1;
1504 render_target->drawing_state.tag2 = tag2;
1507 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1509 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1511 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1513 *tag1 = render_target->drawing_state.tag1;
1514 *tag2 = render_target->drawing_state.tag2;
1517 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext *iface,
1518 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1520 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1523 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *iface)
1525 FIXME("iface %p stub!\n", iface);
1528 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1530 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1532 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1534 if (context->ops && context->ops->device_context_present)
1535 context->ops->device_context_present(context->outer_unknown);
1537 return E_NOTIMPL;
1540 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext *iface,
1541 ID2D1DrawingStateBlock *state_block)
1543 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1544 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1546 TRACE("iface %p, state_block %p.\n", iface, state_block);
1548 state_block_impl->drawing_state = render_target->drawing_state;
1549 if (render_target->text_rendering_params)
1550 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1551 if (state_block_impl->text_rendering_params)
1552 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1553 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1556 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext *iface,
1557 ID2D1DrawingStateBlock *state_block)
1559 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1560 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1562 TRACE("iface %p, state_block %p.\n", iface, state_block);
1564 render_target->drawing_state = state_block_impl->drawing_state;
1565 if (state_block_impl->text_rendering_params)
1566 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1567 if (render_target->text_rendering_params)
1568 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1569 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1572 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext *iface,
1573 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1575 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1576 D2D1_RECT_F transformed_rect;
1577 float x_scale, y_scale;
1578 D2D1_POINT_2F point;
1580 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1582 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1583 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1585 x_scale = render_target->desc.dpiX / 96.0f;
1586 y_scale = render_target->desc.dpiY / 96.0f;
1587 d2d_point_transform(&point, &render_target->drawing_state.transform,
1588 clip_rect->left * x_scale, clip_rect->top * y_scale);
1589 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1590 d2d_point_transform(&point, &render_target->drawing_state.transform,
1591 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1592 d2d_rect_expand(&transformed_rect, &point);
1593 d2d_point_transform(&point, &render_target->drawing_state.transform,
1594 clip_rect->right * x_scale, clip_rect->top * y_scale);
1595 d2d_rect_expand(&transformed_rect, &point);
1596 d2d_point_transform(&point, &render_target->drawing_state.transform,
1597 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1598 d2d_rect_expand(&transformed_rect, &point);
1600 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1601 WARN("Failed to push clip rect.\n");
1604 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext *iface)
1606 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1608 TRACE("iface %p.\n", iface);
1610 d2d_clip_stack_pop(&render_target->clip_stack);
1613 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface, const D2D1_COLOR_F *colour)
1615 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1616 D3D10_SUBRESOURCE_DATA buffer_data;
1617 struct d2d_ps_cb ps_cb_data = {0};
1618 D3D10_BUFFER_DESC buffer_desc;
1619 ID3D10Buffer *vs_cb, *ps_cb;
1620 D2D1_COLOR_F *c;
1621 HRESULT hr;
1623 static const struct
1625 struct
1627 float _11, _21, _31, pad0;
1628 float _12, _22, _32, pad1;
1629 } transform_geometry;
1630 struct d2d_vec4 transform_rtx;
1631 struct d2d_vec4 transform_rty;
1633 vs_cb_data =
1635 {1.0f, 0.0f, 0.0f, 0.0f,
1636 0.0f, 1.0f, 0.0f, 0.0f},
1637 {1.0f, 0.0f, 1.0f, 1.0f},
1638 {0.0f, 1.0f, 1.0f, -1.0f},
1641 TRACE("iface %p, colour %p.\n", iface, colour);
1643 buffer_desc.ByteWidth = sizeof(vs_cb_data);
1644 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1645 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1646 buffer_desc.CPUAccessFlags = 0;
1647 buffer_desc.MiscFlags = 0;
1649 buffer_data.pSysMem = &vs_cb_data;
1650 buffer_data.SysMemPitch = 0;
1651 buffer_data.SysMemSlicePitch = 0;
1653 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
1655 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1656 return;
1659 ps_cb_data.outline = FALSE;
1660 ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1661 ps_cb_data.colour_brush.opacity = 1.0f;
1662 c = &ps_cb_data.colour_brush.u.solid.colour;
1663 if (colour)
1664 *c = *colour;
1665 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1666 c->a = 1.0f;
1667 c->r *= c->a;
1668 c->g *= c->a;
1669 c->b *= c->a;
1671 ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1673 buffer_desc.ByteWidth = sizeof(ps_cb_data);
1674 buffer_data.pSysMem = &ps_cb_data;
1676 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ps_cb)))
1678 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1679 ID3D10Buffer_Release(vs_cb);
1680 return;
1683 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1684 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1686 ID3D10Buffer_Release(ps_cb);
1687 ID3D10Buffer_Release(vs_cb);
1690 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
1692 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1694 TRACE("iface %p.\n", iface);
1696 memset(&render_target->error, 0, sizeof(render_target->error));
1699 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface,
1700 D2D1_TAG *tag1, D2D1_TAG *tag2)
1702 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1703 HRESULT hr;
1705 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1707 if (tag1)
1708 *tag1 = context->error.tag1;
1709 if (tag2)
1710 *tag2 = context->error.tag2;
1712 if (context->ops && context->ops->device_context_present)
1714 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1715 context->error.code = hr;
1718 return context->error.code;
1721 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface,
1722 D2D1_PIXEL_FORMAT *format)
1724 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1726 TRACE("iface %p, format %p.\n", iface, format);
1728 *format = render_target->desc.pixelFormat;
1729 return format;
1732 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext *iface, float dpi_x, float dpi_y)
1734 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1736 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1738 if (dpi_x == 0.0f && dpi_y == 0.0f)
1740 dpi_x = 96.0f;
1741 dpi_y = 96.0f;
1743 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1744 return;
1746 render_target->desc.dpiX = dpi_x;
1747 render_target->desc.dpiY = dpi_y;
1750 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext *iface, float *dpi_x, float *dpi_y)
1752 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1754 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1756 *dpi_x = render_target->desc.dpiX;
1757 *dpi_y = render_target->desc.dpiY;
1760 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext *iface, D2D1_SIZE_F *size)
1762 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1764 TRACE("iface %p, size %p.\n", iface, size);
1766 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1767 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1768 return size;
1771 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext *iface,
1772 D2D1_SIZE_U *pixel_size)
1774 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1776 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1778 *pixel_size = render_target->pixel_size;
1779 return pixel_size;
1782 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext *iface)
1784 TRACE("iface %p.\n", iface);
1786 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1789 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext *iface,
1790 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1792 FIXME("iface %p, desc %p stub!\n", iface, desc);
1794 return FALSE;
1797 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext *iface,
1798 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
1799 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1801 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1802 struct d2d_bitmap *object;
1803 HRESULT hr;
1805 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
1806 iface, size.width, size.height, src_data, pitch, desc, bitmap);
1808 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
1809 *bitmap = &object->ID2D1Bitmap1_iface;
1811 return hr;
1814 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
1815 ID2D1DeviceContext *iface, IWICBitmapSource *bitmap_source,
1816 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1818 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1819 struct d2d_bitmap *object;
1820 HRESULT hr;
1822 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
1824 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
1825 *bitmap = &object->ID2D1Bitmap1_iface;
1827 return hr;
1830 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext *iface,
1831 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
1833 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
1834 iface, space, profile, profile_size, color_context);
1836 return E_NOTIMPL;
1839 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext *iface,
1840 const WCHAR *filename, ID2D1ColorContext **color_context)
1842 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
1844 return E_NOTIMPL;
1847 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext *iface,
1848 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
1850 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
1852 return E_NOTIMPL;
1855 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
1856 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1858 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1859 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
1860 struct d2d_bitmap *object;
1861 HRESULT hr;
1863 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
1865 if (!desc)
1867 DXGI_SURFACE_DESC surface_desc;
1869 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1871 WARN("Failed to get surface desc, hr %#x.\n", hr);
1872 return hr;
1875 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
1876 bitmap_desc.pixelFormat.format = surface_desc.Format;
1877 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1878 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
1879 desc = &bitmap_desc;
1882 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
1883 *bitmap = &object->ID2D1Bitmap1_iface;
1885 return hr;
1888 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
1889 REFCLSID effect_id, ID2D1Effect **effect)
1891 struct d2d_effect *object;
1893 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1895 if (!(object = heap_alloc_zero(sizeof(*object))))
1896 return E_OUTOFMEMORY;
1898 d2d_effect_init(object);
1900 TRACE("Created effect %p.\n", object);
1901 *effect = &object->ID2D1Effect_iface;
1903 return S_OK;
1906 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1907 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1908 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1909 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1910 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1912 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1913 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1914 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1915 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1917 return E_NOTIMPL;
1920 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1921 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1922 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1924 FIXME("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p stub!\n",
1925 iface, image, image_brush_desc, brush_desc, brush);
1927 return E_NOTIMPL;
1930 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1931 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1932 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1934 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1935 struct d2d_brush *object;
1936 HRESULT hr;
1938 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1939 brush_desc, brush);
1941 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1942 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1944 return hr;
1947 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1948 ID2D1CommandList **command_list)
1950 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1952 return E_NOTIMPL;
1955 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1957 FIXME("iface %p, format %#x stub!\n", iface, format);
1959 return FALSE;
1962 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1963 D2D1_BUFFER_PRECISION buffer_precision)
1965 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1967 return FALSE;
1970 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1971 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1973 FIXME("iface %p, image %p, local_bounds %p stub!\n", iface, image, local_bounds);
1976 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
1977 ID2D1Image *image, D2D1_RECT_F *world_bounds)
1979 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
1981 return E_NOTIMPL;
1984 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
1985 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1986 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
1988 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
1989 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
1991 return E_NOTIMPL;
1994 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
1996 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1998 TRACE("iface %p, device %p.\n", iface, device);
2000 *device = context->device;
2001 ID2D1Device_AddRef(*device);
2004 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2006 if (!context->target)
2007 return;
2009 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
2010 context->target = NULL;
2012 /* Note that DPI settings are kept. */
2013 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2014 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2016 ID3D10BlendState_Release(context->bs);
2017 context->bs = NULL;
2020 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
2022 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2023 struct d2d_bitmap *bitmap_impl;
2024 D3D10_BLEND_DESC blend_desc;
2025 ID2D1Bitmap *bitmap;
2026 HRESULT hr;
2028 TRACE("iface %p, target %p.\n", iface, target);
2030 if (!target)
2032 d2d_device_context_reset_target(context);
2033 return;
2036 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2038 FIXME("Only bitmap targets are supported.\n");
2039 return;
2042 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2044 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2046 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2047 return;
2050 d2d_device_context_reset_target(context);
2052 /* Set sizes and pixel format. */
2053 context->pixel_size = bitmap_impl->pixel_size;
2054 context->desc.pixelFormat = bitmap_impl->format;
2055 context->target = bitmap_impl;
2057 memset(&blend_desc, 0, sizeof(blend_desc));
2058 blend_desc.BlendEnable[0] = TRUE;
2059 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2060 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2061 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2062 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2064 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2065 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2067 else
2069 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2070 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2072 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2073 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2074 if (FAILED(hr = ID3D10Device_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2075 WARN("Failed to create blend state, hr %#x.\n", hr);
2078 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2080 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2082 TRACE("iface %p, target %p.\n", iface, target);
2084 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2085 if (*target)
2086 ID2D1Image_AddRef(*target);
2089 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2090 const D2D1_RENDERING_CONTROLS *rendering_controls)
2092 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2095 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2096 D2D1_RENDERING_CONTROLS *rendering_controls)
2098 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2101 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2102 D2D1_PRIMITIVE_BLEND primitive_blend)
2104 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2107 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2109 FIXME("iface %p stub!\n", iface);
2111 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2114 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2116 FIXME("iface %p, unit_mode %#x stub!\n", iface, unit_mode);
2119 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2121 FIXME("iface %p stub!\n", iface);
2123 return D2D1_UNIT_MODE_DIPS;
2126 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2127 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2128 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2130 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
2131 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2132 IDWriteRenderingParams *rendering_params;
2133 DWRITE_RENDERING_MODE rendering_mode;
2134 HRESULT hr;
2136 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2137 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2139 if (FAILED(context->error.code))
2140 return;
2142 rendering_params = context->text_rendering_params ? context->text_rendering_params
2143 : context->default_text_rendering_params;
2145 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
2147 switch (context->drawing_state.textAntialiasMode)
2149 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2150 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
2151 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
2152 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
2153 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
2154 d2d_device_context_set_error(context, E_INVALIDARG);
2155 break;
2157 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2158 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
2159 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2160 d2d_device_context_set_error(context, E_INVALIDARG);
2161 break;
2163 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
2164 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
2165 d2d_device_context_set_error(context, E_INVALIDARG);
2166 break;
2168 default:
2169 break;
2172 if (FAILED(context->error.code))
2173 return;
2175 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
2176 switch (context->drawing_state.textAntialiasMode)
2178 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
2179 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
2180 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2181 break;
2183 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2184 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2185 break;
2187 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2188 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
2189 break;
2191 default:
2192 break;
2195 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2197 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
2198 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
2199 measuring_mode, rendering_params, &rendering_mode)))
2201 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
2202 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
2206 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2207 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
2208 else
2209 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
2210 rendering_mode, measuring_mode, antialias_mode);
2213 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2214 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2215 D2D1_COMPOSITE_MODE composite_mode)
2217 FIXME("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x stub!\n",
2218 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2219 interpolation_mode, composite_mode);
2222 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2223 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2225 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2226 iface, metafile, debug_d2d_point_2f(target_offset));
2229 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2230 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2231 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2233 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2235 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2236 "src_rect %s, perspective_transform %p.\n",
2237 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2238 debug_d2d_rect_f(src_rect), perspective_transform);
2240 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2241 perspective_transform);
2244 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2245 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2247 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2250 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2251 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2253 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2254 iface, effect, input, debug_d2d_rect_f(input_rect));
2256 return E_NOTIMPL;
2259 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2260 ID2D1Effect *effect, UINT32 *rect_count)
2262 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2264 return E_NOTIMPL;
2267 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2268 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2270 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2272 return E_NOTIMPL;
2275 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2276 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2277 D2D1_RECT_F *input_rect, UINT32 input_count)
2279 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2280 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2282 return E_NOTIMPL;
2285 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2286 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2288 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2289 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2292 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2294 d2d_device_context_QueryInterface,
2295 d2d_device_context_AddRef,
2296 d2d_device_context_Release,
2297 d2d_device_context_GetFactory,
2298 d2d_device_context_CreateBitmap,
2299 d2d_device_context_CreateBitmapFromWicBitmap,
2300 d2d_device_context_CreateSharedBitmap,
2301 d2d_device_context_CreateBitmapBrush,
2302 d2d_device_context_CreateSolidColorBrush,
2303 d2d_device_context_CreateGradientStopCollection,
2304 d2d_device_context_CreateLinearGradientBrush,
2305 d2d_device_context_CreateRadialGradientBrush,
2306 d2d_device_context_CreateCompatibleRenderTarget,
2307 d2d_device_context_CreateLayer,
2308 d2d_device_context_CreateMesh,
2309 d2d_device_context_DrawLine,
2310 d2d_device_context_DrawRectangle,
2311 d2d_device_context_FillRectangle,
2312 d2d_device_context_DrawRoundedRectangle,
2313 d2d_device_context_FillRoundedRectangle,
2314 d2d_device_context_DrawEllipse,
2315 d2d_device_context_FillEllipse,
2316 d2d_device_context_DrawGeometry,
2317 d2d_device_context_FillGeometry,
2318 d2d_device_context_FillMesh,
2319 d2d_device_context_FillOpacityMask,
2320 d2d_device_context_DrawBitmap,
2321 d2d_device_context_DrawText,
2322 d2d_device_context_DrawTextLayout,
2323 d2d_device_context_DrawGlyphRun,
2324 d2d_device_context_SetTransform,
2325 d2d_device_context_GetTransform,
2326 d2d_device_context_SetAntialiasMode,
2327 d2d_device_context_GetAntialiasMode,
2328 d2d_device_context_SetTextAntialiasMode,
2329 d2d_device_context_GetTextAntialiasMode,
2330 d2d_device_context_SetTextRenderingParams,
2331 d2d_device_context_GetTextRenderingParams,
2332 d2d_device_context_SetTags,
2333 d2d_device_context_GetTags,
2334 d2d_device_context_PushLayer,
2335 d2d_device_context_PopLayer,
2336 d2d_device_context_Flush,
2337 d2d_device_context_SaveDrawingState,
2338 d2d_device_context_RestoreDrawingState,
2339 d2d_device_context_PushAxisAlignedClip,
2340 d2d_device_context_PopAxisAlignedClip,
2341 d2d_device_context_Clear,
2342 d2d_device_context_BeginDraw,
2343 d2d_device_context_EndDraw,
2344 d2d_device_context_GetPixelFormat,
2345 d2d_device_context_SetDpi,
2346 d2d_device_context_GetDpi,
2347 d2d_device_context_GetSize,
2348 d2d_device_context_GetPixelSize,
2349 d2d_device_context_GetMaximumBitmapSize,
2350 d2d_device_context_IsSupported,
2351 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2352 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2353 d2d_device_context_CreateColorContext,
2354 d2d_device_context_CreateColorContextFromFilename,
2355 d2d_device_context_CreateColorContextFromWicColorContext,
2356 d2d_device_context_CreateBitmapFromDxgiSurface,
2357 d2d_device_context_CreateEffect,
2358 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2359 d2d_device_context_CreateImageBrush,
2360 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2361 d2d_device_context_CreateCommandList,
2362 d2d_device_context_IsDxgiFormatSupported,
2363 d2d_device_context_IsBufferPrecisionSupported,
2364 d2d_device_context_GetImageLocalBounds,
2365 d2d_device_context_GetImageWorldBounds,
2366 d2d_device_context_GetGlyphRunWorldBounds,
2367 d2d_device_context_GetDevice,
2368 d2d_device_context_SetTarget,
2369 d2d_device_context_GetTarget,
2370 d2d_device_context_SetRenderingControls,
2371 d2d_device_context_GetRenderingControls,
2372 d2d_device_context_SetPrimitiveBlend,
2373 d2d_device_context_GetPrimitiveBlend,
2374 d2d_device_context_SetUnitMode,
2375 d2d_device_context_GetUnitMode,
2376 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2377 d2d_device_context_DrawImage,
2378 d2d_device_context_DrawGdiMetafile,
2379 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2380 d2d_device_context_ID2D1DeviceContext_PushLayer,
2381 d2d_device_context_InvalidateEffectInputRectangle,
2382 d2d_device_context_GetEffectInvalidRectangleCount,
2383 d2d_device_context_GetEffectInvalidRectangles,
2384 d2d_device_context_GetEffectRequiredInputRectangles,
2385 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2388 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2390 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2393 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2395 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2397 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2398 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2399 || IsEqualGUID(iid, &IID_IUnknown))
2401 IDWriteTextRenderer_AddRef(iface);
2402 *out = iface;
2403 return S_OK;
2406 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2408 *out = NULL;
2409 return E_NOINTERFACE;
2412 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2414 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2416 TRACE("iface %p.\n", iface);
2418 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2421 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2423 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2425 TRACE("iface %p.\n", iface);
2427 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2430 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2431 void *ctx, BOOL *disabled)
2433 struct d2d_draw_text_layout_ctx *context = ctx;
2435 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2437 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2439 return S_OK;
2442 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2443 void *ctx, DWRITE_MATRIX *transform)
2445 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2447 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2449 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2451 return S_OK;
2454 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2456 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2458 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2460 *ppd = render_target->desc.dpiY / 96.0f;
2462 return S_OK;
2465 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2466 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2467 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2469 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2470 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2471 struct d2d_draw_text_layout_ctx *context = ctx;
2472 BOOL color_font = FALSE;
2473 ID2D1Brush *brush;
2475 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2476 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2477 iface, ctx, baseline_origin_x, baseline_origin_y,
2478 measuring_mode, glyph_run, desc, effect);
2480 if (desc)
2481 WARN("Ignoring glyph run description %p.\n", desc);
2482 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2483 FIXME("Ignoring options %#x.\n", context->options);
2485 brush = d2d_draw_get_text_brush(context, effect);
2487 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2489 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2491 IDWriteFontFace2 *fontface;
2493 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2494 &IID_IDWriteFontFace2, (void **)&fontface)))
2496 color_font = IDWriteFontFace2_IsColorFont(fontface);
2497 IDWriteFontFace2_Release(fontface);
2501 if (color_font)
2503 IDWriteColorGlyphRunEnumerator *layers;
2504 IDWriteFactory2 *dwrite_factory;
2505 HRESULT hr;
2507 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2508 (IUnknown **)&dwrite_factory)))
2510 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2511 ID2D1Brush_Release(brush);
2512 return hr;
2515 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2516 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2517 IDWriteFactory2_Release(dwrite_factory);
2518 if (FAILED(hr))
2520 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
2521 ID2D1Brush_Release(brush);
2522 return hr;
2525 for (;;)
2527 const DWRITE_COLOR_GLYPH_RUN *color_run;
2528 ID2D1Brush *color_brush;
2529 D2D1_POINT_2F origin;
2530 BOOL has_run = FALSE;
2532 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2534 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
2535 break;
2538 if (!has_run)
2539 break;
2541 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2543 ERR("Failed to get current color run, hr %#x.\n", hr);
2544 break;
2547 if (color_run->paletteIndex == 0xffff)
2548 color_brush = brush;
2549 else
2551 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2552 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2554 ERR("Failed to create solid color brush, hr %#x.\n", hr);
2555 break;
2559 origin.x = color_run->baselineOriginX;
2560 origin.y = color_run->baselineOriginY;
2561 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2562 origin, &color_run->glyphRun, color_brush, measuring_mode);
2564 if (color_brush != brush)
2565 ID2D1Brush_Release(color_brush);
2568 IDWriteColorGlyphRunEnumerator_Release(layers);
2570 else
2571 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2572 baseline_origin, glyph_run, brush, measuring_mode);
2574 ID2D1Brush_Release(brush);
2576 return S_OK;
2579 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2580 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2582 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2583 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2584 struct d2d_draw_text_layout_ctx *context = ctx;
2585 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2586 D2D1_POINT_2F start, end;
2587 ID2D1Brush *brush;
2588 float thickness;
2590 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2591 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2593 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2594 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2595 underline->thickness);
2597 brush = d2d_draw_get_text_brush(context, effect);
2599 start.x = baseline_origin_x;
2600 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2601 end.x = start.x + underline->width;
2602 end.y = start.y;
2603 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2604 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2605 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2607 ID2D1Brush_Release(brush);
2609 return S_OK;
2612 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2613 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2615 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2616 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2617 struct d2d_draw_text_layout_ctx *context = ctx;
2618 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2619 D2D1_POINT_2F start, end;
2620 ID2D1Brush *brush;
2621 float thickness;
2623 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2624 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2626 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2627 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2628 strikethrough->thickness);
2630 brush = d2d_draw_get_text_brush(context, effect);
2632 start.x = baseline_origin_x;
2633 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2634 end.x = start.x + strikethrough->width;
2635 end.y = start.y;
2636 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2637 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2638 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2640 ID2D1Brush_Release(brush);
2642 return S_OK;
2645 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2646 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2648 struct d2d_draw_text_layout_ctx *context = ctx;
2649 ID2D1Brush *brush;
2650 HRESULT hr;
2652 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2653 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2655 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2656 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2657 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2658 brush is selected at Direct2D level. */
2659 brush = context->brush;
2660 context->brush = d2d_draw_get_text_brush(context, effect);
2662 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2664 ID2D1Brush_Release(context->brush);
2665 context->brush = brush;
2667 return hr;
2670 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2672 d2d_text_renderer_QueryInterface,
2673 d2d_text_renderer_AddRef,
2674 d2d_text_renderer_Release,
2675 d2d_text_renderer_IsPixelSnappingDisabled,
2676 d2d_text_renderer_GetCurrentTransform,
2677 d2d_text_renderer_GetPixelsPerDip,
2678 d2d_text_renderer_DrawGlyphRun,
2679 d2d_text_renderer_DrawUnderline,
2680 d2d_text_renderer_DrawStrikethrough,
2681 d2d_text_renderer_DrawInlineObject,
2684 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2686 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2689 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2690 REFIID iid, void **out)
2692 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2694 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2696 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2699 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2701 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2703 TRACE("iface %p.\n", iface);
2705 return IUnknown_AddRef(render_target->outer_unknown);
2708 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2710 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2712 TRACE("iface %p.\n", iface);
2714 return IUnknown_Release(render_target->outer_unknown);
2717 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2719 ID3D10Resource *resource;
2720 HRESULT hr;
2722 ID3D10RenderTargetView_GetResource(render_target->target->rtv, &resource);
2723 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2724 ID3D10Resource_Release(resource);
2725 if (FAILED(hr))
2727 *surface = NULL;
2728 WARN("Failed to get DXGI surface, %#x.\n", hr);
2729 return hr;
2732 return hr;
2735 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2736 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2738 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2739 IDXGISurface1 *surface;
2740 HRESULT hr;
2742 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2744 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2745 return hr;
2747 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2748 IDXGISurface1_Release(surface);
2750 return hr;
2753 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2754 const RECT *update)
2756 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2757 IDXGISurface1 *surface;
2758 RECT update_rect;
2759 HRESULT hr;
2761 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2763 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2764 return hr;
2766 if (update)
2767 update_rect = *update;
2768 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2769 IDXGISurface1_Release(surface);
2771 return hr;
2774 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2776 d2d_gdi_interop_render_target_QueryInterface,
2777 d2d_gdi_interop_render_target_AddRef,
2778 d2d_gdi_interop_render_target_Release,
2779 d2d_gdi_interop_render_target_GetDC,
2780 d2d_gdi_interop_render_target_ReleaseDC,
2783 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2784 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2786 D3D10_SUBRESOURCE_DATA buffer_data;
2787 D3D10_STATE_BLOCK_MASK state_mask;
2788 struct d2d_device *device_impl;
2789 IDWriteFactory *dwrite_factory;
2790 D3D10_RASTERIZER_DESC rs_desc;
2791 D3D10_BUFFER_DESC buffer_desc;
2792 unsigned int i;
2793 HRESULT hr;
2795 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2797 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2798 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2799 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2801 static const D3D10_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
2803 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2804 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2805 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2806 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2807 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2808 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2810 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2812 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2814 static const D3D10_INPUT_ELEMENT_DESC il_desc_curve[] =
2816 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2817 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2819 static const DWORD vs_code_outline[] =
2821 #if 0
2822 float3x2 transform_geometry;
2823 float stroke_width;
2824 float4 transform_rtx;
2825 float4 transform_rty;
2827 struct output
2829 float2 p : WORLD_POSITION;
2830 float4 b : BEZIER;
2831 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2832 float4 position : SV_POSITION;
2835 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2837 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2839 * Where:
2841 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2842 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2843 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2844 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2846 float2 q_prev, q_next, v_p, q_i;
2847 float2x2 geom;
2848 float l;
2850 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2852 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2853 q_prev = normalize(mul(geom, prev));
2854 q_next = normalize(mul(geom, next));
2856 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2857 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2858 v_p = float2(-q_prev.y, q_prev.x);
2859 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2860 q_i = l * q_prev + v_p;
2862 o.b = float4(0.0, 0.0, 0.0, 0.0);
2864 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2865 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2866 * float2(transform_rtx.w, transform_rty.w);
2867 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2869 #endif
2870 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2871 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2872 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2873 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2874 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2875 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2876 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2877 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2878 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2879 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2880 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2881 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2882 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2883 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2884 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2885 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2886 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2887 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2888 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2889 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2890 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2891 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2892 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2893 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2894 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2895 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2896 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2897 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2898 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2899 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2900 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2901 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2902 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2903 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2904 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2905 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2906 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2907 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2908 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2909 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2910 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2911 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2912 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2913 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2914 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2915 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2916 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2917 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2918 0x3f800000, 0x0100003e,
2920 /* ⎡p0.x p0.y 1⎤
2921 * A = ⎢p1.x p1.y 1⎥
2922 * ⎣p2.x p2.y 1⎦
2924 * ⎡0 0⎤
2925 * B = ⎢½ 0⎥
2926 * ⎣1 1⎦
2928 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2929 * ⎣p2.x-p0.x p2.y-p0.y⎦
2931 * B' = ⎡½ 0⎤
2932 * ⎣1 1⎦
2934 * A'T = B'
2935 * T = A'⁻¹B'
2937 static const DWORD vs_code_bezier_outline[] =
2939 #if 0
2940 float3x2 transform_geometry;
2941 float stroke_width;
2942 float4 transform_rtx;
2943 float4 transform_rty;
2945 struct output
2947 float2 p : WORLD_POSITION;
2948 float4 b : BEZIER;
2949 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2950 float4 position : SV_POSITION;
2953 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2954 float2 prev : PREV, float2 next : NEXT, out struct output o)
2956 float2 q_prev, q_next, v_p, q_i, p;
2957 float2x2 geom, rt;
2958 float l;
2960 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2961 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2962 o.stroke_transform = rt * stroke_width * 0.5f;
2964 p = mul(geom, position);
2965 p0 = mul(geom, p0);
2966 p1 = mul(geom, p1);
2967 p2 = mul(geom, p2);
2969 p -= p0;
2970 p1 -= p0;
2971 p2 -= p0;
2973 q_prev = normalize(mul(geom, prev));
2974 q_next = normalize(mul(geom, next));
2976 v_p = float2(-q_prev.y, q_prev.x);
2977 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2978 q_i = l * q_prev + v_p;
2979 p += 0.5f * stroke_width * q_i;
2981 v_p = mul(rt, p2);
2982 v_p = normalize(float2(-v_p.y, v_p.x));
2983 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
2985 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
2986 o.b.y = dot(mul(rt, p), v_p);
2988 else
2990 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
2991 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
2992 o.b.x = dot(v_p, p1 - 0.5f * p2);
2993 o.b.y = dot(v_p, p1);
2996 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
2997 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2998 * float2(transform_rtx.w, transform_rty.w);
2999 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3001 #endif
3002 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3003 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3004 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3005 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3006 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3007 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3008 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3009 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3010 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3011 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3012 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3013 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3014 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3015 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3016 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3017 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3018 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3019 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3020 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3021 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3022 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3023 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3024 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3025 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3026 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3027 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3028 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3029 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3030 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3031 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3032 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3033 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3034 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3035 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3036 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3037 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3038 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3039 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3040 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3041 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3042 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3043 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3044 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3045 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3046 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3047 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3048 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3049 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3050 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3051 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3052 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3053 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3054 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3055 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3056 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3057 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3058 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3059 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3060 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3061 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3062 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3063 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3064 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3065 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3066 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3067 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3068 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3069 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3070 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3071 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3072 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3073 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3074 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3075 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3076 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3077 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3078 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3079 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3080 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3081 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3082 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3083 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3084 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3085 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3086 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3087 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3088 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3089 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3091 /* ⎡p0.x p0.y 1⎤
3092 * A = ⎢p1.x p1.y 1⎥
3093 * ⎣p2.x p2.y 1⎦
3095 * ⎡1 0⎤
3096 * B = ⎢1 1⎥
3097 * ⎣0 1⎦
3099 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3100 * ⎣p2.x-p0.x p2.y-p0.y⎦
3102 * B' = ⎡ 0 1⎤
3103 * ⎣-1 1⎦
3105 * A'T = B'
3106 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3108 static const DWORD vs_code_arc_outline[] =
3110 #if 0
3111 float3x2 transform_geometry;
3112 float stroke_width;
3113 float4 transform_rtx;
3114 float4 transform_rty;
3116 struct output
3118 float2 p : WORLD_POSITION;
3119 float4 b : BEZIER;
3120 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3121 float4 position : SV_POSITION;
3124 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3125 float2 prev : PREV, float2 next : NEXT, out struct output o)
3127 float2 q_prev, q_next, v_p, q_i, p;
3128 float2x2 geom, rt, p_inv;
3129 float l;
3130 float a;
3131 float2 bc;
3133 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3134 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3135 o.stroke_transform = rt * stroke_width * 0.5f;
3137 p = mul(geom, position);
3138 p0 = mul(geom, p0);
3139 p1 = mul(geom, p1);
3140 p2 = mul(geom, p2);
3142 p -= p0;
3143 p1 -= p0;
3144 p2 -= p0;
3146 q_prev = normalize(mul(geom, prev));
3147 q_next = normalize(mul(geom, next));
3149 v_p = float2(-q_prev.y, q_prev.x);
3150 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3151 q_i = l * q_prev + v_p;
3152 p += 0.5f * stroke_width * q_i;
3154 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3155 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3156 o.b.zw = 0.0f;
3158 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3159 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3160 * float2(transform_rtx.w, transform_rty.w);
3161 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3163 #endif
3164 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3165 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3166 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3167 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3168 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3169 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3170 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3171 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3172 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3173 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3174 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3175 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3176 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3177 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3178 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3179 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3180 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3181 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3182 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3183 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3184 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3185 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3186 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3187 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3188 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3189 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3190 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3191 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3192 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3193 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3194 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3195 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3196 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3197 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3198 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3199 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3200 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3201 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3202 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3203 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3204 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3205 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3206 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3207 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3208 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3209 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3210 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3211 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3212 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3213 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3214 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3215 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3216 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3217 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3218 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3219 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3220 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3221 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3222 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3223 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3224 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3225 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3226 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3227 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3228 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3229 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3230 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3231 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3232 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3233 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3234 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3235 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3236 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3237 0x0100003e,
3239 static const DWORD vs_code_triangle[] =
3241 #if 0
3242 float3x2 transform_geometry;
3243 float4 transform_rtx;
3244 float4 transform_rty;
3246 struct output
3248 float2 p : WORLD_POSITION;
3249 float4 b : BEZIER;
3250 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3251 float4 position : SV_POSITION;
3254 void main(float2 position : POSITION, out struct output o)
3256 o.p = mul(float3(position, 1.0f), transform_geometry);
3257 o.b = float4(1.0, 0.0, 1.0, 1.0);
3258 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3259 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3260 * float2(transform_rtx.w, transform_rty.w);
3261 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3263 #endif
3264 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3265 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3266 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3267 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3268 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3269 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3270 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3271 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3272 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3273 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3274 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3275 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3276 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3277 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3278 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3279 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3280 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3281 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3282 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3283 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3284 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3285 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3286 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3287 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3288 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3289 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3290 0x00000000, 0x3f800000, 0x0100003e,
3292 static const DWORD vs_code_curve[] =
3294 #if 0
3295 float3x2 transform_geometry;
3296 float4 transform_rtx;
3297 float4 transform_rty;
3299 struct output
3301 float2 p : WORLD_POSITION;
3302 float4 b : BEZIER;
3303 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3304 float4 position : SV_POSITION;
3307 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3309 o.p = mul(float3(position, 1.0f), transform_geometry);
3310 o.b = float4(texcoord, 1.0);
3311 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3312 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3313 * float2(transform_rtx.w, transform_rty.w);
3314 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3316 #endif
3317 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3318 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3319 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3320 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3321 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3322 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3323 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3324 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3325 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3326 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3327 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3328 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3329 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3330 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3331 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3332 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3333 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3334 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3335 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3336 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3337 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3338 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3339 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3340 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3341 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3342 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3343 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3344 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3346 static const DWORD ps_code[] =
3348 #if 0
3349 #define BRUSH_TYPE_SOLID 0
3350 #define BRUSH_TYPE_LINEAR 1
3351 #define BRUSH_TYPE_RADIAL 2
3352 #define BRUSH_TYPE_BITMAP 3
3353 #define BRUSH_TYPE_COUNT 4
3355 bool outline;
3356 bool is_arc;
3357 struct brush
3359 uint type;
3360 float opacity;
3361 float4 data[3];
3362 } colour_brush, opacity_brush;
3364 SamplerState s0, s1;
3365 Texture2D t0, t1;
3366 Buffer<float4> b0, b1;
3368 struct input
3370 float2 p : WORLD_POSITION;
3371 float4 b : BEZIER;
3372 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3375 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3377 float4 c_low, c_high;
3378 float p_low, p_high;
3379 uint i;
3381 p_low = gradient.Load(0).x;
3382 c_low = gradient.Load(1);
3383 c_high = c_low;
3385 if (position < p_low)
3386 return c_low;
3388 for (i = 1; i < stop_count; ++i)
3390 p_high = gradient.Load(i * 2).x;
3391 c_high = gradient.Load(i * 2 + 1);
3393 if (position >= p_low && position <= p_high)
3394 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3396 p_low = p_high;
3397 c_low = c_high;
3400 return c_high;
3403 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3405 float2 start, end, v_p, v_q;
3406 uint stop_count;
3407 float p;
3409 start = brush.data[0].xy;
3410 end = brush.data[0].zw;
3411 stop_count = asuint(brush.data[1].x);
3413 v_p = position - start;
3414 v_q = end - start;
3415 p = dot(v_q, v_p) / dot(v_q, v_q);
3417 return sample_gradient(gradient, stop_count, p);
3420 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3422 float2 centre, offset, ra, rb, v_p, v_q, r;
3423 float b, c, l, t;
3424 uint stop_count;
3426 centre = brush.data[0].xy;
3427 offset = brush.data[0].zw;
3428 ra = brush.data[1].xy;
3429 rb = brush.data[1].zw;
3430 stop_count = asuint(brush.data[2].x);
3432 /* Project onto ra, rb. */
3433 r = float2(dot(ra, ra), dot(rb, rb));
3434 v_p = position - (centre + offset);
3435 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3436 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3438 /* ‖t·p̂ + q⃑‖ = 1
3439 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3440 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3442 * b = p̂·q⃑
3443 * c = q⃑·q⃑ - 1
3444 * t = -b + √(b² - c) */
3445 l = length(v_p);
3446 b = dot(v_p, v_q) / l;
3447 c = dot(v_q, v_q) - 1.0;
3448 t = -b + sqrt(b * b - c);
3450 return sample_gradient(gradient, stop_count, l / t);
3453 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3455 float3 transform[2];
3456 bool ignore_alpha;
3457 float2 texcoord;
3458 float4 colour;
3460 transform[0] = brush.data[0].xyz;
3461 transform[1] = brush.data[1].xyz;
3462 ignore_alpha = asuint(brush.data[1].w);
3464 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3465 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3466 colour = t.Sample(s, texcoord);
3467 if (ignore_alpha)
3468 colour.a = 1.0;
3469 return colour;
3472 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3474 if (brush.type == BRUSH_TYPE_SOLID)
3475 return brush.data[0] * brush.opacity;
3476 if (brush.type == BRUSH_TYPE_LINEAR)
3477 return brush_linear(brush, b, position) * brush.opacity;
3478 if (brush.type == BRUSH_TYPE_RADIAL)
3479 return brush_radial(brush, b, position) * brush.opacity;
3480 if (brush.type == BRUSH_TYPE_BITMAP)
3481 return brush_bitmap(brush, t, s, position) * brush.opacity;
3482 return float4(0.0, 0.0, 0.0, brush.opacity);
3485 float4 main(struct input i) : SV_Target
3487 float4 colour;
3489 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3490 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3491 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3493 if (outline)
3495 float2 du, dv, df;
3496 float4 uv;
3498 /* Evaluate the implicit form of the curve (u² - v = 0
3499 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3500 * space, using the screen-space partial derivatives
3501 * to convert the calculated distance to object space.
3503 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3504 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3506 * For Béziers:
3507 * f(x, y) = u(x, y)² - v(x, y)
3508 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3509 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3511 * For arcs:
3512 * f(x, y) = u(x, y)² + v(x, y)² - 1
3513 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3514 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3515 uv = i.b;
3516 du = float2(ddx(uv.x), ddy(uv.x));
3517 dv = float2(ddx(uv.y), ddy(uv.y));
3519 if (!is_arc)
3521 df = 2.0f * uv.x * du - dv;
3523 clip(dot(df, uv.zw));
3524 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3526 else
3528 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3530 clip(dot(df, uv.zw));
3531 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3534 else
3536 /* Evaluate the implicit form of the curve in texture space.
3537 * "i.b.z" determines which side of the curve is shaded. */
3538 if (!is_arc)
3540 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3542 else
3544 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3548 return colour;
3550 #endif
3551 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3552 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3553 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3554 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3555 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3556 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3557 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3558 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3559 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3560 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3561 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3562 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3563 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3564 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3565 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3566 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3567 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3568 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3569 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3570 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3571 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3572 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3573 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3574 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3575 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3576 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3577 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3578 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3579 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3580 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3581 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3582 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3583 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3584 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3585 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3586 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3587 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3588 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3589 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3590 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3591 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3592 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3593 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3594 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3595 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3596 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3597 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3598 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3599 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3600 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3601 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3602 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3603 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3604 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3605 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3606 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3607 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3608 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3609 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3610 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3611 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3612 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3613 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3614 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3615 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3616 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3617 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3618 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3619 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3620 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3621 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3622 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3623 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3624 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3625 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3626 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3627 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3628 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3629 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3630 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3631 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3632 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3633 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3634 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3635 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3636 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3637 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3638 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3639 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3640 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3641 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3642 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3643 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3644 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3645 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3646 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3647 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3648 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3649 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3650 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3651 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3652 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3653 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3654 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3655 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3656 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3657 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3658 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3659 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3660 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3661 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3662 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3663 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3664 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3665 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3666 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3667 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3668 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3669 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3670 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3671 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3672 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3673 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3674 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3675 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3676 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3677 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3678 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3679 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3680 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3681 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3682 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3683 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3684 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3685 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3686 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3687 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3688 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3689 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3690 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3691 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3692 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3693 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3694 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3695 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3696 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3697 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3698 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3699 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3700 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3701 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3702 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3703 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3704 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3705 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3706 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3707 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3708 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3709 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3710 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3711 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3712 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3713 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3714 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3715 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3716 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3717 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3718 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3719 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3720 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3721 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3722 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3723 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3724 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3725 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3726 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3727 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3728 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3729 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3730 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3731 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3732 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3733 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3734 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3735 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3736 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3737 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3738 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3739 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3740 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3741 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3742 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3743 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3744 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3745 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3746 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3747 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3748 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3749 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3750 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3751 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3752 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3753 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3754 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3755 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3756 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3757 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3758 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3759 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3760 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3761 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3762 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3763 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3764 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
3765 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
3766 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
3767 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
3768 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
3769 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
3770 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
3771 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
3772 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3773 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
3774 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
3775 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
3776 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
3777 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
3778 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
3779 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
3780 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
3781 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
3782 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
3783 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
3784 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
3785 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
3786 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
3787 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
3788 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
3789 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
3790 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
3791 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
3792 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
3793 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3794 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
3795 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
3796 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
3797 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
3798 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
3799 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
3800 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
3801 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
3802 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
3803 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
3804 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
3805 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
3806 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
3808 static const struct shape_info
3810 enum d2d_shape_type shape_type;
3811 const D3D10_INPUT_ELEMENT_DESC *il_desc;
3812 unsigned int il_element_count;
3813 const void *vs_code;
3814 size_t vs_code_size;
3816 shape_info[] =
3818 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3819 vs_code_outline, sizeof(vs_code_outline)},
3820 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3821 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3822 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3823 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
3824 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3825 vs_code_triangle, sizeof(vs_code_triangle)},
3826 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
3827 vs_code_curve, sizeof(vs_code_curve)},
3829 static const struct
3831 float x, y;
3833 quad[] =
3835 {-1.0f, 1.0f},
3836 {-1.0f, -1.0f},
3837 { 1.0f, 1.0f},
3838 { 1.0f, -1.0f},
3840 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3842 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3843 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3844 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3845 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3846 render_target->refcount = 1;
3847 ID2D1Device_GetFactory(device, &render_target->factory);
3848 render_target->device = device;
3849 ID2D1Device_AddRef(render_target->device);
3851 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3852 render_target->ops = ops;
3854 device_impl = unsafe_impl_from_ID2D1Device(device);
3855 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3856 &IID_ID3D10Device, (void **)&render_target->d3d_device)))
3858 WARN("Failed to get device interface, hr %#x.\n", hr);
3859 ID2D1Factory_Release(render_target->factory);
3860 return hr;
3863 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
3865 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
3866 goto err;
3869 if (FAILED(hr = D3D10CreateStateBlock(render_target->d3d_device, &state_mask, &render_target->stateblock)))
3871 WARN("Failed to create stateblock, hr %#x.\n", hr);
3872 goto err;
3875 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3877 const struct shape_info *si = &shape_info[i];
3879 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3880 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3882 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3883 goto err;
3886 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->d3d_device, si->vs_code,
3887 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
3889 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3890 goto err;
3895 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->d3d_device,
3896 ps_code, sizeof(ps_code), &render_target->ps)))
3898 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3899 goto err;
3902 buffer_desc.ByteWidth = sizeof(indices);
3903 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
3904 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
3905 buffer_desc.CPUAccessFlags = 0;
3906 buffer_desc.MiscFlags = 0;
3908 buffer_data.pSysMem = indices;
3909 buffer_data.SysMemPitch = 0;
3910 buffer_data.SysMemSlicePitch = 0;
3912 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3913 &buffer_desc, &buffer_data, &render_target->ib)))
3915 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3916 goto err;
3919 buffer_desc.ByteWidth = sizeof(quad);
3920 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
3921 buffer_data.pSysMem = quad;
3923 render_target->vb_stride = sizeof(*quad);
3924 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3925 &buffer_desc, &buffer_data, &render_target->vb)))
3927 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3928 goto err;
3931 rs_desc.FillMode = D3D10_FILL_SOLID;
3932 rs_desc.CullMode = D3D10_CULL_NONE;
3933 rs_desc.FrontCounterClockwise = FALSE;
3934 rs_desc.DepthBias = 0;
3935 rs_desc.DepthBiasClamp = 0.0f;
3936 rs_desc.SlopeScaledDepthBias = 0.0f;
3937 rs_desc.DepthClipEnable = TRUE;
3938 rs_desc.ScissorEnable = TRUE;
3939 rs_desc.MultisampleEnable = FALSE;
3940 rs_desc.AntialiasedLineEnable = FALSE;
3941 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
3943 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3944 goto err;
3947 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3948 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3950 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3951 goto err;
3954 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3955 IDWriteFactory_Release(dwrite_factory);
3956 if (FAILED(hr))
3958 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
3959 goto err;
3962 render_target->drawing_state.transform = identity;
3964 if (!d2d_clip_stack_init(&render_target->clip_stack))
3966 WARN("Failed to initialize clip stack.\n");
3967 hr = E_FAIL;
3968 goto err;
3971 render_target->desc.dpiX = 96.0f;
3972 render_target->desc.dpiY = 96.0f;
3974 return S_OK;
3976 err:
3977 if (render_target->default_text_rendering_params)
3978 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
3979 if (render_target->rs)
3980 ID3D10RasterizerState_Release(render_target->rs);
3981 if (render_target->vb)
3982 ID3D10Buffer_Release(render_target->vb);
3983 if (render_target->ib)
3984 ID3D10Buffer_Release(render_target->ib);
3985 if (render_target->ps)
3986 ID3D10PixelShader_Release(render_target->ps);
3987 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
3989 if (render_target->shape_resources[i].vs)
3990 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
3991 if (render_target->shape_resources[i].il)
3992 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
3994 if (render_target->stateblock)
3995 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
3996 if (render_target->d3d_device)
3997 ID3D10Device_Release(render_target->d3d_device);
3998 ID2D1Device_Release(render_target->device);
3999 ID2D1Factory_Release(render_target->factory);
4000 return hr;
4003 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4004 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4006 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4007 struct d2d_device_context *object;
4008 ID2D1Bitmap1 *bitmap;
4009 HRESULT hr;
4011 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4012 WARN("Ignoring render target type %#x.\n", desc->type);
4013 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4014 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4015 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4016 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4018 bitmap_desc.dpiX = desc->dpiX;
4019 bitmap_desc.dpiY = desc->dpiY;
4021 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4023 bitmap_desc.dpiX = 96.0f;
4024 bitmap_desc.dpiY = 96.0f;
4026 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4027 return E_INVALIDARG;
4029 if (!(object = heap_alloc_zero(sizeof(*object))))
4030 return E_OUTOFMEMORY;
4032 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4034 WARN("Failed to initialize render target, hr %#x.\n", hr);
4035 heap_free(object);
4036 return hr;
4039 ID2D1DeviceContext_SetDpi(&object->ID2D1DeviceContext_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4041 if (surface)
4043 bitmap_desc.pixelFormat = desc->pixelFormat;
4044 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4045 bitmap_desc.colorContext = NULL;
4047 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
4048 surface, &bitmap_desc, &bitmap)))
4050 WARN("Failed to create target bitmap, hr %#x.\n", hr);
4051 IUnknown_Release(&object->IUnknown_iface);
4052 heap_free(object);
4053 return hr;
4056 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
4057 ID2D1Bitmap1_Release(bitmap);
4059 else
4060 object->desc.pixelFormat = desc->pixelFormat;
4062 TRACE("Created render target %p.\n", object);
4063 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
4065 return S_OK;
4068 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
4070 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4072 if (IsEqualGUID(iid, &IID_ID2D1Device)
4073 || IsEqualGUID(iid, &IID_ID2D1Resource)
4074 || IsEqualGUID(iid, &IID_IUnknown))
4076 ID2D1Device_AddRef(iface);
4077 *out = iface;
4078 return S_OK;
4081 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4083 *out = NULL;
4084 return E_NOINTERFACE;
4087 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
4089 struct d2d_device *device = impl_from_ID2D1Device(iface);
4090 ULONG refcount = InterlockedIncrement(&device->refcount);
4092 TRACE("%p increasing refcount to %u.\n", iface, refcount);
4094 return refcount;
4097 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
4099 struct d2d_device *device = impl_from_ID2D1Device(iface);
4100 ULONG refcount = InterlockedDecrement(&device->refcount);
4102 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
4104 if (!refcount)
4106 IDXGIDevice_Release(device->dxgi_device);
4107 ID2D1Factory1_Release(device->factory);
4108 heap_free(device);
4111 return refcount;
4114 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
4116 struct d2d_device *device = impl_from_ID2D1Device(iface);
4118 TRACE("iface %p, factory %p.\n", iface, factory);
4120 *factory = (ID2D1Factory *)device->factory;
4121 ID2D1Factory1_AddRef(device->factory);
4124 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4125 ID2D1DeviceContext **context)
4127 struct d2d_device_context *object;
4128 HRESULT hr;
4130 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4132 if (options)
4133 FIXME("Options are ignored %#x.\n", options);
4135 if (!(object = heap_alloc_zero(sizeof(*object))))
4136 return E_OUTOFMEMORY;
4138 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
4140 WARN("Failed to initialize device context, hr %#x.\n", hr);
4141 heap_free(object);
4142 return hr;
4145 TRACE("Created device context %p.\n", object);
4146 *context = &object->ID2D1DeviceContext_iface;
4148 return S_OK;
4151 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
4152 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4153 ID2D1PrintControl **print_control)
4155 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4156 document_target, desc, print_control);
4158 return E_NOTIMPL;
4161 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
4163 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4166 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
4168 FIXME("iface %p stub!\n", iface);
4170 return 0;
4173 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
4175 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4177 return E_NOTIMPL;
4180 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
4182 d2d_device_QueryInterface,
4183 d2d_device_AddRef,
4184 d2d_device_Release,
4185 d2d_device_GetFactory,
4186 d2d_device_CreateDeviceContext,
4187 d2d_device_CreatePrintControl,
4188 d2d_device_SetMaximumTextureMemory,
4189 d2d_device_GetMaximumTextureMemory,
4190 d2d_device_ClearResources,
4193 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
4195 if (!iface)
4196 return NULL;
4197 assert(iface->lpVtbl == &d2d_device_vtbl);
4198 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
4201 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4203 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
4204 device->refcount = 1;
4205 device->factory = iface;
4206 ID2D1Factory1_AddRef(device->factory);
4207 device->dxgi_device = dxgi_device;
4208 IDXGIDevice_AddRef(device->dxgi_device);