msvcirt: Implement stdiostream constructors.
[wine.git] / dlls / d2d1 / render_target.c
blobbc31f4d48a71168ecdb63f4a3e71d3aa755331ab
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 struct d2d_draw_text_layout_ctx
30 ID2D1Brush *brush;
31 D2D1_DRAW_TEXT_OPTIONS options;
34 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
36 ID2D1Brush *brush = NULL;
38 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
39 return brush;
41 ID2D1Brush_AddRef(context->brush);
42 return context->brush;
45 static void d2d_point_set(D2D1_POINT_2F *dst, float x, float y)
47 dst->x = x;
48 dst->y = y;
51 static void d2d_point_transform(D2D1_POINT_2F *dst, const D2D1_MATRIX_3X2_F *matrix, float x, float y)
53 dst->x = x * matrix->_11 + y * matrix->_21 + matrix->_31;
54 dst->y = x * matrix->_12 + y * matrix->_22 + matrix->_32;
57 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
59 if (point->x < dst->left)
60 dst->left = point->x;
61 if (point->y < dst->top)
62 dst->top = point->y;
63 if (point->x > dst->right)
64 dst->right = point->x;
65 if (point->y > dst->bottom)
66 dst->bottom = point->y;
69 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
71 if (src->left > dst->left)
72 dst->left = src->left;
73 if (src->top > dst->top)
74 dst->top = src->top;
75 if (src->right < dst->right)
76 dst->right = src->right;
77 if (src->bottom < dst->bottom)
78 dst->bottom = src->bottom;
81 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
83 dst->left = left;
84 dst->top = top;
85 dst->right = right;
86 dst->bottom = bottom;
89 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
91 dst->width = width;
92 dst->height = height;
95 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
97 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
98 return FALSE;
100 stack->size = INITIAL_CLIP_STACK_SIZE;
101 stack->count = 0;
103 return TRUE;
106 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
108 HeapFree(GetProcessHeap(), 0, stack->stack);
111 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
113 D2D1_RECT_F r;
115 if (stack->count == stack->size)
117 D2D1_RECT_F *new_stack;
118 unsigned int new_size;
120 if (stack->size > UINT_MAX / 2)
121 return FALSE;
123 new_size = stack->size * 2;
124 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
125 return FALSE;
127 stack->stack = new_stack;
128 stack->size = new_size;
131 r = *rect;
132 if (stack->count)
133 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
134 stack->stack[stack->count++] = r;
136 return TRUE;
139 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
141 if (!stack->count)
142 return;
143 --stack->count;
146 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
147 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
148 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
150 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
151 ID3D10Device *device = render_target->device;
152 D3D10_RECT scissor_rect;
153 unsigned int offset;
154 D3D10_VIEWPORT vp;
155 HRESULT hr;
157 vp.TopLeftX = 0;
158 vp.TopLeftY = 0;
159 vp.Width = render_target->pixel_size.width;
160 vp.Height = render_target->pixel_size.height;
161 vp.MinDepth = 0.0f;
162 vp.MaxDepth = 1.0f;
164 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
166 WARN("Failed to capture stateblock, hr %#x.\n", hr);
167 return;
170 ID3D10Device_ClearState(device);
172 ID3D10Device_IASetInputLayout(device, shape_resources->il);
173 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
174 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
175 offset = 0;
176 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
177 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
178 ID3D10Device_VSSetShader(device, shape_resources->vs);
179 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
180 ID3D10Device_RSSetViewports(device, 1, &vp);
181 if (render_target->clip_stack.count)
183 const D2D1_RECT_F *clip_rect;
185 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
186 scissor_rect.left = clip_rect->left + 0.5f;
187 scissor_rect.top = clip_rect->top + 0.5f;
188 scissor_rect.right = clip_rect->right + 0.5f;
189 scissor_rect.bottom = clip_rect->bottom + 0.5f;
191 else
193 scissor_rect.left = 0.0f;
194 scissor_rect.top = 0.0f;
195 scissor_rect.right = render_target->pixel_size.width;
196 scissor_rect.bottom = render_target->pixel_size.height;
198 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
199 ID3D10Device_RSSetState(device, render_target->rs);
200 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
201 if (brush)
202 d2d_brush_bind_resources(brush, opacity_brush, render_target, shape_type);
203 else
204 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID][D2D_BRUSH_TYPE_COUNT]);
206 if (ib)
207 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
208 else
209 ID3D10Device_Draw(device, index_count, 0);
211 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
212 WARN("Failed to apply stateblock, hr %#x.\n", hr);
215 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
217 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
220 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
222 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
224 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
225 || IsEqualGUID(iid, &IID_ID2D1Resource)
226 || IsEqualGUID(iid, &IID_IUnknown))
228 ID2D1RenderTarget_AddRef(iface);
229 *out = iface;
230 return S_OK;
233 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
235 *out = NULL;
236 return E_NOINTERFACE;
239 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
241 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
242 ULONG refcount = InterlockedIncrement(&render_target->refcount);
244 TRACE("%p increasing refcount to %u.\n", iface, refcount);
246 return refcount;
249 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
251 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
252 ULONG refcount = InterlockedDecrement(&render_target->refcount);
254 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
256 if (!refcount)
258 unsigned int i, j, k;
260 d2d_clip_stack_cleanup(&render_target->clip_stack);
261 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
262 if (render_target->text_rendering_params)
263 IDWriteRenderingParams_Release(render_target->text_rendering_params);
264 ID3D10BlendState_Release(render_target->bs);
265 ID3D10RasterizerState_Release(render_target->rs);
266 ID3D10Buffer_Release(render_target->vb);
267 ID3D10Buffer_Release(render_target->ib);
268 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
270 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
272 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
274 if (render_target->shape_resources[i].ps[j][k])
275 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
278 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
279 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
281 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
282 ID3D10RenderTargetView_Release(render_target->view);
283 ID3D10Device_Release(render_target->device);
284 ID2D1Factory_Release(render_target->factory);
285 HeapFree(GetProcessHeap(), 0, render_target);
288 return refcount;
291 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
293 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
295 TRACE("iface %p, factory %p.\n", iface, factory);
297 *factory = render_target->factory;
298 ID2D1Factory_AddRef(*factory);
301 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
302 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
304 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
305 struct d2d_bitmap *object;
306 HRESULT hr;
308 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
309 iface, size.width, size.height, src_data, pitch, desc, bitmap);
311 if (SUCCEEDED(hr = d2d_bitmap_create(render_target->factory, render_target->device, size, src_data, pitch, desc, &object)))
312 *bitmap = &object->ID2D1Bitmap_iface;
314 return hr;
317 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
318 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
320 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
321 struct d2d_bitmap *object;
322 HRESULT hr;
324 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
325 iface, bitmap_source, desc, bitmap);
327 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(render_target->factory, render_target->device, bitmap_source,
328 desc, &object)))
329 *bitmap = &object->ID2D1Bitmap_iface;
331 return hr;
334 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
335 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
337 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
338 struct d2d_bitmap *object;
339 HRESULT hr;
341 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
342 iface, debugstr_guid(iid), data, desc, bitmap);
344 if (SUCCEEDED(hr = d2d_bitmap_create_shared(iface, render_target->device, iid, data, desc, &object)))
345 *bitmap = &object->ID2D1Bitmap_iface;
347 return hr;
350 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
351 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
352 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
354 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
355 struct d2d_brush *object;
356 HRESULT hr;
358 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
359 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
361 if (SUCCEEDED(hr = d2d_bitmap_brush_create(render_target->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
362 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
364 return hr;
367 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
368 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
370 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
371 struct d2d_brush *object;
372 HRESULT hr;
374 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
376 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
377 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
379 return hr;
382 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
383 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
384 ID2D1GradientStopCollection **gradient)
386 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
387 struct d2d_gradient *object;
388 HRESULT hr;
390 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
391 iface, stops, stop_count, gamma, extend_mode, gradient);
393 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, stops, stop_count, gamma, extend_mode, &object)))
394 *gradient = &object->ID2D1GradientStopCollection_iface;
396 return hr;
399 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
400 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
401 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
403 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
404 struct d2d_brush *object;
405 HRESULT hr;
407 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
408 iface, gradient_brush_desc, brush_desc, gradient, brush);
410 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
411 gradient, &object)))
412 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
414 return hr;
417 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
418 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
419 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
421 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
422 iface, gradient_brush_desc, brush_desc, gradient, brush);
424 return E_NOTIMPL;
427 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
428 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
429 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
431 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
432 struct d2d_bitmap_render_target *object;
433 HRESULT hr;
435 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
436 iface, size, pixel_size, format, options, rt);
438 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
439 return E_OUTOFMEMORY;
441 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
442 format, options)))
444 WARN("Failed to initialize render target, hr %#x.\n", hr);
445 HeapFree(GetProcessHeap(), 0, object);
446 return hr;
449 TRACE("Created render target %p.\n", object);
450 *rt = &object->ID2D1BitmapRenderTarget_iface;
452 return S_OK;
455 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
456 const D2D1_SIZE_F *size, ID2D1Layer **layer)
458 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
460 return E_NOTIMPL;
463 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
465 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
466 struct d2d_mesh *object;
467 HRESULT hr;
469 TRACE("iface %p, mesh %p.\n", iface, mesh);
471 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
472 *mesh = &object->ID2D1Mesh_iface;
474 return hr;
477 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
478 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
480 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
481 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
484 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
485 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
487 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
488 ID2D1RectangleGeometry *geometry;
489 HRESULT hr;
491 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
492 iface, rect, brush, stroke_width, stroke_style);
494 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
496 ERR("Failed to create geometry, hr %#x.\n", hr);
497 return;
500 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
501 ID2D1RectangleGeometry_Release(geometry);
504 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
505 const D2D1_RECT_F *rect, ID2D1Brush *brush)
507 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
508 ID2D1RectangleGeometry *geometry;
509 HRESULT hr;
511 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
513 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
515 ERR("Failed to create geometry, hr %#x.\n", hr);
516 return;
519 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
520 ID2D1RectangleGeometry_Release(geometry);
523 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
524 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
526 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
527 ID2D1RoundedRectangleGeometry *geometry;
528 HRESULT hr;
530 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
531 iface, rect, brush, stroke_width, stroke_style);
533 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
535 ERR("Failed to create geometry, hr %#x.\n", hr);
536 return;
539 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
540 ID2D1RoundedRectangleGeometry_Release(geometry);
543 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
544 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
546 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
547 ID2D1RoundedRectangleGeometry *geometry;
548 HRESULT hr;
550 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
552 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
554 ERR("Failed to create geometry, hr %#x.\n", hr);
555 return;
558 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
559 ID2D1RoundedRectangleGeometry_Release(geometry);
562 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
563 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
565 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
566 ID2D1EllipseGeometry *geometry;
567 HRESULT hr;
569 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
570 iface, ellipse, brush, stroke_width, stroke_style);
572 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
574 ERR("Failed to create geometry, hr %#x.\n", hr);
575 return;
578 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
579 ID2D1EllipseGeometry_Release(geometry);
582 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
583 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
585 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
586 ID2D1EllipseGeometry *geometry;
587 HRESULT hr;
589 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
591 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
593 ERR("Failed to create geometry, hr %#x.\n", hr);
594 return;
597 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
598 ID2D1EllipseGeometry_Release(geometry);
601 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
602 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
604 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
605 iface, geometry, brush, stroke_width, stroke_style);
608 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
609 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
611 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
612 D3D10_SUBRESOURCE_DATA buffer_data;
613 D3D10_BUFFER_DESC buffer_desc;
614 D2D1_MATRIX_3X2_F w, g;
615 float tmp_x, tmp_y;
616 HRESULT hr;
617 struct
619 float _11, _21, _31, pad0;
620 float _12, _22, _32, pad1;
621 } transform;
623 tmp_x = (2.0f * render_target->desc.dpiX) / (96.0f * render_target->pixel_size.width);
624 tmp_y = -(2.0f * render_target->desc.dpiY) / (96.0f * render_target->pixel_size.height);
625 w = render_target->drawing_state.transform;
626 w._11 *= tmp_x;
627 w._21 *= tmp_x;
628 w._31 = w._31 * tmp_x - 1.0f;
629 w._12 *= tmp_y;
630 w._22 *= tmp_y;
631 w._32 = w._32 * tmp_y + 1.0f;
633 g = geometry->transform;
634 d2d_matrix_multiply(&g, &w);
636 transform._11 = g._11;
637 transform._21 = g._21;
638 transform._31 = g._31;
639 transform.pad0 = 0.0f;
640 transform._12 = g._12;
641 transform._22 = g._22;
642 transform._32 = g._32;
643 transform.pad1 = 0.0f;
645 buffer_desc.ByteWidth = sizeof(transform);
646 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
647 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
648 buffer_desc.CPUAccessFlags = 0;
649 buffer_desc.MiscFlags = 0;
651 buffer_data.pSysMem = &transform;
652 buffer_data.SysMemPitch = 0;
653 buffer_data.SysMemSlicePitch = 0;
655 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
657 WARN("Failed to create constant buffer, hr %#x.\n", hr);
658 return;
661 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, render_target, &ps_cb)))
663 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
664 ID3D10Buffer_Release(vs_cb);
665 return;
668 if (geometry->face_count)
670 buffer_desc.ByteWidth = geometry->face_count * sizeof(*geometry->faces);
671 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
672 buffer_data.pSysMem = geometry->faces;
674 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
676 WARN("Failed to create index buffer, hr %#x.\n", hr);
677 goto done;
680 buffer_desc.ByteWidth = geometry->vertex_count * sizeof(*geometry->vertices);
681 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
682 buffer_data.pSysMem = geometry->vertices;
684 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
686 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
687 ID3D10Buffer_Release(ib);
688 goto done;
691 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->face_count, vb,
692 sizeof(*geometry->vertices), vs_cb, ps_cb, brush, opacity_brush);
694 ID3D10Buffer_Release(vb);
695 ID3D10Buffer_Release(ib);
698 if (geometry->bezier_count)
700 buffer_desc.ByteWidth = geometry->bezier_count * sizeof(*geometry->beziers);
701 buffer_data.pSysMem = geometry->beziers;
703 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
705 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
706 goto done;
709 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, 3 * geometry->bezier_count, vb,
710 sizeof(*geometry->beziers->v), vs_cb, ps_cb, brush, opacity_brush);
712 ID3D10Buffer_Release(vb);
715 done:
716 ID3D10Buffer_Release(ps_cb);
717 ID3D10Buffer_Release(vs_cb);
720 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
721 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
723 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
724 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
725 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
726 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
728 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
730 if (FAILED(render_target->error.code))
731 return;
733 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
735 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
736 render_target->error.tag1 = render_target->drawing_state.tag1;
737 render_target->error.tag2 = render_target->drawing_state.tag2;
738 return;
741 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
744 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
745 ID2D1Mesh *mesh, ID2D1Brush *brush)
747 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
750 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
751 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
752 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
754 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
755 iface, mask, brush, content, dst_rect, src_rect);
758 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
759 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
760 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
762 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
763 D2D1_BRUSH_PROPERTIES brush_desc;
764 ID2D1BitmapBrush *brush;
765 D2D1_RECT_F s, d;
766 HRESULT hr;
768 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
769 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
771 if (src_rect)
773 s = *src_rect;
775 else
777 D2D1_SIZE_F size;
779 size = ID2D1Bitmap_GetSize(bitmap);
780 s.left = 0.0f;
781 s.top = 0.0f;
782 s.right = size.width;
783 s.bottom = size.height;
786 if (dst_rect)
788 d = *dst_rect;
790 else
792 d.left = 0.0f;
793 d.top = 0.0f;
794 d.right = s.right - s.left;
795 d.bottom = s.bottom - s.top;
798 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
799 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
800 bitmap_brush_desc.interpolationMode = interpolation_mode;
802 brush_desc.opacity = opacity;
803 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
804 brush_desc.transform._21 = 0.0f;
805 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
806 brush_desc.transform._12 = 0.0f;
807 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
808 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
810 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
812 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
813 return;
816 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
817 ID2D1BitmapBrush_Release(brush);
820 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
821 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
822 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
824 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
825 IDWriteTextLayout *text_layout;
826 IDWriteFactory *dwrite_factory;
827 D2D1_POINT_2F origin;
828 HRESULT hr;
830 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
831 "brush %p, options %#x, measuring_mode %#x.\n",
832 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
833 brush, options, measuring_mode);
835 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
836 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
838 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
839 return;
842 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
843 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
844 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
845 else
846 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
847 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
848 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
849 IDWriteFactory_Release(dwrite_factory);
850 if (FAILED(hr))
852 ERR("Failed to create text layout, hr %#x.\n", hr);
853 return;
856 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
857 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
858 IDWriteTextLayout_Release(text_layout);
861 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
862 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
864 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
865 struct d2d_draw_text_layout_ctx ctx;
866 HRESULT hr;
868 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
869 iface, origin.x, origin.y, layout, brush, options);
871 ctx.brush = brush;
872 ctx.options = options;
874 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
875 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
876 FIXME("Failed to draw text layout, hr %#x.\n", hr);
879 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
880 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
882 D2D1_MATRIX_3X2_F *transform, prev_transform;
883 ID2D1PathGeometry *geometry;
884 ID2D1GeometrySink *sink;
885 HRESULT hr;
887 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
889 ERR("Failed to create geometry, hr %#x.\n", hr);
890 return;
893 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
895 ERR("Failed to open geometry sink, hr %#x.\n", hr);
896 ID2D1PathGeometry_Release(geometry);
897 return;
900 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
901 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
902 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
904 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
905 ID2D1GeometrySink_Release(sink);
906 ID2D1PathGeometry_Release(geometry);
907 return;
910 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
911 ERR("Failed to close geometry sink, hr %#x.\n", hr);
912 ID2D1GeometrySink_Release(sink);
914 transform = &render_target->drawing_state.transform;
915 prev_transform = *transform;
916 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
917 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
918 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
919 unsafe_impl_from_ID2D1Brush(brush), NULL);
920 *transform = prev_transform;
922 ID2D1PathGeometry_Release(geometry);
925 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
926 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
927 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode)
929 ID2D1RectangleGeometry *geometry = NULL;
930 ID2D1BitmapBrush *opacity_brush = NULL;
931 D2D1_BITMAP_PROPERTIES bitmap_desc;
932 ID2D1Bitmap *opacity_bitmap = NULL;
933 IDWriteGlyphRunAnalysis *analysis;
934 DWRITE_TEXTURE_TYPE texture_type;
935 D2D1_BRUSH_PROPERTIES brush_desc;
936 IDWriteFactory *dwrite_factory;
937 void *opacity_values = NULL;
938 size_t opacity_values_size;
939 D2D1_SIZE_U bitmap_size;
940 D2D1_RECT_F run_rect;
941 RECT bounds;
942 HRESULT hr;
944 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
945 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
947 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
948 return;
951 hr = IDWriteFactory_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, ppd, NULL,
952 rendering_mode, measuring_mode, baseline_origin.x, baseline_origin.y, &analysis);
953 IDWriteFactory_Release(dwrite_factory);
954 if (FAILED(hr))
956 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
957 return;
960 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
961 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
962 else
963 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
965 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
967 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
968 goto done;
971 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
972 if (!bitmap_size.width || !bitmap_size.height)
974 /* Empty run, nothing to do. */
975 goto done;
978 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
979 bitmap_size.width *= 3;
980 opacity_values_size = bitmap_size.width * bitmap_size.height;
981 if (!(opacity_values = HeapAlloc(GetProcessHeap(), 0, opacity_values_size)))
983 ERR("Failed to allocate opacity values.\n");
984 goto done;
987 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
988 texture_type, &bounds, opacity_values, opacity_values_size)))
990 ERR("Failed to create alpha texture, hr %#x.\n", hr);
991 goto done;
994 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
995 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
996 bitmap_desc.dpiX = render_target->desc.dpiX;
997 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
998 bitmap_desc.dpiX *= 3.0f;
999 bitmap_desc.dpiY = render_target->desc.dpiY;
1000 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
1001 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1003 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1004 goto done;
1007 brush_desc.opacity = 1.0f;
1008 brush_desc.transform._11 = 1.0f;
1009 brush_desc.transform._12 = 0.0f;
1010 brush_desc.transform._21 = 0.0f;
1011 brush_desc.transform._22 = 1.0f;
1012 brush_desc.transform._31 = bounds.left;
1013 brush_desc.transform._32 = bounds.top;
1014 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
1015 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1017 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1018 goto done;
1021 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
1022 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1024 ERR("Failed to create geometry, hr %#x.\n", hr);
1025 goto done;
1028 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1029 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1031 done:
1032 if (geometry)
1033 ID2D1RectangleGeometry_Release(geometry);
1034 if (opacity_brush)
1035 ID2D1BitmapBrush_Release(opacity_brush);
1036 if (opacity_bitmap)
1037 ID2D1Bitmap_Release(opacity_bitmap);
1038 HeapFree(GetProcessHeap(), 0, opacity_values);
1039 IDWriteGlyphRunAnalysis_Release(analysis);
1042 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
1043 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1044 DWRITE_MEASURING_MODE measuring_mode)
1046 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1047 IDWriteRenderingParams *rendering_params;
1048 DWRITE_RENDERING_MODE rendering_mode;
1049 HRESULT hr;
1050 float ppd;
1052 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1053 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
1055 if (FAILED(render_target->error.code))
1056 return;
1058 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
1059 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
1061 ppd = max(render_target->desc.dpiX, render_target->desc.dpiY) / 96.0f;
1062 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1063 : render_target->default_text_rendering_params;
1064 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1065 ppd, measuring_mode, rendering_params, &rendering_mode)))
1067 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1068 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1071 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1072 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1073 else
1074 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1075 ppd, rendering_mode, measuring_mode);
1078 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1079 const D2D1_MATRIX_3X2_F *transform)
1081 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1083 TRACE("iface %p, transform %p.\n", iface, transform);
1085 render_target->drawing_state.transform = *transform;
1088 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1089 D2D1_MATRIX_3X2_F *transform)
1091 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1093 TRACE("iface %p, transform %p.\n", iface, transform);
1095 *transform = render_target->drawing_state.transform;
1098 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1099 D2D1_ANTIALIAS_MODE antialias_mode)
1101 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1103 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1105 render_target->drawing_state.antialiasMode = antialias_mode;
1108 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1110 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1112 TRACE("iface %p.\n", iface);
1114 return render_target->drawing_state.antialiasMode;
1117 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1118 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1120 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1122 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1124 render_target->drawing_state.textAntialiasMode = antialias_mode;
1127 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1129 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1131 TRACE("iface %p.\n", iface);
1133 return render_target->drawing_state.textAntialiasMode;
1136 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1137 IDWriteRenderingParams *text_rendering_params)
1139 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1141 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1143 if (text_rendering_params)
1144 IDWriteRenderingParams_AddRef(text_rendering_params);
1145 if (render_target->text_rendering_params)
1146 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1147 render_target->text_rendering_params = text_rendering_params;
1150 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1151 IDWriteRenderingParams **text_rendering_params)
1153 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1155 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1157 if ((*text_rendering_params = render_target->text_rendering_params))
1158 IDWriteRenderingParams_AddRef(*text_rendering_params);
1161 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1163 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1165 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1167 render_target->drawing_state.tag1 = tag1;
1168 render_target->drawing_state.tag2 = tag2;
1171 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1173 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1175 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1177 *tag1 = render_target->drawing_state.tag1;
1178 *tag2 = render_target->drawing_state.tag2;
1181 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1182 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1184 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1187 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1189 FIXME("iface %p stub!\n", iface);
1192 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1194 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1196 return E_NOTIMPL;
1199 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1200 ID2D1DrawingStateBlock *state_block)
1202 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1203 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1205 TRACE("iface %p, state_block %p.\n", iface, state_block);
1207 state_block_impl->drawing_state = render_target->drawing_state;
1208 if (render_target->text_rendering_params)
1209 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1210 if (state_block_impl->text_rendering_params)
1211 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1212 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1215 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1216 ID2D1DrawingStateBlock *state_block)
1218 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1219 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1221 TRACE("iface %p, state_block %p.\n", iface, state_block);
1223 render_target->drawing_state = state_block_impl->drawing_state;
1224 if (state_block_impl->text_rendering_params)
1225 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1226 if (render_target->text_rendering_params)
1227 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1228 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1231 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1232 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1234 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1235 D2D1_RECT_F transformed_rect;
1236 float x_scale, y_scale;
1237 D2D1_POINT_2F point;
1239 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1241 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1242 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1244 x_scale = render_target->desc.dpiX / 96.0f;
1245 y_scale = render_target->desc.dpiY / 96.0f;
1246 d2d_point_transform(&point, &render_target->drawing_state.transform,
1247 clip_rect->left * x_scale, clip_rect->top * y_scale);
1248 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1249 d2d_point_transform(&point, &render_target->drawing_state.transform,
1250 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1251 d2d_rect_expand(&transformed_rect, &point);
1252 d2d_point_transform(&point, &render_target->drawing_state.transform,
1253 clip_rect->right * x_scale, clip_rect->top * y_scale);
1254 d2d_rect_expand(&transformed_rect, &point);
1255 d2d_point_transform(&point, &render_target->drawing_state.transform,
1256 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1257 d2d_rect_expand(&transformed_rect, &point);
1259 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1260 WARN("Failed to push clip rect.\n");
1263 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1265 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1267 TRACE("iface %p.\n", iface);
1269 d2d_clip_stack_pop(&render_target->clip_stack);
1272 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1274 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1275 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1276 D3D10_SUBRESOURCE_DATA buffer_data;
1277 D3D10_BUFFER_DESC buffer_desc;
1278 ID3D10Buffer *vs_cb, *ps_cb;
1279 HRESULT hr;
1281 static const float transform[] =
1283 1.0f, 0.0f, 0.0f, 0.0f,
1284 0.0f, -1.0f, 0.0f, 0.0f,
1287 TRACE("iface %p, color %p.\n", iface, color);
1289 buffer_desc.ByteWidth = sizeof(transform);
1290 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1291 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1292 buffer_desc.CPUAccessFlags = 0;
1293 buffer_desc.MiscFlags = 0;
1295 buffer_data.pSysMem = transform;
1296 buffer_data.SysMemPitch = 0;
1297 buffer_data.SysMemSlicePitch = 0;
1299 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1301 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1302 return;
1305 if (color)
1306 c = *color;
1307 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1308 c.a = 1.0f;
1309 c.r *= c.a;
1310 c.g *= c.a;
1311 c.b *= c.a;
1312 buffer_desc.ByteWidth = sizeof(c);
1313 buffer_data.pSysMem = &c;
1315 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1317 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1318 ID3D10Buffer_Release(vs_cb);
1319 return;
1322 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1323 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1325 ID3D10Buffer_Release(ps_cb);
1326 ID3D10Buffer_Release(vs_cb);
1329 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1331 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1333 TRACE("iface %p.\n", iface);
1335 memset(&render_target->error, 0, sizeof(render_target->error));
1338 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1339 D2D1_TAG *tag1, D2D1_TAG *tag2)
1341 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1343 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1345 if (tag1)
1346 *tag1 = render_target->error.tag1;
1347 if (tag2)
1348 *tag2 = render_target->error.tag2;
1350 return render_target->error.code;
1353 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1354 D2D1_PIXEL_FORMAT *format)
1356 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1358 TRACE("iface %p, format %p.\n", iface, format);
1360 *format = render_target->desc.pixelFormat;
1361 return format;
1364 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1366 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1368 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1370 if (dpi_x == 0.0f && dpi_y == 0.0f)
1372 dpi_x = 96.0f;
1373 dpi_y = 96.0f;
1375 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1376 return;
1378 render_target->desc.dpiX = dpi_x;
1379 render_target->desc.dpiY = dpi_y;
1382 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1384 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1386 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1388 *dpi_x = render_target->desc.dpiX;
1389 *dpi_y = render_target->desc.dpiY;
1392 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1394 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1396 TRACE("iface %p, size %p.\n", iface, size);
1398 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1399 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1400 return size;
1403 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1404 D2D1_SIZE_U *pixel_size)
1406 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1408 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1410 *pixel_size = render_target->pixel_size;
1411 return pixel_size;
1414 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1416 FIXME("iface %p stub!\n", iface);
1418 return 0;
1421 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1422 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1424 FIXME("iface %p, desc %p stub!\n", iface, desc);
1426 return FALSE;
1429 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1431 d2d_d3d_render_target_QueryInterface,
1432 d2d_d3d_render_target_AddRef,
1433 d2d_d3d_render_target_Release,
1434 d2d_d3d_render_target_GetFactory,
1435 d2d_d3d_render_target_CreateBitmap,
1436 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1437 d2d_d3d_render_target_CreateSharedBitmap,
1438 d2d_d3d_render_target_CreateBitmapBrush,
1439 d2d_d3d_render_target_CreateSolidColorBrush,
1440 d2d_d3d_render_target_CreateGradientStopCollection,
1441 d2d_d3d_render_target_CreateLinearGradientBrush,
1442 d2d_d3d_render_target_CreateRadialGradientBrush,
1443 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1444 d2d_d3d_render_target_CreateLayer,
1445 d2d_d3d_render_target_CreateMesh,
1446 d2d_d3d_render_target_DrawLine,
1447 d2d_d3d_render_target_DrawRectangle,
1448 d2d_d3d_render_target_FillRectangle,
1449 d2d_d3d_render_target_DrawRoundedRectangle,
1450 d2d_d3d_render_target_FillRoundedRectangle,
1451 d2d_d3d_render_target_DrawEllipse,
1452 d2d_d3d_render_target_FillEllipse,
1453 d2d_d3d_render_target_DrawGeometry,
1454 d2d_d3d_render_target_FillGeometry,
1455 d2d_d3d_render_target_FillMesh,
1456 d2d_d3d_render_target_FillOpacityMask,
1457 d2d_d3d_render_target_DrawBitmap,
1458 d2d_d3d_render_target_DrawText,
1459 d2d_d3d_render_target_DrawTextLayout,
1460 d2d_d3d_render_target_DrawGlyphRun,
1461 d2d_d3d_render_target_SetTransform,
1462 d2d_d3d_render_target_GetTransform,
1463 d2d_d3d_render_target_SetAntialiasMode,
1464 d2d_d3d_render_target_GetAntialiasMode,
1465 d2d_d3d_render_target_SetTextAntialiasMode,
1466 d2d_d3d_render_target_GetTextAntialiasMode,
1467 d2d_d3d_render_target_SetTextRenderingParams,
1468 d2d_d3d_render_target_GetTextRenderingParams,
1469 d2d_d3d_render_target_SetTags,
1470 d2d_d3d_render_target_GetTags,
1471 d2d_d3d_render_target_PushLayer,
1472 d2d_d3d_render_target_PopLayer,
1473 d2d_d3d_render_target_Flush,
1474 d2d_d3d_render_target_SaveDrawingState,
1475 d2d_d3d_render_target_RestoreDrawingState,
1476 d2d_d3d_render_target_PushAxisAlignedClip,
1477 d2d_d3d_render_target_PopAxisAlignedClip,
1478 d2d_d3d_render_target_Clear,
1479 d2d_d3d_render_target_BeginDraw,
1480 d2d_d3d_render_target_EndDraw,
1481 d2d_d3d_render_target_GetPixelFormat,
1482 d2d_d3d_render_target_SetDpi,
1483 d2d_d3d_render_target_GetDpi,
1484 d2d_d3d_render_target_GetSize,
1485 d2d_d3d_render_target_GetPixelSize,
1486 d2d_d3d_render_target_GetMaximumBitmapSize,
1487 d2d_d3d_render_target_IsSupported,
1490 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1492 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1495 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1497 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1499 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1500 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1501 || IsEqualGUID(iid, &IID_IUnknown))
1503 IDWriteTextRenderer_AddRef(iface);
1504 *out = iface;
1505 return S_OK;
1508 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1510 *out = NULL;
1511 return E_NOINTERFACE;
1514 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1516 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1518 TRACE("iface %p.\n", iface);
1520 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1523 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1525 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1527 TRACE("iface %p.\n", iface);
1529 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1532 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1533 void *ctx, BOOL *disabled)
1535 struct d2d_draw_text_layout_ctx *context = ctx;
1537 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1539 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1541 return S_OK;
1544 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1545 void *ctx, DWRITE_MATRIX *transform)
1547 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1549 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1551 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1553 return S_OK;
1556 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1558 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1560 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1562 *ppd = render_target->desc.dpiY / 96.0f;
1564 return S_OK;
1567 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1568 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1569 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1571 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1572 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1573 struct d2d_draw_text_layout_ctx *context = ctx;
1574 ID2D1Brush *brush;
1576 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1577 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1578 iface, ctx, baseline_origin_x, baseline_origin_y,
1579 measuring_mode, glyph_run, desc, effect);
1581 if (desc)
1582 WARN("Ignoring glyph run description %p.\n", desc);
1583 if (context->options & ~D2D1_DRAW_TEXT_OPTIONS_NO_SNAP)
1584 FIXME("Ignoring options %#x.\n", context->options);
1586 brush = d2d_draw_get_text_brush(context, effect);
1588 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1589 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1590 baseline_origin, glyph_run, brush, measuring_mode);
1592 ID2D1Brush_Release(brush);
1594 return S_OK;
1597 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1598 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1600 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1601 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1602 struct d2d_draw_text_layout_ctx *context = ctx;
1603 float min_thickness;
1604 ID2D1Brush *brush;
1605 D2D1_RECT_F rect;
1607 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1608 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1610 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1611 min_thickness = 96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22));
1613 rect.left = baseline_origin_x;
1614 rect.top = baseline_origin_y + underline->offset;
1615 rect.right = baseline_origin_x + underline->width;
1616 rect.bottom = baseline_origin_y + underline->offset + max(underline->thickness, min_thickness);
1618 brush = d2d_draw_get_text_brush(context, effect);
1620 ID2D1RenderTarget_FillRectangle(&render_target->ID2D1RenderTarget_iface, &rect, brush);
1622 ID2D1Brush_Release(brush);
1624 return S_OK;
1627 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1628 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1630 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1631 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1633 return E_NOTIMPL;
1636 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1637 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1639 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1640 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1642 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1645 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1647 d2d_text_renderer_QueryInterface,
1648 d2d_text_renderer_AddRef,
1649 d2d_text_renderer_Release,
1650 d2d_text_renderer_IsPixelSnappingDisabled,
1651 d2d_text_renderer_GetCurrentTransform,
1652 d2d_text_renderer_GetPixelsPerDip,
1653 d2d_text_renderer_DrawGlyphRun,
1654 d2d_text_renderer_DrawUnderline,
1655 d2d_text_renderer_DrawStrikethrough,
1656 d2d_text_renderer_DrawInlineObject,
1659 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1660 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1662 D3D10_SUBRESOURCE_DATA buffer_data;
1663 D3D10_STATE_BLOCK_MASK state_mask;
1664 DXGI_SURFACE_DESC surface_desc;
1665 IDWriteFactory *dwrite_factory;
1666 D3D10_RASTERIZER_DESC rs_desc;
1667 D3D10_BUFFER_DESC buffer_desc;
1668 D3D10_BLEND_DESC blend_desc;
1669 ID3D10Resource *resource;
1670 unsigned int i, j, k;
1671 HRESULT hr;
1673 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
1675 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1677 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
1679 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1680 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
1682 static const DWORD vs_code_triangle[] =
1684 /* float3x2 transform;
1686 * float4 main(float4 position : POSITION) : SV_POSITION
1688 * return float4(mul(position.xyw, transform), position.zw);
1689 * } */
1690 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1691 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1692 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1693 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1694 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1695 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1696 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1697 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1698 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1699 0x00000000, 0x0100003e,
1701 static const DWORD vs_code_bezier[] =
1703 #if 0
1704 float3x2 transform;
1706 float4 main(float4 position : POSITION,
1707 inout float3 texcoord : TEXCOORD0) : SV_POSITION
1709 return float4(mul(position.xyw, transform), position.zw);
1711 #endif
1712 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
1713 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
1714 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
1715 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
1716 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
1717 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
1718 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
1719 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
1720 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
1721 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
1722 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
1723 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
1724 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
1726 static const DWORD ps_code_triangle_solid[] =
1728 /* float4 color;
1730 * float4 main(float4 position : SV_POSITION) : SV_Target
1732 * return color;
1733 * } */
1734 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1735 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1736 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1737 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1738 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1739 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1740 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1742 static const DWORD ps_code_triangle_solid_bitmap[] =
1744 #if 0
1745 float4 color;
1747 float3x2 transform;
1748 float opacity;
1749 bool ignore_alpha;
1751 SamplerState s;
1752 Texture2D t;
1754 float4 main(float4 position : SV_POSITION) : SV_Target
1756 float2 texcoord;
1757 float4 ret;
1759 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1760 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1761 ret = t.Sample(s, texcoord) * opacity;
1762 if (ignore_alpha)
1763 ret.a = opacity;
1765 return color * ret.a;
1767 #endif
1768 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
1769 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1770 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1771 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1772 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1773 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1774 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1775 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1776 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
1777 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
1778 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
1779 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
1780 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
1781 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
1782 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
1783 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
1784 0x00000000, 0x0100003e,
1786 static const DWORD ps_code_triangle_bitmap[] =
1788 #if 0
1789 float3x2 transform;
1790 float opacity;
1791 bool ignore_alpha;
1793 SamplerState s;
1794 Texture2D t;
1796 float4 main(float4 position : SV_POSITION) : SV_Target
1798 float2 texcoord;
1799 float4 ret;
1801 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1802 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1803 ret = t.Sample(s, texcoord) * opacity;
1804 if (ignore_alpha)
1805 ret.a = opacity;
1807 return ret;
1809 #endif
1810 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
1811 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1812 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1813 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1814 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
1815 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
1816 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1817 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1818 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1819 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1820 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1821 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1822 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1823 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
1824 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1825 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
1827 static const DWORD ps_code_triangle_bitmap_solid[] =
1829 #if 0
1830 float3x2 transform;
1831 float opacity;
1832 bool ignore_alpha;
1834 float4 color;
1836 SamplerState s;
1837 Texture2D t;
1839 float4 main(float4 position : SV_POSITION) : SV_Target
1841 float2 texcoord;
1842 float4 ret;
1844 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1845 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1846 ret = t.Sample(s, texcoord) * opacity;
1847 if (ignore_alpha)
1848 ret.a = opacity;
1850 return ret * color.a;
1852 #endif
1853 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
1854 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1855 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1856 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1857 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1858 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1859 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1860 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1861 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1862 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1863 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1864 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1865 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1866 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
1867 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1868 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
1869 0x00000003, 0x0100003e,
1871 static const DWORD ps_code_triangle_bitmap_bitmap[] =
1873 #if 0
1874 struct brush
1876 float3x2 transform;
1877 float opacity;
1878 bool ignore_alpha;
1879 } brush0, brush1;
1881 SamplerState s0, s1;
1882 Texture2D t0, t1;
1884 float4 main(float4 position : SV_POSITION) : SV_Target
1886 float2 texcoord;
1887 float opacity;
1888 float4 ret;
1890 texcoord.x = position.x * brush0.transform._11 + position.y * brush0.transform._21 + brush0.transform._31;
1891 texcoord.y = position.x * brush0.transform._12 + position.y * brush0.transform._22 + brush0.transform._32;
1892 ret = t0.Sample(s0, texcoord) * brush0.opacity;
1893 if (brush0.ignore_alpha)
1894 ret.a = brush0.opacity;
1896 texcoord.x = position.x * brush1.transform._11 + position.y * brush1.transform._21 + brush1.transform._31;
1897 texcoord.y = position.x * brush1.transform._12 + position.y * brush1.transform._22 + brush1.transform._32;
1898 opacity = t1.Sample(s1, texcoord).a * brush1.opacity;
1899 if (brush1.ignore_alpha)
1900 opacity = brush1.opacity;
1902 return ret * opacity;
1904 #endif
1905 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
1906 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1907 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1908 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1909 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
1910 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
1911 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
1912 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
1913 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
1914 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
1915 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
1916 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
1917 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
1918 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
1919 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
1920 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
1921 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
1922 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
1923 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
1924 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
1925 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
1926 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
1927 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
1928 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
1929 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
1931 /* The basic idea here is to evaluate the implicit form of the curve in
1932 * texture space. "t.z" determines which side of the curve is shaded. */
1933 static const DWORD ps_code_bezier_solid[] =
1935 #if 0
1936 float4 color;
1938 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
1940 clip((t.x * t.x - t.y) * t.z);
1941 return color;
1943 #endif
1944 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
1945 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
1946 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
1947 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
1948 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
1949 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
1950 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
1951 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
1952 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
1953 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
1954 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
1955 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1957 static const struct brush_shader
1959 const void *byte_code;
1960 size_t byte_code_size;
1961 enum d2d_shape_type shape_type;
1962 enum d2d_brush_type brush_type;
1963 enum d2d_brush_type opacity_brush_type;
1965 brush_shaders[] =
1967 {ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
1968 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
1969 {ps_code_triangle_solid_bitmap, sizeof(ps_code_triangle_solid_bitmap),
1970 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_BITMAP},
1971 {ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
1972 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_COUNT},
1973 {ps_code_triangle_bitmap_solid, sizeof(ps_code_triangle_bitmap_solid),
1974 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_SOLID},
1975 {ps_code_triangle_bitmap_bitmap, sizeof(ps_code_triangle_bitmap_bitmap),
1976 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_BITMAP},
1977 {ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
1978 D2D_SHAPE_TYPE_BEZIER, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
1980 static const struct
1982 float x, y;
1984 quad[] =
1986 {-1.0f, 1.0f},
1987 {-1.0f, -1.0f},
1988 { 1.0f, 1.0f},
1989 { 1.0f, -1.0f},
1991 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
1992 static const D2D1_MATRIX_3X2_F identity =
1994 1.0f, 0.0f,
1995 0.0f, 1.0f,
1996 0.0f, 0.0f,
1998 float dpi_x, dpi_y;
2000 dpi_x = desc->dpiX;
2001 dpi_y = desc->dpiY;
2003 if (dpi_x == 0.0f && dpi_y == 0.0f)
2005 dpi_x = 96.0f;
2006 dpi_y = 96.0f;
2008 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
2009 return E_INVALIDARG;
2011 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
2012 WARN("Ignoring render target type %#x.\n", desc->type);
2013 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
2014 FIXME("Ignoring render target usage %#x.\n", desc->usage);
2015 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
2016 WARN("Ignoring feature level %#x.\n", desc->minLevel);
2018 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
2019 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
2020 render_target->refcount = 1;
2021 render_target->factory = factory;
2022 ID2D1Factory_AddRef(render_target->factory);
2024 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
2026 WARN("Failed to get device interface, hr %#x.\n", hr);
2027 ID2D1Factory_Release(render_target->factory);
2028 return hr;
2031 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2033 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2034 goto err;
2037 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
2038 ID3D10Resource_Release(resource);
2039 if (FAILED(hr))
2041 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2042 goto err;
2045 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
2047 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
2048 goto err;
2051 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
2053 WARN("Failed to create stateblock, hr %#x.\n", hr);
2054 goto err;
2057 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
2058 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
2059 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
2061 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
2062 goto err;
2065 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
2066 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
2067 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
2069 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
2070 goto err;
2073 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
2074 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
2076 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
2077 goto err;
2080 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
2081 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
2083 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
2084 goto err;
2087 for (i = 0; i < sizeof(brush_shaders) / sizeof(*brush_shaders); ++i)
2089 const struct brush_shader *bs = &brush_shaders[i];
2090 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, bs->byte_code, bs->byte_code_size,
2091 &render_target->shape_resources[bs->shape_type].ps[bs->brush_type][bs->opacity_brush_type])))
2093 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
2094 bs->shape_type, bs->brush_type, bs->opacity_brush_type);
2095 goto err;
2099 buffer_desc.ByteWidth = sizeof(indices);
2100 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
2101 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
2102 buffer_desc.CPUAccessFlags = 0;
2103 buffer_desc.MiscFlags = 0;
2105 buffer_data.pSysMem = indices;
2106 buffer_data.SysMemPitch = 0;
2107 buffer_data.SysMemSlicePitch = 0;
2109 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2110 &buffer_desc, &buffer_data, &render_target->ib)))
2112 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
2113 goto err;
2116 buffer_desc.ByteWidth = sizeof(quad);
2117 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
2118 buffer_data.pSysMem = quad;
2120 render_target->vb_stride = sizeof(*quad);
2121 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2122 &buffer_desc, &buffer_data, &render_target->vb)))
2124 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
2125 goto err;
2128 rs_desc.FillMode = D3D10_FILL_SOLID;
2129 rs_desc.CullMode = D3D10_CULL_NONE;
2130 rs_desc.FrontCounterClockwise = FALSE;
2131 rs_desc.DepthBias = 0;
2132 rs_desc.DepthBiasClamp = 0.0f;
2133 rs_desc.SlopeScaledDepthBias = 0.0f;
2134 rs_desc.DepthClipEnable = TRUE;
2135 rs_desc.ScissorEnable = TRUE;
2136 rs_desc.MultisampleEnable = FALSE;
2137 rs_desc.AntialiasedLineEnable = FALSE;
2138 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
2140 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
2141 goto err;
2144 memset(&blend_desc, 0, sizeof(blend_desc));
2145 blend_desc.BlendEnable[0] = TRUE;
2146 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2147 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2148 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2149 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2151 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2152 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2154 else
2156 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2157 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2159 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2160 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2161 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
2163 WARN("Failed to create blend state, hr %#x.\n", hr);
2164 goto err;
2167 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
2168 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
2170 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2171 goto err;
2174 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
2175 IDWriteFactory_Release(dwrite_factory);
2176 if (FAILED(hr))
2178 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
2179 goto err;
2182 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2184 WARN("Failed to get surface desc, hr %#x.\n", hr);
2185 goto err;
2188 render_target->desc.pixelFormat = desc->pixelFormat;
2189 render_target->pixel_size.width = surface_desc.Width;
2190 render_target->pixel_size.height = surface_desc.Height;
2191 render_target->drawing_state.transform = identity;
2193 if (!d2d_clip_stack_init(&render_target->clip_stack))
2195 WARN("Failed to initialize clip stack.\n");
2196 hr = E_FAIL;
2197 goto err;
2200 render_target->desc.dpiX = dpi_x;
2201 render_target->desc.dpiY = dpi_y;
2203 return S_OK;
2205 err:
2206 if (render_target->default_text_rendering_params)
2207 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
2208 if (render_target->bs)
2209 ID3D10BlendState_Release(render_target->bs);
2210 if (render_target->rs)
2211 ID3D10RasterizerState_Release(render_target->rs);
2212 if (render_target->vb)
2213 ID3D10Buffer_Release(render_target->vb);
2214 if (render_target->ib)
2215 ID3D10Buffer_Release(render_target->ib);
2216 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
2218 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2220 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2222 if (render_target->shape_resources[i].ps[j][k])
2223 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
2226 if (render_target->shape_resources[i].vs)
2227 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
2228 if (render_target->shape_resources[i].il)
2229 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
2231 if (render_target->stateblock)
2232 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
2233 if (render_target->view)
2234 ID3D10RenderTargetView_Release(render_target->view);
2235 if (render_target->device)
2236 ID3D10Device_Release(render_target->device);
2237 ID2D1Factory_Release(render_target->factory);
2238 return hr;
2241 HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1 *surface)
2243 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
2244 DXGI_SURFACE_DESC surface_desc;
2245 ID3D10RenderTargetView *view;
2246 ID3D10Resource *resource;
2247 HRESULT hr;
2249 if (!surface)
2251 ID3D10RenderTargetView_Release(render_target->view);
2252 render_target->view = NULL;
2253 return S_OK;
2256 if (FAILED(hr = IDXGISurface1_GetDesc(surface, &surface_desc)))
2258 WARN("Failed to get surface desc, hr %#x.\n", hr);
2259 return hr;
2262 if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2264 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2265 return hr;
2268 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &view);
2269 ID3D10Resource_Release(resource);
2270 if (FAILED(hr))
2272 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2273 return hr;
2276 render_target->pixel_size.width = surface_desc.Width;
2277 render_target->pixel_size.height = surface_desc.Height;
2278 ID3D10RenderTargetView_Release(render_target->view);
2279 render_target->view = view;
2281 return S_OK;