d2d1: Take the recommended rendering mode into account in d2d_d3d_render_target_DrawG...
[wine.git] / dlls / d2d1 / render_target.c
blobbd20d5d0b19637cc8bd45498a65138aff6c7252d
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"
23 #include "wincodec.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
27 #define INITIAL_CLIP_STACK_SIZE 4
29 struct d2d_draw_text_layout_ctx
31 ID2D1Brush *brush;
32 D2D1_DRAW_TEXT_OPTIONS options;
35 static void d2d_point_set(D2D1_POINT_2F *dst, float x, float y)
37 dst->x = x;
38 dst->y = y;
41 static void d2d_point_transform(D2D1_POINT_2F *dst, const D2D1_MATRIX_3X2_F *matrix, float x, float y)
43 dst->x = x * matrix->_11 + y * matrix->_21 + matrix->_31;
44 dst->y = x * matrix->_12 + y * matrix->_22 + matrix->_32;
47 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
49 if (point->x < dst->left)
50 dst->left = point->x;
51 if (point->y < dst->top)
52 dst->top = point->y;
53 if (point->x > dst->right)
54 dst->right = point->x;
55 if (point->y > dst->bottom)
56 dst->bottom = point->y;
59 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
61 if (src->left > dst->left)
62 dst->left = src->left;
63 if (src->top > dst->top)
64 dst->top = src->top;
65 if (src->right < dst->right)
66 dst->right = src->right;
67 if (src->bottom < dst->bottom)
68 dst->bottom = src->bottom;
71 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
73 dst->left = left;
74 dst->top = top;
75 dst->right = right;
76 dst->bottom = bottom;
79 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
81 dst->width = width;
82 dst->height = height;
85 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
87 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
88 return FALSE;
90 stack->size = INITIAL_CLIP_STACK_SIZE;
91 stack->count = 0;
93 return TRUE;
96 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
98 HeapFree(GetProcessHeap(), 0, stack->stack);
101 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
103 D2D1_RECT_F r;
105 if (stack->count == stack->size)
107 D2D1_RECT_F *new_stack;
108 unsigned int new_size;
110 if (stack->size > UINT_MAX / 2)
111 return FALSE;
113 new_size = stack->size * 2;
114 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
115 return FALSE;
117 stack->stack = new_stack;
118 stack->size = new_size;
121 r = *rect;
122 if (stack->count)
123 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
124 stack->stack[stack->count++] = r;
126 return TRUE;
129 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
131 if (!stack->count)
132 return;
133 --stack->count;
136 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
137 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
138 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
140 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
141 ID3D10Device *device = render_target->device;
142 D3D10_RECT scissor_rect;
143 unsigned int offset;
144 D3D10_VIEWPORT vp;
145 HRESULT hr;
147 vp.TopLeftX = 0;
148 vp.TopLeftY = 0;
149 vp.Width = render_target->pixel_size.width;
150 vp.Height = render_target->pixel_size.height;
151 vp.MinDepth = 0.0f;
152 vp.MaxDepth = 1.0f;
154 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
156 WARN("Failed to capture stateblock, hr %#x.\n", hr);
157 return;
160 ID3D10Device_ClearState(device);
162 ID3D10Device_IASetInputLayout(device, shape_resources->il);
163 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
164 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
165 offset = 0;
166 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
167 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
168 ID3D10Device_VSSetShader(device, shape_resources->vs);
169 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
170 ID3D10Device_RSSetViewports(device, 1, &vp);
171 if (render_target->clip_stack.count)
173 const D2D1_RECT_F *clip_rect;
175 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
176 scissor_rect.left = clip_rect->left + 0.5f;
177 scissor_rect.top = clip_rect->top + 0.5f;
178 scissor_rect.right = clip_rect->right + 0.5f;
179 scissor_rect.bottom = clip_rect->bottom + 0.5f;
181 else
183 scissor_rect.left = 0.0f;
184 scissor_rect.top = 0.0f;
185 scissor_rect.right = render_target->pixel_size.width;
186 scissor_rect.bottom = render_target->pixel_size.height;
188 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
189 ID3D10Device_RSSetState(device, render_target->rs);
190 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
191 if (brush)
192 d2d_brush_bind_resources(brush, opacity_brush, render_target, shape_type);
193 else
194 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID][D2D_BRUSH_TYPE_COUNT]);
196 if (ib)
197 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
198 else
199 ID3D10Device_Draw(device, index_count, 0);
201 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
202 WARN("Failed to apply stateblock, hr %#x.\n", hr);
205 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
207 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
210 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
212 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
214 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
215 || IsEqualGUID(iid, &IID_ID2D1Resource)
216 || IsEqualGUID(iid, &IID_IUnknown))
218 ID2D1RenderTarget_AddRef(iface);
219 *out = iface;
220 return S_OK;
223 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
225 *out = NULL;
226 return E_NOINTERFACE;
229 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
231 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
232 ULONG refcount = InterlockedIncrement(&render_target->refcount);
234 TRACE("%p increasing refcount to %u.\n", iface, refcount);
236 return refcount;
239 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
241 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
242 ULONG refcount = InterlockedDecrement(&render_target->refcount);
244 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
246 if (!refcount)
248 unsigned int i, j, k;
250 d2d_clip_stack_cleanup(&render_target->clip_stack);
251 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
252 if (render_target->text_rendering_params)
253 IDWriteRenderingParams_Release(render_target->text_rendering_params);
254 ID3D10BlendState_Release(render_target->bs);
255 ID3D10RasterizerState_Release(render_target->rs);
256 ID3D10Buffer_Release(render_target->vb);
257 ID3D10Buffer_Release(render_target->ib);
258 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
260 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
262 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
264 if (render_target->shape_resources[i].ps[j][k])
265 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
268 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
269 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
271 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
272 ID3D10RenderTargetView_Release(render_target->view);
273 ID3D10Device_Release(render_target->device);
274 ID2D1Factory_Release(render_target->factory);
275 HeapFree(GetProcessHeap(), 0, render_target);
278 return refcount;
281 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
283 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
285 TRACE("iface %p, factory %p.\n", iface, factory);
287 *factory = render_target->factory;
288 ID2D1Factory_AddRef(*factory);
291 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
292 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
294 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
295 struct d2d_bitmap *object;
296 HRESULT hr;
298 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
299 iface, size.width, size.height, src_data, pitch, desc, bitmap);
301 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
302 return E_OUTOFMEMORY;
304 if (FAILED(hr = d2d_bitmap_init_memory(object, render_target, size, src_data, pitch, desc)))
306 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
307 HeapFree(GetProcessHeap(), 0, object);
308 return hr;
311 TRACE("Created bitmap %p.\n", object);
312 *bitmap = &object->ID2D1Bitmap_iface;
314 return S_OK;
317 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
318 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
320 const D2D1_PIXEL_FORMAT *d2d_format;
321 D2D1_BITMAP_PROPERTIES bitmap_desc;
322 WICPixelFormatGUID wic_format;
323 unsigned int bpp, data_size;
324 D2D1_SIZE_U size;
325 unsigned int i;
326 WICRect rect;
327 UINT32 pitch;
328 HRESULT hr;
329 void *data;
331 static const struct
333 const WICPixelFormatGUID *wic;
334 D2D1_PIXEL_FORMAT d2d;
336 format_lookup[] =
338 {&GUID_WICPixelFormat32bppPBGRA, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED}},
339 {&GUID_WICPixelFormat32bppBGR, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE}},
342 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
343 iface, bitmap_source, desc, bitmap);
345 if (FAILED(hr = IWICBitmapSource_GetSize(bitmap_source, &size.width, &size.height)))
347 WARN("Failed to get bitmap size, hr %#x.\n", hr);
348 return hr;
351 if (!desc)
353 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
354 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
355 bitmap_desc.dpiX = 0.0f;
356 bitmap_desc.dpiY = 0.0f;
358 else
360 bitmap_desc = *desc;
363 if (FAILED(hr = IWICBitmapSource_GetPixelFormat(bitmap_source, &wic_format)))
365 WARN("Failed to get bitmap format, hr %#x.\n", hr);
366 return hr;
369 for (i = 0, d2d_format = NULL; i < sizeof(format_lookup) / sizeof(*format_lookup); ++i)
371 if (IsEqualGUID(&wic_format, format_lookup[i].wic))
373 d2d_format = &format_lookup[i].d2d;
374 break;
378 if (!d2d_format)
380 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format));
381 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
384 if (bitmap_desc.pixelFormat.format == DXGI_FORMAT_UNKNOWN)
385 bitmap_desc.pixelFormat.format = d2d_format->format;
386 if (bitmap_desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_UNKNOWN)
387 bitmap_desc.pixelFormat.alphaMode = d2d_format->alphaMode;
389 switch (bitmap_desc.pixelFormat.format)
391 case DXGI_FORMAT_B8G8R8A8_UNORM:
392 bpp = 4;
393 break;
395 default:
396 FIXME("Unhandled format %#x.\n", bitmap_desc.pixelFormat.format);
397 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
400 pitch = ((bpp * size.width) + 15) & ~15;
401 data_size = pitch * size.height;
402 if (!(data = HeapAlloc(GetProcessHeap(), 0, data_size)))
403 return E_OUTOFMEMORY;
405 rect.X = 0;
406 rect.Y = 0;
407 rect.Width = size.width;
408 rect.Height = size.height;
409 if (FAILED(hr = IWICBitmapSource_CopyPixels(bitmap_source, &rect, pitch, data_size, data)))
411 WARN("Failed to copy bitmap pixels, hr %#x.\n", hr);
412 HeapFree(GetProcessHeap(), 0, data);
413 return hr;
416 hr = d2d_d3d_render_target_CreateBitmap(iface, size, data, pitch, &bitmap_desc, bitmap);
418 HeapFree(GetProcessHeap(), 0, data);
420 return hr;
423 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
424 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
426 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
427 struct d2d_bitmap *object;
428 HRESULT hr;
430 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
431 iface, debugstr_guid(iid), data, desc, bitmap);
433 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
434 return E_OUTOFMEMORY;
436 if (FAILED(hr = d2d_bitmap_init_shared(object, render_target, iid, data, desc)))
438 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
439 HeapFree(GetProcessHeap(), 0, object);
440 return hr;
443 TRACE("Created bitmap %p.\n", object);
444 *bitmap = &object->ID2D1Bitmap_iface;
446 return S_OK;
449 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
450 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
451 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
453 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
454 struct d2d_brush *object;
456 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
457 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
459 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
460 return E_OUTOFMEMORY;
462 d2d_bitmap_brush_init(object, render_target->factory, bitmap, bitmap_brush_desc, brush_desc);
464 TRACE("Created brush %p.\n", object);
465 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
467 return S_OK;
470 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
471 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
473 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
474 struct d2d_brush *object;
476 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
478 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
479 return E_OUTOFMEMORY;
481 d2d_solid_color_brush_init(object, render_target->factory, color, desc);
483 TRACE("Created brush %p.\n", object);
484 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
486 return S_OK;
489 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
490 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
491 ID2D1GradientStopCollection **gradient)
493 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
494 struct d2d_gradient *object;
495 HRESULT hr;
497 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
498 iface, stops, stop_count, gamma, extend_mode, gradient);
500 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
501 return E_OUTOFMEMORY;
503 if (FAILED(hr = d2d_gradient_init(object, render_target->factory, stops, stop_count, gamma, extend_mode)))
505 WARN("Failed to initialize gradient, hr %#x.\n", hr);
506 HeapFree(GetProcessHeap(), 0, object);
507 return hr;
510 TRACE("Created gradient %p.\n", object);
511 *gradient = &object->ID2D1GradientStopCollection_iface;
513 return S_OK;
516 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
517 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
518 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
520 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
521 struct d2d_brush *object;
523 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
524 iface, gradient_brush_desc, brush_desc, gradient, brush);
526 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
527 return E_OUTOFMEMORY;
529 d2d_linear_gradient_brush_init(object, render_target->factory, gradient_brush_desc, brush_desc, gradient);
531 TRACE("Created brush %p.\n", object);
532 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
534 return S_OK;
537 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
538 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
539 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
541 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
542 iface, gradient_brush_desc, brush_desc, gradient, brush);
544 return E_NOTIMPL;
547 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
548 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
549 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **render_target)
551 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
552 iface, size, pixel_size, format, options, render_target);
554 return E_NOTIMPL;
557 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
558 const D2D1_SIZE_F *size, ID2D1Layer **layer)
560 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
562 return E_NOTIMPL;
565 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
567 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
568 struct d2d_mesh *object;
570 TRACE("iface %p, mesh %p.\n", iface, mesh);
572 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
573 return E_OUTOFMEMORY;
575 d2d_mesh_init(object, render_target->factory);
577 TRACE("Created mesh %p.\n", object);
578 *mesh = &object->ID2D1Mesh_iface;
580 return S_OK;
583 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
584 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
586 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
587 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
590 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
591 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
593 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
594 iface, rect, brush, stroke_width, stroke_style);
597 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
598 const D2D1_RECT_F *rect, ID2D1Brush *brush)
600 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
601 ID2D1RectangleGeometry *geometry;
602 HRESULT hr;
604 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
606 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
608 ERR("Failed to create geometry, hr %#x.\n", hr);
609 return;
612 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
613 ID2D1RectangleGeometry_Release(geometry);
616 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
617 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
619 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
620 iface, rect, brush, stroke_width, stroke_style);
623 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
624 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
626 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
627 ID2D1RoundedRectangleGeometry *geometry;
628 HRESULT hr;
630 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
632 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
634 ERR("Failed to create geometry, hr %#x.\n", hr);
635 return;
638 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
639 ID2D1RoundedRectangleGeometry_Release(geometry);
642 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
643 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
645 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
646 iface, ellipse, brush, stroke_width, stroke_style);
649 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
650 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
652 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
653 ID2D1EllipseGeometry *geometry;
654 HRESULT hr;
656 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
658 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
660 ERR("Failed to create geometry, hr %#x.\n", hr);
661 return;
664 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
665 ID2D1EllipseGeometry_Release(geometry);
668 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
669 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
671 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
672 iface, geometry, brush, stroke_width, stroke_style);
675 static void STDMETHODCALLTYPE d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
676 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
678 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
679 D3D10_SUBRESOURCE_DATA buffer_data;
680 D3D10_BUFFER_DESC buffer_desc;
681 D2D1_MATRIX_3X2_F w, g;
682 float tmp_x, tmp_y;
683 HRESULT hr;
684 struct
686 float _11, _21, _31, pad0;
687 float _12, _22, _32, pad1;
688 } transform;
690 tmp_x = (2.0f * render_target->dpi_x) / (96.0f * render_target->pixel_size.width);
691 tmp_y = -(2.0f * render_target->dpi_y) / (96.0f * render_target->pixel_size.height);
692 w = render_target->drawing_state.transform;
693 w._11 *= tmp_x;
694 w._21 *= tmp_x;
695 w._31 = w._31 * tmp_x - 1.0f;
696 w._12 *= tmp_y;
697 w._22 *= tmp_y;
698 w._32 = w._32 * tmp_y + 1.0f;
700 g = geometry->transform;
701 d2d_matrix_multiply(&g, &w);
703 transform._11 = g._11;
704 transform._21 = g._21;
705 transform._31 = g._31;
706 transform.pad0 = 0.0f;
707 transform._12 = g._12;
708 transform._22 = g._22;
709 transform._32 = g._32;
710 transform.pad1 = 0.0f;
712 buffer_desc.ByteWidth = sizeof(transform);
713 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
714 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
715 buffer_desc.CPUAccessFlags = 0;
716 buffer_desc.MiscFlags = 0;
718 buffer_data.pSysMem = &transform;
719 buffer_data.SysMemPitch = 0;
720 buffer_data.SysMemSlicePitch = 0;
722 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
724 WARN("Failed to create constant buffer, hr %#x.\n", hr);
725 return;
728 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, render_target, &ps_cb)))
730 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
731 ID3D10Buffer_Release(vs_cb);
732 return;
735 if (geometry->face_count)
737 buffer_desc.ByteWidth = geometry->face_count * sizeof(*geometry->faces);
738 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
739 buffer_data.pSysMem = geometry->faces;
741 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
743 WARN("Failed to create index buffer, hr %#x.\n", hr);
744 goto done;
747 buffer_desc.ByteWidth = geometry->vertex_count * sizeof(*geometry->vertices);
748 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
749 buffer_data.pSysMem = geometry->vertices;
751 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
753 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
754 ID3D10Buffer_Release(ib);
755 goto done;
758 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->face_count, vb,
759 sizeof(*geometry->vertices), vs_cb, ps_cb, brush, opacity_brush);
761 ID3D10Buffer_Release(vb);
762 ID3D10Buffer_Release(ib);
765 if (geometry->bezier_count)
767 buffer_desc.ByteWidth = geometry->bezier_count * sizeof(*geometry->beziers);
768 buffer_data.pSysMem = geometry->beziers;
770 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
772 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
773 goto done;
776 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, 3 * geometry->bezier_count, vb,
777 sizeof(*geometry->beziers->v), vs_cb, ps_cb, brush, opacity_brush);
779 ID3D10Buffer_Release(vb);
782 done:
783 ID3D10Buffer_Release(ps_cb);
784 ID3D10Buffer_Release(vs_cb);
787 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
788 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
790 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
791 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
792 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
793 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
795 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
797 if (FAILED(render_target->error.code))
798 return;
800 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
802 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
803 render_target->error.tag1 = render_target->drawing_state.tag1;
804 render_target->error.tag2 = render_target->drawing_state.tag2;
805 return;
808 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
811 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
812 ID2D1Mesh *mesh, ID2D1Brush *brush)
814 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
817 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
818 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
819 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
821 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
822 iface, mask, brush, content, dst_rect, src_rect);
825 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
826 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
827 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
829 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
830 D2D1_BRUSH_PROPERTIES brush_desc;
831 ID2D1BitmapBrush *brush;
832 D2D1_RECT_F s, d;
833 HRESULT hr;
835 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
836 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
838 if (src_rect)
840 s = *src_rect;
842 else
844 D2D1_SIZE_F size;
846 size = ID2D1Bitmap_GetSize(bitmap);
847 s.left = 0.0f;
848 s.top = 0.0f;
849 s.right = size.width;
850 s.bottom = size.height;
853 if (dst_rect)
855 d = *dst_rect;
857 else
859 d.left = 0.0f;
860 d.top = 0.0f;
861 d.right = s.right - s.left;
862 d.bottom = s.bottom - s.top;
865 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
866 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
867 bitmap_brush_desc.interpolationMode = interpolation_mode;
869 brush_desc.opacity = opacity;
870 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
871 brush_desc.transform._21 = 0.0f;
872 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
873 brush_desc.transform._12 = 0.0f;
874 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
875 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
877 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
879 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
880 return;
883 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
884 ID2D1BitmapBrush_Release(brush);
887 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
888 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
889 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
891 IDWriteTextLayout *text_layout;
892 IDWriteFactory *dwrite_factory;
893 D2D1_POINT_2F origin;
894 HRESULT hr;
896 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
897 "brush %p, options %#x, measuring_mode %#x.\n",
898 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
899 brush, options, measuring_mode);
901 if (measuring_mode != DWRITE_MEASURING_MODE_NATURAL)
902 FIXME("Ignoring measuring mode %#x.\n", measuring_mode);
904 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
905 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
907 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
908 return;
911 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
912 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
913 IDWriteFactory_Release(dwrite_factory);
914 if (FAILED(hr))
916 ERR("Failed to create text layout, hr %#x.\n", hr);
917 return;
920 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
921 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
922 IDWriteTextLayout_Release(text_layout);
925 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
926 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
928 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
929 struct d2d_draw_text_layout_ctx ctx;
930 HRESULT hr;
932 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
933 iface, origin.x, origin.y, layout, brush, options);
935 ctx.brush = brush;
936 ctx.options = options;
938 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
939 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
940 FIXME("Failed to draw text layout, hr %#x.\n", hr);
943 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
944 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
946 D2D1_MATRIX_3X2_F *transform, prev_transform;
947 ID2D1PathGeometry *geometry;
948 ID2D1GeometrySink *sink;
949 HRESULT hr;
951 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
953 ERR("Failed to create geometry, hr %#x.\n", hr);
954 return;
957 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
959 ERR("Failed to open geometry sink, hr %#x.\n", hr);
960 ID2D1PathGeometry_Release(geometry);
961 return;
964 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
965 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
966 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
968 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
969 ID2D1GeometrySink_Release(sink);
970 ID2D1PathGeometry_Release(geometry);
971 return;
974 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
975 ERR("Failed to close geometry sink, hr %#x.\n", hr);
976 ID2D1GeometrySink_Release(sink);
978 transform = &render_target->drawing_state.transform;
979 prev_transform = *transform;
980 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
981 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
982 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
983 unsafe_impl_from_ID2D1Brush(brush), NULL);
984 *transform = prev_transform;
986 ID2D1PathGeometry_Release(geometry);
989 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
990 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
991 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode)
993 ID2D1RectangleGeometry *geometry = NULL;
994 ID2D1BitmapBrush *opacity_brush = NULL;
995 D2D1_BITMAP_PROPERTIES bitmap_desc;
996 ID2D1Bitmap *opacity_bitmap = NULL;
997 IDWriteGlyphRunAnalysis *analysis;
998 DWRITE_TEXTURE_TYPE texture_type;
999 D2D1_BRUSH_PROPERTIES brush_desc;
1000 IDWriteFactory *dwrite_factory;
1001 void *opacity_values = NULL;
1002 size_t opacity_values_size;
1003 D2D1_SIZE_U bitmap_size;
1004 D2D1_RECT_F run_rect;
1005 RECT bounds;
1006 HRESULT hr;
1008 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1009 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1011 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1012 return;
1015 hr = IDWriteFactory_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, ppd, NULL,
1016 rendering_mode, measuring_mode, baseline_origin.x, baseline_origin.y, &analysis);
1017 IDWriteFactory_Release(dwrite_factory);
1018 if (FAILED(hr))
1020 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1021 return;
1024 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1025 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1026 else
1027 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1029 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1031 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1032 goto done;
1035 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1036 if (!bitmap_size.width || !bitmap_size.height)
1038 /* Empty run, nothing to do. */
1039 goto done;
1042 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1043 bitmap_size.width *= 3;
1044 opacity_values_size = bitmap_size.width * bitmap_size.height;
1045 if (!(opacity_values = HeapAlloc(GetProcessHeap(), 0, opacity_values_size)))
1047 ERR("Failed to allocate opacity values.\n");
1048 goto done;
1051 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1052 texture_type, &bounds, opacity_values, opacity_values_size)))
1054 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1055 goto done;
1058 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1059 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1060 bitmap_desc.dpiX = render_target->dpi_x;
1061 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1062 bitmap_desc.dpiX *= 3.0f;
1063 bitmap_desc.dpiY = render_target->dpi_y;
1064 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
1065 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1067 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1068 goto done;
1071 brush_desc.opacity = 1.0f;
1072 brush_desc.transform._11 = 1.0f;
1073 brush_desc.transform._12 = 0.0f;
1074 brush_desc.transform._21 = 0.0f;
1075 brush_desc.transform._22 = 1.0f;
1076 brush_desc.transform._31 = bounds.left;
1077 brush_desc.transform._32 = bounds.top;
1078 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
1079 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1081 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1082 goto done;
1085 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
1086 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1088 ERR("Failed to create geometry, hr %#x.\n", hr);
1089 goto done;
1092 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1093 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1095 done:
1096 if (geometry)
1097 ID2D1RectangleGeometry_Release(geometry);
1098 if (opacity_brush)
1099 ID2D1BitmapBrush_Release(opacity_brush);
1100 if (opacity_bitmap)
1101 ID2D1Bitmap_Release(opacity_bitmap);
1102 HeapFree(GetProcessHeap(), 0, opacity_values);
1103 IDWriteGlyphRunAnalysis_Release(analysis);
1106 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
1107 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1108 DWRITE_MEASURING_MODE measuring_mode)
1110 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1111 IDWriteRenderingParams *rendering_params;
1112 DWRITE_RENDERING_MODE rendering_mode;
1113 HRESULT hr;
1114 float ppd;
1116 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1117 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
1119 if (FAILED(render_target->error.code))
1120 return;
1122 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
1123 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
1125 ppd = max(render_target->dpi_x, render_target->dpi_y) / 96.0f;
1126 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1127 : render_target->default_text_rendering_params;
1128 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1129 ppd, measuring_mode, rendering_params, &rendering_mode)))
1131 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1132 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1135 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1136 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1137 else
1138 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1139 ppd, rendering_mode, measuring_mode);
1142 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1143 const D2D1_MATRIX_3X2_F *transform)
1145 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1147 TRACE("iface %p, transform %p.\n", iface, transform);
1149 render_target->drawing_state.transform = *transform;
1152 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1153 D2D1_MATRIX_3X2_F *transform)
1155 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1157 TRACE("iface %p, transform %p.\n", iface, transform);
1159 *transform = render_target->drawing_state.transform;
1162 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1163 D2D1_ANTIALIAS_MODE antialias_mode)
1165 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1167 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1169 render_target->drawing_state.antialiasMode = antialias_mode;
1172 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1174 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1176 TRACE("iface %p.\n", iface);
1178 return render_target->drawing_state.antialiasMode;
1181 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1182 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1184 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1186 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1188 render_target->drawing_state.textAntialiasMode = antialias_mode;
1191 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1193 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1195 TRACE("iface %p.\n", iface);
1197 return render_target->drawing_state.textAntialiasMode;
1200 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1201 IDWriteRenderingParams *text_rendering_params)
1203 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1205 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1207 if (text_rendering_params)
1208 IDWriteRenderingParams_AddRef(text_rendering_params);
1209 if (render_target->text_rendering_params)
1210 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1211 render_target->text_rendering_params = text_rendering_params;
1214 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1215 IDWriteRenderingParams **text_rendering_params)
1217 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1219 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1221 if ((*text_rendering_params = render_target->text_rendering_params))
1222 IDWriteRenderingParams_AddRef(*text_rendering_params);
1225 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1227 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1229 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1231 render_target->drawing_state.tag1 = tag1;
1232 render_target->drawing_state.tag2 = tag2;
1235 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1237 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1239 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1241 *tag1 = render_target->drawing_state.tag1;
1242 *tag2 = render_target->drawing_state.tag2;
1245 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1246 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1248 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1251 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1253 FIXME("iface %p stub!\n", iface);
1256 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1258 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1260 return E_NOTIMPL;
1263 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1264 ID2D1DrawingStateBlock *state_block)
1266 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1267 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1269 TRACE("iface %p, state_block %p.\n", iface, state_block);
1271 state_block_impl->drawing_state = render_target->drawing_state;
1272 if (render_target->text_rendering_params)
1273 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1274 if (state_block_impl->text_rendering_params)
1275 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1276 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1279 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1280 ID2D1DrawingStateBlock *state_block)
1282 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1283 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1285 TRACE("iface %p, state_block %p.\n", iface, state_block);
1287 render_target->drawing_state = state_block_impl->drawing_state;
1288 if (state_block_impl->text_rendering_params)
1289 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1290 if (render_target->text_rendering_params)
1291 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1292 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1295 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1296 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1298 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1299 D2D1_RECT_F transformed_rect;
1300 float x_scale, y_scale;
1301 D2D1_POINT_2F point;
1303 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1305 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1306 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1308 x_scale = render_target->dpi_x / 96.0f;
1309 y_scale = render_target->dpi_y / 96.0f;
1310 d2d_point_transform(&point, &render_target->drawing_state.transform,
1311 clip_rect->left * x_scale, clip_rect->top * y_scale);
1312 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1313 d2d_point_transform(&point, &render_target->drawing_state.transform,
1314 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1315 d2d_rect_expand(&transformed_rect, &point);
1316 d2d_point_transform(&point, &render_target->drawing_state.transform,
1317 clip_rect->right * x_scale, clip_rect->top * y_scale);
1318 d2d_rect_expand(&transformed_rect, &point);
1319 d2d_point_transform(&point, &render_target->drawing_state.transform,
1320 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1321 d2d_rect_expand(&transformed_rect, &point);
1323 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1324 WARN("Failed to push clip rect.\n");
1327 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1329 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1331 TRACE("iface %p.\n", iface);
1333 d2d_clip_stack_pop(&render_target->clip_stack);
1336 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1338 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1339 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1340 D3D10_SUBRESOURCE_DATA buffer_data;
1341 D3D10_BUFFER_DESC buffer_desc;
1342 ID3D10Buffer *vs_cb, *ps_cb;
1343 HRESULT hr;
1345 static const float transform[] =
1347 1.0f, 0.0f, 0.0f, 0.0f,
1348 0.0f, -1.0f, 0.0f, 0.0f,
1351 TRACE("iface %p, color %p.\n", iface, color);
1353 buffer_desc.ByteWidth = sizeof(transform);
1354 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1355 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1356 buffer_desc.CPUAccessFlags = 0;
1357 buffer_desc.MiscFlags = 0;
1359 buffer_data.pSysMem = transform;
1360 buffer_data.SysMemPitch = 0;
1361 buffer_data.SysMemSlicePitch = 0;
1363 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1365 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1366 return;
1369 if (color)
1370 c = *color;
1371 if (render_target->format.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1372 c.a = 1.0f;
1373 c.r *= c.a;
1374 c.g *= c.a;
1375 c.b *= c.a;
1376 buffer_desc.ByteWidth = sizeof(c);
1377 buffer_data.pSysMem = &c;
1379 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1381 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1382 ID3D10Buffer_Release(vs_cb);
1383 return;
1386 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1387 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1389 ID3D10Buffer_Release(ps_cb);
1390 ID3D10Buffer_Release(vs_cb);
1393 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1395 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1397 TRACE("iface %p.\n", iface);
1399 memset(&render_target->error, 0, sizeof(render_target->error));
1402 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1403 D2D1_TAG *tag1, D2D1_TAG *tag2)
1405 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1407 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1409 if (tag1)
1410 *tag1 = render_target->error.tag1;
1411 if (tag2)
1412 *tag1 = render_target->error.tag2;
1414 return render_target->error.code;
1417 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1418 D2D1_PIXEL_FORMAT *format)
1420 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1422 TRACE("iface %p, format %p.\n", iface, format);
1424 *format = render_target->format;
1425 return format;
1428 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1430 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1432 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1434 if (dpi_x == 0.0f && dpi_y == 0.0f)
1436 dpi_x = 96.0f;
1437 dpi_y = 96.0f;
1440 render_target->dpi_x = dpi_x;
1441 render_target->dpi_y = dpi_y;
1444 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1446 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1448 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1450 *dpi_x = render_target->dpi_x;
1451 *dpi_y = render_target->dpi_y;
1454 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1456 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1458 TRACE("iface %p, size %p.\n", iface, size);
1460 size->width = render_target->pixel_size.width / (render_target->dpi_x / 96.0f);
1461 size->height = render_target->pixel_size.height / (render_target->dpi_y / 96.0f);
1462 return size;
1465 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1466 D2D1_SIZE_U *pixel_size)
1468 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1470 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1472 *pixel_size = render_target->pixel_size;
1473 return pixel_size;
1476 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1478 FIXME("iface %p stub!\n", iface);
1480 return 0;
1483 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1484 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1486 FIXME("iface %p, desc %p stub!\n", iface, desc);
1488 return FALSE;
1491 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1493 d2d_d3d_render_target_QueryInterface,
1494 d2d_d3d_render_target_AddRef,
1495 d2d_d3d_render_target_Release,
1496 d2d_d3d_render_target_GetFactory,
1497 d2d_d3d_render_target_CreateBitmap,
1498 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1499 d2d_d3d_render_target_CreateSharedBitmap,
1500 d2d_d3d_render_target_CreateBitmapBrush,
1501 d2d_d3d_render_target_CreateSolidColorBrush,
1502 d2d_d3d_render_target_CreateGradientStopCollection,
1503 d2d_d3d_render_target_CreateLinearGradientBrush,
1504 d2d_d3d_render_target_CreateRadialGradientBrush,
1505 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1506 d2d_d3d_render_target_CreateLayer,
1507 d2d_d3d_render_target_CreateMesh,
1508 d2d_d3d_render_target_DrawLine,
1509 d2d_d3d_render_target_DrawRectangle,
1510 d2d_d3d_render_target_FillRectangle,
1511 d2d_d3d_render_target_DrawRoundedRectangle,
1512 d2d_d3d_render_target_FillRoundedRectangle,
1513 d2d_d3d_render_target_DrawEllipse,
1514 d2d_d3d_render_target_FillEllipse,
1515 d2d_d3d_render_target_DrawGeometry,
1516 d2d_d3d_render_target_FillGeometry,
1517 d2d_d3d_render_target_FillMesh,
1518 d2d_d3d_render_target_FillOpacityMask,
1519 d2d_d3d_render_target_DrawBitmap,
1520 d2d_d3d_render_target_DrawText,
1521 d2d_d3d_render_target_DrawTextLayout,
1522 d2d_d3d_render_target_DrawGlyphRun,
1523 d2d_d3d_render_target_SetTransform,
1524 d2d_d3d_render_target_GetTransform,
1525 d2d_d3d_render_target_SetAntialiasMode,
1526 d2d_d3d_render_target_GetAntialiasMode,
1527 d2d_d3d_render_target_SetTextAntialiasMode,
1528 d2d_d3d_render_target_GetTextAntialiasMode,
1529 d2d_d3d_render_target_SetTextRenderingParams,
1530 d2d_d3d_render_target_GetTextRenderingParams,
1531 d2d_d3d_render_target_SetTags,
1532 d2d_d3d_render_target_GetTags,
1533 d2d_d3d_render_target_PushLayer,
1534 d2d_d3d_render_target_PopLayer,
1535 d2d_d3d_render_target_Flush,
1536 d2d_d3d_render_target_SaveDrawingState,
1537 d2d_d3d_render_target_RestoreDrawingState,
1538 d2d_d3d_render_target_PushAxisAlignedClip,
1539 d2d_d3d_render_target_PopAxisAlignedClip,
1540 d2d_d3d_render_target_Clear,
1541 d2d_d3d_render_target_BeginDraw,
1542 d2d_d3d_render_target_EndDraw,
1543 d2d_d3d_render_target_GetPixelFormat,
1544 d2d_d3d_render_target_SetDpi,
1545 d2d_d3d_render_target_GetDpi,
1546 d2d_d3d_render_target_GetSize,
1547 d2d_d3d_render_target_GetPixelSize,
1548 d2d_d3d_render_target_GetMaximumBitmapSize,
1549 d2d_d3d_render_target_IsSupported,
1552 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1554 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1557 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1559 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1561 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1562 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1563 || IsEqualGUID(iid, &IID_IUnknown))
1565 IDWriteTextRenderer_AddRef(iface);
1566 *out = iface;
1567 return S_OK;
1570 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1572 *out = NULL;
1573 return E_NOINTERFACE;
1576 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1578 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1580 TRACE("iface %p.\n", iface);
1582 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1585 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1587 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1589 TRACE("iface %p.\n", iface);
1591 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1594 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1595 void *ctx, BOOL *disabled)
1597 struct d2d_draw_text_layout_ctx *context = ctx;
1599 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1601 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1603 return S_OK;
1606 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1607 void *ctx, DWRITE_MATRIX *transform)
1609 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1611 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1613 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1615 return S_OK;
1618 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1620 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1622 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1624 *ppd = render_target->dpi_y / 96.0f;
1626 return S_OK;
1629 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1630 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1631 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1633 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1634 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1635 struct d2d_draw_text_layout_ctx *context = ctx;
1637 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1638 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1639 iface, ctx, baseline_origin_x, baseline_origin_y,
1640 measuring_mode, glyph_run, desc, effect);
1642 if (desc)
1643 WARN("Ignoring glyph run description %p.\n", desc);
1644 if (effect)
1645 FIXME("Ignoring effect %p.\n", effect);
1646 if (context->options & ~D2D1_DRAW_TEXT_OPTIONS_NO_SNAP)
1647 FIXME("Ignoring options %#x.\n", context->options);
1649 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1650 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1651 baseline_origin, glyph_run, context->brush, measuring_mode);
1653 return S_OK;
1656 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1657 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1659 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p stub!\n",
1660 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1662 return E_NOTIMPL;
1665 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1666 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1668 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1669 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1671 return E_NOTIMPL;
1674 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1675 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1677 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1678 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1680 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1683 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1685 d2d_text_renderer_QueryInterface,
1686 d2d_text_renderer_AddRef,
1687 d2d_text_renderer_Release,
1688 d2d_text_renderer_IsPixelSnappingDisabled,
1689 d2d_text_renderer_GetCurrentTransform,
1690 d2d_text_renderer_GetPixelsPerDip,
1691 d2d_text_renderer_DrawGlyphRun,
1692 d2d_text_renderer_DrawUnderline,
1693 d2d_text_renderer_DrawStrikethrough,
1694 d2d_text_renderer_DrawInlineObject,
1697 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1698 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1700 D3D10_SUBRESOURCE_DATA buffer_data;
1701 D3D10_STATE_BLOCK_MASK state_mask;
1702 DXGI_SURFACE_DESC surface_desc;
1703 IDWriteFactory *dwrite_factory;
1704 D3D10_RASTERIZER_DESC rs_desc;
1705 D3D10_BUFFER_DESC buffer_desc;
1706 D3D10_BLEND_DESC blend_desc;
1707 ID3D10Resource *resource;
1708 unsigned int i, j, k;
1709 HRESULT hr;
1711 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
1713 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1715 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
1717 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1718 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
1720 static const DWORD vs_code_triangle[] =
1722 /* float3x2 transform;
1724 * float4 main(float4 position : POSITION) : SV_POSITION
1726 * return float4(mul(position.xyw, transform), position.zw);
1727 * } */
1728 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1729 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1730 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1731 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1732 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1733 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1734 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1735 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1736 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1737 0x00000000, 0x0100003e,
1739 static const DWORD vs_code_bezier[] =
1741 #if 0
1742 float3x2 transform;
1744 float4 main(float4 position : POSITION,
1745 inout float3 texcoord : TEXCOORD0) : SV_POSITION
1747 return float4(mul(position.xyw, transform), position.zw);
1749 #endif
1750 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
1751 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
1752 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
1753 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
1754 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
1755 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
1756 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
1757 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
1758 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
1759 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
1760 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
1761 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
1762 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
1764 static const DWORD ps_code_triangle_solid[] =
1766 /* float4 color;
1768 * float4 main(float4 position : SV_POSITION) : SV_Target
1770 * return color;
1771 * } */
1772 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1773 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1774 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1775 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1776 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1777 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1778 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1780 static const DWORD ps_code_triangle_solid_bitmap[] =
1782 #if 0
1783 float4 color;
1785 float3x2 transform;
1786 float opacity;
1787 bool ignore_alpha;
1789 SamplerState s;
1790 Texture2D t;
1792 float4 main(float4 position : SV_POSITION) : SV_Target
1794 float2 texcoord;
1795 float4 ret;
1797 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1798 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1799 ret = t.Sample(s, texcoord) * opacity;
1800 if (ignore_alpha)
1801 ret.a = opacity;
1803 return color * ret.a;
1805 #endif
1806 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
1807 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1808 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1809 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1810 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1811 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1812 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1813 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1814 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
1815 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
1816 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
1817 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
1818 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
1819 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
1820 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
1821 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
1822 0x00000000, 0x0100003e,
1824 static const DWORD ps_code_triangle_bitmap[] =
1826 #if 0
1827 float3x2 transform;
1828 float opacity;
1829 bool ignore_alpha;
1831 SamplerState s;
1832 Texture2D t;
1834 float4 main(float4 position : SV_POSITION) : SV_Target
1836 float2 texcoord;
1837 float4 ret;
1839 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1840 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1841 ret = t.Sample(s, texcoord) * opacity;
1842 if (ignore_alpha)
1843 ret.a = opacity;
1845 return ret;
1847 #endif
1848 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 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, 0x00000160, 0x00000040,
1853 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
1854 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1855 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1856 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1857 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1858 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1859 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1860 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1861 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
1862 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1863 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
1865 static const DWORD ps_code_triangle_bitmap_solid[] =
1867 #if 0
1868 float3x2 transform;
1869 float opacity;
1870 bool ignore_alpha;
1872 float4 color;
1874 SamplerState s;
1875 Texture2D t;
1877 float4 main(float4 position : SV_POSITION) : SV_Target
1879 float2 texcoord;
1880 float4 ret;
1882 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1883 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1884 ret = t.Sample(s, texcoord) * opacity;
1885 if (ignore_alpha)
1886 ret.a = opacity;
1888 return ret * color.a;
1890 #endif
1891 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
1892 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1893 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1894 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1895 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1896 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1897 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1898 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1899 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1900 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1901 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1902 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1903 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1904 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
1905 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1906 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
1907 0x00000003, 0x0100003e,
1909 static const DWORD ps_code_triangle_bitmap_bitmap[] =
1911 #if 0
1912 struct brush
1914 float3x2 transform;
1915 float opacity;
1916 bool ignore_alpha;
1917 } brush0, brush1;
1919 SamplerState s0, s1;
1920 Texture2D t0, t1;
1922 float4 main(float4 position : SV_POSITION) : SV_Target
1924 float2 texcoord;
1925 float opacity;
1926 float4 ret;
1928 texcoord.x = position.x * brush0.transform._11 + position.y * brush0.transform._21 + brush0.transform._31;
1929 texcoord.y = position.x * brush0.transform._12 + position.y * brush0.transform._22 + brush0.transform._32;
1930 ret = t0.Sample(s0, texcoord) * brush0.opacity;
1931 if (brush0.ignore_alpha)
1932 ret.a = brush0.opacity;
1934 texcoord.x = position.x * brush1.transform._11 + position.y * brush1.transform._21 + brush1.transform._31;
1935 texcoord.y = position.x * brush1.transform._12 + position.y * brush1.transform._22 + brush1.transform._32;
1936 opacity = t1.Sample(s1, texcoord).a * brush1.opacity;
1937 if (brush1.ignore_alpha)
1938 opacity = brush1.opacity;
1940 return ret * opacity;
1942 #endif
1943 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
1944 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1945 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1946 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1947 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
1948 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
1949 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
1950 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
1951 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
1952 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
1953 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
1954 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
1955 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
1956 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
1957 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
1958 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
1959 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
1960 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
1961 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
1962 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
1963 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
1964 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
1965 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
1966 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
1967 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
1969 /* The basic idea here is to evaluate the implicit form of the curve in
1970 * texture space. "t.z" determines which side of the curve is shaded. */
1971 static const DWORD ps_code_bezier_solid[] =
1973 #if 0
1974 float4 color;
1976 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
1978 clip((t.x * t.x - t.y) * t.z);
1979 return color;
1981 #endif
1982 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
1983 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
1984 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
1985 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
1986 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
1987 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
1988 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
1989 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
1990 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
1991 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
1992 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
1993 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1995 static const struct brush_shader
1997 const void *byte_code;
1998 size_t byte_code_size;
1999 enum d2d_shape_type shape_type;
2000 enum d2d_brush_type brush_type;
2001 enum d2d_brush_type opacity_brush_type;
2003 brush_shaders[] =
2005 {ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
2006 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2007 {ps_code_triangle_solid_bitmap, sizeof(ps_code_triangle_solid_bitmap),
2008 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_BITMAP},
2009 {ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
2010 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_COUNT},
2011 {ps_code_triangle_bitmap_solid, sizeof(ps_code_triangle_bitmap_solid),
2012 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_SOLID},
2013 {ps_code_triangle_bitmap_bitmap, sizeof(ps_code_triangle_bitmap_bitmap),
2014 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_BITMAP},
2015 {ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
2016 D2D_SHAPE_TYPE_BEZIER, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2018 static const struct
2020 float x, y;
2022 quad[] =
2024 {-1.0f, 1.0f},
2025 {-1.0f, -1.0f},
2026 { 1.0f, 1.0f},
2027 { 1.0f, -1.0f},
2029 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
2030 static const D2D1_MATRIX_3X2_F identity =
2032 1.0f, 0.0f,
2033 0.0f, 1.0f,
2034 0.0f, 0.0f,
2037 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
2038 WARN("Ignoring render target type %#x.\n", desc->type);
2039 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
2040 FIXME("Ignoring render target usage %#x.\n", desc->usage);
2041 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
2042 WARN("Ignoring feature level %#x.\n", desc->minLevel);
2044 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
2045 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
2046 render_target->refcount = 1;
2047 render_target->factory = factory;
2048 ID2D1Factory_AddRef(render_target->factory);
2050 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
2052 WARN("Failed to get device interface, hr %#x.\n", hr);
2053 ID2D1Factory_Release(render_target->factory);
2054 return hr;
2057 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2059 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2060 goto err;
2063 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
2064 ID3D10Resource_Release(resource);
2065 if (FAILED(hr))
2067 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2068 goto err;
2071 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
2073 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
2074 goto err;
2077 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
2079 WARN("Failed to create stateblock, hr %#x.\n", hr);
2080 goto err;
2083 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
2084 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
2085 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
2087 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
2088 goto err;
2091 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
2092 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
2093 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
2095 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
2096 goto err;
2099 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
2100 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
2102 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
2103 goto err;
2106 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
2107 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
2109 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
2110 goto err;
2113 for (i = 0; i < sizeof(brush_shaders) / sizeof(*brush_shaders); ++i)
2115 const struct brush_shader *bs = &brush_shaders[i];
2116 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, bs->byte_code, bs->byte_code_size,
2117 &render_target->shape_resources[bs->shape_type].ps[bs->brush_type][bs->opacity_brush_type])))
2119 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
2120 bs->shape_type, bs->brush_type, bs->opacity_brush_type);
2121 goto err;
2125 buffer_desc.ByteWidth = sizeof(indices);
2126 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
2127 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
2128 buffer_desc.CPUAccessFlags = 0;
2129 buffer_desc.MiscFlags = 0;
2131 buffer_data.pSysMem = indices;
2132 buffer_data.SysMemPitch = 0;
2133 buffer_data.SysMemSlicePitch = 0;
2135 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2136 &buffer_desc, &buffer_data, &render_target->ib)))
2138 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
2139 goto err;
2142 buffer_desc.ByteWidth = sizeof(quad);
2143 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
2144 buffer_data.pSysMem = quad;
2146 render_target->vb_stride = sizeof(*quad);
2147 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2148 &buffer_desc, &buffer_data, &render_target->vb)))
2150 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
2151 goto err;
2154 rs_desc.FillMode = D3D10_FILL_SOLID;
2155 rs_desc.CullMode = D3D10_CULL_NONE;
2156 rs_desc.FrontCounterClockwise = FALSE;
2157 rs_desc.DepthBias = 0;
2158 rs_desc.DepthBiasClamp = 0.0f;
2159 rs_desc.SlopeScaledDepthBias = 0.0f;
2160 rs_desc.DepthClipEnable = TRUE;
2161 rs_desc.ScissorEnable = TRUE;
2162 rs_desc.MultisampleEnable = FALSE;
2163 rs_desc.AntialiasedLineEnable = FALSE;
2164 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
2166 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
2167 goto err;
2170 memset(&blend_desc, 0, sizeof(blend_desc));
2171 blend_desc.BlendEnable[0] = TRUE;
2172 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2173 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2174 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2175 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2177 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2178 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2180 else
2182 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2183 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2185 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2186 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2187 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
2189 WARN("Failed to create blend state, hr %#x.\n", hr);
2190 goto err;
2193 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
2194 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
2196 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2197 goto err;
2200 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
2201 IDWriteFactory_Release(dwrite_factory);
2202 if (FAILED(hr))
2204 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
2205 goto err;
2208 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2210 WARN("Failed to get surface desc, hr %#x.\n", hr);
2211 goto err;
2214 render_target->format = desc->pixelFormat;
2215 render_target->pixel_size.width = surface_desc.Width;
2216 render_target->pixel_size.height = surface_desc.Height;
2217 render_target->drawing_state.transform = identity;
2219 if (!d2d_clip_stack_init(&render_target->clip_stack))
2221 WARN("Failed to initialize clip stack.\n");
2222 hr = E_FAIL;
2223 goto err;
2226 render_target->dpi_x = desc->dpiX;
2227 render_target->dpi_y = desc->dpiY;
2229 if (render_target->dpi_x == 0.0f && render_target->dpi_y == 0.0f)
2231 render_target->dpi_x = 96.0f;
2232 render_target->dpi_y = 96.0f;
2235 return S_OK;
2237 err:
2238 if (render_target->default_text_rendering_params)
2239 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
2240 if (render_target->bs)
2241 ID3D10BlendState_Release(render_target->bs);
2242 if (render_target->rs)
2243 ID3D10RasterizerState_Release(render_target->rs);
2244 if (render_target->vb)
2245 ID3D10Buffer_Release(render_target->vb);
2246 if (render_target->ib)
2247 ID3D10Buffer_Release(render_target->ib);
2248 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
2250 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2252 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2254 if (render_target->shape_resources[i].ps[j][k])
2255 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
2258 if (render_target->shape_resources[i].vs)
2259 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
2260 if (render_target->shape_resources[i].il)
2261 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
2263 if (render_target->stateblock)
2264 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
2265 if (render_target->view)
2266 ID3D10RenderTargetView_Release(render_target->view);
2267 if (render_target->device)
2268 ID3D10Device_Release(render_target->device);
2269 ID2D1Factory_Release(render_target->factory);
2270 return hr;