d2d1: Implement d2d_path_geometry_FillContainsPoint().
[wine.git] / dlls / d2d1 / render_target.c
blob798dd0de59327f8788b0dab6207edba3293551ef
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_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
53 if (point->x < dst->left)
54 dst->left = point->x;
55 if (point->y < dst->top)
56 dst->top = point->y;
57 if (point->x > dst->right)
58 dst->right = point->x;
59 if (point->y > dst->bottom)
60 dst->bottom = point->y;
63 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
65 if (src->left > dst->left)
66 dst->left = src->left;
67 if (src->top > dst->top)
68 dst->top = src->top;
69 if (src->right < dst->right)
70 dst->right = src->right;
71 if (src->bottom < dst->bottom)
72 dst->bottom = src->bottom;
75 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
77 dst->left = left;
78 dst->top = top;
79 dst->right = right;
80 dst->bottom = bottom;
83 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
85 dst->width = width;
86 dst->height = height;
89 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
91 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
92 return FALSE;
94 stack->size = INITIAL_CLIP_STACK_SIZE;
95 stack->count = 0;
97 return TRUE;
100 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
102 HeapFree(GetProcessHeap(), 0, stack->stack);
105 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
107 D2D1_RECT_F r;
109 if (stack->count == stack->size)
111 D2D1_RECT_F *new_stack;
112 unsigned int new_size;
114 if (stack->size > UINT_MAX / 2)
115 return FALSE;
117 new_size = stack->size * 2;
118 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
119 return FALSE;
121 stack->stack = new_stack;
122 stack->size = new_size;
125 r = *rect;
126 if (stack->count)
127 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
128 stack->stack[stack->count++] = r;
130 return TRUE;
133 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
135 if (!stack->count)
136 return;
137 --stack->count;
140 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
141 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
142 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
144 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
145 ID3D10Device *device = render_target->device;
146 D3D10_RECT scissor_rect;
147 unsigned int offset;
148 D3D10_VIEWPORT vp;
149 HRESULT hr;
151 vp.TopLeftX = 0;
152 vp.TopLeftY = 0;
153 vp.Width = render_target->pixel_size.width;
154 vp.Height = render_target->pixel_size.height;
155 vp.MinDepth = 0.0f;
156 vp.MaxDepth = 1.0f;
158 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
160 WARN("Failed to capture stateblock, hr %#x.\n", hr);
161 return;
164 ID3D10Device_ClearState(device);
166 ID3D10Device_IASetInputLayout(device, shape_resources->il);
167 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
168 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
169 offset = 0;
170 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
171 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
172 ID3D10Device_VSSetShader(device, shape_resources->vs);
173 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
174 ID3D10Device_RSSetViewports(device, 1, &vp);
175 if (render_target->clip_stack.count)
177 const D2D1_RECT_F *clip_rect;
179 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
180 scissor_rect.left = clip_rect->left + 0.5f;
181 scissor_rect.top = clip_rect->top + 0.5f;
182 scissor_rect.right = clip_rect->right + 0.5f;
183 scissor_rect.bottom = clip_rect->bottom + 0.5f;
185 else
187 scissor_rect.left = 0.0f;
188 scissor_rect.top = 0.0f;
189 scissor_rect.right = render_target->pixel_size.width;
190 scissor_rect.bottom = render_target->pixel_size.height;
192 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
193 ID3D10Device_RSSetState(device, render_target->rs);
194 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
195 if (brush)
196 d2d_brush_bind_resources(brush, opacity_brush, render_target, shape_type);
197 else
198 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID][D2D_BRUSH_TYPE_COUNT]);
200 if (ib)
201 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
202 else
203 ID3D10Device_Draw(device, index_count, 0);
205 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
206 WARN("Failed to apply stateblock, hr %#x.\n", hr);
209 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
211 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
214 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
216 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
218 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
219 || IsEqualGUID(iid, &IID_ID2D1Resource)
220 || IsEqualGUID(iid, &IID_IUnknown))
222 ID2D1RenderTarget_AddRef(iface);
223 *out = iface;
224 return S_OK;
227 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
229 *out = NULL;
230 return E_NOINTERFACE;
233 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
235 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
236 ULONG refcount = InterlockedIncrement(&render_target->refcount);
238 TRACE("%p increasing refcount to %u.\n", iface, refcount);
240 return refcount;
243 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
245 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
246 ULONG refcount = InterlockedDecrement(&render_target->refcount);
248 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
250 if (!refcount)
252 unsigned int i, j, k;
254 d2d_clip_stack_cleanup(&render_target->clip_stack);
255 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
256 if (render_target->text_rendering_params)
257 IDWriteRenderingParams_Release(render_target->text_rendering_params);
258 ID3D10BlendState_Release(render_target->bs);
259 ID3D10RasterizerState_Release(render_target->rs);
260 ID3D10Buffer_Release(render_target->vb);
261 ID3D10Buffer_Release(render_target->ib);
262 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
264 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
266 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
268 if (render_target->shape_resources[i].ps[j][k])
269 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
272 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
273 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
275 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
276 ID3D10RenderTargetView_Release(render_target->view);
277 ID3D10Device_Release(render_target->device);
278 ID2D1Factory_Release(render_target->factory);
279 HeapFree(GetProcessHeap(), 0, render_target);
282 return refcount;
285 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
287 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
289 TRACE("iface %p, factory %p.\n", iface, factory);
291 *factory = render_target->factory;
292 ID2D1Factory_AddRef(*factory);
295 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
296 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
298 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
299 struct d2d_bitmap *object;
300 HRESULT hr;
302 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
303 iface, size.width, size.height, src_data, pitch, desc, bitmap);
305 if (SUCCEEDED(hr = d2d_bitmap_create(render_target->factory, render_target->device, size, src_data, pitch, desc, &object)))
306 *bitmap = &object->ID2D1Bitmap_iface;
308 return hr;
311 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
312 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
314 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
315 struct d2d_bitmap *object;
316 HRESULT hr;
318 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
319 iface, bitmap_source, desc, bitmap);
321 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(render_target->factory, render_target->device, bitmap_source,
322 desc, &object)))
323 *bitmap = &object->ID2D1Bitmap_iface;
325 return hr;
328 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
329 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
331 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
332 struct d2d_bitmap *object;
333 HRESULT hr;
335 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
336 iface, debugstr_guid(iid), data, desc, bitmap);
338 if (SUCCEEDED(hr = d2d_bitmap_create_shared(iface, render_target->device, iid, data, desc, &object)))
339 *bitmap = &object->ID2D1Bitmap_iface;
341 return hr;
344 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
345 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
346 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
348 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
349 struct d2d_brush *object;
350 HRESULT hr;
352 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
353 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
355 if (SUCCEEDED(hr = d2d_bitmap_brush_create(render_target->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
356 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
358 return hr;
361 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
362 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
364 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
365 struct d2d_brush *object;
366 HRESULT hr;
368 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
370 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
371 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
373 return hr;
376 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
377 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
378 ID2D1GradientStopCollection **gradient)
380 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
381 struct d2d_gradient *object;
382 HRESULT hr;
384 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
385 iface, stops, stop_count, gamma, extend_mode, gradient);
387 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, stops, stop_count, gamma, extend_mode, &object)))
388 *gradient = &object->ID2D1GradientStopCollection_iface;
390 return hr;
393 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
394 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
395 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
397 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
398 struct d2d_brush *object;
399 HRESULT hr;
401 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
402 iface, gradient_brush_desc, brush_desc, gradient, brush);
404 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
405 gradient, &object)))
406 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
408 return hr;
411 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
412 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
413 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
415 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
416 iface, gradient_brush_desc, brush_desc, gradient, brush);
418 return E_NOTIMPL;
421 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
422 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
423 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
425 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
426 struct d2d_bitmap_render_target *object;
427 HRESULT hr;
429 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
430 iface, size, pixel_size, format, options, rt);
432 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
433 return E_OUTOFMEMORY;
435 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
436 format, options)))
438 WARN("Failed to initialize render target, hr %#x.\n", hr);
439 HeapFree(GetProcessHeap(), 0, object);
440 return hr;
443 TRACE("Created render target %p.\n", object);
444 *rt = &object->ID2D1BitmapRenderTarget_iface;
446 return S_OK;
449 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
450 const D2D1_SIZE_F *size, ID2D1Layer **layer)
452 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
454 return E_NOTIMPL;
457 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
459 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
460 struct d2d_mesh *object;
461 HRESULT hr;
463 TRACE("iface %p, mesh %p.\n", iface, mesh);
465 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
466 *mesh = &object->ID2D1Mesh_iface;
468 return hr;
471 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
472 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
474 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
475 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
478 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
479 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
481 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
482 ID2D1RectangleGeometry *geometry;
483 HRESULT hr;
485 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
486 iface, rect, brush, stroke_width, stroke_style);
488 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
490 ERR("Failed to create geometry, hr %#x.\n", hr);
491 return;
494 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
495 ID2D1RectangleGeometry_Release(geometry);
498 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
499 const D2D1_RECT_F *rect, ID2D1Brush *brush)
501 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
502 ID2D1RectangleGeometry *geometry;
503 HRESULT hr;
505 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
507 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
509 ERR("Failed to create geometry, hr %#x.\n", hr);
510 return;
513 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
514 ID2D1RectangleGeometry_Release(geometry);
517 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
518 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
520 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
521 ID2D1RoundedRectangleGeometry *geometry;
522 HRESULT hr;
524 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
525 iface, rect, brush, stroke_width, stroke_style);
527 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
529 ERR("Failed to create geometry, hr %#x.\n", hr);
530 return;
533 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
534 ID2D1RoundedRectangleGeometry_Release(geometry);
537 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
538 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
540 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
541 ID2D1RoundedRectangleGeometry *geometry;
542 HRESULT hr;
544 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
546 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
548 ERR("Failed to create geometry, hr %#x.\n", hr);
549 return;
552 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
553 ID2D1RoundedRectangleGeometry_Release(geometry);
556 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
557 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
559 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
560 ID2D1EllipseGeometry *geometry;
561 HRESULT hr;
563 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
564 iface, ellipse, brush, stroke_width, stroke_style);
566 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
568 ERR("Failed to create geometry, hr %#x.\n", hr);
569 return;
572 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
573 ID2D1EllipseGeometry_Release(geometry);
576 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
577 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
579 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
580 ID2D1EllipseGeometry *geometry;
581 HRESULT hr;
583 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
585 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
587 ERR("Failed to create geometry, hr %#x.\n", hr);
588 return;
591 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
592 ID2D1EllipseGeometry_Release(geometry);
595 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
596 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
598 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
599 iface, geometry, brush, stroke_width, stroke_style);
602 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
603 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
605 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
606 D3D10_SUBRESOURCE_DATA buffer_data;
607 D3D10_BUFFER_DESC buffer_desc;
608 D2D1_MATRIX_3X2_F w, g;
609 float tmp_x, tmp_y;
610 HRESULT hr;
611 struct
613 float _11, _21, _31, pad0;
614 float _12, _22, _32, pad1;
615 } transform;
617 tmp_x = (2.0f * render_target->desc.dpiX) / (96.0f * render_target->pixel_size.width);
618 tmp_y = -(2.0f * render_target->desc.dpiY) / (96.0f * render_target->pixel_size.height);
619 w = render_target->drawing_state.transform;
620 w._11 *= tmp_x;
621 w._21 *= tmp_x;
622 w._31 = w._31 * tmp_x - 1.0f;
623 w._12 *= tmp_y;
624 w._22 *= tmp_y;
625 w._32 = w._32 * tmp_y + 1.0f;
627 g = geometry->transform;
628 d2d_matrix_multiply(&g, &w);
630 transform._11 = g._11;
631 transform._21 = g._21;
632 transform._31 = g._31;
633 transform.pad0 = 0.0f;
634 transform._12 = g._12;
635 transform._22 = g._22;
636 transform._32 = g._32;
637 transform.pad1 = 0.0f;
639 buffer_desc.ByteWidth = sizeof(transform);
640 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
641 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
642 buffer_desc.CPUAccessFlags = 0;
643 buffer_desc.MiscFlags = 0;
645 buffer_data.pSysMem = &transform;
646 buffer_data.SysMemPitch = 0;
647 buffer_data.SysMemSlicePitch = 0;
649 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
651 WARN("Failed to create constant buffer, hr %#x.\n", hr);
652 return;
655 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, render_target, &ps_cb)))
657 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
658 ID3D10Buffer_Release(vs_cb);
659 return;
662 if (geometry->face_count)
664 buffer_desc.ByteWidth = geometry->face_count * sizeof(*geometry->faces);
665 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
666 buffer_data.pSysMem = geometry->faces;
668 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
670 WARN("Failed to create index buffer, hr %#x.\n", hr);
671 goto done;
674 buffer_desc.ByteWidth = geometry->vertex_count * sizeof(*geometry->vertices);
675 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
676 buffer_data.pSysMem = geometry->vertices;
678 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
680 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
681 ID3D10Buffer_Release(ib);
682 goto done;
685 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->face_count, vb,
686 sizeof(*geometry->vertices), vs_cb, ps_cb, brush, opacity_brush);
688 ID3D10Buffer_Release(vb);
689 ID3D10Buffer_Release(ib);
692 if (geometry->bezier_count)
694 buffer_desc.ByteWidth = geometry->bezier_count * sizeof(*geometry->beziers);
695 buffer_data.pSysMem = geometry->beziers;
697 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
699 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
700 goto done;
703 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, 3 * geometry->bezier_count, vb,
704 sizeof(*geometry->beziers->v), vs_cb, ps_cb, brush, opacity_brush);
706 ID3D10Buffer_Release(vb);
709 done:
710 ID3D10Buffer_Release(ps_cb);
711 ID3D10Buffer_Release(vs_cb);
714 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
715 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
717 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
718 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
719 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
720 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
722 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
724 if (FAILED(render_target->error.code))
725 return;
727 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
729 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
730 render_target->error.tag1 = render_target->drawing_state.tag1;
731 render_target->error.tag2 = render_target->drawing_state.tag2;
732 return;
735 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
738 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
739 ID2D1Mesh *mesh, ID2D1Brush *brush)
741 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
744 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
745 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
746 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
748 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
749 iface, mask, brush, content, dst_rect, src_rect);
752 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
753 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
754 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
756 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
757 D2D1_BRUSH_PROPERTIES brush_desc;
758 ID2D1BitmapBrush *brush;
759 D2D1_RECT_F s, d;
760 HRESULT hr;
762 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
763 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
765 if (src_rect)
767 s = *src_rect;
769 else
771 D2D1_SIZE_F size;
773 size = ID2D1Bitmap_GetSize(bitmap);
774 s.left = 0.0f;
775 s.top = 0.0f;
776 s.right = size.width;
777 s.bottom = size.height;
780 if (dst_rect)
782 d = *dst_rect;
784 else
786 d.left = 0.0f;
787 d.top = 0.0f;
788 d.right = s.right - s.left;
789 d.bottom = s.bottom - s.top;
792 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
793 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
794 bitmap_brush_desc.interpolationMode = interpolation_mode;
796 brush_desc.opacity = opacity;
797 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
798 brush_desc.transform._21 = 0.0f;
799 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
800 brush_desc.transform._12 = 0.0f;
801 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
802 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
804 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
806 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
807 return;
810 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
811 ID2D1BitmapBrush_Release(brush);
814 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
815 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
816 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
818 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
819 IDWriteTextLayout *text_layout;
820 IDWriteFactory *dwrite_factory;
821 D2D1_POINT_2F origin;
822 HRESULT hr;
824 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
825 "brush %p, options %#x, measuring_mode %#x.\n",
826 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
827 brush, options, measuring_mode);
829 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
830 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
832 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
833 return;
836 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
837 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
838 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
839 else
840 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
841 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
842 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
843 IDWriteFactory_Release(dwrite_factory);
844 if (FAILED(hr))
846 ERR("Failed to create text layout, hr %#x.\n", hr);
847 return;
850 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
851 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
852 IDWriteTextLayout_Release(text_layout);
855 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
856 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
858 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
859 struct d2d_draw_text_layout_ctx ctx;
860 HRESULT hr;
862 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
863 iface, origin.x, origin.y, layout, brush, options);
865 ctx.brush = brush;
866 ctx.options = options;
868 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
869 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
870 FIXME("Failed to draw text layout, hr %#x.\n", hr);
873 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
874 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
876 D2D1_MATRIX_3X2_F *transform, prev_transform;
877 ID2D1PathGeometry *geometry;
878 ID2D1GeometrySink *sink;
879 HRESULT hr;
881 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
883 ERR("Failed to create geometry, hr %#x.\n", hr);
884 return;
887 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
889 ERR("Failed to open geometry sink, hr %#x.\n", hr);
890 ID2D1PathGeometry_Release(geometry);
891 return;
894 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
895 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
896 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
898 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
899 ID2D1GeometrySink_Release(sink);
900 ID2D1PathGeometry_Release(geometry);
901 return;
904 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
905 ERR("Failed to close geometry sink, hr %#x.\n", hr);
906 ID2D1GeometrySink_Release(sink);
908 transform = &render_target->drawing_state.transform;
909 prev_transform = *transform;
910 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
911 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
912 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
913 unsafe_impl_from_ID2D1Brush(brush), NULL);
914 *transform = prev_transform;
916 ID2D1PathGeometry_Release(geometry);
919 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
920 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
921 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode)
923 ID2D1RectangleGeometry *geometry = NULL;
924 ID2D1BitmapBrush *opacity_brush = NULL;
925 D2D1_BITMAP_PROPERTIES bitmap_desc;
926 ID2D1Bitmap *opacity_bitmap = NULL;
927 IDWriteGlyphRunAnalysis *analysis;
928 DWRITE_TEXTURE_TYPE texture_type;
929 D2D1_BRUSH_PROPERTIES brush_desc;
930 IDWriteFactory *dwrite_factory;
931 void *opacity_values = NULL;
932 size_t opacity_values_size;
933 D2D1_SIZE_U bitmap_size;
934 D2D1_RECT_F run_rect;
935 RECT bounds;
936 HRESULT hr;
938 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
939 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
941 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
942 return;
945 hr = IDWriteFactory_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, ppd, NULL,
946 rendering_mode, measuring_mode, baseline_origin.x, baseline_origin.y, &analysis);
947 IDWriteFactory_Release(dwrite_factory);
948 if (FAILED(hr))
950 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
951 return;
954 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
955 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
956 else
957 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
959 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
961 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
962 goto done;
965 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
966 if (!bitmap_size.width || !bitmap_size.height)
968 /* Empty run, nothing to do. */
969 goto done;
972 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
973 bitmap_size.width *= 3;
974 opacity_values_size = bitmap_size.width * bitmap_size.height;
975 if (!(opacity_values = HeapAlloc(GetProcessHeap(), 0, opacity_values_size)))
977 ERR("Failed to allocate opacity values.\n");
978 goto done;
981 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
982 texture_type, &bounds, opacity_values, opacity_values_size)))
984 ERR("Failed to create alpha texture, hr %#x.\n", hr);
985 goto done;
988 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
989 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
990 bitmap_desc.dpiX = render_target->desc.dpiX;
991 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
992 bitmap_desc.dpiX *= 3.0f;
993 bitmap_desc.dpiY = render_target->desc.dpiY;
994 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
995 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
997 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
998 goto done;
1001 brush_desc.opacity = 1.0f;
1002 brush_desc.transform._11 = 1.0f;
1003 brush_desc.transform._12 = 0.0f;
1004 brush_desc.transform._21 = 0.0f;
1005 brush_desc.transform._22 = 1.0f;
1006 brush_desc.transform._31 = bounds.left;
1007 brush_desc.transform._32 = bounds.top;
1008 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
1009 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1011 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1012 goto done;
1015 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
1016 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1018 ERR("Failed to create geometry, hr %#x.\n", hr);
1019 goto done;
1022 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1023 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1025 done:
1026 if (geometry)
1027 ID2D1RectangleGeometry_Release(geometry);
1028 if (opacity_brush)
1029 ID2D1BitmapBrush_Release(opacity_brush);
1030 if (opacity_bitmap)
1031 ID2D1Bitmap_Release(opacity_bitmap);
1032 HeapFree(GetProcessHeap(), 0, opacity_values);
1033 IDWriteGlyphRunAnalysis_Release(analysis);
1036 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
1037 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1038 DWRITE_MEASURING_MODE measuring_mode)
1040 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1041 IDWriteRenderingParams *rendering_params;
1042 DWRITE_RENDERING_MODE rendering_mode;
1043 HRESULT hr;
1044 float ppd;
1046 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1047 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
1049 if (FAILED(render_target->error.code))
1050 return;
1052 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
1053 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
1055 ppd = max(render_target->desc.dpiX, render_target->desc.dpiY) / 96.0f;
1056 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1057 : render_target->default_text_rendering_params;
1058 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1059 ppd, measuring_mode, rendering_params, &rendering_mode)))
1061 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1062 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1065 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1066 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1067 else
1068 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1069 ppd, rendering_mode, measuring_mode);
1072 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1073 const D2D1_MATRIX_3X2_F *transform)
1075 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1077 TRACE("iface %p, transform %p.\n", iface, transform);
1079 render_target->drawing_state.transform = *transform;
1082 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1083 D2D1_MATRIX_3X2_F *transform)
1085 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1087 TRACE("iface %p, transform %p.\n", iface, transform);
1089 *transform = render_target->drawing_state.transform;
1092 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1093 D2D1_ANTIALIAS_MODE antialias_mode)
1095 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1097 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1099 render_target->drawing_state.antialiasMode = antialias_mode;
1102 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1104 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1106 TRACE("iface %p.\n", iface);
1108 return render_target->drawing_state.antialiasMode;
1111 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1112 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1114 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1116 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1118 render_target->drawing_state.textAntialiasMode = antialias_mode;
1121 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1123 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1125 TRACE("iface %p.\n", iface);
1127 return render_target->drawing_state.textAntialiasMode;
1130 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1131 IDWriteRenderingParams *text_rendering_params)
1133 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1135 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1137 if (text_rendering_params)
1138 IDWriteRenderingParams_AddRef(text_rendering_params);
1139 if (render_target->text_rendering_params)
1140 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1141 render_target->text_rendering_params = text_rendering_params;
1144 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1145 IDWriteRenderingParams **text_rendering_params)
1147 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1149 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1151 if ((*text_rendering_params = render_target->text_rendering_params))
1152 IDWriteRenderingParams_AddRef(*text_rendering_params);
1155 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1157 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1159 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1161 render_target->drawing_state.tag1 = tag1;
1162 render_target->drawing_state.tag2 = tag2;
1165 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1167 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1169 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1171 *tag1 = render_target->drawing_state.tag1;
1172 *tag2 = render_target->drawing_state.tag2;
1175 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1176 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1178 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1181 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1183 FIXME("iface %p stub!\n", iface);
1186 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1188 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1190 return E_NOTIMPL;
1193 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1194 ID2D1DrawingStateBlock *state_block)
1196 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1197 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1199 TRACE("iface %p, state_block %p.\n", iface, state_block);
1201 state_block_impl->drawing_state = render_target->drawing_state;
1202 if (render_target->text_rendering_params)
1203 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1204 if (state_block_impl->text_rendering_params)
1205 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1206 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1209 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1210 ID2D1DrawingStateBlock *state_block)
1212 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1213 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1215 TRACE("iface %p, state_block %p.\n", iface, state_block);
1217 render_target->drawing_state = state_block_impl->drawing_state;
1218 if (state_block_impl->text_rendering_params)
1219 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1220 if (render_target->text_rendering_params)
1221 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1222 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1225 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1226 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1228 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1229 D2D1_RECT_F transformed_rect;
1230 float x_scale, y_scale;
1231 D2D1_POINT_2F point;
1233 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1235 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1236 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1238 x_scale = render_target->desc.dpiX / 96.0f;
1239 y_scale = render_target->desc.dpiY / 96.0f;
1240 d2d_point_transform(&point, &render_target->drawing_state.transform,
1241 clip_rect->left * x_scale, clip_rect->top * y_scale);
1242 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1243 d2d_point_transform(&point, &render_target->drawing_state.transform,
1244 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1245 d2d_rect_expand(&transformed_rect, &point);
1246 d2d_point_transform(&point, &render_target->drawing_state.transform,
1247 clip_rect->right * x_scale, clip_rect->top * y_scale);
1248 d2d_rect_expand(&transformed_rect, &point);
1249 d2d_point_transform(&point, &render_target->drawing_state.transform,
1250 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1251 d2d_rect_expand(&transformed_rect, &point);
1253 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1254 WARN("Failed to push clip rect.\n");
1257 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1259 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1261 TRACE("iface %p.\n", iface);
1263 d2d_clip_stack_pop(&render_target->clip_stack);
1266 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1268 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1269 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1270 D3D10_SUBRESOURCE_DATA buffer_data;
1271 D3D10_BUFFER_DESC buffer_desc;
1272 ID3D10Buffer *vs_cb, *ps_cb;
1273 HRESULT hr;
1275 static const float transform[] =
1277 1.0f, 0.0f, 0.0f, 0.0f,
1278 0.0f, -1.0f, 0.0f, 0.0f,
1281 TRACE("iface %p, color %p.\n", iface, color);
1283 buffer_desc.ByteWidth = sizeof(transform);
1284 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1285 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1286 buffer_desc.CPUAccessFlags = 0;
1287 buffer_desc.MiscFlags = 0;
1289 buffer_data.pSysMem = transform;
1290 buffer_data.SysMemPitch = 0;
1291 buffer_data.SysMemSlicePitch = 0;
1293 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1295 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1296 return;
1299 if (color)
1300 c = *color;
1301 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1302 c.a = 1.0f;
1303 c.r *= c.a;
1304 c.g *= c.a;
1305 c.b *= c.a;
1306 buffer_desc.ByteWidth = sizeof(c);
1307 buffer_data.pSysMem = &c;
1309 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1311 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1312 ID3D10Buffer_Release(vs_cb);
1313 return;
1316 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1317 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1319 ID3D10Buffer_Release(ps_cb);
1320 ID3D10Buffer_Release(vs_cb);
1323 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1325 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1327 TRACE("iface %p.\n", iface);
1329 memset(&render_target->error, 0, sizeof(render_target->error));
1332 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1333 D2D1_TAG *tag1, D2D1_TAG *tag2)
1335 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1337 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1339 if (tag1)
1340 *tag1 = render_target->error.tag1;
1341 if (tag2)
1342 *tag2 = render_target->error.tag2;
1344 return render_target->error.code;
1347 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1348 D2D1_PIXEL_FORMAT *format)
1350 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1352 TRACE("iface %p, format %p.\n", iface, format);
1354 *format = render_target->desc.pixelFormat;
1355 return format;
1358 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1360 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1362 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1364 if (dpi_x == 0.0f && dpi_y == 0.0f)
1366 dpi_x = 96.0f;
1367 dpi_y = 96.0f;
1369 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1370 return;
1372 render_target->desc.dpiX = dpi_x;
1373 render_target->desc.dpiY = dpi_y;
1376 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1378 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1380 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1382 *dpi_x = render_target->desc.dpiX;
1383 *dpi_y = render_target->desc.dpiY;
1386 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1388 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1390 TRACE("iface %p, size %p.\n", iface, size);
1392 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1393 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1394 return size;
1397 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1398 D2D1_SIZE_U *pixel_size)
1400 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1402 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1404 *pixel_size = render_target->pixel_size;
1405 return pixel_size;
1408 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1410 FIXME("iface %p stub!\n", iface);
1412 return 0;
1415 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1416 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1418 FIXME("iface %p, desc %p stub!\n", iface, desc);
1420 return FALSE;
1423 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1425 d2d_d3d_render_target_QueryInterface,
1426 d2d_d3d_render_target_AddRef,
1427 d2d_d3d_render_target_Release,
1428 d2d_d3d_render_target_GetFactory,
1429 d2d_d3d_render_target_CreateBitmap,
1430 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1431 d2d_d3d_render_target_CreateSharedBitmap,
1432 d2d_d3d_render_target_CreateBitmapBrush,
1433 d2d_d3d_render_target_CreateSolidColorBrush,
1434 d2d_d3d_render_target_CreateGradientStopCollection,
1435 d2d_d3d_render_target_CreateLinearGradientBrush,
1436 d2d_d3d_render_target_CreateRadialGradientBrush,
1437 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1438 d2d_d3d_render_target_CreateLayer,
1439 d2d_d3d_render_target_CreateMesh,
1440 d2d_d3d_render_target_DrawLine,
1441 d2d_d3d_render_target_DrawRectangle,
1442 d2d_d3d_render_target_FillRectangle,
1443 d2d_d3d_render_target_DrawRoundedRectangle,
1444 d2d_d3d_render_target_FillRoundedRectangle,
1445 d2d_d3d_render_target_DrawEllipse,
1446 d2d_d3d_render_target_FillEllipse,
1447 d2d_d3d_render_target_DrawGeometry,
1448 d2d_d3d_render_target_FillGeometry,
1449 d2d_d3d_render_target_FillMesh,
1450 d2d_d3d_render_target_FillOpacityMask,
1451 d2d_d3d_render_target_DrawBitmap,
1452 d2d_d3d_render_target_DrawText,
1453 d2d_d3d_render_target_DrawTextLayout,
1454 d2d_d3d_render_target_DrawGlyphRun,
1455 d2d_d3d_render_target_SetTransform,
1456 d2d_d3d_render_target_GetTransform,
1457 d2d_d3d_render_target_SetAntialiasMode,
1458 d2d_d3d_render_target_GetAntialiasMode,
1459 d2d_d3d_render_target_SetTextAntialiasMode,
1460 d2d_d3d_render_target_GetTextAntialiasMode,
1461 d2d_d3d_render_target_SetTextRenderingParams,
1462 d2d_d3d_render_target_GetTextRenderingParams,
1463 d2d_d3d_render_target_SetTags,
1464 d2d_d3d_render_target_GetTags,
1465 d2d_d3d_render_target_PushLayer,
1466 d2d_d3d_render_target_PopLayer,
1467 d2d_d3d_render_target_Flush,
1468 d2d_d3d_render_target_SaveDrawingState,
1469 d2d_d3d_render_target_RestoreDrawingState,
1470 d2d_d3d_render_target_PushAxisAlignedClip,
1471 d2d_d3d_render_target_PopAxisAlignedClip,
1472 d2d_d3d_render_target_Clear,
1473 d2d_d3d_render_target_BeginDraw,
1474 d2d_d3d_render_target_EndDraw,
1475 d2d_d3d_render_target_GetPixelFormat,
1476 d2d_d3d_render_target_SetDpi,
1477 d2d_d3d_render_target_GetDpi,
1478 d2d_d3d_render_target_GetSize,
1479 d2d_d3d_render_target_GetPixelSize,
1480 d2d_d3d_render_target_GetMaximumBitmapSize,
1481 d2d_d3d_render_target_IsSupported,
1484 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1486 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1489 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1491 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1493 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1494 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1495 || IsEqualGUID(iid, &IID_IUnknown))
1497 IDWriteTextRenderer_AddRef(iface);
1498 *out = iface;
1499 return S_OK;
1502 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1504 *out = NULL;
1505 return E_NOINTERFACE;
1508 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1510 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1512 TRACE("iface %p.\n", iface);
1514 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1517 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1519 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1521 TRACE("iface %p.\n", iface);
1523 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1526 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1527 void *ctx, BOOL *disabled)
1529 struct d2d_draw_text_layout_ctx *context = ctx;
1531 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1533 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1535 return S_OK;
1538 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1539 void *ctx, DWRITE_MATRIX *transform)
1541 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1543 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1545 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1547 return S_OK;
1550 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1552 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1554 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1556 *ppd = render_target->desc.dpiY / 96.0f;
1558 return S_OK;
1561 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1562 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1563 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1565 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1566 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1567 struct d2d_draw_text_layout_ctx *context = ctx;
1568 ID2D1Brush *brush;
1570 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1571 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1572 iface, ctx, baseline_origin_x, baseline_origin_y,
1573 measuring_mode, glyph_run, desc, effect);
1575 if (desc)
1576 WARN("Ignoring glyph run description %p.\n", desc);
1577 if (context->options & ~D2D1_DRAW_TEXT_OPTIONS_NO_SNAP)
1578 FIXME("Ignoring options %#x.\n", context->options);
1580 brush = d2d_draw_get_text_brush(context, effect);
1582 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1583 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1584 baseline_origin, glyph_run, brush, measuring_mode);
1586 ID2D1Brush_Release(brush);
1588 return S_OK;
1591 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1592 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1594 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1595 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1596 struct d2d_draw_text_layout_ctx *context = ctx;
1597 float min_thickness;
1598 ID2D1Brush *brush;
1599 D2D1_RECT_F rect;
1601 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1602 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1604 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1605 min_thickness = 96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22));
1607 rect.left = baseline_origin_x;
1608 rect.top = baseline_origin_y + underline->offset;
1609 rect.right = baseline_origin_x + underline->width;
1610 rect.bottom = baseline_origin_y + underline->offset + max(underline->thickness, min_thickness);
1612 brush = d2d_draw_get_text_brush(context, effect);
1614 ID2D1RenderTarget_FillRectangle(&render_target->ID2D1RenderTarget_iface, &rect, brush);
1616 ID2D1Brush_Release(brush);
1618 return S_OK;
1621 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1622 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1624 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1625 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1627 return E_NOTIMPL;
1630 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1631 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1633 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1634 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1636 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1639 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1641 d2d_text_renderer_QueryInterface,
1642 d2d_text_renderer_AddRef,
1643 d2d_text_renderer_Release,
1644 d2d_text_renderer_IsPixelSnappingDisabled,
1645 d2d_text_renderer_GetCurrentTransform,
1646 d2d_text_renderer_GetPixelsPerDip,
1647 d2d_text_renderer_DrawGlyphRun,
1648 d2d_text_renderer_DrawUnderline,
1649 d2d_text_renderer_DrawStrikethrough,
1650 d2d_text_renderer_DrawInlineObject,
1653 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1654 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1656 D3D10_SUBRESOURCE_DATA buffer_data;
1657 D3D10_STATE_BLOCK_MASK state_mask;
1658 DXGI_SURFACE_DESC surface_desc;
1659 IDWriteFactory *dwrite_factory;
1660 D3D10_RASTERIZER_DESC rs_desc;
1661 D3D10_BUFFER_DESC buffer_desc;
1662 D3D10_BLEND_DESC blend_desc;
1663 ID3D10Resource *resource;
1664 unsigned int i, j, k;
1665 HRESULT hr;
1667 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
1669 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1671 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
1673 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1674 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
1676 static const DWORD vs_code_triangle[] =
1678 /* float3x2 transform;
1680 * float4 main(float4 position : POSITION) : SV_POSITION
1682 * return float4(mul(position.xyw, transform), position.zw);
1683 * } */
1684 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1685 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1686 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1687 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1688 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1689 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1690 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1691 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1692 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1693 0x00000000, 0x0100003e,
1695 static const DWORD vs_code_bezier[] =
1697 #if 0
1698 float3x2 transform;
1700 float4 main(float4 position : POSITION,
1701 inout float3 texcoord : TEXCOORD0) : SV_POSITION
1703 return float4(mul(position.xyw, transform), position.zw);
1705 #endif
1706 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
1707 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
1708 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
1709 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
1710 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
1711 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
1712 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
1713 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
1714 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
1715 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
1716 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
1717 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
1718 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
1720 static const DWORD ps_code_triangle_solid[] =
1722 /* float4 color;
1724 * float4 main(float4 position : SV_POSITION) : SV_Target
1726 * return color;
1727 * } */
1728 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1729 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1730 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1731 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1732 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1733 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1734 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1736 static const DWORD ps_code_triangle_solid_bitmap[] =
1738 #if 0
1739 float4 color;
1741 float3x2 transform;
1742 float opacity;
1743 bool ignore_alpha;
1745 SamplerState s;
1746 Texture2D t;
1748 float4 main(float4 position : SV_POSITION) : SV_Target
1750 float2 texcoord;
1751 float4 ret;
1753 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1754 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1755 ret = t.Sample(s, texcoord) * opacity;
1756 if (ignore_alpha)
1757 ret.a = opacity;
1759 return color * ret.a;
1761 #endif
1762 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
1763 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1764 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1765 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1766 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1767 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1768 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1769 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1770 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
1771 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
1772 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
1773 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
1774 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
1775 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
1776 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
1777 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
1778 0x00000000, 0x0100003e,
1780 static const DWORD ps_code_triangle_bitmap[] =
1782 #if 0
1783 float3x2 transform;
1784 float opacity;
1785 bool ignore_alpha;
1787 SamplerState s;
1788 Texture2D t;
1790 float4 main(float4 position : SV_POSITION) : SV_Target
1792 float2 texcoord;
1793 float4 ret;
1795 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1796 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1797 ret = t.Sample(s, texcoord) * opacity;
1798 if (ignore_alpha)
1799 ret.a = opacity;
1801 return ret;
1803 #endif
1804 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
1805 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1806 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1807 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1808 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
1809 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
1810 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1811 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1812 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1813 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1814 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1815 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1816 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1817 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
1818 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1819 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
1821 static const DWORD ps_code_triangle_bitmap_solid[] =
1823 #if 0
1824 float3x2 transform;
1825 float opacity;
1826 bool ignore_alpha;
1828 float4 color;
1830 SamplerState s;
1831 Texture2D t;
1833 float4 main(float4 position : SV_POSITION) : SV_Target
1835 float2 texcoord;
1836 float4 ret;
1838 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1839 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1840 ret = t.Sample(s, texcoord) * opacity;
1841 if (ignore_alpha)
1842 ret.a = opacity;
1844 return ret * color.a;
1846 #endif
1847 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
1848 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1849 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1850 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1851 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1852 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1853 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1854 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1855 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1856 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1857 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1858 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1859 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1860 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
1861 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1862 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
1863 0x00000003, 0x0100003e,
1865 static const DWORD ps_code_triangle_bitmap_bitmap[] =
1867 #if 0
1868 struct brush
1870 float3x2 transform;
1871 float opacity;
1872 bool ignore_alpha;
1873 } brush0, brush1;
1875 SamplerState s0, s1;
1876 Texture2D t0, t1;
1878 float4 main(float4 position : SV_POSITION) : SV_Target
1880 float2 texcoord;
1881 float opacity;
1882 float4 ret;
1884 texcoord.x = position.x * brush0.transform._11 + position.y * brush0.transform._21 + brush0.transform._31;
1885 texcoord.y = position.x * brush0.transform._12 + position.y * brush0.transform._22 + brush0.transform._32;
1886 ret = t0.Sample(s0, texcoord) * brush0.opacity;
1887 if (brush0.ignore_alpha)
1888 ret.a = brush0.opacity;
1890 texcoord.x = position.x * brush1.transform._11 + position.y * brush1.transform._21 + brush1.transform._31;
1891 texcoord.y = position.x * brush1.transform._12 + position.y * brush1.transform._22 + brush1.transform._32;
1892 opacity = t1.Sample(s1, texcoord).a * brush1.opacity;
1893 if (brush1.ignore_alpha)
1894 opacity = brush1.opacity;
1896 return ret * opacity;
1898 #endif
1899 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
1900 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1901 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1902 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1903 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
1904 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
1905 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
1906 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
1907 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
1908 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
1909 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
1910 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
1911 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
1912 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
1913 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
1914 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
1915 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
1916 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
1917 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
1918 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
1919 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
1920 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
1921 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
1922 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
1923 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
1925 /* The basic idea here is to evaluate the implicit form of the curve in
1926 * texture space. "t.z" determines which side of the curve is shaded. */
1927 static const DWORD ps_code_bezier_solid[] =
1929 #if 0
1930 float4 color;
1932 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
1934 clip((t.x * t.x - t.y) * t.z);
1935 return color;
1937 #endif
1938 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
1939 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
1940 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
1941 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
1942 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
1943 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
1944 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
1945 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
1946 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
1947 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
1948 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
1949 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1951 static const struct brush_shader
1953 const void *byte_code;
1954 size_t byte_code_size;
1955 enum d2d_shape_type shape_type;
1956 enum d2d_brush_type brush_type;
1957 enum d2d_brush_type opacity_brush_type;
1959 brush_shaders[] =
1961 {ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
1962 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
1963 {ps_code_triangle_solid_bitmap, sizeof(ps_code_triangle_solid_bitmap),
1964 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_BITMAP},
1965 {ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
1966 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_COUNT},
1967 {ps_code_triangle_bitmap_solid, sizeof(ps_code_triangle_bitmap_solid),
1968 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_SOLID},
1969 {ps_code_triangle_bitmap_bitmap, sizeof(ps_code_triangle_bitmap_bitmap),
1970 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_BITMAP},
1971 {ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
1972 D2D_SHAPE_TYPE_BEZIER, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
1974 static const struct
1976 float x, y;
1978 quad[] =
1980 {-1.0f, 1.0f},
1981 {-1.0f, -1.0f},
1982 { 1.0f, 1.0f},
1983 { 1.0f, -1.0f},
1985 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
1986 static const D2D1_MATRIX_3X2_F identity =
1988 1.0f, 0.0f,
1989 0.0f, 1.0f,
1990 0.0f, 0.0f,
1992 float dpi_x, dpi_y;
1994 dpi_x = desc->dpiX;
1995 dpi_y = desc->dpiY;
1997 if (dpi_x == 0.0f && dpi_y == 0.0f)
1999 dpi_x = 96.0f;
2000 dpi_y = 96.0f;
2002 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
2003 return E_INVALIDARG;
2005 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
2006 WARN("Ignoring render target type %#x.\n", desc->type);
2007 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
2008 FIXME("Ignoring render target usage %#x.\n", desc->usage);
2009 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
2010 WARN("Ignoring feature level %#x.\n", desc->minLevel);
2012 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
2013 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
2014 render_target->refcount = 1;
2015 render_target->factory = factory;
2016 ID2D1Factory_AddRef(render_target->factory);
2018 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
2020 WARN("Failed to get device interface, hr %#x.\n", hr);
2021 ID2D1Factory_Release(render_target->factory);
2022 return hr;
2025 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2027 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2028 goto err;
2031 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
2032 ID3D10Resource_Release(resource);
2033 if (FAILED(hr))
2035 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2036 goto err;
2039 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
2041 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
2042 goto err;
2045 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
2047 WARN("Failed to create stateblock, hr %#x.\n", hr);
2048 goto err;
2051 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
2052 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
2053 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
2055 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
2056 goto err;
2059 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
2060 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
2061 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
2063 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
2064 goto err;
2067 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
2068 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
2070 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
2071 goto err;
2074 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
2075 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
2077 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
2078 goto err;
2081 for (i = 0; i < sizeof(brush_shaders) / sizeof(*brush_shaders); ++i)
2083 const struct brush_shader *bs = &brush_shaders[i];
2084 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, bs->byte_code, bs->byte_code_size,
2085 &render_target->shape_resources[bs->shape_type].ps[bs->brush_type][bs->opacity_brush_type])))
2087 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
2088 bs->shape_type, bs->brush_type, bs->opacity_brush_type);
2089 goto err;
2093 buffer_desc.ByteWidth = sizeof(indices);
2094 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
2095 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
2096 buffer_desc.CPUAccessFlags = 0;
2097 buffer_desc.MiscFlags = 0;
2099 buffer_data.pSysMem = indices;
2100 buffer_data.SysMemPitch = 0;
2101 buffer_data.SysMemSlicePitch = 0;
2103 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2104 &buffer_desc, &buffer_data, &render_target->ib)))
2106 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
2107 goto err;
2110 buffer_desc.ByteWidth = sizeof(quad);
2111 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
2112 buffer_data.pSysMem = quad;
2114 render_target->vb_stride = sizeof(*quad);
2115 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2116 &buffer_desc, &buffer_data, &render_target->vb)))
2118 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
2119 goto err;
2122 rs_desc.FillMode = D3D10_FILL_SOLID;
2123 rs_desc.CullMode = D3D10_CULL_NONE;
2124 rs_desc.FrontCounterClockwise = FALSE;
2125 rs_desc.DepthBias = 0;
2126 rs_desc.DepthBiasClamp = 0.0f;
2127 rs_desc.SlopeScaledDepthBias = 0.0f;
2128 rs_desc.DepthClipEnable = TRUE;
2129 rs_desc.ScissorEnable = TRUE;
2130 rs_desc.MultisampleEnable = FALSE;
2131 rs_desc.AntialiasedLineEnable = FALSE;
2132 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
2134 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
2135 goto err;
2138 memset(&blend_desc, 0, sizeof(blend_desc));
2139 blend_desc.BlendEnable[0] = TRUE;
2140 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2141 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2142 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2143 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2145 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2146 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2148 else
2150 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2151 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2153 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2154 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2155 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
2157 WARN("Failed to create blend state, hr %#x.\n", hr);
2158 goto err;
2161 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
2162 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
2164 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2165 goto err;
2168 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
2169 IDWriteFactory_Release(dwrite_factory);
2170 if (FAILED(hr))
2172 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
2173 goto err;
2176 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2178 WARN("Failed to get surface desc, hr %#x.\n", hr);
2179 goto err;
2182 render_target->desc.pixelFormat = desc->pixelFormat;
2183 render_target->pixel_size.width = surface_desc.Width;
2184 render_target->pixel_size.height = surface_desc.Height;
2185 render_target->drawing_state.transform = identity;
2187 if (!d2d_clip_stack_init(&render_target->clip_stack))
2189 WARN("Failed to initialize clip stack.\n");
2190 hr = E_FAIL;
2191 goto err;
2194 render_target->desc.dpiX = dpi_x;
2195 render_target->desc.dpiY = dpi_y;
2197 return S_OK;
2199 err:
2200 if (render_target->default_text_rendering_params)
2201 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
2202 if (render_target->bs)
2203 ID3D10BlendState_Release(render_target->bs);
2204 if (render_target->rs)
2205 ID3D10RasterizerState_Release(render_target->rs);
2206 if (render_target->vb)
2207 ID3D10Buffer_Release(render_target->vb);
2208 if (render_target->ib)
2209 ID3D10Buffer_Release(render_target->ib);
2210 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
2212 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2214 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2216 if (render_target->shape_resources[i].ps[j][k])
2217 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
2220 if (render_target->shape_resources[i].vs)
2221 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
2222 if (render_target->shape_resources[i].il)
2223 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
2225 if (render_target->stateblock)
2226 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
2227 if (render_target->view)
2228 ID3D10RenderTargetView_Release(render_target->view);
2229 if (render_target->device)
2230 ID3D10Device_Release(render_target->device);
2231 ID2D1Factory_Release(render_target->factory);
2232 return hr;
2235 HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1 *surface)
2237 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
2238 DXGI_SURFACE_DESC surface_desc;
2239 ID3D10RenderTargetView *view;
2240 ID3D10Resource *resource;
2241 HRESULT hr;
2243 if (!surface)
2245 ID3D10RenderTargetView_Release(render_target->view);
2246 render_target->view = NULL;
2247 return S_OK;
2250 if (FAILED(hr = IDXGISurface1_GetDesc(surface, &surface_desc)))
2252 WARN("Failed to get surface desc, hr %#x.\n", hr);
2253 return hr;
2256 if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2258 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2259 return hr;
2262 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &view);
2263 ID3D10Resource_Release(resource);
2264 if (FAILED(hr))
2266 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2267 return hr;
2270 render_target->pixel_size.width = surface_desc.Width;
2271 render_target->pixel_size.height = surface_desc.Height;
2272 ID3D10RenderTargetView_Release(render_target->view);
2273 render_target->view = view;
2275 return S_OK;