dwrite: Partially implement GetGlyphImageFormats().
[wine.git] / dlls / d2d1 / render_target.c
blob8b1dfb7977b9232d369e819b2872eccfb2b9249c
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
20 #include "wine/port.h"
22 #include "d2d1_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
26 #define INITIAL_CLIP_STACK_SIZE 4
28 static const D2D1_MATRIX_3X2_F identity =
30 1.0f, 0.0f,
31 0.0f, 1.0f,
32 0.0f, 0.0f,
35 struct d2d_draw_text_layout_ctx
37 ID2D1Brush *brush;
38 D2D1_DRAW_TEXT_OPTIONS options;
41 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
43 ID2D1Brush *brush = NULL;
45 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
46 return brush;
48 ID2D1Brush_AddRef(context->brush);
49 return context->brush;
52 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
54 if (point->x < dst->left)
55 dst->left = point->x;
56 if (point->y < dst->top)
57 dst->top = point->y;
58 if (point->x > dst->right)
59 dst->right = point->x;
60 if (point->y > dst->bottom)
61 dst->bottom = point->y;
64 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
66 if (src->left > dst->left)
67 dst->left = src->left;
68 if (src->top > dst->top)
69 dst->top = src->top;
70 if (src->right < dst->right)
71 dst->right = src->right;
72 if (src->bottom < dst->bottom)
73 dst->bottom = src->bottom;
76 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
78 dst->left = left;
79 dst->top = top;
80 dst->right = right;
81 dst->bottom = bottom;
84 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
86 dst->width = width;
87 dst->height = height;
90 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
92 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
93 return FALSE;
95 stack->size = INITIAL_CLIP_STACK_SIZE;
96 stack->count = 0;
98 return TRUE;
101 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
103 HeapFree(GetProcessHeap(), 0, stack->stack);
106 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
108 D2D1_RECT_F r;
110 if (stack->count == stack->size)
112 D2D1_RECT_F *new_stack;
113 unsigned int new_size;
115 if (stack->size > UINT_MAX / 2)
116 return FALSE;
118 new_size = stack->size * 2;
119 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
120 return FALSE;
122 stack->stack = new_stack;
123 stack->size = new_size;
126 r = *rect;
127 if (stack->count)
128 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
129 stack->stack[stack->count++] = r;
131 return TRUE;
134 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
136 if (!stack->count)
137 return;
138 --stack->count;
141 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
142 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
143 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
145 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
146 ID3D10Device *device = render_target->device;
147 D3D10_RECT scissor_rect;
148 unsigned int offset;
149 D3D10_VIEWPORT vp;
150 HRESULT hr;
152 vp.TopLeftX = 0;
153 vp.TopLeftY = 0;
154 vp.Width = render_target->pixel_size.width;
155 vp.Height = render_target->pixel_size.height;
156 vp.MinDepth = 0.0f;
157 vp.MaxDepth = 1.0f;
159 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
161 WARN("Failed to capture stateblock, hr %#x.\n", hr);
162 return;
165 ID3D10Device_ClearState(device);
167 ID3D10Device_IASetInputLayout(device, shape_resources->il);
168 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
169 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
170 offset = 0;
171 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
172 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
173 ID3D10Device_VSSetShader(device, shape_resources->vs);
174 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
175 ID3D10Device_RSSetViewports(device, 1, &vp);
176 if (render_target->clip_stack.count)
178 const D2D1_RECT_F *clip_rect;
180 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
181 scissor_rect.left = clip_rect->left + 0.5f;
182 scissor_rect.top = clip_rect->top + 0.5f;
183 scissor_rect.right = clip_rect->right + 0.5f;
184 scissor_rect.bottom = clip_rect->bottom + 0.5f;
186 else
188 scissor_rect.left = 0.0f;
189 scissor_rect.top = 0.0f;
190 scissor_rect.right = render_target->pixel_size.width;
191 scissor_rect.bottom = render_target->pixel_size.height;
193 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
194 ID3D10Device_RSSetState(device, render_target->rs);
195 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
196 if (brush)
197 d2d_brush_bind_resources(brush, opacity_brush, render_target, shape_type);
198 else
199 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID][D2D_BRUSH_TYPE_COUNT]);
201 if (ib)
202 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
203 else
204 ID3D10Device_Draw(device, index_count, 0);
206 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
207 WARN("Failed to apply stateblock, hr %#x.\n", hr);
210 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
212 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
215 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
217 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
219 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
221 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
222 || IsEqualGUID(iid, &IID_ID2D1Resource)
223 || IsEqualGUID(iid, &IID_IUnknown))
225 ID2D1RenderTarget_AddRef(iface);
226 *out = iface;
227 return S_OK;
229 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
231 ID2D1GdiInteropRenderTarget_AddRef(&render_target->ID2D1GdiInteropRenderTarget_iface);
232 *out = &render_target->ID2D1GdiInteropRenderTarget_iface;
233 return S_OK;
236 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
238 *out = NULL;
239 return E_NOINTERFACE;
242 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
244 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
245 ULONG refcount = InterlockedIncrement(&render_target->refcount);
247 TRACE("%p increasing refcount to %u.\n", iface, refcount);
249 return refcount;
252 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
254 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
255 ULONG refcount = InterlockedDecrement(&render_target->refcount);
257 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
259 if (!refcount)
261 unsigned int i, j, k;
263 d2d_clip_stack_cleanup(&render_target->clip_stack);
264 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
265 if (render_target->text_rendering_params)
266 IDWriteRenderingParams_Release(render_target->text_rendering_params);
267 ID3D10BlendState_Release(render_target->bs);
268 ID3D10RasterizerState_Release(render_target->rs);
269 ID3D10Buffer_Release(render_target->vb);
270 ID3D10Buffer_Release(render_target->ib);
271 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
273 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
275 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
277 if (render_target->shape_resources[i].ps[j][k])
278 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
281 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
282 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
284 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
285 ID3D10RenderTargetView_Release(render_target->view);
286 ID3D10Device_Release(render_target->device);
287 ID2D1Factory_Release(render_target->factory);
288 HeapFree(GetProcessHeap(), 0, render_target);
291 return refcount;
294 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
296 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
298 TRACE("iface %p, factory %p.\n", iface, factory);
300 *factory = render_target->factory;
301 ID2D1Factory_AddRef(*factory);
304 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
305 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
307 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
308 struct d2d_bitmap *object;
309 HRESULT hr;
311 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
312 iface, size.width, size.height, src_data, pitch, desc, bitmap);
314 if (SUCCEEDED(hr = d2d_bitmap_create(render_target->factory, render_target->device, size, src_data, pitch, desc, &object)))
315 *bitmap = &object->ID2D1Bitmap_iface;
317 return hr;
320 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
321 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
323 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
324 struct d2d_bitmap *object;
325 HRESULT hr;
327 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
328 iface, bitmap_source, desc, bitmap);
330 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(render_target->factory, render_target->device, bitmap_source,
331 desc, &object)))
332 *bitmap = &object->ID2D1Bitmap_iface;
334 return hr;
337 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
338 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
340 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
341 struct d2d_bitmap *object;
342 HRESULT hr;
344 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
345 iface, debugstr_guid(iid), data, desc, bitmap);
347 if (SUCCEEDED(hr = d2d_bitmap_create_shared(iface, render_target->device, iid, data, desc, &object)))
348 *bitmap = &object->ID2D1Bitmap_iface;
350 return hr;
353 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
354 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
355 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
357 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
358 struct d2d_brush *object;
359 HRESULT hr;
361 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
362 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
364 if (SUCCEEDED(hr = d2d_bitmap_brush_create(render_target->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
365 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
367 return hr;
370 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
371 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
373 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
374 struct d2d_brush *object;
375 HRESULT hr;
377 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
379 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
380 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
382 return hr;
385 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
386 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
387 ID2D1GradientStopCollection **gradient)
389 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
390 struct d2d_gradient *object;
391 HRESULT hr;
393 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
394 iface, stops, stop_count, gamma, extend_mode, gradient);
396 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, stops, stop_count, gamma, extend_mode, &object)))
397 *gradient = &object->ID2D1GradientStopCollection_iface;
399 return hr;
402 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
403 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
404 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
406 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
407 struct d2d_brush *object;
408 HRESULT hr;
410 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
411 iface, gradient_brush_desc, brush_desc, gradient, brush);
413 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
414 gradient, &object)))
415 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
417 return hr;
420 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
421 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
422 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
424 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
425 iface, gradient_brush_desc, brush_desc, gradient, brush);
427 return E_NOTIMPL;
430 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
431 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
432 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
434 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
435 struct d2d_bitmap_render_target *object;
436 HRESULT hr;
438 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
439 iface, size, pixel_size, format, options, rt);
441 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
442 return E_OUTOFMEMORY;
444 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
445 format, options)))
447 WARN("Failed to initialize render target, hr %#x.\n", hr);
448 HeapFree(GetProcessHeap(), 0, object);
449 return hr;
452 TRACE("Created render target %p.\n", object);
453 *rt = &object->ID2D1BitmapRenderTarget_iface;
455 return S_OK;
458 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
459 const D2D1_SIZE_F *size, ID2D1Layer **layer)
461 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
463 return E_NOTIMPL;
466 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
468 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
469 struct d2d_mesh *object;
470 HRESULT hr;
472 TRACE("iface %p, mesh %p.\n", iface, mesh);
474 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
475 *mesh = &object->ID2D1Mesh_iface;
477 return hr;
480 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
481 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
483 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
484 ID2D1PathGeometry *geometry;
485 ID2D1GeometrySink *sink;
486 HRESULT hr;
488 TRACE("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p.\n",
489 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
491 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
493 WARN("Failed to create path geometry, %#x.\n", hr);
494 return;
497 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
499 WARN("Open() failed, %#x.\n", hr);
500 ID2D1PathGeometry_Release(geometry);
501 return;
504 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
505 ID2D1GeometrySink_AddLine(sink, p1);
506 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
507 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
508 WARN("Close() failed, %#x.\n", hr);
509 ID2D1GeometrySink_Release(sink);
511 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
512 ID2D1PathGeometry_Release(geometry);
515 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
516 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
518 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
519 ID2D1RectangleGeometry *geometry;
520 HRESULT hr;
522 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
523 iface, rect, brush, stroke_width, stroke_style);
525 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
527 ERR("Failed to create geometry, hr %#x.\n", hr);
528 return;
531 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
532 ID2D1RectangleGeometry_Release(geometry);
535 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
536 const D2D1_RECT_F *rect, ID2D1Brush *brush)
538 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
539 ID2D1RectangleGeometry *geometry;
540 HRESULT hr;
542 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
544 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
546 ERR("Failed to create geometry, hr %#x.\n", hr);
547 return;
550 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
551 ID2D1RectangleGeometry_Release(geometry);
554 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
555 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
557 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
558 ID2D1RoundedRectangleGeometry *geometry;
559 HRESULT hr;
561 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
562 iface, rect, brush, stroke_width, stroke_style);
564 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
566 ERR("Failed to create geometry, hr %#x.\n", hr);
567 return;
570 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
571 ID2D1RoundedRectangleGeometry_Release(geometry);
574 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
575 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
577 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
578 ID2D1RoundedRectangleGeometry *geometry;
579 HRESULT hr;
581 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
583 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
585 ERR("Failed to create geometry, hr %#x.\n", hr);
586 return;
589 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
590 ID2D1RoundedRectangleGeometry_Release(geometry);
593 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
594 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
596 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
597 ID2D1EllipseGeometry *geometry;
598 HRESULT hr;
600 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
601 iface, ellipse, brush, stroke_width, stroke_style);
603 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
605 ERR("Failed to create geometry, hr %#x.\n", hr);
606 return;
609 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
610 ID2D1EllipseGeometry_Release(geometry);
613 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
614 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
616 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
617 ID2D1EllipseGeometry *geometry;
618 HRESULT hr;
620 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
622 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
624 ERR("Failed to create geometry, hr %#x.\n", hr);
625 return;
628 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
629 ID2D1EllipseGeometry_Release(geometry);
632 static void d2d_rt_draw_geometry(struct d2d_d3d_render_target *render_target,
633 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
635 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
636 D3D10_SUBRESOURCE_DATA buffer_data;
637 D3D10_BUFFER_DESC buffer_desc;
638 const D2D1_MATRIX_3X2_F *w;
639 float tmp_x, tmp_y;
640 HRESULT hr;
641 struct
643 struct
645 float _11, _21, _31, pad0;
646 float _12, _22, _32, stroke_width;
647 } transform_geometry;
648 struct d2d_vec4 transform_rtx;
649 struct d2d_vec4 transform_rty;
650 } vs_cb_data;
652 vs_cb_data.transform_geometry._11 = geometry->transform._11;
653 vs_cb_data.transform_geometry._21 = geometry->transform._21;
654 vs_cb_data.transform_geometry._31 = geometry->transform._31;
655 vs_cb_data.transform_geometry.pad0 = 0.0f;
656 vs_cb_data.transform_geometry._12 = geometry->transform._12;
657 vs_cb_data.transform_geometry._22 = geometry->transform._22;
658 vs_cb_data.transform_geometry._32 = geometry->transform._32;
659 vs_cb_data.transform_geometry.stroke_width = stroke_width;
661 w = &render_target->drawing_state.transform;
663 tmp_x = render_target->desc.dpiX / 96.0f;
664 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
665 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
666 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
667 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
669 tmp_y = render_target->desc.dpiY / 96.0f;
670 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
671 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
672 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
673 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
675 buffer_desc.ByteWidth = sizeof(vs_cb_data);
676 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
677 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
678 buffer_desc.CPUAccessFlags = 0;
679 buffer_desc.MiscFlags = 0;
681 buffer_data.pSysMem = &vs_cb_data;
682 buffer_data.SysMemPitch = 0;
683 buffer_data.SysMemSlicePitch = 0;
685 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
687 WARN("Failed to create constant buffer, hr %#x.\n", hr);
688 return;
691 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, render_target, &ps_cb)))
693 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
694 ID3D10Buffer_Release(vs_cb);
695 return;
698 if (geometry->outline.face_count)
700 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
701 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
702 buffer_data.pSysMem = geometry->outline.faces;
704 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
706 WARN("Failed to create index buffer, hr %#x.\n", hr);
707 goto done;
710 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
711 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
712 buffer_data.pSysMem = geometry->outline.vertices;
714 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
716 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
717 ID3D10Buffer_Release(ib);
718 goto done;
721 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
722 sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
724 ID3D10Buffer_Release(vb);
725 ID3D10Buffer_Release(ib);
728 done:
729 ID3D10Buffer_Release(ps_cb);
730 ID3D10Buffer_Release(vs_cb);
733 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
734 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
736 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
737 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
738 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
740 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
741 iface, geometry, brush, stroke_width, stroke_style);
743 if (stroke_style)
744 FIXME("Ignoring stoke style %p.\n", stroke_style);
746 d2d_rt_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
749 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
750 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
752 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
753 D3D10_SUBRESOURCE_DATA buffer_data;
754 D3D10_BUFFER_DESC buffer_desc;
755 D2D1_MATRIX_3X2_F w, g;
756 float tmp_x, tmp_y;
757 HRESULT hr;
758 struct
760 float _11, _21, _31, pad0;
761 float _12, _22, _32, pad1;
762 } transform;
764 tmp_x = (2.0f * render_target->desc.dpiX) / (96.0f * render_target->pixel_size.width);
765 tmp_y = -(2.0f * render_target->desc.dpiY) / (96.0f * render_target->pixel_size.height);
766 w = render_target->drawing_state.transform;
767 w._11 *= tmp_x;
768 w._21 *= tmp_x;
769 w._31 = w._31 * tmp_x - 1.0f;
770 w._12 *= tmp_y;
771 w._22 *= tmp_y;
772 w._32 = w._32 * tmp_y + 1.0f;
774 g = geometry->transform;
775 d2d_matrix_multiply(&g, &w);
777 transform._11 = g._11;
778 transform._21 = g._21;
779 transform._31 = g._31;
780 transform.pad0 = 0.0f;
781 transform._12 = g._12;
782 transform._22 = g._22;
783 transform._32 = g._32;
784 transform.pad1 = 0.0f;
786 buffer_desc.ByteWidth = sizeof(transform);
787 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
788 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
789 buffer_desc.CPUAccessFlags = 0;
790 buffer_desc.MiscFlags = 0;
792 buffer_data.pSysMem = &transform;
793 buffer_data.SysMemPitch = 0;
794 buffer_data.SysMemSlicePitch = 0;
796 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
798 WARN("Failed to create constant buffer, hr %#x.\n", hr);
799 return;
802 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, render_target, &ps_cb)))
804 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
805 ID3D10Buffer_Release(vs_cb);
806 return;
809 if (geometry->fill.face_count)
811 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
812 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
813 buffer_data.pSysMem = geometry->fill.faces;
815 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
817 WARN("Failed to create index buffer, hr %#x.\n", hr);
818 goto done;
821 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
822 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
823 buffer_data.pSysMem = geometry->fill.vertices;
825 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
827 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
828 ID3D10Buffer_Release(ib);
829 goto done;
832 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
833 sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush);
835 ID3D10Buffer_Release(vb);
836 ID3D10Buffer_Release(ib);
839 if (geometry->fill.bezier_vertex_count)
841 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
842 buffer_data.pSysMem = geometry->fill.bezier_vertices;
844 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
846 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
847 goto done;
850 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb,
851 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush);
853 ID3D10Buffer_Release(vb);
856 done:
857 ID3D10Buffer_Release(ps_cb);
858 ID3D10Buffer_Release(vs_cb);
861 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
862 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
864 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
865 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
866 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
867 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
869 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
871 if (FAILED(render_target->error.code))
872 return;
874 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
876 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
877 render_target->error.tag1 = render_target->drawing_state.tag1;
878 render_target->error.tag2 = render_target->drawing_state.tag2;
879 return;
882 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
885 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
886 ID2D1Mesh *mesh, ID2D1Brush *brush)
888 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
891 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
892 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
893 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
895 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
896 iface, mask, brush, content, dst_rect, src_rect);
899 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
900 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
901 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
903 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
904 D2D1_BRUSH_PROPERTIES brush_desc;
905 ID2D1BitmapBrush *brush;
906 D2D1_RECT_F s, d;
907 HRESULT hr;
909 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
910 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
912 if (src_rect)
914 s = *src_rect;
916 else
918 D2D1_SIZE_F size;
920 size = ID2D1Bitmap_GetSize(bitmap);
921 s.left = 0.0f;
922 s.top = 0.0f;
923 s.right = size.width;
924 s.bottom = size.height;
927 if (dst_rect)
929 d = *dst_rect;
931 else
933 d.left = 0.0f;
934 d.top = 0.0f;
935 d.right = s.right - s.left;
936 d.bottom = s.bottom - s.top;
939 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
940 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
941 bitmap_brush_desc.interpolationMode = interpolation_mode;
943 brush_desc.opacity = opacity;
944 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
945 brush_desc.transform._21 = 0.0f;
946 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
947 brush_desc.transform._12 = 0.0f;
948 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
949 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
951 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
953 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
954 return;
957 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
958 ID2D1BitmapBrush_Release(brush);
961 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
962 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
963 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
965 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
966 IDWriteTextLayout *text_layout;
967 IDWriteFactory *dwrite_factory;
968 D2D1_POINT_2F origin;
969 HRESULT hr;
971 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
972 "brush %p, options %#x, measuring_mode %#x.\n",
973 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
974 brush, options, measuring_mode);
976 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
977 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
979 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
980 return;
983 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
984 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
985 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
986 else
987 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
988 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
989 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
990 IDWriteFactory_Release(dwrite_factory);
991 if (FAILED(hr))
993 ERR("Failed to create text layout, hr %#x.\n", hr);
994 return;
997 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
998 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
999 IDWriteTextLayout_Release(text_layout);
1002 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
1003 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1005 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1006 struct d2d_draw_text_layout_ctx ctx;
1007 HRESULT hr;
1009 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
1010 iface, origin.x, origin.y, layout, brush, options);
1012 ctx.brush = brush;
1013 ctx.options = options;
1015 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1016 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1017 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1020 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
1021 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1023 D2D1_MATRIX_3X2_F *transform, prev_transform;
1024 ID2D1PathGeometry *geometry;
1025 ID2D1GeometrySink *sink;
1026 HRESULT hr;
1028 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1030 ERR("Failed to create geometry, hr %#x.\n", hr);
1031 return;
1034 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1036 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1037 ID2D1PathGeometry_Release(geometry);
1038 return;
1041 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1042 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1043 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1045 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1046 ID2D1GeometrySink_Release(sink);
1047 ID2D1PathGeometry_Release(geometry);
1048 return;
1051 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1052 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1053 ID2D1GeometrySink_Release(sink);
1055 transform = &render_target->drawing_state.transform;
1056 prev_transform = *transform;
1057 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1058 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1059 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1060 unsafe_impl_from_ID2D1Brush(brush), NULL);
1061 *transform = prev_transform;
1063 ID2D1PathGeometry_Release(geometry);
1066 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
1067 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1068 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode)
1070 D2D1_MATRIX_3X2_F prev_transform, *transform;
1071 ID2D1RectangleGeometry *geometry = NULL;
1072 ID2D1BitmapBrush *opacity_brush = NULL;
1073 D2D1_BITMAP_PROPERTIES bitmap_desc;
1074 ID2D1Bitmap *opacity_bitmap = NULL;
1075 IDWriteGlyphRunAnalysis *analysis;
1076 DWRITE_TEXTURE_TYPE texture_type;
1077 D2D1_BRUSH_PROPERTIES brush_desc;
1078 IDWriteFactory *dwrite_factory;
1079 void *opacity_values = NULL;
1080 size_t opacity_values_size;
1081 D2D1_SIZE_U bitmap_size;
1082 D2D1_RECT_F run_rect;
1083 RECT bounds;
1084 HRESULT hr;
1086 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1087 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1089 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1090 return;
1093 hr = IDWriteFactory_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, ppd,
1094 (DWRITE_MATRIX *)&render_target->drawing_state.transform, rendering_mode, measuring_mode,
1095 baseline_origin.x, baseline_origin.y, &analysis);
1096 IDWriteFactory_Release(dwrite_factory);
1097 if (FAILED(hr))
1099 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1100 return;
1103 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1104 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1105 else
1106 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1108 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1110 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1111 goto done;
1114 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1115 if (!bitmap_size.width || !bitmap_size.height)
1117 /* Empty run, nothing to do. */
1118 goto done;
1121 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1122 bitmap_size.width *= 3;
1123 opacity_values_size = bitmap_size.width * bitmap_size.height;
1124 if (!(opacity_values = HeapAlloc(GetProcessHeap(), 0, opacity_values_size)))
1126 ERR("Failed to allocate opacity values.\n");
1127 goto done;
1130 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1131 texture_type, &bounds, opacity_values, opacity_values_size)))
1133 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1134 goto done;
1137 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1138 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1139 bitmap_desc.dpiX = render_target->desc.dpiX;
1140 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1141 bitmap_desc.dpiX *= 3.0f;
1142 bitmap_desc.dpiY = render_target->desc.dpiY;
1143 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
1144 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1146 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1147 goto done;
1150 brush_desc.opacity = 1.0f;
1151 brush_desc.transform._11 = 1.0f;
1152 brush_desc.transform._12 = 0.0f;
1153 brush_desc.transform._21 = 0.0f;
1154 brush_desc.transform._22 = 1.0f;
1155 brush_desc.transform._31 = bounds.left;
1156 brush_desc.transform._32 = bounds.top;
1157 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
1158 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1160 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1161 goto done;
1164 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
1165 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1167 ERR("Failed to create geometry, hr %#x.\n", hr);
1168 goto done;
1171 transform = &render_target->drawing_state.transform;
1172 prev_transform = *transform;
1173 *transform = identity;
1174 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1175 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1176 *transform = prev_transform;
1178 done:
1179 if (geometry)
1180 ID2D1RectangleGeometry_Release(geometry);
1181 if (opacity_brush)
1182 ID2D1BitmapBrush_Release(opacity_brush);
1183 if (opacity_bitmap)
1184 ID2D1Bitmap_Release(opacity_bitmap);
1185 HeapFree(GetProcessHeap(), 0, opacity_values);
1186 IDWriteGlyphRunAnalysis_Release(analysis);
1189 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
1190 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1191 DWRITE_MEASURING_MODE measuring_mode)
1193 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1194 IDWriteRenderingParams *rendering_params;
1195 DWRITE_RENDERING_MODE rendering_mode;
1196 HRESULT hr;
1197 float ppd;
1199 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1200 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
1202 if (FAILED(render_target->error.code))
1203 return;
1205 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
1206 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
1208 ppd = max(render_target->desc.dpiX, render_target->desc.dpiY) / 96.0f;
1209 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1210 : render_target->default_text_rendering_params;
1211 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1212 ppd, measuring_mode, rendering_params, &rendering_mode)))
1214 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1215 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1218 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1219 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1220 else
1221 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1222 ppd, rendering_mode, measuring_mode);
1225 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1226 const D2D1_MATRIX_3X2_F *transform)
1228 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1230 TRACE("iface %p, transform %p.\n", iface, transform);
1232 render_target->drawing_state.transform = *transform;
1235 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1236 D2D1_MATRIX_3X2_F *transform)
1238 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1240 TRACE("iface %p, transform %p.\n", iface, transform);
1242 *transform = render_target->drawing_state.transform;
1245 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1246 D2D1_ANTIALIAS_MODE antialias_mode)
1248 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1250 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1252 render_target->drawing_state.antialiasMode = antialias_mode;
1255 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1257 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1259 TRACE("iface %p.\n", iface);
1261 return render_target->drawing_state.antialiasMode;
1264 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1265 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1267 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1269 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1271 render_target->drawing_state.textAntialiasMode = antialias_mode;
1274 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1276 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1278 TRACE("iface %p.\n", iface);
1280 return render_target->drawing_state.textAntialiasMode;
1283 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1284 IDWriteRenderingParams *text_rendering_params)
1286 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1288 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1290 if (text_rendering_params)
1291 IDWriteRenderingParams_AddRef(text_rendering_params);
1292 if (render_target->text_rendering_params)
1293 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1294 render_target->text_rendering_params = text_rendering_params;
1297 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1298 IDWriteRenderingParams **text_rendering_params)
1300 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1302 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1304 if ((*text_rendering_params = render_target->text_rendering_params))
1305 IDWriteRenderingParams_AddRef(*text_rendering_params);
1308 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1310 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1312 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1314 render_target->drawing_state.tag1 = tag1;
1315 render_target->drawing_state.tag2 = tag2;
1318 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1320 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1322 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1324 *tag1 = render_target->drawing_state.tag1;
1325 *tag2 = render_target->drawing_state.tag2;
1328 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1329 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1331 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1334 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1336 FIXME("iface %p stub!\n", iface);
1339 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1341 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1343 return E_NOTIMPL;
1346 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1347 ID2D1DrawingStateBlock *state_block)
1349 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1350 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1352 TRACE("iface %p, state_block %p.\n", iface, state_block);
1354 state_block_impl->drawing_state = render_target->drawing_state;
1355 if (render_target->text_rendering_params)
1356 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1357 if (state_block_impl->text_rendering_params)
1358 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1359 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1362 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1363 ID2D1DrawingStateBlock *state_block)
1365 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1366 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1368 TRACE("iface %p, state_block %p.\n", iface, state_block);
1370 render_target->drawing_state = state_block_impl->drawing_state;
1371 if (state_block_impl->text_rendering_params)
1372 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1373 if (render_target->text_rendering_params)
1374 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1375 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1378 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1379 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1381 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1382 D2D1_RECT_F transformed_rect;
1383 float x_scale, y_scale;
1384 D2D1_POINT_2F point;
1386 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1388 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1389 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1391 x_scale = render_target->desc.dpiX / 96.0f;
1392 y_scale = render_target->desc.dpiY / 96.0f;
1393 d2d_point_transform(&point, &render_target->drawing_state.transform,
1394 clip_rect->left * x_scale, clip_rect->top * y_scale);
1395 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1396 d2d_point_transform(&point, &render_target->drawing_state.transform,
1397 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1398 d2d_rect_expand(&transformed_rect, &point);
1399 d2d_point_transform(&point, &render_target->drawing_state.transform,
1400 clip_rect->right * x_scale, clip_rect->top * y_scale);
1401 d2d_rect_expand(&transformed_rect, &point);
1402 d2d_point_transform(&point, &render_target->drawing_state.transform,
1403 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1404 d2d_rect_expand(&transformed_rect, &point);
1406 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1407 WARN("Failed to push clip rect.\n");
1410 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1412 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1414 TRACE("iface %p.\n", iface);
1416 d2d_clip_stack_pop(&render_target->clip_stack);
1419 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1421 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1422 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1423 D3D10_SUBRESOURCE_DATA buffer_data;
1424 D3D10_BUFFER_DESC buffer_desc;
1425 ID3D10Buffer *vs_cb, *ps_cb;
1426 HRESULT hr;
1428 static const float transform[] =
1430 1.0f, 0.0f, 0.0f, 0.0f,
1431 0.0f, -1.0f, 0.0f, 0.0f,
1434 TRACE("iface %p, color %p.\n", iface, color);
1436 buffer_desc.ByteWidth = sizeof(transform);
1437 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1438 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1439 buffer_desc.CPUAccessFlags = 0;
1440 buffer_desc.MiscFlags = 0;
1442 buffer_data.pSysMem = transform;
1443 buffer_data.SysMemPitch = 0;
1444 buffer_data.SysMemSlicePitch = 0;
1446 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1448 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1449 return;
1452 if (color)
1453 c = *color;
1454 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1455 c.a = 1.0f;
1456 c.r *= c.a;
1457 c.g *= c.a;
1458 c.b *= c.a;
1459 buffer_desc.ByteWidth = sizeof(c);
1460 buffer_data.pSysMem = &c;
1462 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1464 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1465 ID3D10Buffer_Release(vs_cb);
1466 return;
1469 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1470 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1472 ID3D10Buffer_Release(ps_cb);
1473 ID3D10Buffer_Release(vs_cb);
1476 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1478 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1480 TRACE("iface %p.\n", iface);
1482 memset(&render_target->error, 0, sizeof(render_target->error));
1485 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1486 D2D1_TAG *tag1, D2D1_TAG *tag2)
1488 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1490 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1492 if (tag1)
1493 *tag1 = render_target->error.tag1;
1494 if (tag2)
1495 *tag2 = render_target->error.tag2;
1497 return render_target->error.code;
1500 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1501 D2D1_PIXEL_FORMAT *format)
1503 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1505 TRACE("iface %p, format %p.\n", iface, format);
1507 *format = render_target->desc.pixelFormat;
1508 return format;
1511 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1513 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1515 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1517 if (dpi_x == 0.0f && dpi_y == 0.0f)
1519 dpi_x = 96.0f;
1520 dpi_y = 96.0f;
1522 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1523 return;
1525 render_target->desc.dpiX = dpi_x;
1526 render_target->desc.dpiY = dpi_y;
1529 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1531 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1533 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1535 *dpi_x = render_target->desc.dpiX;
1536 *dpi_y = render_target->desc.dpiY;
1539 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1541 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1543 TRACE("iface %p, size %p.\n", iface, size);
1545 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1546 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1547 return size;
1550 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1551 D2D1_SIZE_U *pixel_size)
1553 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1555 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1557 *pixel_size = render_target->pixel_size;
1558 return pixel_size;
1561 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1563 FIXME("iface %p stub!\n", iface);
1565 return 0;
1568 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1569 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1571 FIXME("iface %p, desc %p stub!\n", iface, desc);
1573 return FALSE;
1576 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1578 d2d_d3d_render_target_QueryInterface,
1579 d2d_d3d_render_target_AddRef,
1580 d2d_d3d_render_target_Release,
1581 d2d_d3d_render_target_GetFactory,
1582 d2d_d3d_render_target_CreateBitmap,
1583 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1584 d2d_d3d_render_target_CreateSharedBitmap,
1585 d2d_d3d_render_target_CreateBitmapBrush,
1586 d2d_d3d_render_target_CreateSolidColorBrush,
1587 d2d_d3d_render_target_CreateGradientStopCollection,
1588 d2d_d3d_render_target_CreateLinearGradientBrush,
1589 d2d_d3d_render_target_CreateRadialGradientBrush,
1590 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1591 d2d_d3d_render_target_CreateLayer,
1592 d2d_d3d_render_target_CreateMesh,
1593 d2d_d3d_render_target_DrawLine,
1594 d2d_d3d_render_target_DrawRectangle,
1595 d2d_d3d_render_target_FillRectangle,
1596 d2d_d3d_render_target_DrawRoundedRectangle,
1597 d2d_d3d_render_target_FillRoundedRectangle,
1598 d2d_d3d_render_target_DrawEllipse,
1599 d2d_d3d_render_target_FillEllipse,
1600 d2d_d3d_render_target_DrawGeometry,
1601 d2d_d3d_render_target_FillGeometry,
1602 d2d_d3d_render_target_FillMesh,
1603 d2d_d3d_render_target_FillOpacityMask,
1604 d2d_d3d_render_target_DrawBitmap,
1605 d2d_d3d_render_target_DrawText,
1606 d2d_d3d_render_target_DrawTextLayout,
1607 d2d_d3d_render_target_DrawGlyphRun,
1608 d2d_d3d_render_target_SetTransform,
1609 d2d_d3d_render_target_GetTransform,
1610 d2d_d3d_render_target_SetAntialiasMode,
1611 d2d_d3d_render_target_GetAntialiasMode,
1612 d2d_d3d_render_target_SetTextAntialiasMode,
1613 d2d_d3d_render_target_GetTextAntialiasMode,
1614 d2d_d3d_render_target_SetTextRenderingParams,
1615 d2d_d3d_render_target_GetTextRenderingParams,
1616 d2d_d3d_render_target_SetTags,
1617 d2d_d3d_render_target_GetTags,
1618 d2d_d3d_render_target_PushLayer,
1619 d2d_d3d_render_target_PopLayer,
1620 d2d_d3d_render_target_Flush,
1621 d2d_d3d_render_target_SaveDrawingState,
1622 d2d_d3d_render_target_RestoreDrawingState,
1623 d2d_d3d_render_target_PushAxisAlignedClip,
1624 d2d_d3d_render_target_PopAxisAlignedClip,
1625 d2d_d3d_render_target_Clear,
1626 d2d_d3d_render_target_BeginDraw,
1627 d2d_d3d_render_target_EndDraw,
1628 d2d_d3d_render_target_GetPixelFormat,
1629 d2d_d3d_render_target_SetDpi,
1630 d2d_d3d_render_target_GetDpi,
1631 d2d_d3d_render_target_GetSize,
1632 d2d_d3d_render_target_GetPixelSize,
1633 d2d_d3d_render_target_GetMaximumBitmapSize,
1634 d2d_d3d_render_target_IsSupported,
1637 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1639 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1642 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1644 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1646 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1647 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1648 || IsEqualGUID(iid, &IID_IUnknown))
1650 IDWriteTextRenderer_AddRef(iface);
1651 *out = iface;
1652 return S_OK;
1655 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1657 *out = NULL;
1658 return E_NOINTERFACE;
1661 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1663 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1665 TRACE("iface %p.\n", iface);
1667 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1670 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1672 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1674 TRACE("iface %p.\n", iface);
1676 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1679 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1680 void *ctx, BOOL *disabled)
1682 struct d2d_draw_text_layout_ctx *context = ctx;
1684 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1686 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1688 return S_OK;
1691 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1692 void *ctx, DWRITE_MATRIX *transform)
1694 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1696 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1698 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1700 return S_OK;
1703 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1705 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1707 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1709 *ppd = render_target->desc.dpiY / 96.0f;
1711 return S_OK;
1714 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1715 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1716 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1718 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1719 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1720 struct d2d_draw_text_layout_ctx *context = ctx;
1721 BOOL color_font = FALSE;
1722 ID2D1Brush *brush;
1724 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1725 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1726 iface, ctx, baseline_origin_x, baseline_origin_y,
1727 measuring_mode, glyph_run, desc, effect);
1729 if (desc)
1730 WARN("Ignoring glyph run description %p.\n", desc);
1731 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
1732 FIXME("Ignoring options %#x.\n", context->options);
1734 brush = d2d_draw_get_text_brush(context, effect);
1736 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1738 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
1740 IDWriteFontFace2 *fontface;
1742 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
1743 &IID_IDWriteFontFace2, (void **)&fontface)))
1745 color_font = IDWriteFontFace2_IsColorFont(fontface);
1746 IDWriteFontFace2_Release(fontface);
1750 if (color_font)
1752 IDWriteColorGlyphRunEnumerator *layers;
1753 IDWriteFactory2 *dwrite_factory;
1754 HRESULT hr;
1756 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
1757 (IUnknown **)&dwrite_factory)))
1759 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1760 ID2D1Brush_Release(brush);
1761 return hr;
1764 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
1765 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
1766 IDWriteFactory2_Release(dwrite_factory);
1767 if (FAILED(hr))
1769 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
1770 ID2D1Brush_Release(brush);
1771 return hr;
1774 for (;;)
1776 const DWRITE_COLOR_GLYPH_RUN *color_run;
1777 ID2D1Brush *color_brush;
1778 D2D1_POINT_2F origin;
1779 BOOL has_run = FALSE;
1781 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
1783 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
1784 break;
1787 if (!has_run)
1788 break;
1790 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
1792 ERR("Failed to get current color run, hr %#x.\n", hr);
1793 break;
1796 if (color_run->paletteIndex == 0xffff)
1797 color_brush = brush;
1798 else
1800 if (FAILED(hr = ID2D1RenderTarget_CreateSolidColorBrush(&render_target->ID2D1RenderTarget_iface,
1801 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
1803 ERR("Failed to create solid color brush, hr %#x.\n", hr);
1804 break;
1808 origin.x = color_run->baselineOriginX;
1809 origin.y = color_run->baselineOriginY;
1810 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1811 origin, &color_run->glyphRun, color_brush, measuring_mode);
1813 if (color_brush != brush)
1814 ID2D1Brush_Release(color_brush);
1817 IDWriteColorGlyphRunEnumerator_Release(layers);
1819 else
1820 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1821 baseline_origin, glyph_run, brush, measuring_mode);
1823 ID2D1Brush_Release(brush);
1825 return S_OK;
1828 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1829 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1831 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1832 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1833 struct d2d_draw_text_layout_ctx *context = ctx;
1834 D2D1_POINT_2F start, end;
1835 ID2D1Brush *brush;
1836 float thickness;
1838 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1839 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1841 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1842 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
1843 underline->thickness);
1845 brush = d2d_draw_get_text_brush(context, effect);
1847 start.x = baseline_origin_x;
1848 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
1849 end.x = start.x + underline->width;
1850 end.y = start.y;
1851 d2d_d3d_render_target_DrawLine(&render_target->ID2D1RenderTarget_iface, start, end, brush, thickness, NULL);
1853 ID2D1Brush_Release(brush);
1855 return S_OK;
1858 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1859 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1861 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1862 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1863 struct d2d_draw_text_layout_ctx *context = ctx;
1864 D2D1_POINT_2F start, end;
1865 ID2D1Brush *brush;
1866 float thickness;
1868 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
1869 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1871 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1872 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
1873 strikethrough->thickness);
1875 brush = d2d_draw_get_text_brush(context, effect);
1877 start.x = baseline_origin_x;
1878 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
1879 end.x = start.x + strikethrough->width;
1880 end.y = start.y;
1881 d2d_d3d_render_target_DrawLine(&render_target->ID2D1RenderTarget_iface, start, end, brush, thickness, NULL);
1883 ID2D1Brush_Release(brush);
1885 return S_OK;
1888 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1889 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1891 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1892 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1894 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1897 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1899 d2d_text_renderer_QueryInterface,
1900 d2d_text_renderer_AddRef,
1901 d2d_text_renderer_Release,
1902 d2d_text_renderer_IsPixelSnappingDisabled,
1903 d2d_text_renderer_GetCurrentTransform,
1904 d2d_text_renderer_GetPixelsPerDip,
1905 d2d_text_renderer_DrawGlyphRun,
1906 d2d_text_renderer_DrawUnderline,
1907 d2d_text_renderer_DrawStrikethrough,
1908 d2d_text_renderer_DrawInlineObject,
1911 static inline struct d2d_d3d_render_target *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
1913 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1GdiInteropRenderTarget_iface);
1916 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
1917 REFIID iid, void **out)
1919 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1921 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1923 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
1926 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
1928 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1930 TRACE("iface %p.\n", iface);
1932 return IUnknown_AddRef(render_target->outer_unknown);
1935 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
1937 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1939 TRACE("iface %p.\n", iface);
1941 return IUnknown_Release(render_target->outer_unknown);
1944 static HRESULT d2d_d3d_render_target_get_surface(struct d2d_d3d_render_target *render_target, IDXGISurface1 **surface)
1946 ID3D10Resource *resource;
1947 HRESULT hr;
1949 ID3D10RenderTargetView_GetResource(render_target->view, &resource);
1950 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
1951 ID3D10Resource_Release(resource);
1952 if (FAILED(hr))
1954 *surface = NULL;
1955 WARN("Failed to get DXGI surface, %#x.\n", hr);
1956 return hr;
1959 return hr;
1962 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
1963 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
1965 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1966 IDXGISurface1 *surface;
1967 HRESULT hr;
1969 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
1971 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
1972 return hr;
1974 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
1975 IDXGISurface1_Release(surface);
1977 return hr;
1980 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
1981 const RECT *update)
1983 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1984 IDXGISurface1 *surface;
1985 RECT update_rect;
1986 HRESULT hr;
1988 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
1990 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
1991 return hr;
1993 if (update)
1994 update_rect = *update;
1995 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
1996 IDXGISurface1_Release(surface);
1998 return hr;
2001 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2003 d2d_gdi_interop_render_target_QueryInterface,
2004 d2d_gdi_interop_render_target_AddRef,
2005 d2d_gdi_interop_render_target_Release,
2006 d2d_gdi_interop_render_target_GetDC,
2007 d2d_gdi_interop_render_target_ReleaseDC,
2010 static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
2011 IDXGISurface *surface, IUnknown *outer_unknown, const D2D1_RENDER_TARGET_PROPERTIES *desc)
2013 D3D10_SUBRESOURCE_DATA buffer_data;
2014 D3D10_STATE_BLOCK_MASK state_mask;
2015 DXGI_SURFACE_DESC surface_desc;
2016 IDWriteFactory *dwrite_factory;
2017 D3D10_RASTERIZER_DESC rs_desc;
2018 D3D10_BUFFER_DESC buffer_desc;
2019 D3D10_BLEND_DESC blend_desc;
2020 ID3D10Resource *resource;
2021 unsigned int i, j, k;
2022 HRESULT hr;
2024 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2026 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2027 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2028 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2030 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2032 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2034 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
2036 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2037 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2039 static const DWORD vs_code_outline[] =
2041 #if 0
2042 float3x2 transform_geometry;
2043 float stroke_width;
2044 float4 transform_rtx;
2045 float4 transform_rty;
2047 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2049 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2051 * Where:
2053 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2054 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2055 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2056 float4 main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT) : SV_POSITION
2058 float2 q_prev, q_next, v_p, q_i;
2059 float l;
2061 q_prev = float2(dot(prev, transform_geometry._11_21), dot(prev, transform_geometry._12_22));
2062 q_prev = normalize(q_prev);
2064 q_next = float2(dot(next, transform_geometry._11_21), dot(next, transform_geometry._12_22));
2065 q_next = normalize(q_next);
2067 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2068 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2069 v_p = float2(-q_prev.y, q_prev.x);
2070 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2071 q_i = l * q_prev + v_p;
2072 position = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2074 return float4(mul(float2x3(transform_rtx.xyz * transform_rtx.w, transform_rty.xyz * transform_rty.w),
2075 float3(position.xy, 1.0f)) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2077 #endif
2078 0x43425844, 0xe88f7af5, 0x480b101b, 0xfd80f66b, 0xd878e0b8, 0x00000001, 0x0000047c, 0x00000003,
2079 0x0000002c, 0x00000098, 0x000000cc, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2080 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2081 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2082 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x0000002c,
2083 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f,
2084 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x000003a8, 0x00010040, 0x000000ea, 0x04000059,
2085 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032,
2086 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
2087 0x02000068, 0x00000003, 0x0800000f, 0x00100012, 0x00000000, 0x00101046, 0x00000002, 0x00208046,
2088 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000002, 0x00208046,
2089 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
2090 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032,
2091 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001,
2092 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000001,
2093 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000,
2094 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a,
2095 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001,
2096 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042,
2097 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000,
2098 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a,
2099 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041,
2100 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000,
2101 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a,
2102 0x00000000, 0x00000001, 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046,
2103 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
2104 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
2105 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032,
2106 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x09000038,
2107 0x00100072, 0x00000001, 0x00208ff6, 0x00000000, 0x00000002, 0x00208246, 0x00000000, 0x00000002,
2108 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x07000010, 0x00100012, 0x00000001,
2109 0x00100246, 0x00000001, 0x00100246, 0x00000000, 0x09000038, 0x00100072, 0x00000002, 0x00208ff6,
2110 0x00000000, 0x00000003, 0x00208246, 0x00000000, 0x00000003, 0x07000010, 0x00100022, 0x00000001,
2111 0x00100246, 0x00000002, 0x00100246, 0x00000000, 0x0a000000, 0x00102032, 0x00000000, 0x00100046,
2112 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
2113 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
2115 static const DWORD vs_code_triangle[] =
2117 /* float3x2 transform;
2119 * float4 main(float4 position : POSITION) : SV_POSITION
2121 * return float4(mul(position.xyw, transform), position.zw);
2122 * } */
2123 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
2124 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2125 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
2126 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
2127 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
2128 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
2129 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
2130 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
2131 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
2132 0x00000000, 0x0100003e,
2134 static const DWORD vs_code_bezier[] =
2136 #if 0
2137 float3x2 transform;
2139 float4 main(float4 position : POSITION,
2140 inout float3 texcoord : TEXCOORD0) : SV_POSITION
2142 return float4(mul(position.xyw, transform), position.zw);
2144 #endif
2145 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
2146 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
2147 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
2148 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
2149 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
2150 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
2151 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
2152 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
2153 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
2154 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
2155 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
2156 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
2157 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
2159 static const DWORD ps_code_triangle_solid[] =
2161 /* float4 color;
2163 * float4 main(float4 position : SV_POSITION) : SV_Target
2165 * return color;
2166 * } */
2167 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
2168 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2169 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
2170 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2171 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
2172 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
2173 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2175 static const DWORD ps_code_triangle_solid_bitmap[] =
2177 #if 0
2178 float4 color;
2180 float3x2 transform;
2181 float opacity;
2182 bool ignore_alpha;
2184 SamplerState s;
2185 Texture2D t;
2187 float4 main(float4 position : SV_POSITION) : SV_Target
2189 float2 texcoord;
2190 float4 ret;
2192 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2193 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2194 ret = t.Sample(s, texcoord) * opacity;
2195 if (ignore_alpha)
2196 ret.a = opacity;
2198 return color * ret.a;
2200 #endif
2201 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
2202 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2203 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2204 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2205 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
2206 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
2207 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2208 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2209 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
2210 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
2211 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
2212 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
2213 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
2214 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
2215 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
2216 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
2217 0x00000000, 0x0100003e,
2219 static const DWORD ps_code_triangle_bitmap[] =
2221 #if 0
2222 float3x2 transform;
2223 float opacity;
2224 bool ignore_alpha;
2226 SamplerState s;
2227 Texture2D t;
2229 float4 main(float4 position : SV_POSITION) : SV_Target
2231 float2 texcoord;
2232 float4 ret;
2234 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2235 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2236 ret = t.Sample(s, texcoord) * opacity;
2237 if (ignore_alpha)
2238 ret.a = opacity;
2240 return ret;
2242 #endif
2243 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
2244 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2245 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2246 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2247 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
2248 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
2249 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2250 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2251 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
2252 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
2253 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
2254 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
2255 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
2256 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
2257 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
2258 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
2260 static const DWORD ps_code_triangle_bitmap_solid[] =
2262 #if 0
2263 float3x2 transform;
2264 float opacity;
2265 bool ignore_alpha;
2267 float4 color;
2269 SamplerState s;
2270 Texture2D t;
2272 float4 main(float4 position : SV_POSITION) : SV_Target
2274 float2 texcoord;
2275 float4 ret;
2277 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2278 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2279 ret = t.Sample(s, texcoord) * opacity;
2280 if (ignore_alpha)
2281 ret.a = opacity;
2283 return ret * color.a;
2285 #endif
2286 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
2287 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2288 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2289 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2290 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
2291 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
2292 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2293 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2294 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
2295 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
2296 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
2297 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
2298 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
2299 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
2300 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
2301 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
2302 0x00000003, 0x0100003e,
2304 static const DWORD ps_code_triangle_bitmap_bitmap[] =
2306 #if 0
2307 struct brush
2309 float3x2 transform;
2310 float opacity;
2311 bool ignore_alpha;
2312 } brush0, brush1;
2314 SamplerState s0, s1;
2315 Texture2D t0, t1;
2317 float4 main(float4 position : SV_POSITION) : SV_Target
2319 float2 texcoord;
2320 float opacity;
2321 float4 ret;
2323 texcoord.x = position.x * brush0.transform._11 + position.y * brush0.transform._21 + brush0.transform._31;
2324 texcoord.y = position.x * brush0.transform._12 + position.y * brush0.transform._22 + brush0.transform._32;
2325 ret = t0.Sample(s0, texcoord) * brush0.opacity;
2326 if (brush0.ignore_alpha)
2327 ret.a = brush0.opacity;
2329 texcoord.x = position.x * brush1.transform._11 + position.y * brush1.transform._21 + brush1.transform._31;
2330 texcoord.y = position.x * brush1.transform._12 + position.y * brush1.transform._22 + brush1.transform._32;
2331 opacity = t1.Sample(s1, texcoord).a * brush1.opacity;
2332 if (brush1.ignore_alpha)
2333 opacity = brush1.opacity;
2335 return ret * opacity;
2337 #endif
2338 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
2339 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2340 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2341 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2342 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
2343 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
2344 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
2345 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
2346 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
2347 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
2348 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
2349 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
2350 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
2351 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
2352 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
2353 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
2354 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
2355 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
2356 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
2357 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
2358 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
2359 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
2360 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
2361 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
2362 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
2364 /* The basic idea here is to evaluate the implicit form of the curve in
2365 * texture space. "t.z" determines which side of the curve is shaded. */
2366 static const DWORD ps_code_bezier_solid[] =
2368 #if 0
2369 float4 color;
2371 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
2373 clip((t.x * t.x - t.y) * t.z);
2374 return color;
2376 #endif
2377 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
2378 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
2379 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
2380 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
2381 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
2382 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
2383 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
2384 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
2385 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
2386 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
2387 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
2388 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2390 static const struct brush_shader
2392 const void *byte_code;
2393 size_t byte_code_size;
2394 enum d2d_shape_type shape_type;
2395 enum d2d_brush_type brush_type;
2396 enum d2d_brush_type opacity_brush_type;
2398 brush_shaders[] =
2400 {ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
2401 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2402 {ps_code_triangle_solid_bitmap, sizeof(ps_code_triangle_solid_bitmap),
2403 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_BITMAP},
2404 {ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
2405 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_COUNT},
2406 {ps_code_triangle_bitmap_solid, sizeof(ps_code_triangle_bitmap_solid),
2407 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_SOLID},
2408 {ps_code_triangle_bitmap_bitmap, sizeof(ps_code_triangle_bitmap_bitmap),
2409 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_BITMAP},
2410 {ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
2411 D2D_SHAPE_TYPE_BEZIER, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2413 static const struct
2415 float x, y;
2417 quad[] =
2419 {-1.0f, 1.0f},
2420 {-1.0f, -1.0f},
2421 { 1.0f, 1.0f},
2422 { 1.0f, -1.0f},
2424 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
2425 float dpi_x, dpi_y;
2427 dpi_x = desc->dpiX;
2428 dpi_y = desc->dpiY;
2430 if (dpi_x == 0.0f && dpi_y == 0.0f)
2432 dpi_x = 96.0f;
2433 dpi_y = 96.0f;
2435 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
2436 return E_INVALIDARG;
2438 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
2439 WARN("Ignoring render target type %#x.\n", desc->type);
2440 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
2441 FIXME("Ignoring render target usage %#x.\n", desc->usage);
2442 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
2443 WARN("Ignoring feature level %#x.\n", desc->minLevel);
2445 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
2446 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
2447 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
2448 render_target->refcount = 1;
2449 render_target->factory = factory;
2450 ID2D1Factory_AddRef(render_target->factory);
2452 render_target->outer_unknown = outer_unknown ? outer_unknown :
2453 (IUnknown *)&render_target->ID2D1RenderTarget_iface;
2455 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
2457 WARN("Failed to get device interface, hr %#x.\n", hr);
2458 ID2D1Factory_Release(render_target->factory);
2459 return hr;
2462 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2464 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2465 goto err;
2468 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
2469 ID3D10Resource_Release(resource);
2470 if (FAILED(hr))
2472 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2473 goto err;
2476 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
2478 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
2479 goto err;
2482 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
2484 WARN("Failed to create stateblock, hr %#x.\n", hr);
2485 goto err;
2488 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_outline,
2489 sizeof(il_desc_outline) / sizeof(*il_desc_outline), vs_code_outline, sizeof(vs_code_outline),
2490 &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE].il)))
2492 WARN("Failed to create outline input layout, hr %#x.\n", hr);
2493 goto err;
2496 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
2497 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
2498 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
2500 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
2501 goto err;
2504 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
2505 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
2506 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
2508 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
2509 goto err;
2512 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_outline,
2513 sizeof(vs_code_outline), &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE].vs)))
2515 WARN("Failed to create outline vertex shader, hr %#x.\n", hr);
2516 goto err;
2519 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
2520 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
2522 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
2523 goto err;
2526 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
2527 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
2529 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
2530 goto err;
2533 for (i = 0; i < sizeof(brush_shaders) / sizeof(*brush_shaders); ++i)
2535 const struct brush_shader *bs = &brush_shaders[i];
2536 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, bs->byte_code, bs->byte_code_size,
2537 &render_target->shape_resources[bs->shape_type].ps[bs->brush_type][bs->opacity_brush_type])))
2539 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
2540 bs->shape_type, bs->brush_type, bs->opacity_brush_type);
2541 goto err;
2545 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2547 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2549 struct d2d_shape_resources *outline = &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE];
2550 struct d2d_shape_resources *triangle = &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE];
2552 if (triangle->ps[j][k])
2553 ID3D10PixelShader_AddRef(outline->ps[j][k] = triangle->ps[j][k]);
2557 buffer_desc.ByteWidth = sizeof(indices);
2558 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
2559 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
2560 buffer_desc.CPUAccessFlags = 0;
2561 buffer_desc.MiscFlags = 0;
2563 buffer_data.pSysMem = indices;
2564 buffer_data.SysMemPitch = 0;
2565 buffer_data.SysMemSlicePitch = 0;
2567 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2568 &buffer_desc, &buffer_data, &render_target->ib)))
2570 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
2571 goto err;
2574 buffer_desc.ByteWidth = sizeof(quad);
2575 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
2576 buffer_data.pSysMem = quad;
2578 render_target->vb_stride = sizeof(*quad);
2579 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2580 &buffer_desc, &buffer_data, &render_target->vb)))
2582 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
2583 goto err;
2586 rs_desc.FillMode = D3D10_FILL_SOLID;
2587 rs_desc.CullMode = D3D10_CULL_NONE;
2588 rs_desc.FrontCounterClockwise = FALSE;
2589 rs_desc.DepthBias = 0;
2590 rs_desc.DepthBiasClamp = 0.0f;
2591 rs_desc.SlopeScaledDepthBias = 0.0f;
2592 rs_desc.DepthClipEnable = TRUE;
2593 rs_desc.ScissorEnable = TRUE;
2594 rs_desc.MultisampleEnable = FALSE;
2595 rs_desc.AntialiasedLineEnable = FALSE;
2596 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
2598 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
2599 goto err;
2602 memset(&blend_desc, 0, sizeof(blend_desc));
2603 blend_desc.BlendEnable[0] = TRUE;
2604 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2605 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2606 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2607 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2609 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2610 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2612 else
2614 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2615 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2617 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2618 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2619 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
2621 WARN("Failed to create blend state, hr %#x.\n", hr);
2622 goto err;
2625 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
2626 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
2628 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2629 goto err;
2632 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
2633 IDWriteFactory_Release(dwrite_factory);
2634 if (FAILED(hr))
2636 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
2637 goto err;
2640 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2642 WARN("Failed to get surface desc, hr %#x.\n", hr);
2643 goto err;
2646 render_target->desc.pixelFormat = desc->pixelFormat;
2647 render_target->pixel_size.width = surface_desc.Width;
2648 render_target->pixel_size.height = surface_desc.Height;
2649 render_target->drawing_state.transform = identity;
2651 if (!d2d_clip_stack_init(&render_target->clip_stack))
2653 WARN("Failed to initialize clip stack.\n");
2654 hr = E_FAIL;
2655 goto err;
2658 render_target->desc.dpiX = dpi_x;
2659 render_target->desc.dpiY = dpi_y;
2661 return S_OK;
2663 err:
2664 if (render_target->default_text_rendering_params)
2665 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
2666 if (render_target->bs)
2667 ID3D10BlendState_Release(render_target->bs);
2668 if (render_target->rs)
2669 ID3D10RasterizerState_Release(render_target->rs);
2670 if (render_target->vb)
2671 ID3D10Buffer_Release(render_target->vb);
2672 if (render_target->ib)
2673 ID3D10Buffer_Release(render_target->ib);
2674 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
2676 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2678 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2680 if (render_target->shape_resources[i].ps[j][k])
2681 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
2684 if (render_target->shape_resources[i].vs)
2685 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
2686 if (render_target->shape_resources[i].il)
2687 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
2689 if (render_target->stateblock)
2690 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
2691 if (render_target->view)
2692 ID3D10RenderTargetView_Release(render_target->view);
2693 if (render_target->device)
2694 ID3D10Device_Release(render_target->device);
2695 ID2D1Factory_Release(render_target->factory);
2696 return hr;
2699 HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown,
2700 const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target)
2702 struct d2d_d3d_render_target *object;
2703 HRESULT hr;
2705 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
2706 return E_OUTOFMEMORY;
2708 if (FAILED(hr = d2d_d3d_render_target_init(object, factory, surface, outer_unknown, desc)))
2710 WARN("Failed to initialize render target, hr %#x.\n", hr);
2711 HeapFree(GetProcessHeap(), 0, object);
2712 return hr;
2715 TRACE("Created render target %p.\n", object);
2716 *render_target = &object->ID2D1RenderTarget_iface;
2718 return S_OK;
2721 HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1 *surface)
2723 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
2724 DXGI_SURFACE_DESC surface_desc;
2725 ID3D10RenderTargetView *view;
2726 ID3D10Resource *resource;
2727 HRESULT hr;
2729 if (!surface)
2731 ID3D10RenderTargetView_Release(render_target->view);
2732 render_target->view = NULL;
2733 return S_OK;
2736 if (FAILED(hr = IDXGISurface1_GetDesc(surface, &surface_desc)))
2738 WARN("Failed to get surface desc, hr %#x.\n", hr);
2739 return hr;
2742 if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2744 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2745 return hr;
2748 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &view);
2749 ID3D10Resource_Release(resource);
2750 if (FAILED(hr))
2752 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2753 return hr;
2756 render_target->pixel_size.width = surface_desc.Width;
2757 render_target->pixel_size.height = surface_desc.Height;
2758 if (render_target->view)
2759 ID3D10RenderTargetView_Release(render_target->view);
2760 render_target->view = view;
2762 return S_OK;