wined3d: Use the texture dimension helpers in wined3d_texture_update_overlay().
[wine.git] / dlls / d2d1 / render_target.c
blob5005840ecd475ce8d594e084373ce65239d8d698
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(render_target->factory, 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 **render_target)
431 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
432 iface, size, pixel_size, format, options, render_target);
434 return E_NOTIMPL;
437 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
438 const D2D1_SIZE_F *size, ID2D1Layer **layer)
440 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
442 return E_NOTIMPL;
445 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
447 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
448 struct d2d_mesh *object;
449 HRESULT hr;
451 TRACE("iface %p, mesh %p.\n", iface, mesh);
453 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
454 *mesh = &object->ID2D1Mesh_iface;
456 return hr;
459 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
460 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
462 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
463 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
466 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
467 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
469 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
470 iface, rect, brush, stroke_width, stroke_style);
473 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
474 const D2D1_RECT_F *rect, ID2D1Brush *brush)
476 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
477 ID2D1RectangleGeometry *geometry;
478 HRESULT hr;
480 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
482 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
484 ERR("Failed to create geometry, hr %#x.\n", hr);
485 return;
488 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
489 ID2D1RectangleGeometry_Release(geometry);
492 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
493 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
495 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
496 iface, rect, brush, stroke_width, stroke_style);
499 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
500 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
502 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
503 ID2D1RoundedRectangleGeometry *geometry;
504 HRESULT hr;
506 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
508 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
510 ERR("Failed to create geometry, hr %#x.\n", hr);
511 return;
514 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
515 ID2D1RoundedRectangleGeometry_Release(geometry);
518 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
519 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
521 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
522 iface, ellipse, brush, stroke_width, stroke_style);
525 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
526 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
528 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
529 ID2D1EllipseGeometry *geometry;
530 HRESULT hr;
532 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
534 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
536 ERR("Failed to create geometry, hr %#x.\n", hr);
537 return;
540 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
541 ID2D1EllipseGeometry_Release(geometry);
544 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
545 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
547 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
548 iface, geometry, brush, stroke_width, stroke_style);
551 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
552 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
554 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
555 D3D10_SUBRESOURCE_DATA buffer_data;
556 D3D10_BUFFER_DESC buffer_desc;
557 D2D1_MATRIX_3X2_F w, g;
558 float tmp_x, tmp_y;
559 HRESULT hr;
560 struct
562 float _11, _21, _31, pad0;
563 float _12, _22, _32, pad1;
564 } transform;
566 tmp_x = (2.0f * render_target->dpi_x) / (96.0f * render_target->pixel_size.width);
567 tmp_y = -(2.0f * render_target->dpi_y) / (96.0f * render_target->pixel_size.height);
568 w = render_target->drawing_state.transform;
569 w._11 *= tmp_x;
570 w._21 *= tmp_x;
571 w._31 = w._31 * tmp_x - 1.0f;
572 w._12 *= tmp_y;
573 w._22 *= tmp_y;
574 w._32 = w._32 * tmp_y + 1.0f;
576 g = geometry->transform;
577 d2d_matrix_multiply(&g, &w);
579 transform._11 = g._11;
580 transform._21 = g._21;
581 transform._31 = g._31;
582 transform.pad0 = 0.0f;
583 transform._12 = g._12;
584 transform._22 = g._22;
585 transform._32 = g._32;
586 transform.pad1 = 0.0f;
588 buffer_desc.ByteWidth = sizeof(transform);
589 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
590 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
591 buffer_desc.CPUAccessFlags = 0;
592 buffer_desc.MiscFlags = 0;
594 buffer_data.pSysMem = &transform;
595 buffer_data.SysMemPitch = 0;
596 buffer_data.SysMemSlicePitch = 0;
598 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
600 WARN("Failed to create constant buffer, hr %#x.\n", hr);
601 return;
604 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, render_target, &ps_cb)))
606 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
607 ID3D10Buffer_Release(vs_cb);
608 return;
611 if (geometry->face_count)
613 buffer_desc.ByteWidth = geometry->face_count * sizeof(*geometry->faces);
614 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
615 buffer_data.pSysMem = geometry->faces;
617 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
619 WARN("Failed to create index buffer, hr %#x.\n", hr);
620 goto done;
623 buffer_desc.ByteWidth = geometry->vertex_count * sizeof(*geometry->vertices);
624 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
625 buffer_data.pSysMem = geometry->vertices;
627 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
629 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
630 ID3D10Buffer_Release(ib);
631 goto done;
634 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->face_count, vb,
635 sizeof(*geometry->vertices), vs_cb, ps_cb, brush, opacity_brush);
637 ID3D10Buffer_Release(vb);
638 ID3D10Buffer_Release(ib);
641 if (geometry->bezier_count)
643 buffer_desc.ByteWidth = geometry->bezier_count * sizeof(*geometry->beziers);
644 buffer_data.pSysMem = geometry->beziers;
646 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
648 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
649 goto done;
652 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, 3 * geometry->bezier_count, vb,
653 sizeof(*geometry->beziers->v), vs_cb, ps_cb, brush, opacity_brush);
655 ID3D10Buffer_Release(vb);
658 done:
659 ID3D10Buffer_Release(ps_cb);
660 ID3D10Buffer_Release(vs_cb);
663 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
664 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
666 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
667 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
668 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
669 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
671 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
673 if (FAILED(render_target->error.code))
674 return;
676 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
678 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
679 render_target->error.tag1 = render_target->drawing_state.tag1;
680 render_target->error.tag2 = render_target->drawing_state.tag2;
681 return;
684 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
687 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
688 ID2D1Mesh *mesh, ID2D1Brush *brush)
690 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
693 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
694 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
695 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
697 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
698 iface, mask, brush, content, dst_rect, src_rect);
701 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
702 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
703 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
705 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
706 D2D1_BRUSH_PROPERTIES brush_desc;
707 ID2D1BitmapBrush *brush;
708 D2D1_RECT_F s, d;
709 HRESULT hr;
711 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
712 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
714 if (src_rect)
716 s = *src_rect;
718 else
720 D2D1_SIZE_F size;
722 size = ID2D1Bitmap_GetSize(bitmap);
723 s.left = 0.0f;
724 s.top = 0.0f;
725 s.right = size.width;
726 s.bottom = size.height;
729 if (dst_rect)
731 d = *dst_rect;
733 else
735 d.left = 0.0f;
736 d.top = 0.0f;
737 d.right = s.right - s.left;
738 d.bottom = s.bottom - s.top;
741 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
742 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
743 bitmap_brush_desc.interpolationMode = interpolation_mode;
745 brush_desc.opacity = opacity;
746 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
747 brush_desc.transform._21 = 0.0f;
748 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
749 brush_desc.transform._12 = 0.0f;
750 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
751 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
753 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
755 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
756 return;
759 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
760 ID2D1BitmapBrush_Release(brush);
763 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
764 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
765 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
767 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
768 IDWriteTextLayout *text_layout;
769 IDWriteFactory *dwrite_factory;
770 D2D1_POINT_2F origin;
771 HRESULT hr;
773 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
774 "brush %p, options %#x, measuring_mode %#x.\n",
775 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
776 brush, options, measuring_mode);
778 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
779 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
781 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
782 return;
785 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
786 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
787 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
788 else
789 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
790 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->dpi_x / 96.0f,
791 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
792 IDWriteFactory_Release(dwrite_factory);
793 if (FAILED(hr))
795 ERR("Failed to create text layout, hr %#x.\n", hr);
796 return;
799 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
800 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
801 IDWriteTextLayout_Release(text_layout);
804 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
805 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
807 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
808 struct d2d_draw_text_layout_ctx ctx;
809 HRESULT hr;
811 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
812 iface, origin.x, origin.y, layout, brush, options);
814 ctx.brush = brush;
815 ctx.options = options;
817 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
818 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
819 FIXME("Failed to draw text layout, hr %#x.\n", hr);
822 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
823 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
825 D2D1_MATRIX_3X2_F *transform, prev_transform;
826 ID2D1PathGeometry *geometry;
827 ID2D1GeometrySink *sink;
828 HRESULT hr;
830 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
832 ERR("Failed to create geometry, hr %#x.\n", hr);
833 return;
836 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
838 ERR("Failed to open geometry sink, hr %#x.\n", hr);
839 ID2D1PathGeometry_Release(geometry);
840 return;
843 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
844 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
845 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
847 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
848 ID2D1GeometrySink_Release(sink);
849 ID2D1PathGeometry_Release(geometry);
850 return;
853 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
854 ERR("Failed to close geometry sink, hr %#x.\n", hr);
855 ID2D1GeometrySink_Release(sink);
857 transform = &render_target->drawing_state.transform;
858 prev_transform = *transform;
859 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
860 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
861 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
862 unsafe_impl_from_ID2D1Brush(brush), NULL);
863 *transform = prev_transform;
865 ID2D1PathGeometry_Release(geometry);
868 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
869 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
870 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode)
872 ID2D1RectangleGeometry *geometry = NULL;
873 ID2D1BitmapBrush *opacity_brush = NULL;
874 D2D1_BITMAP_PROPERTIES bitmap_desc;
875 ID2D1Bitmap *opacity_bitmap = NULL;
876 IDWriteGlyphRunAnalysis *analysis;
877 DWRITE_TEXTURE_TYPE texture_type;
878 D2D1_BRUSH_PROPERTIES brush_desc;
879 IDWriteFactory *dwrite_factory;
880 void *opacity_values = NULL;
881 size_t opacity_values_size;
882 D2D1_SIZE_U bitmap_size;
883 D2D1_RECT_F run_rect;
884 RECT bounds;
885 HRESULT hr;
887 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
888 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
890 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
891 return;
894 hr = IDWriteFactory_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, ppd, NULL,
895 rendering_mode, measuring_mode, baseline_origin.x, baseline_origin.y, &analysis);
896 IDWriteFactory_Release(dwrite_factory);
897 if (FAILED(hr))
899 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
900 return;
903 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
904 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
905 else
906 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
908 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
910 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
911 goto done;
914 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
915 if (!bitmap_size.width || !bitmap_size.height)
917 /* Empty run, nothing to do. */
918 goto done;
921 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
922 bitmap_size.width *= 3;
923 opacity_values_size = bitmap_size.width * bitmap_size.height;
924 if (!(opacity_values = HeapAlloc(GetProcessHeap(), 0, opacity_values_size)))
926 ERR("Failed to allocate opacity values.\n");
927 goto done;
930 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
931 texture_type, &bounds, opacity_values, opacity_values_size)))
933 ERR("Failed to create alpha texture, hr %#x.\n", hr);
934 goto done;
937 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
938 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
939 bitmap_desc.dpiX = render_target->dpi_x;
940 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
941 bitmap_desc.dpiX *= 3.0f;
942 bitmap_desc.dpiY = render_target->dpi_y;
943 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
944 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
946 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
947 goto done;
950 brush_desc.opacity = 1.0f;
951 brush_desc.transform._11 = 1.0f;
952 brush_desc.transform._12 = 0.0f;
953 brush_desc.transform._21 = 0.0f;
954 brush_desc.transform._22 = 1.0f;
955 brush_desc.transform._31 = bounds.left;
956 brush_desc.transform._32 = bounds.top;
957 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
958 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
960 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
961 goto done;
964 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
965 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
967 ERR("Failed to create geometry, hr %#x.\n", hr);
968 goto done;
971 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
972 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
974 done:
975 if (geometry)
976 ID2D1RectangleGeometry_Release(geometry);
977 if (opacity_brush)
978 ID2D1BitmapBrush_Release(opacity_brush);
979 if (opacity_bitmap)
980 ID2D1Bitmap_Release(opacity_bitmap);
981 HeapFree(GetProcessHeap(), 0, opacity_values);
982 IDWriteGlyphRunAnalysis_Release(analysis);
985 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
986 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
987 DWRITE_MEASURING_MODE measuring_mode)
989 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
990 IDWriteRenderingParams *rendering_params;
991 DWRITE_RENDERING_MODE rendering_mode;
992 HRESULT hr;
993 float ppd;
995 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
996 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
998 if (FAILED(render_target->error.code))
999 return;
1001 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
1002 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
1004 ppd = max(render_target->dpi_x, render_target->dpi_y) / 96.0f;
1005 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1006 : render_target->default_text_rendering_params;
1007 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1008 ppd, measuring_mode, rendering_params, &rendering_mode)))
1010 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1011 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1014 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1015 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1016 else
1017 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1018 ppd, rendering_mode, measuring_mode);
1021 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1022 const D2D1_MATRIX_3X2_F *transform)
1024 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1026 TRACE("iface %p, transform %p.\n", iface, transform);
1028 render_target->drawing_state.transform = *transform;
1031 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1032 D2D1_MATRIX_3X2_F *transform)
1034 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1036 TRACE("iface %p, transform %p.\n", iface, transform);
1038 *transform = render_target->drawing_state.transform;
1041 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1042 D2D1_ANTIALIAS_MODE antialias_mode)
1044 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1046 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1048 render_target->drawing_state.antialiasMode = antialias_mode;
1051 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1053 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1055 TRACE("iface %p.\n", iface);
1057 return render_target->drawing_state.antialiasMode;
1060 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1061 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1063 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1065 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1067 render_target->drawing_state.textAntialiasMode = antialias_mode;
1070 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1072 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1074 TRACE("iface %p.\n", iface);
1076 return render_target->drawing_state.textAntialiasMode;
1079 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1080 IDWriteRenderingParams *text_rendering_params)
1082 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1084 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1086 if (text_rendering_params)
1087 IDWriteRenderingParams_AddRef(text_rendering_params);
1088 if (render_target->text_rendering_params)
1089 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1090 render_target->text_rendering_params = text_rendering_params;
1093 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1094 IDWriteRenderingParams **text_rendering_params)
1096 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1098 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1100 if ((*text_rendering_params = render_target->text_rendering_params))
1101 IDWriteRenderingParams_AddRef(*text_rendering_params);
1104 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1106 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1108 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1110 render_target->drawing_state.tag1 = tag1;
1111 render_target->drawing_state.tag2 = tag2;
1114 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1116 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1118 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1120 *tag1 = render_target->drawing_state.tag1;
1121 *tag2 = render_target->drawing_state.tag2;
1124 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1125 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1127 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1130 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1132 FIXME("iface %p stub!\n", iface);
1135 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1137 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1139 return E_NOTIMPL;
1142 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1143 ID2D1DrawingStateBlock *state_block)
1145 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1146 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1148 TRACE("iface %p, state_block %p.\n", iface, state_block);
1150 state_block_impl->drawing_state = render_target->drawing_state;
1151 if (render_target->text_rendering_params)
1152 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1153 if (state_block_impl->text_rendering_params)
1154 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1155 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1158 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1159 ID2D1DrawingStateBlock *state_block)
1161 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1162 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1164 TRACE("iface %p, state_block %p.\n", iface, state_block);
1166 render_target->drawing_state = state_block_impl->drawing_state;
1167 if (state_block_impl->text_rendering_params)
1168 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1169 if (render_target->text_rendering_params)
1170 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1171 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1174 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1175 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1177 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1178 D2D1_RECT_F transformed_rect;
1179 float x_scale, y_scale;
1180 D2D1_POINT_2F point;
1182 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1184 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1185 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1187 x_scale = render_target->dpi_x / 96.0f;
1188 y_scale = render_target->dpi_y / 96.0f;
1189 d2d_point_transform(&point, &render_target->drawing_state.transform,
1190 clip_rect->left * x_scale, clip_rect->top * y_scale);
1191 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1192 d2d_point_transform(&point, &render_target->drawing_state.transform,
1193 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1194 d2d_rect_expand(&transformed_rect, &point);
1195 d2d_point_transform(&point, &render_target->drawing_state.transform,
1196 clip_rect->right * x_scale, clip_rect->top * y_scale);
1197 d2d_rect_expand(&transformed_rect, &point);
1198 d2d_point_transform(&point, &render_target->drawing_state.transform,
1199 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1200 d2d_rect_expand(&transformed_rect, &point);
1202 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1203 WARN("Failed to push clip rect.\n");
1206 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1208 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1210 TRACE("iface %p.\n", iface);
1212 d2d_clip_stack_pop(&render_target->clip_stack);
1215 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1217 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1218 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1219 D3D10_SUBRESOURCE_DATA buffer_data;
1220 D3D10_BUFFER_DESC buffer_desc;
1221 ID3D10Buffer *vs_cb, *ps_cb;
1222 HRESULT hr;
1224 static const float transform[] =
1226 1.0f, 0.0f, 0.0f, 0.0f,
1227 0.0f, -1.0f, 0.0f, 0.0f,
1230 TRACE("iface %p, color %p.\n", iface, color);
1232 buffer_desc.ByteWidth = sizeof(transform);
1233 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1234 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1235 buffer_desc.CPUAccessFlags = 0;
1236 buffer_desc.MiscFlags = 0;
1238 buffer_data.pSysMem = transform;
1239 buffer_data.SysMemPitch = 0;
1240 buffer_data.SysMemSlicePitch = 0;
1242 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1244 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1245 return;
1248 if (color)
1249 c = *color;
1250 if (render_target->format.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1251 c.a = 1.0f;
1252 c.r *= c.a;
1253 c.g *= c.a;
1254 c.b *= c.a;
1255 buffer_desc.ByteWidth = sizeof(c);
1256 buffer_data.pSysMem = &c;
1258 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1260 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1261 ID3D10Buffer_Release(vs_cb);
1262 return;
1265 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1266 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1268 ID3D10Buffer_Release(ps_cb);
1269 ID3D10Buffer_Release(vs_cb);
1272 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1274 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1276 TRACE("iface %p.\n", iface);
1278 memset(&render_target->error, 0, sizeof(render_target->error));
1281 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1282 D2D1_TAG *tag1, D2D1_TAG *tag2)
1284 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1286 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1288 if (tag1)
1289 *tag1 = render_target->error.tag1;
1290 if (tag2)
1291 *tag2 = render_target->error.tag2;
1293 return render_target->error.code;
1296 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1297 D2D1_PIXEL_FORMAT *format)
1299 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1301 TRACE("iface %p, format %p.\n", iface, format);
1303 *format = render_target->format;
1304 return format;
1307 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1309 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1311 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1313 if (dpi_x == 0.0f && dpi_y == 0.0f)
1315 dpi_x = 96.0f;
1316 dpi_y = 96.0f;
1318 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1319 return;
1321 render_target->dpi_x = dpi_x;
1322 render_target->dpi_y = dpi_y;
1325 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1327 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1329 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1331 *dpi_x = render_target->dpi_x;
1332 *dpi_y = render_target->dpi_y;
1335 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1337 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1339 TRACE("iface %p, size %p.\n", iface, size);
1341 size->width = render_target->pixel_size.width / (render_target->dpi_x / 96.0f);
1342 size->height = render_target->pixel_size.height / (render_target->dpi_y / 96.0f);
1343 return size;
1346 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1347 D2D1_SIZE_U *pixel_size)
1349 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1351 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1353 *pixel_size = render_target->pixel_size;
1354 return pixel_size;
1357 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1359 FIXME("iface %p stub!\n", iface);
1361 return 0;
1364 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1365 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1367 FIXME("iface %p, desc %p stub!\n", iface, desc);
1369 return FALSE;
1372 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1374 d2d_d3d_render_target_QueryInterface,
1375 d2d_d3d_render_target_AddRef,
1376 d2d_d3d_render_target_Release,
1377 d2d_d3d_render_target_GetFactory,
1378 d2d_d3d_render_target_CreateBitmap,
1379 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1380 d2d_d3d_render_target_CreateSharedBitmap,
1381 d2d_d3d_render_target_CreateBitmapBrush,
1382 d2d_d3d_render_target_CreateSolidColorBrush,
1383 d2d_d3d_render_target_CreateGradientStopCollection,
1384 d2d_d3d_render_target_CreateLinearGradientBrush,
1385 d2d_d3d_render_target_CreateRadialGradientBrush,
1386 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1387 d2d_d3d_render_target_CreateLayer,
1388 d2d_d3d_render_target_CreateMesh,
1389 d2d_d3d_render_target_DrawLine,
1390 d2d_d3d_render_target_DrawRectangle,
1391 d2d_d3d_render_target_FillRectangle,
1392 d2d_d3d_render_target_DrawRoundedRectangle,
1393 d2d_d3d_render_target_FillRoundedRectangle,
1394 d2d_d3d_render_target_DrawEllipse,
1395 d2d_d3d_render_target_FillEllipse,
1396 d2d_d3d_render_target_DrawGeometry,
1397 d2d_d3d_render_target_FillGeometry,
1398 d2d_d3d_render_target_FillMesh,
1399 d2d_d3d_render_target_FillOpacityMask,
1400 d2d_d3d_render_target_DrawBitmap,
1401 d2d_d3d_render_target_DrawText,
1402 d2d_d3d_render_target_DrawTextLayout,
1403 d2d_d3d_render_target_DrawGlyphRun,
1404 d2d_d3d_render_target_SetTransform,
1405 d2d_d3d_render_target_GetTransform,
1406 d2d_d3d_render_target_SetAntialiasMode,
1407 d2d_d3d_render_target_GetAntialiasMode,
1408 d2d_d3d_render_target_SetTextAntialiasMode,
1409 d2d_d3d_render_target_GetTextAntialiasMode,
1410 d2d_d3d_render_target_SetTextRenderingParams,
1411 d2d_d3d_render_target_GetTextRenderingParams,
1412 d2d_d3d_render_target_SetTags,
1413 d2d_d3d_render_target_GetTags,
1414 d2d_d3d_render_target_PushLayer,
1415 d2d_d3d_render_target_PopLayer,
1416 d2d_d3d_render_target_Flush,
1417 d2d_d3d_render_target_SaveDrawingState,
1418 d2d_d3d_render_target_RestoreDrawingState,
1419 d2d_d3d_render_target_PushAxisAlignedClip,
1420 d2d_d3d_render_target_PopAxisAlignedClip,
1421 d2d_d3d_render_target_Clear,
1422 d2d_d3d_render_target_BeginDraw,
1423 d2d_d3d_render_target_EndDraw,
1424 d2d_d3d_render_target_GetPixelFormat,
1425 d2d_d3d_render_target_SetDpi,
1426 d2d_d3d_render_target_GetDpi,
1427 d2d_d3d_render_target_GetSize,
1428 d2d_d3d_render_target_GetPixelSize,
1429 d2d_d3d_render_target_GetMaximumBitmapSize,
1430 d2d_d3d_render_target_IsSupported,
1433 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1435 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1438 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1440 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1442 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1443 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1444 || IsEqualGUID(iid, &IID_IUnknown))
1446 IDWriteTextRenderer_AddRef(iface);
1447 *out = iface;
1448 return S_OK;
1451 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1453 *out = NULL;
1454 return E_NOINTERFACE;
1457 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1459 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1461 TRACE("iface %p.\n", iface);
1463 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1466 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1468 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1470 TRACE("iface %p.\n", iface);
1472 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1475 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1476 void *ctx, BOOL *disabled)
1478 struct d2d_draw_text_layout_ctx *context = ctx;
1480 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1482 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1484 return S_OK;
1487 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1488 void *ctx, DWRITE_MATRIX *transform)
1490 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1492 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1494 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1496 return S_OK;
1499 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1501 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1503 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1505 *ppd = render_target->dpi_y / 96.0f;
1507 return S_OK;
1510 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1511 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1512 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1514 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1515 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1516 struct d2d_draw_text_layout_ctx *context = ctx;
1517 ID2D1Brush *brush;
1519 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1520 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1521 iface, ctx, baseline_origin_x, baseline_origin_y,
1522 measuring_mode, glyph_run, desc, effect);
1524 if (desc)
1525 WARN("Ignoring glyph run description %p.\n", desc);
1526 if (context->options & ~D2D1_DRAW_TEXT_OPTIONS_NO_SNAP)
1527 FIXME("Ignoring options %#x.\n", context->options);
1529 brush = d2d_draw_get_text_brush(context, effect);
1531 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1532 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1533 baseline_origin, glyph_run, brush, measuring_mode);
1535 ID2D1Brush_Release(brush);
1537 return S_OK;
1540 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1541 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1543 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1544 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1545 struct d2d_draw_text_layout_ctx *context = ctx;
1546 float min_thickness;
1547 ID2D1Brush *brush;
1548 D2D1_RECT_F rect;
1550 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1551 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1553 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1554 min_thickness = 96.0f / (render_target->dpi_y * sqrtf(m->_21 * m->_21 + m->_22 * m->_22));
1556 rect.left = baseline_origin_x;
1557 rect.top = baseline_origin_y + underline->offset;
1558 rect.right = baseline_origin_x + underline->width;
1559 rect.bottom = baseline_origin_y + underline->offset + max(underline->thickness, min_thickness);
1561 brush = d2d_draw_get_text_brush(context, effect);
1563 ID2D1RenderTarget_FillRectangle(&render_target->ID2D1RenderTarget_iface, &rect, brush);
1565 ID2D1Brush_Release(brush);
1567 return S_OK;
1570 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1571 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1573 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1574 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1576 return E_NOTIMPL;
1579 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1580 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1582 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1583 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1585 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1588 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1590 d2d_text_renderer_QueryInterface,
1591 d2d_text_renderer_AddRef,
1592 d2d_text_renderer_Release,
1593 d2d_text_renderer_IsPixelSnappingDisabled,
1594 d2d_text_renderer_GetCurrentTransform,
1595 d2d_text_renderer_GetPixelsPerDip,
1596 d2d_text_renderer_DrawGlyphRun,
1597 d2d_text_renderer_DrawUnderline,
1598 d2d_text_renderer_DrawStrikethrough,
1599 d2d_text_renderer_DrawInlineObject,
1602 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1603 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1605 D3D10_SUBRESOURCE_DATA buffer_data;
1606 D3D10_STATE_BLOCK_MASK state_mask;
1607 DXGI_SURFACE_DESC surface_desc;
1608 IDWriteFactory *dwrite_factory;
1609 D3D10_RASTERIZER_DESC rs_desc;
1610 D3D10_BUFFER_DESC buffer_desc;
1611 D3D10_BLEND_DESC blend_desc;
1612 ID3D10Resource *resource;
1613 unsigned int i, j, k;
1614 HRESULT hr;
1616 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
1618 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1620 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
1622 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1623 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
1625 static const DWORD vs_code_triangle[] =
1627 /* float3x2 transform;
1629 * float4 main(float4 position : POSITION) : SV_POSITION
1631 * return float4(mul(position.xyw, transform), position.zw);
1632 * } */
1633 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1634 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1635 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1636 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1637 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1638 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1639 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1640 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1641 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1642 0x00000000, 0x0100003e,
1644 static const DWORD vs_code_bezier[] =
1646 #if 0
1647 float3x2 transform;
1649 float4 main(float4 position : POSITION,
1650 inout float3 texcoord : TEXCOORD0) : SV_POSITION
1652 return float4(mul(position.xyw, transform), position.zw);
1654 #endif
1655 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
1656 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
1657 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
1658 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
1659 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
1660 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
1661 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
1662 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
1663 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
1664 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
1665 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
1666 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
1667 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
1669 static const DWORD ps_code_triangle_solid[] =
1671 /* float4 color;
1673 * float4 main(float4 position : SV_POSITION) : SV_Target
1675 * return color;
1676 * } */
1677 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1678 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1679 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1680 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1681 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1682 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1683 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1685 static const DWORD ps_code_triangle_solid_bitmap[] =
1687 #if 0
1688 float4 color;
1690 float3x2 transform;
1691 float opacity;
1692 bool ignore_alpha;
1694 SamplerState s;
1695 Texture2D t;
1697 float4 main(float4 position : SV_POSITION) : SV_Target
1699 float2 texcoord;
1700 float4 ret;
1702 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1703 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1704 ret = t.Sample(s, texcoord) * opacity;
1705 if (ignore_alpha)
1706 ret.a = opacity;
1708 return color * ret.a;
1710 #endif
1711 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
1712 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1713 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1714 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1715 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1716 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1717 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1718 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1719 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
1720 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
1721 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
1722 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
1723 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
1724 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
1725 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
1726 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
1727 0x00000000, 0x0100003e,
1729 static const DWORD ps_code_triangle_bitmap[] =
1731 #if 0
1732 float3x2 transform;
1733 float opacity;
1734 bool ignore_alpha;
1736 SamplerState s;
1737 Texture2D t;
1739 float4 main(float4 position : SV_POSITION) : SV_Target
1741 float2 texcoord;
1742 float4 ret;
1744 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1745 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1746 ret = t.Sample(s, texcoord) * opacity;
1747 if (ignore_alpha)
1748 ret.a = opacity;
1750 return ret;
1752 #endif
1753 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
1754 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1755 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1756 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1757 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
1758 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
1759 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1760 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1761 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1762 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1763 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1764 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1765 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1766 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
1767 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1768 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
1770 static const DWORD ps_code_triangle_bitmap_solid[] =
1772 #if 0
1773 float3x2 transform;
1774 float opacity;
1775 bool ignore_alpha;
1777 float4 color;
1779 SamplerState s;
1780 Texture2D t;
1782 float4 main(float4 position : SV_POSITION) : SV_Target
1784 float2 texcoord;
1785 float4 ret;
1787 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1788 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1789 ret = t.Sample(s, texcoord) * opacity;
1790 if (ignore_alpha)
1791 ret.a = opacity;
1793 return ret * color.a;
1795 #endif
1796 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
1797 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1798 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1799 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1800 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1801 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1802 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1803 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1804 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1805 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1806 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1807 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1808 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1809 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
1810 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1811 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
1812 0x00000003, 0x0100003e,
1814 static const DWORD ps_code_triangle_bitmap_bitmap[] =
1816 #if 0
1817 struct brush
1819 float3x2 transform;
1820 float opacity;
1821 bool ignore_alpha;
1822 } brush0, brush1;
1824 SamplerState s0, s1;
1825 Texture2D t0, t1;
1827 float4 main(float4 position : SV_POSITION) : SV_Target
1829 float2 texcoord;
1830 float opacity;
1831 float4 ret;
1833 texcoord.x = position.x * brush0.transform._11 + position.y * brush0.transform._21 + brush0.transform._31;
1834 texcoord.y = position.x * brush0.transform._12 + position.y * brush0.transform._22 + brush0.transform._32;
1835 ret = t0.Sample(s0, texcoord) * brush0.opacity;
1836 if (brush0.ignore_alpha)
1837 ret.a = brush0.opacity;
1839 texcoord.x = position.x * brush1.transform._11 + position.y * brush1.transform._21 + brush1.transform._31;
1840 texcoord.y = position.x * brush1.transform._12 + position.y * brush1.transform._22 + brush1.transform._32;
1841 opacity = t1.Sample(s1, texcoord).a * brush1.opacity;
1842 if (brush1.ignore_alpha)
1843 opacity = brush1.opacity;
1845 return ret * opacity;
1847 #endif
1848 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
1849 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1850 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1851 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1852 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
1853 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
1854 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
1855 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
1856 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
1857 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
1858 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
1859 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
1860 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
1861 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
1862 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
1863 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
1864 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
1865 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
1866 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
1867 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
1868 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
1869 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
1870 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
1871 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
1872 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
1874 /* The basic idea here is to evaluate the implicit form of the curve in
1875 * texture space. "t.z" determines which side of the curve is shaded. */
1876 static const DWORD ps_code_bezier_solid[] =
1878 #if 0
1879 float4 color;
1881 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
1883 clip((t.x * t.x - t.y) * t.z);
1884 return color;
1886 #endif
1887 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
1888 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
1889 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
1890 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
1891 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
1892 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
1893 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
1894 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
1895 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
1896 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
1897 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
1898 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1900 static const struct brush_shader
1902 const void *byte_code;
1903 size_t byte_code_size;
1904 enum d2d_shape_type shape_type;
1905 enum d2d_brush_type brush_type;
1906 enum d2d_brush_type opacity_brush_type;
1908 brush_shaders[] =
1910 {ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
1911 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
1912 {ps_code_triangle_solid_bitmap, sizeof(ps_code_triangle_solid_bitmap),
1913 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_BITMAP},
1914 {ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
1915 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_COUNT},
1916 {ps_code_triangle_bitmap_solid, sizeof(ps_code_triangle_bitmap_solid),
1917 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_SOLID},
1918 {ps_code_triangle_bitmap_bitmap, sizeof(ps_code_triangle_bitmap_bitmap),
1919 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_BITMAP},
1920 {ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
1921 D2D_SHAPE_TYPE_BEZIER, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
1923 static const struct
1925 float x, y;
1927 quad[] =
1929 {-1.0f, 1.0f},
1930 {-1.0f, -1.0f},
1931 { 1.0f, 1.0f},
1932 { 1.0f, -1.0f},
1934 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
1935 static const D2D1_MATRIX_3X2_F identity =
1937 1.0f, 0.0f,
1938 0.0f, 1.0f,
1939 0.0f, 0.0f,
1941 float dpi_x, dpi_y;
1943 dpi_x = desc->dpiX;
1944 dpi_y = desc->dpiY;
1946 if (dpi_x == 0.0f && dpi_y == 0.0f)
1948 dpi_x = 96.0f;
1949 dpi_y = 96.0f;
1951 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1952 return E_INVALIDARG;
1954 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
1955 WARN("Ignoring render target type %#x.\n", desc->type);
1956 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
1957 FIXME("Ignoring render target usage %#x.\n", desc->usage);
1958 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
1959 WARN("Ignoring feature level %#x.\n", desc->minLevel);
1961 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
1962 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
1963 render_target->refcount = 1;
1964 render_target->factory = factory;
1965 ID2D1Factory_AddRef(render_target->factory);
1967 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
1969 WARN("Failed to get device interface, hr %#x.\n", hr);
1970 ID2D1Factory_Release(render_target->factory);
1971 return hr;
1974 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
1976 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
1977 goto err;
1980 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
1981 ID3D10Resource_Release(resource);
1982 if (FAILED(hr))
1984 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
1985 goto err;
1988 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
1990 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
1991 goto err;
1994 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
1996 WARN("Failed to create stateblock, hr %#x.\n", hr);
1997 goto err;
2000 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
2001 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
2002 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
2004 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
2005 goto err;
2008 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
2009 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
2010 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
2012 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
2013 goto err;
2016 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
2017 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
2019 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
2020 goto err;
2023 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
2024 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
2026 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
2027 goto err;
2030 for (i = 0; i < sizeof(brush_shaders) / sizeof(*brush_shaders); ++i)
2032 const struct brush_shader *bs = &brush_shaders[i];
2033 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, bs->byte_code, bs->byte_code_size,
2034 &render_target->shape_resources[bs->shape_type].ps[bs->brush_type][bs->opacity_brush_type])))
2036 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
2037 bs->shape_type, bs->brush_type, bs->opacity_brush_type);
2038 goto err;
2042 buffer_desc.ByteWidth = sizeof(indices);
2043 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
2044 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
2045 buffer_desc.CPUAccessFlags = 0;
2046 buffer_desc.MiscFlags = 0;
2048 buffer_data.pSysMem = indices;
2049 buffer_data.SysMemPitch = 0;
2050 buffer_data.SysMemSlicePitch = 0;
2052 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2053 &buffer_desc, &buffer_data, &render_target->ib)))
2055 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
2056 goto err;
2059 buffer_desc.ByteWidth = sizeof(quad);
2060 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
2061 buffer_data.pSysMem = quad;
2063 render_target->vb_stride = sizeof(*quad);
2064 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2065 &buffer_desc, &buffer_data, &render_target->vb)))
2067 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
2068 goto err;
2071 rs_desc.FillMode = D3D10_FILL_SOLID;
2072 rs_desc.CullMode = D3D10_CULL_NONE;
2073 rs_desc.FrontCounterClockwise = FALSE;
2074 rs_desc.DepthBias = 0;
2075 rs_desc.DepthBiasClamp = 0.0f;
2076 rs_desc.SlopeScaledDepthBias = 0.0f;
2077 rs_desc.DepthClipEnable = TRUE;
2078 rs_desc.ScissorEnable = TRUE;
2079 rs_desc.MultisampleEnable = FALSE;
2080 rs_desc.AntialiasedLineEnable = FALSE;
2081 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
2083 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
2084 goto err;
2087 memset(&blend_desc, 0, sizeof(blend_desc));
2088 blend_desc.BlendEnable[0] = TRUE;
2089 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2090 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2091 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2092 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2094 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2095 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2097 else
2099 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2100 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2102 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2103 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2104 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
2106 WARN("Failed to create blend state, hr %#x.\n", hr);
2107 goto err;
2110 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
2111 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
2113 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2114 goto err;
2117 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
2118 IDWriteFactory_Release(dwrite_factory);
2119 if (FAILED(hr))
2121 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
2122 goto err;
2125 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2127 WARN("Failed to get surface desc, hr %#x.\n", hr);
2128 goto err;
2131 render_target->format = desc->pixelFormat;
2132 render_target->pixel_size.width = surface_desc.Width;
2133 render_target->pixel_size.height = surface_desc.Height;
2134 render_target->drawing_state.transform = identity;
2136 if (!d2d_clip_stack_init(&render_target->clip_stack))
2138 WARN("Failed to initialize clip stack.\n");
2139 hr = E_FAIL;
2140 goto err;
2143 render_target->dpi_x = dpi_x;
2144 render_target->dpi_y = dpi_y;
2146 return S_OK;
2148 err:
2149 if (render_target->default_text_rendering_params)
2150 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
2151 if (render_target->bs)
2152 ID3D10BlendState_Release(render_target->bs);
2153 if (render_target->rs)
2154 ID3D10RasterizerState_Release(render_target->rs);
2155 if (render_target->vb)
2156 ID3D10Buffer_Release(render_target->vb);
2157 if (render_target->ib)
2158 ID3D10Buffer_Release(render_target->ib);
2159 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
2161 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2163 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2165 if (render_target->shape_resources[i].ps[j][k])
2166 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
2169 if (render_target->shape_resources[i].vs)
2170 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
2171 if (render_target->shape_resources[i].il)
2172 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
2174 if (render_target->stateblock)
2175 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
2176 if (render_target->view)
2177 ID3D10RenderTargetView_Release(render_target->view);
2178 if (render_target->device)
2179 ID3D10Device_Release(render_target->device);
2180 ID2D1Factory_Release(render_target->factory);
2181 return hr;