d2d1: Force appropriate antialiasing mode when drawing text elements using 2D primitives.
[wine.git] / dlls / d2d1 / render_target.c
blobcf559c16a3ff0a3e87112d37feb44eab5b16308b
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
20 #include "wine/port.h"
22 #include "d2d1_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
26 #define INITIAL_CLIP_STACK_SIZE 4
28 static const D2D1_MATRIX_3X2_F identity =
30 1.0f, 0.0f,
31 0.0f, 1.0f,
32 0.0f, 0.0f,
35 struct d2d_draw_text_layout_ctx
37 ID2D1Brush *brush;
38 D2D1_DRAW_TEXT_OPTIONS options;
41 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
43 ID2D1Brush *brush = NULL;
45 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
46 return brush;
48 ID2D1Brush_AddRef(context->brush);
49 return context->brush;
52 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
54 if (src->left > dst->left)
55 dst->left = src->left;
56 if (src->top > dst->top)
57 dst->top = src->top;
58 if (src->right < dst->right)
59 dst->right = src->right;
60 if (src->bottom < dst->bottom)
61 dst->bottom = src->bottom;
64 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
66 dst->left = left;
67 dst->top = top;
68 dst->right = right;
69 dst->bottom = bottom;
72 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
74 dst->width = width;
75 dst->height = height;
78 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
80 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
81 return FALSE;
83 stack->size = INITIAL_CLIP_STACK_SIZE;
84 stack->count = 0;
86 return TRUE;
89 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
91 HeapFree(GetProcessHeap(), 0, stack->stack);
94 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
96 D2D1_RECT_F r;
98 if (stack->count == stack->size)
100 D2D1_RECT_F *new_stack;
101 unsigned int new_size;
103 if (stack->size > UINT_MAX / 2)
104 return FALSE;
106 new_size = stack->size * 2;
107 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
108 return FALSE;
110 stack->stack = new_stack;
111 stack->size = new_size;
114 r = *rect;
115 if (stack->count)
116 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
117 stack->stack[stack->count++] = r;
119 return TRUE;
122 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
124 if (!stack->count)
125 return;
126 --stack->count;
129 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
130 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
131 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
133 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
134 ID3D10Device *device = render_target->device;
135 D3D10_RECT scissor_rect;
136 unsigned int offset;
137 D3D10_VIEWPORT vp;
138 HRESULT hr;
140 vp.TopLeftX = 0;
141 vp.TopLeftY = 0;
142 vp.Width = render_target->pixel_size.width;
143 vp.Height = render_target->pixel_size.height;
144 vp.MinDepth = 0.0f;
145 vp.MaxDepth = 1.0f;
147 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
149 WARN("Failed to capture stateblock, hr %#x.\n", hr);
150 return;
153 ID3D10Device_ClearState(device);
155 ID3D10Device_IASetInputLayout(device, shape_resources->il);
156 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
157 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
158 offset = 0;
159 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
160 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
161 ID3D10Device_VSSetShader(device, shape_resources->vs);
162 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
163 ID3D10Device_RSSetViewports(device, 1, &vp);
164 if (render_target->clip_stack.count)
166 const D2D1_RECT_F *clip_rect;
168 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
169 scissor_rect.left = clip_rect->left + 0.5f;
170 scissor_rect.top = clip_rect->top + 0.5f;
171 scissor_rect.right = clip_rect->right + 0.5f;
172 scissor_rect.bottom = clip_rect->bottom + 0.5f;
174 else
176 scissor_rect.left = 0.0f;
177 scissor_rect.top = 0.0f;
178 scissor_rect.right = render_target->pixel_size.width;
179 scissor_rect.bottom = render_target->pixel_size.height;
181 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
182 ID3D10Device_RSSetState(device, render_target->rs);
183 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
184 if (brush)
185 d2d_brush_bind_resources(brush, opacity_brush, render_target, shape_type);
186 else
187 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID][D2D_BRUSH_TYPE_COUNT]);
189 if (ib)
190 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
191 else
192 ID3D10Device_Draw(device, index_count, 0);
194 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
195 WARN("Failed to apply stateblock, hr %#x.\n", hr);
198 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
200 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
203 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
205 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
207 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
209 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
210 || IsEqualGUID(iid, &IID_ID2D1Resource)
211 || IsEqualGUID(iid, &IID_IUnknown))
213 ID2D1RenderTarget_AddRef(iface);
214 *out = iface;
215 return S_OK;
217 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
219 ID2D1GdiInteropRenderTarget_AddRef(&render_target->ID2D1GdiInteropRenderTarget_iface);
220 *out = &render_target->ID2D1GdiInteropRenderTarget_iface;
221 return S_OK;
224 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
226 *out = NULL;
227 return E_NOINTERFACE;
230 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
232 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
233 ULONG refcount = InterlockedIncrement(&render_target->refcount);
235 TRACE("%p increasing refcount to %u.\n", iface, refcount);
237 return refcount;
240 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
242 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
243 ULONG refcount = InterlockedDecrement(&render_target->refcount);
245 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
247 if (!refcount)
249 unsigned int i, j, k;
251 d2d_clip_stack_cleanup(&render_target->clip_stack);
252 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
253 if (render_target->text_rendering_params)
254 IDWriteRenderingParams_Release(render_target->text_rendering_params);
255 ID3D10BlendState_Release(render_target->bs);
256 ID3D10RasterizerState_Release(render_target->rs);
257 ID3D10Buffer_Release(render_target->vb);
258 ID3D10Buffer_Release(render_target->ib);
259 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
261 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
263 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
265 if (render_target->shape_resources[i].ps[j][k])
266 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
269 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
270 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
272 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
273 ID3D10RenderTargetView_Release(render_target->view);
274 ID3D10Device_Release(render_target->device);
275 ID2D1Factory_Release(render_target->factory);
276 HeapFree(GetProcessHeap(), 0, render_target);
279 return refcount;
282 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
284 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
286 TRACE("iface %p, factory %p.\n", iface, factory);
288 *factory = render_target->factory;
289 ID2D1Factory_AddRef(*factory);
292 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
293 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
295 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
296 struct d2d_bitmap *object;
297 HRESULT hr;
299 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
300 iface, size.width, size.height, src_data, pitch, desc, bitmap);
302 if (SUCCEEDED(hr = d2d_bitmap_create(render_target->factory, render_target->device, size, src_data, pitch, desc, &object)))
303 *bitmap = &object->ID2D1Bitmap_iface;
305 return hr;
308 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
309 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
311 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
312 struct d2d_bitmap *object;
313 HRESULT hr;
315 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
316 iface, bitmap_source, desc, bitmap);
318 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(render_target->factory, render_target->device, bitmap_source,
319 desc, &object)))
320 *bitmap = &object->ID2D1Bitmap_iface;
322 return hr;
325 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
326 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
328 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
329 struct d2d_bitmap *object;
330 HRESULT hr;
332 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
333 iface, debugstr_guid(iid), data, desc, bitmap);
335 if (SUCCEEDED(hr = d2d_bitmap_create_shared(iface, render_target->device, iid, data, desc, &object)))
336 *bitmap = &object->ID2D1Bitmap_iface;
338 return hr;
341 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
342 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
343 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
345 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
346 struct d2d_brush *object;
347 HRESULT hr;
349 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
350 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
352 if (SUCCEEDED(hr = d2d_bitmap_brush_create(render_target->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
353 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
355 return hr;
358 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
359 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
361 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
362 struct d2d_brush *object;
363 HRESULT hr;
365 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
367 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
368 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
370 return hr;
373 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
374 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
375 ID2D1GradientStopCollection **gradient)
377 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
378 struct d2d_gradient *object;
379 HRESULT hr;
381 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
382 iface, stops, stop_count, gamma, extend_mode, gradient);
384 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, stops, stop_count, gamma, extend_mode, &object)))
385 *gradient = &object->ID2D1GradientStopCollection_iface;
387 return hr;
390 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
391 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
392 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
394 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
395 struct d2d_brush *object;
396 HRESULT hr;
398 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
399 iface, gradient_brush_desc, brush_desc, gradient, brush);
401 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
402 gradient, &object)))
403 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
405 return hr;
408 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
409 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
410 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
412 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
413 iface, gradient_brush_desc, brush_desc, gradient, brush);
415 return E_NOTIMPL;
418 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
419 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
420 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
422 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
423 struct d2d_bitmap_render_target *object;
424 HRESULT hr;
426 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
427 iface, size, pixel_size, format, options, rt);
429 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
430 return E_OUTOFMEMORY;
432 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
433 format, options)))
435 WARN("Failed to initialize render target, hr %#x.\n", hr);
436 HeapFree(GetProcessHeap(), 0, object);
437 return hr;
440 TRACE("Created render target %p.\n", object);
441 *rt = &object->ID2D1BitmapRenderTarget_iface;
443 return S_OK;
446 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
447 const D2D1_SIZE_F *size, ID2D1Layer **layer)
449 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
450 struct d2d_layer *object;
451 HRESULT hr;
453 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
455 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
456 *layer = &object->ID2D1Layer_iface;
458 return hr;
461 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
463 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
464 struct d2d_mesh *object;
465 HRESULT hr;
467 TRACE("iface %p, mesh %p.\n", iface, mesh);
469 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
470 *mesh = &object->ID2D1Mesh_iface;
472 return hr;
475 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
476 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
478 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
479 ID2D1PathGeometry *geometry;
480 ID2D1GeometrySink *sink;
481 HRESULT hr;
483 TRACE("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p.\n",
484 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
486 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
488 WARN("Failed to create path geometry, %#x.\n", hr);
489 return;
492 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
494 WARN("Open() failed, %#x.\n", hr);
495 ID2D1PathGeometry_Release(geometry);
496 return;
499 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
500 ID2D1GeometrySink_AddLine(sink, p1);
501 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
502 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
503 WARN("Close() failed, %#x.\n", hr);
504 ID2D1GeometrySink_Release(sink);
506 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
507 ID2D1PathGeometry_Release(geometry);
510 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
511 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
513 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
514 ID2D1RectangleGeometry *geometry;
515 HRESULT hr;
517 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
518 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
520 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
522 ERR("Failed to create geometry, hr %#x.\n", hr);
523 return;
526 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
527 ID2D1RectangleGeometry_Release(geometry);
530 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
531 const D2D1_RECT_F *rect, ID2D1Brush *brush)
533 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
534 ID2D1RectangleGeometry *geometry;
535 HRESULT hr;
537 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
539 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
541 ERR("Failed to create geometry, hr %#x.\n", hr);
542 return;
545 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
546 ID2D1RectangleGeometry_Release(geometry);
549 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
550 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
552 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
553 ID2D1RoundedRectangleGeometry *geometry;
554 HRESULT hr;
556 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
557 iface, rect, brush, stroke_width, stroke_style);
559 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
561 ERR("Failed to create geometry, hr %#x.\n", hr);
562 return;
565 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
566 ID2D1RoundedRectangleGeometry_Release(geometry);
569 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
570 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
572 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
573 ID2D1RoundedRectangleGeometry *geometry;
574 HRESULT hr;
576 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
578 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
580 ERR("Failed to create geometry, hr %#x.\n", hr);
581 return;
584 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
585 ID2D1RoundedRectangleGeometry_Release(geometry);
588 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
589 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
591 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
592 ID2D1EllipseGeometry *geometry;
593 HRESULT hr;
595 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
596 iface, ellipse, brush, stroke_width, stroke_style);
598 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
600 ERR("Failed to create geometry, hr %#x.\n", hr);
601 return;
604 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
605 ID2D1EllipseGeometry_Release(geometry);
608 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
609 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
611 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
612 ID2D1EllipseGeometry *geometry;
613 HRESULT hr;
615 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
617 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
619 ERR("Failed to create geometry, hr %#x.\n", hr);
620 return;
623 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
624 ID2D1EllipseGeometry_Release(geometry);
627 static void d2d_rt_draw_geometry(struct d2d_d3d_render_target *render_target,
628 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
630 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
631 D3D10_SUBRESOURCE_DATA buffer_data;
632 D3D10_BUFFER_DESC buffer_desc;
633 const D2D1_MATRIX_3X2_F *w;
634 float tmp_x, tmp_y;
635 HRESULT hr;
636 struct
638 struct
640 float _11, _21, _31, pad0;
641 float _12, _22, _32, stroke_width;
642 } transform_geometry;
643 struct d2d_vec4 transform_rtx;
644 struct d2d_vec4 transform_rty;
645 } vs_cb_data;
647 vs_cb_data.transform_geometry._11 = geometry->transform._11;
648 vs_cb_data.transform_geometry._21 = geometry->transform._21;
649 vs_cb_data.transform_geometry._31 = geometry->transform._31;
650 vs_cb_data.transform_geometry.pad0 = 0.0f;
651 vs_cb_data.transform_geometry._12 = geometry->transform._12;
652 vs_cb_data.transform_geometry._22 = geometry->transform._22;
653 vs_cb_data.transform_geometry._32 = geometry->transform._32;
654 vs_cb_data.transform_geometry.stroke_width = stroke_width;
656 w = &render_target->drawing_state.transform;
658 tmp_x = render_target->desc.dpiX / 96.0f;
659 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
660 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
661 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
662 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
664 tmp_y = render_target->desc.dpiY / 96.0f;
665 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
666 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
667 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
668 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
670 buffer_desc.ByteWidth = sizeof(vs_cb_data);
671 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
672 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
673 buffer_desc.CPUAccessFlags = 0;
674 buffer_desc.MiscFlags = 0;
676 buffer_data.pSysMem = &vs_cb_data;
677 buffer_data.SysMemPitch = 0;
678 buffer_data.SysMemSlicePitch = 0;
680 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
682 WARN("Failed to create constant buffer, hr %#x.\n", hr);
683 return;
686 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, render_target, &ps_cb)))
688 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
689 ID3D10Buffer_Release(vs_cb);
690 return;
693 if (geometry->outline.face_count)
695 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
696 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
697 buffer_data.pSysMem = geometry->outline.faces;
699 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
701 WARN("Failed to create index buffer, hr %#x.\n", hr);
702 goto done;
705 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
706 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
707 buffer_data.pSysMem = geometry->outline.vertices;
709 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
711 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
712 ID3D10Buffer_Release(ib);
713 goto done;
716 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
717 sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
719 ID3D10Buffer_Release(vb);
720 ID3D10Buffer_Release(ib);
723 if (geometry->outline.bezier_face_count)
725 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
726 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
727 buffer_data.pSysMem = geometry->outline.bezier_faces;
729 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
731 WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
732 goto done;
735 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
736 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
737 buffer_data.pSysMem = geometry->outline.beziers;
739 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
741 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
742 ID3D10Buffer_Release(ib);
743 goto done;
746 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib, 3 * geometry->outline.bezier_face_count, vb,
747 sizeof(*geometry->outline.beziers), vs_cb, ps_cb, brush, NULL);
749 ID3D10Buffer_Release(vb);
750 ID3D10Buffer_Release(ib);
753 done:
754 ID3D10Buffer_Release(ps_cb);
755 ID3D10Buffer_Release(vs_cb);
758 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
759 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
761 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
762 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
763 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
765 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
766 iface, geometry, brush, stroke_width, stroke_style);
768 if (stroke_style)
769 FIXME("Ignoring stoke style %p.\n", stroke_style);
771 d2d_rt_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
774 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
775 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
777 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
778 D3D10_SUBRESOURCE_DATA buffer_data;
779 D3D10_BUFFER_DESC buffer_desc;
780 D2D1_MATRIX_3X2_F w, g;
781 float tmp_x, tmp_y;
782 HRESULT hr;
783 struct
785 float _11, _21, _31, pad0;
786 float _12, _22, _32, pad1;
787 } transform;
789 tmp_x = (2.0f * render_target->desc.dpiX) / (96.0f * render_target->pixel_size.width);
790 tmp_y = -(2.0f * render_target->desc.dpiY) / (96.0f * render_target->pixel_size.height);
791 w = render_target->drawing_state.transform;
792 w._11 *= tmp_x;
793 w._21 *= tmp_x;
794 w._31 = w._31 * tmp_x - 1.0f;
795 w._12 *= tmp_y;
796 w._22 *= tmp_y;
797 w._32 = w._32 * tmp_y + 1.0f;
799 g = geometry->transform;
800 d2d_matrix_multiply(&g, &w);
802 transform._11 = g._11;
803 transform._21 = g._21;
804 transform._31 = g._31;
805 transform.pad0 = 0.0f;
806 transform._12 = g._12;
807 transform._22 = g._22;
808 transform._32 = g._32;
809 transform.pad1 = 0.0f;
811 buffer_desc.ByteWidth = sizeof(transform);
812 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
813 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
814 buffer_desc.CPUAccessFlags = 0;
815 buffer_desc.MiscFlags = 0;
817 buffer_data.pSysMem = &transform;
818 buffer_data.SysMemPitch = 0;
819 buffer_data.SysMemSlicePitch = 0;
821 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
823 WARN("Failed to create constant buffer, hr %#x.\n", hr);
824 return;
827 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, render_target, &ps_cb)))
829 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
830 ID3D10Buffer_Release(vs_cb);
831 return;
834 if (geometry->fill.face_count)
836 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
837 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
838 buffer_data.pSysMem = geometry->fill.faces;
840 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
842 WARN("Failed to create index buffer, hr %#x.\n", hr);
843 goto done;
846 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
847 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
848 buffer_data.pSysMem = geometry->fill.vertices;
850 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
852 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
853 ID3D10Buffer_Release(ib);
854 goto done;
857 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
858 sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush);
860 ID3D10Buffer_Release(vb);
861 ID3D10Buffer_Release(ib);
864 if (geometry->fill.bezier_vertex_count)
866 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
867 buffer_data.pSysMem = geometry->fill.bezier_vertices;
869 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
871 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
872 goto done;
875 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb,
876 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush);
878 ID3D10Buffer_Release(vb);
881 done:
882 ID3D10Buffer_Release(ps_cb);
883 ID3D10Buffer_Release(vs_cb);
886 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
887 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
889 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
890 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
891 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
892 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
894 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
896 if (FAILED(render_target->error.code))
897 return;
899 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
901 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
902 render_target->error.tag1 = render_target->drawing_state.tag1;
903 render_target->error.tag2 = render_target->drawing_state.tag2;
904 return;
907 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
910 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
911 ID2D1Mesh *mesh, ID2D1Brush *brush)
913 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
916 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
917 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
918 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
920 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
921 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
924 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
925 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
926 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
928 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
929 D2D1_BRUSH_PROPERTIES brush_desc;
930 ID2D1BitmapBrush *brush;
931 D2D1_RECT_F s, d;
932 HRESULT hr;
934 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
935 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
937 if (src_rect)
939 s = *src_rect;
941 else
943 D2D1_SIZE_F size;
945 size = ID2D1Bitmap_GetSize(bitmap);
946 s.left = 0.0f;
947 s.top = 0.0f;
948 s.right = size.width;
949 s.bottom = size.height;
952 if (dst_rect)
954 d = *dst_rect;
956 else
958 d.left = 0.0f;
959 d.top = 0.0f;
960 d.right = s.right - s.left;
961 d.bottom = s.bottom - s.top;
964 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
965 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
966 bitmap_brush_desc.interpolationMode = interpolation_mode;
968 brush_desc.opacity = opacity;
969 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
970 brush_desc.transform._21 = 0.0f;
971 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
972 brush_desc.transform._12 = 0.0f;
973 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
974 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
976 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
978 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
979 return;
982 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
983 ID2D1BitmapBrush_Release(brush);
986 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
987 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
988 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
990 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
991 IDWriteTextLayout *text_layout;
992 IDWriteFactory *dwrite_factory;
993 D2D1_POINT_2F origin;
994 HRESULT hr;
996 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
997 "brush %p, options %#x, measuring_mode %#x.\n",
998 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
999 brush, options, measuring_mode);
1001 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1002 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1004 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1005 return;
1008 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1009 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1010 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
1011 else
1012 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1013 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
1014 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1015 IDWriteFactory_Release(dwrite_factory);
1016 if (FAILED(hr))
1018 ERR("Failed to create text layout, hr %#x.\n", hr);
1019 return;
1022 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
1023 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
1024 IDWriteTextLayout_Release(text_layout);
1027 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
1028 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1030 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1031 struct d2d_draw_text_layout_ctx ctx;
1032 HRESULT hr;
1034 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
1035 iface, origin.x, origin.y, layout, brush, options);
1037 ctx.brush = brush;
1038 ctx.options = options;
1040 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1041 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1042 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1045 static D2D1_ANTIALIAS_MODE d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(struct d2d_d3d_render_target *rt)
1047 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1048 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1049 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1050 return prev_antialias_mode;
1053 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
1054 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1056 D2D1_MATRIX_3X2_F *transform, prev_transform;
1057 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1058 ID2D1PathGeometry *geometry;
1059 ID2D1GeometrySink *sink;
1060 HRESULT hr;
1062 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1064 ERR("Failed to create geometry, hr %#x.\n", hr);
1065 return;
1068 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1070 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1071 ID2D1PathGeometry_Release(geometry);
1072 return;
1075 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1076 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1077 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1079 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1080 ID2D1GeometrySink_Release(sink);
1081 ID2D1PathGeometry_Release(geometry);
1082 return;
1085 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1086 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1087 ID2D1GeometrySink_Release(sink);
1089 transform = &render_target->drawing_state.transform;
1090 prev_transform = *transform;
1091 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1092 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1093 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
1094 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1095 unsafe_impl_from_ID2D1Brush(brush), NULL);
1096 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1097 *transform = prev_transform;
1099 ID2D1PathGeometry_Release(geometry);
1102 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
1103 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1104 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1105 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1107 D2D1_MATRIX_3X2_F prev_transform, *transform;
1108 ID2D1RectangleGeometry *geometry = NULL;
1109 ID2D1BitmapBrush *opacity_brush = NULL;
1110 D2D1_BITMAP_PROPERTIES bitmap_desc;
1111 ID2D1Bitmap *opacity_bitmap = NULL;
1112 IDWriteGlyphRunAnalysis *analysis;
1113 DWRITE_TEXTURE_TYPE texture_type;
1114 D2D1_BRUSH_PROPERTIES brush_desc;
1115 IDWriteFactory2 *dwrite_factory;
1116 DWRITE_GLYPH_RUN scaled_run;
1117 void *opacity_values = NULL;
1118 size_t opacity_values_size;
1119 D2D1_SIZE_U bitmap_size;
1120 D2D1_RECT_F run_rect;
1121 RECT bounds;
1122 HRESULT hr;
1124 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1125 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1127 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1128 return;
1131 scaled_run = *glyph_run;
1132 scaled_run.fontEmSize *= ppd;
1133 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, &scaled_run,
1134 (DWRITE_MATRIX *)&render_target->drawing_state.transform, rendering_mode, measuring_mode,
1135 DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode, baseline_origin.x,
1136 baseline_origin.y, &analysis);
1137 IDWriteFactory2_Release(dwrite_factory);
1138 if (FAILED(hr))
1140 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1141 return;
1144 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1145 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1146 else
1147 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1149 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1151 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1152 goto done;
1155 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1156 if (!bitmap_size.width || !bitmap_size.height)
1158 /* Empty run, nothing to do. */
1159 goto done;
1162 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1163 bitmap_size.width *= 3;
1164 opacity_values_size = bitmap_size.width * bitmap_size.height;
1165 if (!(opacity_values = HeapAlloc(GetProcessHeap(), 0, opacity_values_size)))
1167 ERR("Failed to allocate opacity values.\n");
1168 goto done;
1171 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1172 texture_type, &bounds, opacity_values, opacity_values_size)))
1174 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1175 goto done;
1178 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1179 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1180 bitmap_desc.dpiX = render_target->desc.dpiX;
1181 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1182 bitmap_desc.dpiX *= 3.0f;
1183 bitmap_desc.dpiY = render_target->desc.dpiY;
1184 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
1185 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1187 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1188 goto done;
1191 brush_desc.opacity = 1.0f;
1192 brush_desc.transform._11 = 1.0f;
1193 brush_desc.transform._12 = 0.0f;
1194 brush_desc.transform._21 = 0.0f;
1195 brush_desc.transform._22 = 1.0f;
1196 brush_desc.transform._31 = bounds.left;
1197 brush_desc.transform._32 = bounds.top;
1198 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
1199 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1201 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1202 goto done;
1205 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
1206 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1208 ERR("Failed to create geometry, hr %#x.\n", hr);
1209 goto done;
1212 transform = &render_target->drawing_state.transform;
1213 prev_transform = *transform;
1214 *transform = identity;
1215 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1216 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1217 *transform = prev_transform;
1219 done:
1220 if (geometry)
1221 ID2D1RectangleGeometry_Release(geometry);
1222 if (opacity_brush)
1223 ID2D1BitmapBrush_Release(opacity_brush);
1224 if (opacity_bitmap)
1225 ID2D1Bitmap_Release(opacity_bitmap);
1226 HeapFree(GetProcessHeap(), 0, opacity_values);
1227 IDWriteGlyphRunAnalysis_Release(analysis);
1230 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
1231 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1232 DWRITE_MEASURING_MODE measuring_mode)
1234 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1235 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
1236 IDWriteRenderingParams *rendering_params;
1237 DWRITE_RENDERING_MODE rendering_mode;
1238 HRESULT hr;
1239 float ppd;
1241 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1242 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
1244 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1245 : render_target->default_text_rendering_params;
1247 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
1249 switch (render_target->drawing_state.textAntialiasMode)
1251 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1252 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
1253 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
1254 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
1255 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
1257 render_target->error.code = E_INVALIDARG;
1259 break;
1260 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1261 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
1262 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1264 render_target->error.code = E_INVALIDARG;
1266 break;
1267 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
1268 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1269 render_target->error.code = E_INVALIDARG;
1270 break;
1271 default:
1275 if (FAILED(render_target->error.code))
1276 return;
1278 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
1279 switch (render_target->drawing_state.textAntialiasMode)
1281 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
1282 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
1283 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1284 break;
1285 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1286 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1287 break;
1288 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1289 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
1290 break;
1291 default:
1295 ppd = max(render_target->desc.dpiX, render_target->desc.dpiY) / 96.0f;
1296 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
1298 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1299 ppd, measuring_mode, rendering_params, &rendering_mode)))
1301 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1302 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1306 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1307 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1308 else
1309 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1310 ppd, rendering_mode, measuring_mode, antialias_mode);
1313 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1314 const D2D1_MATRIX_3X2_F *transform)
1316 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1318 TRACE("iface %p, transform %p.\n", iface, transform);
1320 render_target->drawing_state.transform = *transform;
1323 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1324 D2D1_MATRIX_3X2_F *transform)
1326 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1328 TRACE("iface %p, transform %p.\n", iface, transform);
1330 *transform = render_target->drawing_state.transform;
1333 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1334 D2D1_ANTIALIAS_MODE antialias_mode)
1336 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1338 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1340 render_target->drawing_state.antialiasMode = antialias_mode;
1343 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1345 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1347 TRACE("iface %p.\n", iface);
1349 return render_target->drawing_state.antialiasMode;
1352 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1353 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1355 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1357 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1359 render_target->drawing_state.textAntialiasMode = antialias_mode;
1362 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1364 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1366 TRACE("iface %p.\n", iface);
1368 return render_target->drawing_state.textAntialiasMode;
1371 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1372 IDWriteRenderingParams *text_rendering_params)
1374 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1376 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1378 if (text_rendering_params)
1379 IDWriteRenderingParams_AddRef(text_rendering_params);
1380 if (render_target->text_rendering_params)
1381 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1382 render_target->text_rendering_params = text_rendering_params;
1385 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1386 IDWriteRenderingParams **text_rendering_params)
1388 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1390 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1392 if ((*text_rendering_params = render_target->text_rendering_params))
1393 IDWriteRenderingParams_AddRef(*text_rendering_params);
1396 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1398 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1400 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1402 render_target->drawing_state.tag1 = tag1;
1403 render_target->drawing_state.tag2 = tag2;
1406 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1408 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1410 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1412 *tag1 = render_target->drawing_state.tag1;
1413 *tag2 = render_target->drawing_state.tag2;
1416 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1417 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1419 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1422 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1424 FIXME("iface %p stub!\n", iface);
1427 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1429 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1431 return E_NOTIMPL;
1434 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1435 ID2D1DrawingStateBlock *state_block)
1437 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1438 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1440 TRACE("iface %p, state_block %p.\n", iface, state_block);
1442 state_block_impl->drawing_state = render_target->drawing_state;
1443 if (render_target->text_rendering_params)
1444 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1445 if (state_block_impl->text_rendering_params)
1446 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1447 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1450 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1451 ID2D1DrawingStateBlock *state_block)
1453 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1454 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1456 TRACE("iface %p, state_block %p.\n", iface, state_block);
1458 render_target->drawing_state = state_block_impl->drawing_state;
1459 if (state_block_impl->text_rendering_params)
1460 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1461 if (render_target->text_rendering_params)
1462 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1463 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1466 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1467 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1469 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1470 D2D1_RECT_F transformed_rect;
1471 float x_scale, y_scale;
1472 D2D1_POINT_2F point;
1474 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1476 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1477 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1479 x_scale = render_target->desc.dpiX / 96.0f;
1480 y_scale = render_target->desc.dpiY / 96.0f;
1481 d2d_point_transform(&point, &render_target->drawing_state.transform,
1482 clip_rect->left * x_scale, clip_rect->top * y_scale);
1483 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1484 d2d_point_transform(&point, &render_target->drawing_state.transform,
1485 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1486 d2d_rect_expand(&transformed_rect, &point);
1487 d2d_point_transform(&point, &render_target->drawing_state.transform,
1488 clip_rect->right * x_scale, clip_rect->top * y_scale);
1489 d2d_rect_expand(&transformed_rect, &point);
1490 d2d_point_transform(&point, &render_target->drawing_state.transform,
1491 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1492 d2d_rect_expand(&transformed_rect, &point);
1494 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1495 WARN("Failed to push clip rect.\n");
1498 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1500 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1502 TRACE("iface %p.\n", iface);
1504 d2d_clip_stack_pop(&render_target->clip_stack);
1507 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1509 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1510 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1511 D3D10_SUBRESOURCE_DATA buffer_data;
1512 D3D10_BUFFER_DESC buffer_desc;
1513 ID3D10Buffer *vs_cb, *ps_cb;
1514 HRESULT hr;
1516 static const float transform[] =
1518 1.0f, 0.0f, 0.0f, 0.0f,
1519 0.0f, -1.0f, 0.0f, 0.0f,
1522 TRACE("iface %p, color %p.\n", iface, color);
1524 buffer_desc.ByteWidth = sizeof(transform);
1525 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1526 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1527 buffer_desc.CPUAccessFlags = 0;
1528 buffer_desc.MiscFlags = 0;
1530 buffer_data.pSysMem = transform;
1531 buffer_data.SysMemPitch = 0;
1532 buffer_data.SysMemSlicePitch = 0;
1534 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1536 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1537 return;
1540 if (color)
1541 c = *color;
1542 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1543 c.a = 1.0f;
1544 c.r *= c.a;
1545 c.g *= c.a;
1546 c.b *= c.a;
1547 buffer_desc.ByteWidth = sizeof(c);
1548 buffer_data.pSysMem = &c;
1550 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1552 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1553 ID3D10Buffer_Release(vs_cb);
1554 return;
1557 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1558 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1560 ID3D10Buffer_Release(ps_cb);
1561 ID3D10Buffer_Release(vs_cb);
1564 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1566 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1568 TRACE("iface %p.\n", iface);
1570 memset(&render_target->error, 0, sizeof(render_target->error));
1573 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1574 D2D1_TAG *tag1, D2D1_TAG *tag2)
1576 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1578 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1580 if (tag1)
1581 *tag1 = render_target->error.tag1;
1582 if (tag2)
1583 *tag2 = render_target->error.tag2;
1585 return render_target->error.code;
1588 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1589 D2D1_PIXEL_FORMAT *format)
1591 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1593 TRACE("iface %p, format %p.\n", iface, format);
1595 *format = render_target->desc.pixelFormat;
1596 return format;
1599 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1601 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1603 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1605 if (dpi_x == 0.0f && dpi_y == 0.0f)
1607 dpi_x = 96.0f;
1608 dpi_y = 96.0f;
1610 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1611 return;
1613 render_target->desc.dpiX = dpi_x;
1614 render_target->desc.dpiY = dpi_y;
1617 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1619 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1621 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1623 *dpi_x = render_target->desc.dpiX;
1624 *dpi_y = render_target->desc.dpiY;
1627 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1629 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1631 TRACE("iface %p, size %p.\n", iface, size);
1633 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1634 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1635 return size;
1638 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1639 D2D1_SIZE_U *pixel_size)
1641 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1643 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1645 *pixel_size = render_target->pixel_size;
1646 return pixel_size;
1649 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1651 FIXME("iface %p stub!\n", iface);
1653 return 0;
1656 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1657 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1659 FIXME("iface %p, desc %p stub!\n", iface, desc);
1661 return FALSE;
1664 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1666 d2d_d3d_render_target_QueryInterface,
1667 d2d_d3d_render_target_AddRef,
1668 d2d_d3d_render_target_Release,
1669 d2d_d3d_render_target_GetFactory,
1670 d2d_d3d_render_target_CreateBitmap,
1671 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1672 d2d_d3d_render_target_CreateSharedBitmap,
1673 d2d_d3d_render_target_CreateBitmapBrush,
1674 d2d_d3d_render_target_CreateSolidColorBrush,
1675 d2d_d3d_render_target_CreateGradientStopCollection,
1676 d2d_d3d_render_target_CreateLinearGradientBrush,
1677 d2d_d3d_render_target_CreateRadialGradientBrush,
1678 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1679 d2d_d3d_render_target_CreateLayer,
1680 d2d_d3d_render_target_CreateMesh,
1681 d2d_d3d_render_target_DrawLine,
1682 d2d_d3d_render_target_DrawRectangle,
1683 d2d_d3d_render_target_FillRectangle,
1684 d2d_d3d_render_target_DrawRoundedRectangle,
1685 d2d_d3d_render_target_FillRoundedRectangle,
1686 d2d_d3d_render_target_DrawEllipse,
1687 d2d_d3d_render_target_FillEllipse,
1688 d2d_d3d_render_target_DrawGeometry,
1689 d2d_d3d_render_target_FillGeometry,
1690 d2d_d3d_render_target_FillMesh,
1691 d2d_d3d_render_target_FillOpacityMask,
1692 d2d_d3d_render_target_DrawBitmap,
1693 d2d_d3d_render_target_DrawText,
1694 d2d_d3d_render_target_DrawTextLayout,
1695 d2d_d3d_render_target_DrawGlyphRun,
1696 d2d_d3d_render_target_SetTransform,
1697 d2d_d3d_render_target_GetTransform,
1698 d2d_d3d_render_target_SetAntialiasMode,
1699 d2d_d3d_render_target_GetAntialiasMode,
1700 d2d_d3d_render_target_SetTextAntialiasMode,
1701 d2d_d3d_render_target_GetTextAntialiasMode,
1702 d2d_d3d_render_target_SetTextRenderingParams,
1703 d2d_d3d_render_target_GetTextRenderingParams,
1704 d2d_d3d_render_target_SetTags,
1705 d2d_d3d_render_target_GetTags,
1706 d2d_d3d_render_target_PushLayer,
1707 d2d_d3d_render_target_PopLayer,
1708 d2d_d3d_render_target_Flush,
1709 d2d_d3d_render_target_SaveDrawingState,
1710 d2d_d3d_render_target_RestoreDrawingState,
1711 d2d_d3d_render_target_PushAxisAlignedClip,
1712 d2d_d3d_render_target_PopAxisAlignedClip,
1713 d2d_d3d_render_target_Clear,
1714 d2d_d3d_render_target_BeginDraw,
1715 d2d_d3d_render_target_EndDraw,
1716 d2d_d3d_render_target_GetPixelFormat,
1717 d2d_d3d_render_target_SetDpi,
1718 d2d_d3d_render_target_GetDpi,
1719 d2d_d3d_render_target_GetSize,
1720 d2d_d3d_render_target_GetPixelSize,
1721 d2d_d3d_render_target_GetMaximumBitmapSize,
1722 d2d_d3d_render_target_IsSupported,
1725 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1727 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1730 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1732 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1734 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1735 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1736 || IsEqualGUID(iid, &IID_IUnknown))
1738 IDWriteTextRenderer_AddRef(iface);
1739 *out = iface;
1740 return S_OK;
1743 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1745 *out = NULL;
1746 return E_NOINTERFACE;
1749 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1751 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1753 TRACE("iface %p.\n", iface);
1755 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1758 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1760 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1762 TRACE("iface %p.\n", iface);
1764 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1767 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1768 void *ctx, BOOL *disabled)
1770 struct d2d_draw_text_layout_ctx *context = ctx;
1772 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1774 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1776 return S_OK;
1779 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1780 void *ctx, DWRITE_MATRIX *transform)
1782 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1784 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1786 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1788 return S_OK;
1791 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1793 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1795 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1797 *ppd = render_target->desc.dpiY / 96.0f;
1799 return S_OK;
1802 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1803 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1804 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1806 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1807 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1808 struct d2d_draw_text_layout_ctx *context = ctx;
1809 BOOL color_font = FALSE;
1810 ID2D1Brush *brush;
1812 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1813 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1814 iface, ctx, baseline_origin_x, baseline_origin_y,
1815 measuring_mode, glyph_run, desc, effect);
1817 if (desc)
1818 WARN("Ignoring glyph run description %p.\n", desc);
1819 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
1820 FIXME("Ignoring options %#x.\n", context->options);
1822 brush = d2d_draw_get_text_brush(context, effect);
1824 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1826 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
1828 IDWriteFontFace2 *fontface;
1830 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
1831 &IID_IDWriteFontFace2, (void **)&fontface)))
1833 color_font = IDWriteFontFace2_IsColorFont(fontface);
1834 IDWriteFontFace2_Release(fontface);
1838 if (color_font)
1840 IDWriteColorGlyphRunEnumerator *layers;
1841 IDWriteFactory2 *dwrite_factory;
1842 HRESULT hr;
1844 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
1845 (IUnknown **)&dwrite_factory)))
1847 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1848 ID2D1Brush_Release(brush);
1849 return hr;
1852 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
1853 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
1854 IDWriteFactory2_Release(dwrite_factory);
1855 if (FAILED(hr))
1857 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
1858 ID2D1Brush_Release(brush);
1859 return hr;
1862 for (;;)
1864 const DWRITE_COLOR_GLYPH_RUN *color_run;
1865 ID2D1Brush *color_brush;
1866 D2D1_POINT_2F origin;
1867 BOOL has_run = FALSE;
1869 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
1871 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
1872 break;
1875 if (!has_run)
1876 break;
1878 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
1880 ERR("Failed to get current color run, hr %#x.\n", hr);
1881 break;
1884 if (color_run->paletteIndex == 0xffff)
1885 color_brush = brush;
1886 else
1888 if (FAILED(hr = ID2D1RenderTarget_CreateSolidColorBrush(&render_target->ID2D1RenderTarget_iface,
1889 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
1891 ERR("Failed to create solid color brush, hr %#x.\n", hr);
1892 break;
1896 origin.x = color_run->baselineOriginX;
1897 origin.y = color_run->baselineOriginY;
1898 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1899 origin, &color_run->glyphRun, color_brush, measuring_mode);
1901 if (color_brush != brush)
1902 ID2D1Brush_Release(color_brush);
1905 IDWriteColorGlyphRunEnumerator_Release(layers);
1907 else
1908 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1909 baseline_origin, glyph_run, brush, measuring_mode);
1911 ID2D1Brush_Release(brush);
1913 return S_OK;
1916 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1917 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1919 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1920 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1921 struct d2d_draw_text_layout_ctx *context = ctx;
1922 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1923 D2D1_POINT_2F start, end;
1924 ID2D1Brush *brush;
1925 float thickness;
1927 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1928 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1930 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1931 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
1932 underline->thickness);
1934 brush = d2d_draw_get_text_brush(context, effect);
1936 start.x = baseline_origin_x;
1937 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
1938 end.x = start.x + underline->width;
1939 end.y = start.y;
1940 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
1941 d2d_d3d_render_target_DrawLine(&render_target->ID2D1RenderTarget_iface, start, end, brush, thickness, NULL);
1942 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1944 ID2D1Brush_Release(brush);
1946 return S_OK;
1949 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1950 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1952 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1953 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1954 struct d2d_draw_text_layout_ctx *context = ctx;
1955 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1956 D2D1_POINT_2F start, end;
1957 ID2D1Brush *brush;
1958 float thickness;
1960 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
1961 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1963 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1964 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
1965 strikethrough->thickness);
1967 brush = d2d_draw_get_text_brush(context, effect);
1969 start.x = baseline_origin_x;
1970 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
1971 end.x = start.x + strikethrough->width;
1972 end.y = start.y;
1973 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
1974 d2d_d3d_render_target_DrawLine(&render_target->ID2D1RenderTarget_iface, start, end, brush, thickness, NULL);
1975 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1977 ID2D1Brush_Release(brush);
1979 return S_OK;
1982 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1983 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1985 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1986 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1988 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1991 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1993 d2d_text_renderer_QueryInterface,
1994 d2d_text_renderer_AddRef,
1995 d2d_text_renderer_Release,
1996 d2d_text_renderer_IsPixelSnappingDisabled,
1997 d2d_text_renderer_GetCurrentTransform,
1998 d2d_text_renderer_GetPixelsPerDip,
1999 d2d_text_renderer_DrawGlyphRun,
2000 d2d_text_renderer_DrawUnderline,
2001 d2d_text_renderer_DrawStrikethrough,
2002 d2d_text_renderer_DrawInlineObject,
2005 static inline struct d2d_d3d_render_target *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2007 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1GdiInteropRenderTarget_iface);
2010 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2011 REFIID iid, void **out)
2013 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2015 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2017 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2020 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2022 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2024 TRACE("iface %p.\n", iface);
2026 return IUnknown_AddRef(render_target->outer_unknown);
2029 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2031 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2033 TRACE("iface %p.\n", iface);
2035 return IUnknown_Release(render_target->outer_unknown);
2038 static HRESULT d2d_d3d_render_target_get_surface(struct d2d_d3d_render_target *render_target, IDXGISurface1 **surface)
2040 ID3D10Resource *resource;
2041 HRESULT hr;
2043 ID3D10RenderTargetView_GetResource(render_target->view, &resource);
2044 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2045 ID3D10Resource_Release(resource);
2046 if (FAILED(hr))
2048 *surface = NULL;
2049 WARN("Failed to get DXGI surface, %#x.\n", hr);
2050 return hr;
2053 return hr;
2056 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2057 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2059 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2060 IDXGISurface1 *surface;
2061 HRESULT hr;
2063 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2065 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
2066 return hr;
2068 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2069 IDXGISurface1_Release(surface);
2071 return hr;
2074 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2075 const RECT *update)
2077 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2078 IDXGISurface1 *surface;
2079 RECT update_rect;
2080 HRESULT hr;
2082 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2084 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
2085 return hr;
2087 if (update)
2088 update_rect = *update;
2089 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2090 IDXGISurface1_Release(surface);
2092 return hr;
2095 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2097 d2d_gdi_interop_render_target_QueryInterface,
2098 d2d_gdi_interop_render_target_AddRef,
2099 d2d_gdi_interop_render_target_Release,
2100 d2d_gdi_interop_render_target_GetDC,
2101 d2d_gdi_interop_render_target_ReleaseDC,
2104 static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
2105 IDXGISurface *surface, IUnknown *outer_unknown, const D2D1_RENDER_TARGET_PROPERTIES *desc)
2107 D3D10_SUBRESOURCE_DATA buffer_data;
2108 D3D10_STATE_BLOCK_MASK state_mask;
2109 DXGI_SURFACE_DESC surface_desc;
2110 IDWriteFactory *dwrite_factory;
2111 D3D10_RASTERIZER_DESC rs_desc;
2112 D3D10_BUFFER_DESC buffer_desc;
2113 D3D10_BLEND_DESC blend_desc;
2114 ID3D10Resource *resource;
2115 unsigned int i, j, k;
2116 HRESULT hr;
2118 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2120 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2121 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2122 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2124 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2126 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2128 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier_outline[] =
2130 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2131 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2132 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2133 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2134 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2135 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2137 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
2139 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2140 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2142 static const DWORD vs_code_outline[] =
2144 #if 0
2145 float3x2 transform_geometry;
2146 float stroke_width;
2147 float4 transform_rtx;
2148 float4 transform_rty;
2150 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2152 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2154 * Where:
2156 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2157 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2158 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2159 float4 main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT) : SV_POSITION
2161 float2 q_prev, q_next, v_p, q_i;
2162 float l;
2164 q_prev = float2(dot(prev, transform_geometry._11_21), dot(prev, transform_geometry._12_22));
2165 q_prev = normalize(q_prev);
2167 q_next = float2(dot(next, transform_geometry._11_21), dot(next, transform_geometry._12_22));
2168 q_next = normalize(q_next);
2170 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2171 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2172 v_p = float2(-q_prev.y, q_prev.x);
2173 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2174 q_i = l * q_prev + v_p;
2175 position = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2177 return float4(mul(float2x3(transform_rtx.xyz * transform_rtx.w, transform_rty.xyz * transform_rty.w),
2178 float3(position.xy, 1.0f)) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2180 #endif
2181 0x43425844, 0xe88f7af5, 0x480b101b, 0xfd80f66b, 0xd878e0b8, 0x00000001, 0x0000047c, 0x00000003,
2182 0x0000002c, 0x00000098, 0x000000cc, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2183 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2184 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2185 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x0000002c,
2186 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f,
2187 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x000003a8, 0x00010040, 0x000000ea, 0x04000059,
2188 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032,
2189 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
2190 0x02000068, 0x00000003, 0x0800000f, 0x00100012, 0x00000000, 0x00101046, 0x00000002, 0x00208046,
2191 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000002, 0x00208046,
2192 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
2193 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032,
2194 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001,
2195 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000001,
2196 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000,
2197 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a,
2198 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001,
2199 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042,
2200 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000,
2201 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a,
2202 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041,
2203 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000,
2204 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a,
2205 0x00000000, 0x00000001, 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046,
2206 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
2207 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
2208 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032,
2209 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x09000038,
2210 0x00100072, 0x00000001, 0x00208ff6, 0x00000000, 0x00000002, 0x00208246, 0x00000000, 0x00000002,
2211 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x07000010, 0x00100012, 0x00000001,
2212 0x00100246, 0x00000001, 0x00100246, 0x00000000, 0x09000038, 0x00100072, 0x00000002, 0x00208ff6,
2213 0x00000000, 0x00000003, 0x00208246, 0x00000000, 0x00000003, 0x07000010, 0x00100022, 0x00000001,
2214 0x00100246, 0x00000002, 0x00100246, 0x00000000, 0x0a000000, 0x00102032, 0x00000000, 0x00100046,
2215 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
2216 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
2218 static const DWORD vs_code_triangle[] =
2220 /* float3x2 transform;
2222 * float4 main(float4 position : POSITION) : SV_POSITION
2224 * return float4(mul(position.xyw, transform), position.zw);
2225 * } */
2226 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
2227 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2228 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
2229 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
2230 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
2231 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
2232 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
2233 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
2234 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
2235 0x00000000, 0x0100003e,
2237 /* ⎡p0.x p0.y 1⎤
2238 * A = ⎢p1.x p1.y 1⎥
2239 * ⎣p2.x p2.y 1⎦
2241 * ⎡0 0⎤
2242 * B = ⎢½ 0⎥
2243 * ⎣1 1⎦
2245 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2246 * ⎣p2.x-p0.x p2.y-p0.y⎦
2248 * B' = ⎡½ 0⎤
2249 * ⎣1 1⎦
2251 * A'T = B'
2252 * T = A'⁻¹B'
2254 static const DWORD vs_code_bezier_outline[] =
2256 #if 0
2257 float3x2 transform_geometry;
2258 float stroke_width;
2259 float4 transform_rtx;
2260 float4 transform_rty;
2262 float4 main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2263 float2 prev : PREV, float2 next : NEXT, out float4 texcoord : UV,
2264 out float2x2 stroke_transform : STROKE_TRANSFORM) : SV_POSITION
2266 float2 q_prev, q_next, v_p, q_i, p;
2267 float2x2 geom, rt;
2268 float l;
2270 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2271 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2272 stroke_transform = rt * stroke_width * 0.5f;
2274 p = mul(geom, position);
2275 p0 = mul(geom, p0);
2276 p1 = mul(geom, p1);
2277 p2 = mul(geom, p2);
2279 p -= p0;
2280 p1 -= p0;
2281 p2 -= p0;
2283 q_prev = normalize(mul(geom, prev));
2284 q_next = normalize(mul(geom, next));
2286 v_p = float2(-q_prev.y, q_prev.x);
2287 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2288 q_i = l * q_prev + v_p;
2289 p += stroke_width * q_i;
2291 v_p = mul(rt, p2);
2292 v_p = normalize(float2(-v_p.y, v_p.x));
2293 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
2295 texcoord.xzw = float3(0.0f, 0.0f, 0.0f);
2296 texcoord.y = dot(mul(rt, p), v_p);
2298 else
2300 texcoord.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
2301 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
2302 texcoord.x = dot(v_p, p1 - 0.5f * p2);
2303 texcoord.y = dot(v_p, p1);
2306 position = mul(geom, position)
2307 + float2(transform_geometry._31, transform_geometry._32) + stroke_width * q_i;
2308 position = mul(rt, position) + float2(transform_rtx.z, transform_rty.z);
2309 position = position * float2(transform_rtx.w, transform_rty.w) + float2(-1.0f, 1.0f);
2311 return float4(position, 0.0f, 1.0f);
2313 #endif
2314 0x43425844, 0x2b43c2df, 0x861ad5cd, 0x32b8fe33, 0x2d50f992, 0x00000001, 0x00000a9c, 0x00000003,
2315 0x0000002c, 0x000000e4, 0x00000174, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
2316 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
2317 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
2318 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
2319 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
2320 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
2321 0xababab00, 0x4e47534f, 0x00000088, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000001,
2322 0x00000003, 0x00000000, 0x0000000f, 0x00000074, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
2323 0x0000000f, 0x00000077, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000077,
2324 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x505f5653, 0x5449534f, 0x004e4f49,
2325 0x53005655, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x52444853, 0x00000920, 0x00010040,
2326 0x00000248, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2327 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x0300005f, 0x00101032,
2328 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f, 0x00101032, 0x00000005, 0x04000067,
2329 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032,
2330 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x02000068, 0x00000005, 0x0800000f, 0x00100012,
2331 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022,
2332 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042,
2333 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000,
2334 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046,
2335 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046,
2336 0x00000004, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046,
2337 0x00000004, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001,
2338 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001,
2339 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556,
2340 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046,
2341 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000,
2342 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e,
2343 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032,
2344 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001,
2345 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000,
2346 0x08000000, 0x00100012, 0x00000002, 0x0010000a, 0x00000001, 0x0020802a, 0x00000000, 0x00000000,
2347 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000,
2348 0x08000000, 0x00100022, 0x00000002, 0x0010001a, 0x00000001, 0x0020802a, 0x00000000, 0x00000001,
2349 0x0a000032, 0x001000c2, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x00100406, 0x00000000,
2350 0x00100406, 0x00000002, 0x0800000f, 0x00100042, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2351 0x00100ae6, 0x00000000, 0x0800000f, 0x00100042, 0x00000000, 0x00208046, 0x00000000, 0x00000003,
2352 0x00100ae6, 0x00000000, 0x08000000, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x0020802a,
2353 0x00000000, 0x00000003, 0x08000038, 0x00100022, 0x00000002, 0x0010002a, 0x00000000, 0x0020803a,
2354 0x00000000, 0x00000003, 0x08000000, 0x00100042, 0x00000000, 0x0010002a, 0x00000001, 0x0020802a,
2355 0x00000000, 0x00000002, 0x08000038, 0x00100012, 0x00000002, 0x0010002a, 0x00000000, 0x0020803a,
2356 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000000, 0x00100046, 0x00000002, 0x00004002,
2357 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002,
2358 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046,
2359 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000002, 0x00208046,
2360 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x001000c2, 0x00000000, 0x00100406,
2361 0x00000001, 0x80100406, 0x00000041, 0x00000002, 0x0a000032, 0x00100032, 0x00000000, 0x00208ff6,
2362 0x00000000, 0x00000001, 0x00100046, 0x00000000, 0x00100ae6, 0x00000000, 0x0800000f, 0x00100012,
2363 0x00000001, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f, 0x00100022,
2364 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f, 0x00100012,
2365 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f, 0x00100022,
2366 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000, 0x001000c2,
2367 0x00000001, 0x80100406, 0x00000041, 0x00000002, 0x00100406, 0x00000003, 0x0800000f, 0x00100082,
2368 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000001, 0x06000036, 0x00100042,
2369 0x00000002, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000002, 0x00208046,
2370 0x00000000, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000000, 0x00100ae6,
2371 0x00000002, 0x00100ae6, 0x00000002, 0x05000044, 0x00100082, 0x00000000, 0x0010003a, 0x00000000,
2372 0x07000038, 0x001000c2, 0x00000002, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000002, 0x0700000f,
2373 0x00100022, 0x00000003, 0x00100046, 0x00000001, 0x00100ae6, 0x00000002, 0x06000036, 0x00100042,
2374 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046,
2375 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00208046,
2376 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000004, 0x80100046,
2377 0x00000041, 0x00000002, 0x00100046, 0x00000001, 0x06000036, 0x00100042, 0x00000004, 0x8010001a,
2378 0x00000041, 0x00000004, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000004, 0x00100ae6,
2379 0x00000001, 0x0d000032, 0x00100032, 0x00000001, 0x80100ae6, 0x00000041, 0x00000001, 0x00004002,
2380 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000004, 0x0800000e, 0x00100032,
2381 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f, 0x00100012,
2382 0x00000001, 0x00100046, 0x00000000, 0x00100046, 0x00000001, 0x0700000f, 0x00100022, 0x00000001,
2383 0x00100046, 0x00000000, 0x00100046, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
2384 0x00000000, 0x00000002, 0x00100046, 0x00000004, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
2385 0x00000000, 0x00000003, 0x00100046, 0x00000004, 0x0700000f, 0x00100012, 0x00000000, 0x00100046,
2386 0x00000000, 0x00100ae6, 0x00000002, 0x07000031, 0x00100022, 0x00000000, 0x00004001, 0x00000000,
2387 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2388 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000, 0x00004001,
2389 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0010002a,
2390 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038, 0x001000c2,
2391 0x00000001, 0x00100ea6, 0x00000002, 0x00100556, 0x00000000, 0x08000036, 0x001000d2, 0x00000003,
2392 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2, 0x00000001,
2393 0x00100006, 0x00000000, 0x00100e46, 0x00000003, 0x00100e46, 0x00000001, 0x06000036, 0x00100032,
2394 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000, 0x00208406,
2395 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6,
2396 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002,
2397 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002, 0x00100086,
2398 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x0100003e,
2400 static const DWORD vs_code_bezier[] =
2402 #if 0
2403 float3x2 transform;
2405 float4 main(float4 position : POSITION,
2406 inout float3 texcoord : TEXCOORD0) : SV_POSITION
2408 return float4(mul(position.xyw, transform), position.zw);
2410 #endif
2411 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
2412 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
2413 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
2414 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
2415 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
2416 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
2417 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
2418 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
2419 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
2420 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
2421 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
2422 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
2423 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
2425 static const DWORD ps_code_triangle_solid[] =
2427 /* float4 color;
2429 * float4 main(float4 position : SV_POSITION) : SV_Target
2431 * return color;
2432 * } */
2433 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
2434 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2435 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
2436 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2437 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
2438 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
2439 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2441 static const DWORD ps_code_triangle_solid_bitmap[] =
2443 #if 0
2444 float4 color;
2446 float3x2 transform;
2447 float opacity;
2448 bool ignore_alpha;
2450 SamplerState s;
2451 Texture2D t;
2453 float4 main(float4 position : SV_POSITION) : SV_Target
2455 float2 texcoord;
2456 float4 ret;
2458 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2459 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2460 ret = t.Sample(s, texcoord) * opacity;
2461 if (ignore_alpha)
2462 ret.a = opacity;
2464 return color * ret.a;
2466 #endif
2467 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
2468 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2469 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2470 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2471 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
2472 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
2473 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2474 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2475 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
2476 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
2477 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
2478 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
2479 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
2480 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
2481 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
2482 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
2483 0x00000000, 0x0100003e,
2485 static const DWORD ps_code_triangle_bitmap[] =
2487 #if 0
2488 float3x2 transform;
2489 float opacity;
2490 bool ignore_alpha;
2492 SamplerState s;
2493 Texture2D t;
2495 float4 main(float4 position : SV_POSITION) : SV_Target
2497 float2 texcoord;
2498 float4 ret;
2500 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2501 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2502 ret = t.Sample(s, texcoord) * opacity;
2503 if (ignore_alpha)
2504 ret.a = opacity;
2506 return ret;
2508 #endif
2509 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
2510 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2511 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2512 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2513 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
2514 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
2515 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2516 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2517 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
2518 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
2519 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
2520 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
2521 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
2522 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
2523 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
2524 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
2526 static const DWORD ps_code_triangle_bitmap_solid[] =
2528 #if 0
2529 float3x2 transform;
2530 float opacity;
2531 bool ignore_alpha;
2533 float4 color;
2535 SamplerState s;
2536 Texture2D t;
2538 float4 main(float4 position : SV_POSITION) : SV_Target
2540 float2 texcoord;
2541 float4 ret;
2543 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2544 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2545 ret = t.Sample(s, texcoord) * opacity;
2546 if (ignore_alpha)
2547 ret.a = opacity;
2549 return ret * color.a;
2551 #endif
2552 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
2553 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2554 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2555 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2556 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
2557 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
2558 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2559 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2560 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
2561 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
2562 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
2563 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
2564 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
2565 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
2566 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
2567 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
2568 0x00000003, 0x0100003e,
2570 static const DWORD ps_code_triangle_bitmap_bitmap[] =
2572 #if 0
2573 struct brush
2575 float3x2 transform;
2576 float opacity;
2577 bool ignore_alpha;
2578 } brush0, brush1;
2580 SamplerState s0, s1;
2581 Texture2D t0, t1;
2583 float4 main(float4 position : SV_POSITION) : SV_Target
2585 float2 texcoord;
2586 float opacity;
2587 float4 ret;
2589 texcoord.x = position.x * brush0.transform._11 + position.y * brush0.transform._21 + brush0.transform._31;
2590 texcoord.y = position.x * brush0.transform._12 + position.y * brush0.transform._22 + brush0.transform._32;
2591 ret = t0.Sample(s0, texcoord) * brush0.opacity;
2592 if (brush0.ignore_alpha)
2593 ret.a = brush0.opacity;
2595 texcoord.x = position.x * brush1.transform._11 + position.y * brush1.transform._21 + brush1.transform._31;
2596 texcoord.y = position.x * brush1.transform._12 + position.y * brush1.transform._22 + brush1.transform._32;
2597 opacity = t1.Sample(s1, texcoord).a * brush1.opacity;
2598 if (brush1.ignore_alpha)
2599 opacity = brush1.opacity;
2601 return ret * opacity;
2603 #endif
2604 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
2605 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2606 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2607 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2608 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
2609 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
2610 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
2611 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
2612 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
2613 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
2614 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
2615 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
2616 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
2617 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
2618 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
2619 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
2620 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
2621 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
2622 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
2623 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
2624 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
2625 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
2626 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
2627 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
2628 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
2630 /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
2631 * using the screen-space partial derivatives to convert the calculated
2632 * distance to object space.
2634 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
2635 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
2636 * f(x, y) = u(x, y)² - v(x, y)
2637 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
2638 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
2639 static const DWORD ps_code_bezier_solid_outline[] =
2641 #if 0
2642 float4 color;
2644 float4 main(float4 position : SV_POSITION, float4 uv : UV,
2645 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM) : SV_Target
2647 float2 du, dv, df;
2649 du = float2(ddx(uv.x), ddy(uv.x));
2650 dv = float2(ddx(uv.y), ddy(uv.y));
2651 df = 2.0f * uv.x * du - dv;
2653 clip(dot(df, uv.zw));
2654 clip(length(mul(stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
2655 return color;
2657 #endif
2658 0x43425844, 0x9da521d4, 0x4c86449e, 0x4f2c1641, 0x6f798508, 0x00000001, 0x000002f4, 0x00000003,
2659 0x0000002c, 0x000000bc, 0x000000f0, 0x4e475349, 0x00000088, 0x00000004, 0x00000008, 0x00000068,
2660 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000074, 0x00000000, 0x00000000,
2661 0x00000003, 0x00000001, 0x00000f0f, 0x00000077, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2662 0x00000303, 0x00000077, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x505f5653,
2663 0x5449534f, 0x004e4f49, 0x53005655, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x4e47534f,
2664 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
2665 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000001fc, 0x00000040, 0x0000007f,
2666 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x001010f2, 0x00000001, 0x03000862,
2667 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003, 0x03000065, 0x001020f2, 0x00000000,
2668 0x02000068, 0x00000002, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
2669 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x07000000, 0x00100012, 0x00000001, 0x0010100a,
2670 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x00100032, 0x00000000, 0x00100006, 0x00000001,
2671 0x00100086, 0x00000000, 0x801005d6, 0x00000041, 0x00000000, 0x0700000f, 0x00100042, 0x00000000,
2672 0x00100046, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100042, 0x00000000, 0x0010002a,
2673 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010002a, 0x00000000, 0x07000038, 0x00100062,
2674 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100032, 0x00000000,
2675 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596, 0x00000000, 0x0700000f, 0x00100012,
2676 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
2677 0x0010000a, 0x00000000, 0x0a000032, 0x00100022, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a,
2678 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012, 0x00000000, 0x8010001a,
2679 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012, 0x00000000, 0x0010000a,
2680 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x06000036, 0x001020f2,
2681 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2683 /* The basic idea here is to evaluate the implicit form of the curve in
2684 * texture space. "t.z" determines which side of the curve is shaded. */
2685 static const DWORD ps_code_bezier_solid[] =
2687 #if 0
2688 float4 color;
2690 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
2692 clip((t.x * t.x - t.y) * t.z);
2693 return color;
2695 #endif
2696 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
2697 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
2698 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
2699 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
2700 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
2701 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
2702 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
2703 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
2704 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
2705 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
2706 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
2707 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2709 static const struct brush_shader
2711 const void *byte_code;
2712 size_t byte_code_size;
2713 enum d2d_shape_type shape_type;
2714 enum d2d_brush_type brush_type;
2715 enum d2d_brush_type opacity_brush_type;
2717 brush_shaders[] =
2719 {ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
2720 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2721 {ps_code_triangle_solid_bitmap, sizeof(ps_code_triangle_solid_bitmap),
2722 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_BITMAP},
2723 {ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
2724 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_COUNT},
2725 {ps_code_triangle_bitmap_solid, sizeof(ps_code_triangle_bitmap_solid),
2726 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_SOLID},
2727 {ps_code_triangle_bitmap_bitmap, sizeof(ps_code_triangle_bitmap_bitmap),
2728 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_BITMAP},
2729 {ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
2730 D2D_SHAPE_TYPE_BEZIER, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2731 {ps_code_bezier_solid_outline, sizeof(ps_code_bezier_solid_outline),
2732 D2D_SHAPE_TYPE_BEZIER_OUTLINE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2734 static const struct
2736 float x, y;
2738 quad[] =
2740 {-1.0f, 1.0f},
2741 {-1.0f, -1.0f},
2742 { 1.0f, 1.0f},
2743 { 1.0f, -1.0f},
2745 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
2746 float dpi_x, dpi_y;
2748 dpi_x = desc->dpiX;
2749 dpi_y = desc->dpiY;
2751 if (dpi_x == 0.0f && dpi_y == 0.0f)
2753 dpi_x = 96.0f;
2754 dpi_y = 96.0f;
2756 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
2757 return E_INVALIDARG;
2759 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
2760 WARN("Ignoring render target type %#x.\n", desc->type);
2761 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
2762 FIXME("Ignoring render target usage %#x.\n", desc->usage);
2763 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
2764 WARN("Ignoring feature level %#x.\n", desc->minLevel);
2766 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
2767 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
2768 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
2769 render_target->refcount = 1;
2770 render_target->factory = factory;
2771 ID2D1Factory_AddRef(render_target->factory);
2773 render_target->outer_unknown = outer_unknown ? outer_unknown :
2774 (IUnknown *)&render_target->ID2D1RenderTarget_iface;
2776 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
2778 WARN("Failed to get device interface, hr %#x.\n", hr);
2779 ID2D1Factory_Release(render_target->factory);
2780 return hr;
2783 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2785 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2786 goto err;
2789 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
2790 ID3D10Resource_Release(resource);
2791 if (FAILED(hr))
2793 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2794 goto err;
2797 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
2799 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
2800 goto err;
2803 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
2805 WARN("Failed to create stateblock, hr %#x.\n", hr);
2806 goto err;
2809 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_outline,
2810 ARRAY_SIZE(il_desc_outline), vs_code_outline, sizeof(vs_code_outline),
2811 &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE].il)))
2813 WARN("Failed to create outline input layout, hr %#x.\n", hr);
2814 goto err;
2817 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
2818 ARRAY_SIZE(il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
2819 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
2821 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
2822 goto err;
2825 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier_outline,
2826 ARRAY_SIZE(il_desc_bezier_outline), vs_code_bezier_outline, sizeof(vs_code_bezier_outline),
2827 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER_OUTLINE].il)))
2829 WARN("Failed to create bezier outline input layout, hr %#x.\n", hr);
2830 goto err;
2833 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
2834 ARRAY_SIZE(il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
2835 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
2837 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
2838 goto err;
2841 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_outline,
2842 sizeof(vs_code_outline), &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE].vs)))
2844 WARN("Failed to create outline vertex shader, hr %#x.\n", hr);
2845 goto err;
2848 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier_outline,
2849 sizeof(vs_code_bezier_outline), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER_OUTLINE].vs)))
2851 WARN("Failed to create bezier outline vertex shader, hr %#x.\n", hr);
2852 goto err;
2855 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
2856 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
2858 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
2859 goto err;
2862 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
2863 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
2865 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
2866 goto err;
2869 for (i = 0; i < ARRAY_SIZE(brush_shaders); ++i)
2871 const struct brush_shader *bs = &brush_shaders[i];
2872 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, bs->byte_code, bs->byte_code_size,
2873 &render_target->shape_resources[bs->shape_type].ps[bs->brush_type][bs->opacity_brush_type])))
2875 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
2876 bs->shape_type, bs->brush_type, bs->opacity_brush_type);
2877 goto err;
2881 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2883 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2885 struct d2d_shape_resources *outline = &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE];
2886 struct d2d_shape_resources *triangle = &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE];
2888 if (triangle->ps[j][k])
2889 ID3D10PixelShader_AddRef(outline->ps[j][k] = triangle->ps[j][k]);
2893 buffer_desc.ByteWidth = sizeof(indices);
2894 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
2895 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
2896 buffer_desc.CPUAccessFlags = 0;
2897 buffer_desc.MiscFlags = 0;
2899 buffer_data.pSysMem = indices;
2900 buffer_data.SysMemPitch = 0;
2901 buffer_data.SysMemSlicePitch = 0;
2903 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2904 &buffer_desc, &buffer_data, &render_target->ib)))
2906 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
2907 goto err;
2910 buffer_desc.ByteWidth = sizeof(quad);
2911 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
2912 buffer_data.pSysMem = quad;
2914 render_target->vb_stride = sizeof(*quad);
2915 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2916 &buffer_desc, &buffer_data, &render_target->vb)))
2918 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
2919 goto err;
2922 rs_desc.FillMode = D3D10_FILL_SOLID;
2923 rs_desc.CullMode = D3D10_CULL_NONE;
2924 rs_desc.FrontCounterClockwise = FALSE;
2925 rs_desc.DepthBias = 0;
2926 rs_desc.DepthBiasClamp = 0.0f;
2927 rs_desc.SlopeScaledDepthBias = 0.0f;
2928 rs_desc.DepthClipEnable = TRUE;
2929 rs_desc.ScissorEnable = TRUE;
2930 rs_desc.MultisampleEnable = FALSE;
2931 rs_desc.AntialiasedLineEnable = FALSE;
2932 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
2934 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
2935 goto err;
2938 memset(&blend_desc, 0, sizeof(blend_desc));
2939 blend_desc.BlendEnable[0] = TRUE;
2940 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2941 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2942 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2943 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2945 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2946 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2948 else
2950 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2951 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2953 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2954 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2955 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
2957 WARN("Failed to create blend state, hr %#x.\n", hr);
2958 goto err;
2961 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
2962 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
2964 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2965 goto err;
2968 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
2969 IDWriteFactory_Release(dwrite_factory);
2970 if (FAILED(hr))
2972 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
2973 goto err;
2976 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2978 WARN("Failed to get surface desc, hr %#x.\n", hr);
2979 goto err;
2982 render_target->desc.pixelFormat = desc->pixelFormat;
2983 render_target->pixel_size.width = surface_desc.Width;
2984 render_target->pixel_size.height = surface_desc.Height;
2985 render_target->drawing_state.transform = identity;
2987 if (!d2d_clip_stack_init(&render_target->clip_stack))
2989 WARN("Failed to initialize clip stack.\n");
2990 hr = E_FAIL;
2991 goto err;
2994 render_target->desc.dpiX = dpi_x;
2995 render_target->desc.dpiY = dpi_y;
2997 return S_OK;
2999 err:
3000 if (render_target->default_text_rendering_params)
3001 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
3002 if (render_target->bs)
3003 ID3D10BlendState_Release(render_target->bs);
3004 if (render_target->rs)
3005 ID3D10RasterizerState_Release(render_target->rs);
3006 if (render_target->vb)
3007 ID3D10Buffer_Release(render_target->vb);
3008 if (render_target->ib)
3009 ID3D10Buffer_Release(render_target->ib);
3010 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
3012 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
3014 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
3016 if (render_target->shape_resources[i].ps[j][k])
3017 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
3020 if (render_target->shape_resources[i].vs)
3021 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
3022 if (render_target->shape_resources[i].il)
3023 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
3025 if (render_target->stateblock)
3026 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
3027 if (render_target->view)
3028 ID3D10RenderTargetView_Release(render_target->view);
3029 if (render_target->device)
3030 ID3D10Device_Release(render_target->device);
3031 ID2D1Factory_Release(render_target->factory);
3032 return hr;
3035 HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown,
3036 const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target)
3038 struct d2d_d3d_render_target *object;
3039 HRESULT hr;
3041 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
3042 return E_OUTOFMEMORY;
3044 if (FAILED(hr = d2d_d3d_render_target_init(object, factory, surface, outer_unknown, desc)))
3046 WARN("Failed to initialize render target, hr %#x.\n", hr);
3047 HeapFree(GetProcessHeap(), 0, object);
3048 return hr;
3051 TRACE("Created render target %p.\n", object);
3052 *render_target = &object->ID2D1RenderTarget_iface;
3054 return S_OK;
3057 HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1 *surface)
3059 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
3060 DXGI_SURFACE_DESC surface_desc;
3061 ID3D10RenderTargetView *view;
3062 ID3D10Resource *resource;
3063 HRESULT hr;
3065 if (!surface)
3067 ID3D10RenderTargetView_Release(render_target->view);
3068 render_target->view = NULL;
3069 return S_OK;
3072 if (FAILED(hr = IDXGISurface1_GetDesc(surface, &surface_desc)))
3074 WARN("Failed to get surface desc, hr %#x.\n", hr);
3075 return hr;
3078 if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
3080 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
3081 return hr;
3084 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &view);
3085 ID3D10Resource_Release(resource);
3086 if (FAILED(hr))
3088 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
3089 return hr;
3092 render_target->pixel_size.width = surface_desc.Width;
3093 render_target->pixel_size.height = surface_desc.Height;
3094 if (render_target->view)
3095 ID3D10RenderTargetView_Release(render_target->view);
3096 render_target->view = view;
3098 return S_OK;