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
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
=
35 struct d2d_draw_text_layout_ctx
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
)))
48 ID2D1Brush_AddRef(context
->brush
);
49 return context
->brush
;
52 static void d2d_rect_intersect(D2D1_RECT_F
*dst
, const D2D1_RECT_F
*src
)
54 if (src
->left
> dst
->left
)
55 dst
->left
= src
->left
;
56 if (src
->top
> dst
->top
)
58 if (src
->right
< dst
->right
)
59 dst
->right
= src
->right
;
60 if (src
->bottom
< dst
->bottom
)
61 dst
->bottom
= src
->bottom
;
64 static void d2d_rect_set(D2D1_RECT_F
*dst
, float left
, float top
, float right
, float bottom
)
72 static void d2d_size_set(D2D1_SIZE_U
*dst
, float width
, float height
)
78 static BOOL
d2d_clip_stack_init(struct d2d_clip_stack
*stack
)
80 if (!(stack
->stack
= HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE
* sizeof(*stack
->stack
))))
83 stack
->size
= INITIAL_CLIP_STACK_SIZE
;
89 static void d2d_clip_stack_cleanup(struct d2d_clip_stack
*stack
)
91 HeapFree(GetProcessHeap(), 0, stack
->stack
);
94 static BOOL
d2d_clip_stack_push(struct d2d_clip_stack
*stack
, const D2D1_RECT_F
*rect
)
98 if (stack
->count
== stack
->size
)
100 D2D1_RECT_F
*new_stack
;
101 unsigned int new_size
;
103 if (stack
->size
> UINT_MAX
/ 2)
106 new_size
= stack
->size
* 2;
107 if (!(new_stack
= HeapReAlloc(GetProcessHeap(), 0, stack
->stack
, new_size
* sizeof(*stack
->stack
))))
110 stack
->stack
= new_stack
;
111 stack
->size
= new_size
;
116 d2d_rect_intersect(&r
, &stack
->stack
[stack
->count
- 1]);
117 stack
->stack
[stack
->count
++] = r
;
122 static void d2d_clip_stack_pop(struct d2d_clip_stack
*stack
)
129 static void d2d_rt_draw(struct d2d_d3d_render_target
*render_target
, enum d2d_shape_type shape_type
,
130 ID3D10Buffer
*ib
, unsigned int index_count
, ID3D10Buffer
*vb
, unsigned int vb_stride
,
131 ID3D10Buffer
*vs_cb
, ID3D10Buffer
*ps_cb
, struct d2d_brush
*brush
, struct d2d_brush
*opacity_brush
)
133 struct d2d_shape_resources
*shape_resources
= &render_target
->shape_resources
[shape_type
];
134 ID3D10Device
*device
= render_target
->device
;
135 D3D10_RECT scissor_rect
;
142 vp
.Width
= render_target
->pixel_size
.width
;
143 vp
.Height
= render_target
->pixel_size
.height
;
147 if (FAILED(hr
= render_target
->stateblock
->lpVtbl
->Capture(render_target
->stateblock
)))
149 WARN("Failed to capture stateblock, hr %#x.\n", hr
);
153 ID3D10Device_ClearState(device
);
155 ID3D10Device_IASetInputLayout(device
, shape_resources
->il
);
156 ID3D10Device_IASetPrimitiveTopology(device
, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST
);
157 ID3D10Device_IASetIndexBuffer(device
, ib
, DXGI_FORMAT_R16_UINT
, 0);
159 ID3D10Device_IASetVertexBuffers(device
, 0, 1, &vb
, &vb_stride
, &offset
);
160 ID3D10Device_VSSetConstantBuffers(device
, 0, 1, &vs_cb
);
161 ID3D10Device_VSSetShader(device
, shape_resources
->vs
);
162 ID3D10Device_PSSetConstantBuffers(device
, 0, 1, &ps_cb
);
163 ID3D10Device_RSSetViewports(device
, 1, &vp
);
164 if (render_target
->clip_stack
.count
)
166 const D2D1_RECT_F
*clip_rect
;
168 clip_rect
= &render_target
->clip_stack
.stack
[render_target
->clip_stack
.count
- 1];
169 scissor_rect
.left
= clip_rect
->left
+ 0.5f
;
170 scissor_rect
.top
= clip_rect
->top
+ 0.5f
;
171 scissor_rect
.right
= clip_rect
->right
+ 0.5f
;
172 scissor_rect
.bottom
= clip_rect
->bottom
+ 0.5f
;
176 scissor_rect
.left
= 0.0f
;
177 scissor_rect
.top
= 0.0f
;
178 scissor_rect
.right
= render_target
->pixel_size
.width
;
179 scissor_rect
.bottom
= render_target
->pixel_size
.height
;
181 ID3D10Device_RSSetScissorRects(device
, 1, &scissor_rect
);
182 ID3D10Device_RSSetState(device
, render_target
->rs
);
183 ID3D10Device_OMSetRenderTargets(device
, 1, &render_target
->view
, NULL
);
185 d2d_brush_bind_resources(brush
, opacity_brush
, render_target
, shape_type
);
187 ID3D10Device_PSSetShader(device
, shape_resources
->ps
[D2D_BRUSH_TYPE_SOLID
][D2D_BRUSH_TYPE_COUNT
]);
190 ID3D10Device_DrawIndexed(device
, index_count
, 0, 0);
192 ID3D10Device_Draw(device
, index_count
, 0);
194 if (FAILED(hr
= render_target
->stateblock
->lpVtbl
->Apply(render_target
->stateblock
)))
195 WARN("Failed to apply stateblock, hr %#x.\n", hr
);
198 static inline struct d2d_d3d_render_target
*impl_from_ID2D1RenderTarget(ID2D1RenderTarget
*iface
)
200 return CONTAINING_RECORD(iface
, struct d2d_d3d_render_target
, ID2D1RenderTarget_iface
);
203 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget
*iface
, REFIID iid
, void **out
)
205 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
207 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
209 if (IsEqualGUID(iid
, &IID_ID2D1RenderTarget
)
210 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
211 || IsEqualGUID(iid
, &IID_IUnknown
))
213 ID2D1RenderTarget_AddRef(iface
);
217 else if (IsEqualGUID(iid
, &IID_ID2D1GdiInteropRenderTarget
))
219 ID2D1GdiInteropRenderTarget_AddRef(&render_target
->ID2D1GdiInteropRenderTarget_iface
);
220 *out
= &render_target
->ID2D1GdiInteropRenderTarget_iface
;
224 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
227 return E_NOINTERFACE
;
230 static ULONG STDMETHODCALLTYPE
d2d_d3d_render_target_AddRef(ID2D1RenderTarget
*iface
)
232 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
233 ULONG refcount
= InterlockedIncrement(&render_target
->refcount
);
235 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
240 static ULONG STDMETHODCALLTYPE
d2d_d3d_render_target_Release(ID2D1RenderTarget
*iface
)
242 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
243 ULONG refcount
= InterlockedDecrement(&render_target
->refcount
);
245 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
249 unsigned int i
, j
, k
;
251 d2d_clip_stack_cleanup(&render_target
->clip_stack
);
252 IDWriteRenderingParams_Release(render_target
->default_text_rendering_params
);
253 if (render_target
->text_rendering_params
)
254 IDWriteRenderingParams_Release(render_target
->text_rendering_params
);
255 ID3D10BlendState_Release(render_target
->bs
);
256 ID3D10RasterizerState_Release(render_target
->rs
);
257 ID3D10Buffer_Release(render_target
->vb
);
258 ID3D10Buffer_Release(render_target
->ib
);
259 for (i
= 0; i
< D2D_SHAPE_TYPE_COUNT
; ++i
)
261 for (j
= 0; j
< D2D_BRUSH_TYPE_COUNT
; ++j
)
263 for (k
= 0; k
< D2D_BRUSH_TYPE_COUNT
+ 1; ++k
)
265 if (render_target
->shape_resources
[i
].ps
[j
][k
])
266 ID3D10PixelShader_Release(render_target
->shape_resources
[i
].ps
[j
][k
]);
269 ID3D10VertexShader_Release(render_target
->shape_resources
[i
].vs
);
270 ID3D10InputLayout_Release(render_target
->shape_resources
[i
].il
);
272 render_target
->stateblock
->lpVtbl
->Release(render_target
->stateblock
);
273 ID3D10RenderTargetView_Release(render_target
->view
);
274 ID3D10Device_Release(render_target
->device
);
275 ID2D1Factory_Release(render_target
->factory
);
276 HeapFree(GetProcessHeap(), 0, render_target
);
282 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetFactory(ID2D1RenderTarget
*iface
, ID2D1Factory
**factory
)
284 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
286 TRACE("iface %p, factory %p.\n", iface
, factory
);
288 *factory
= render_target
->factory
;
289 ID2D1Factory_AddRef(*factory
);
292 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget
*iface
,
293 D2D1_SIZE_U size
, const void *src_data
, UINT32 pitch
, const D2D1_BITMAP_PROPERTIES
*desc
, ID2D1Bitmap
**bitmap
)
295 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
296 struct d2d_bitmap
*object
;
299 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
300 iface
, size
.width
, size
.height
, src_data
, pitch
, desc
, bitmap
);
302 if (SUCCEEDED(hr
= d2d_bitmap_create(render_target
->factory
, render_target
->device
, size
, src_data
, pitch
, desc
, &object
)))
303 *bitmap
= &object
->ID2D1Bitmap_iface
;
308 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget
*iface
,
309 IWICBitmapSource
*bitmap_source
, const D2D1_BITMAP_PROPERTIES
*desc
, ID2D1Bitmap
**bitmap
)
311 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
312 struct d2d_bitmap
*object
;
315 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
316 iface
, bitmap_source
, desc
, bitmap
);
318 if (SUCCEEDED(hr
= d2d_bitmap_create_from_wic_bitmap(render_target
->factory
, render_target
->device
, bitmap_source
,
320 *bitmap
= &object
->ID2D1Bitmap_iface
;
325 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget
*iface
,
326 REFIID iid
, void *data
, const D2D1_BITMAP_PROPERTIES
*desc
, ID2D1Bitmap
**bitmap
)
328 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
329 struct d2d_bitmap
*object
;
332 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
333 iface
, debugstr_guid(iid
), data
, desc
, bitmap
);
335 if (SUCCEEDED(hr
= d2d_bitmap_create_shared(iface
, render_target
->device
, iid
, data
, desc
, &object
)))
336 *bitmap
= &object
->ID2D1Bitmap_iface
;
341 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget
*iface
,
342 ID2D1Bitmap
*bitmap
, const D2D1_BITMAP_BRUSH_PROPERTIES
*bitmap_brush_desc
,
343 const D2D1_BRUSH_PROPERTIES
*brush_desc
, ID2D1BitmapBrush
**brush
)
345 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
346 struct d2d_brush
*object
;
349 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
350 iface
, bitmap
, bitmap_brush_desc
, brush_desc
, brush
);
352 if (SUCCEEDED(hr
= d2d_bitmap_brush_create(render_target
->factory
, bitmap
, bitmap_brush_desc
, brush_desc
, &object
)))
353 *brush
= (ID2D1BitmapBrush
*)&object
->ID2D1Brush_iface
;
358 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget
*iface
,
359 const D2D1_COLOR_F
*color
, const D2D1_BRUSH_PROPERTIES
*desc
, ID2D1SolidColorBrush
**brush
)
361 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
362 struct d2d_brush
*object
;
365 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface
, color
, desc
, brush
);
367 if (SUCCEEDED(hr
= d2d_solid_color_brush_create(render_target
->factory
, color
, desc
, &object
)))
368 *brush
= (ID2D1SolidColorBrush
*)&object
->ID2D1Brush_iface
;
373 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget
*iface
,
374 const D2D1_GRADIENT_STOP
*stops
, UINT32 stop_count
, D2D1_GAMMA gamma
, D2D1_EXTEND_MODE extend_mode
,
375 ID2D1GradientStopCollection
**gradient
)
377 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
378 struct d2d_gradient
*object
;
381 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
382 iface
, stops
, stop_count
, gamma
, extend_mode
, gradient
);
384 if (SUCCEEDED(hr
= d2d_gradient_create(render_target
->factory
, stops
, stop_count
, gamma
, extend_mode
, &object
)))
385 *gradient
= &object
->ID2D1GradientStopCollection_iface
;
390 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget
*iface
,
391 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES
*gradient_brush_desc
, const D2D1_BRUSH_PROPERTIES
*brush_desc
,
392 ID2D1GradientStopCollection
*gradient
, ID2D1LinearGradientBrush
**brush
)
394 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
395 struct d2d_brush
*object
;
398 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
399 iface
, gradient_brush_desc
, brush_desc
, gradient
, brush
);
401 if (SUCCEEDED(hr
= d2d_linear_gradient_brush_create(render_target
->factory
, gradient_brush_desc
, brush_desc
,
403 *brush
= (ID2D1LinearGradientBrush
*)&object
->ID2D1Brush_iface
;
408 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget
*iface
,
409 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES
*gradient_brush_desc
, const D2D1_BRUSH_PROPERTIES
*brush_desc
,
410 ID2D1GradientStopCollection
*gradient
, ID2D1RadialGradientBrush
**brush
)
412 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
413 iface
, gradient_brush_desc
, brush_desc
, gradient
, brush
);
418 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget
*iface
,
419 const D2D1_SIZE_F
*size
, const D2D1_SIZE_U
*pixel_size
, const D2D1_PIXEL_FORMAT
*format
,
420 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options
, ID2D1BitmapRenderTarget
**rt
)
422 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
423 struct d2d_bitmap_render_target
*object
;
426 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
427 iface
, size
, pixel_size
, format
, options
, rt
);
429 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
430 return E_OUTOFMEMORY
;
432 if (FAILED(hr
= d2d_bitmap_render_target_init(object
, render_target
, size
, pixel_size
,
435 WARN("Failed to initialize render target, hr %#x.\n", hr
);
436 HeapFree(GetProcessHeap(), 0, object
);
440 TRACE("Created render target %p.\n", object
);
441 *rt
= &object
->ID2D1BitmapRenderTarget_iface
;
446 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget
*iface
,
447 const D2D1_SIZE_F
*size
, ID2D1Layer
**layer
)
449 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
450 struct d2d_layer
*object
;
453 TRACE("iface %p, size %p, layer %p.\n", iface
, size
, layer
);
455 if (SUCCEEDED(hr
= d2d_layer_create(render_target
->factory
, size
, &object
)))
456 *layer
= &object
->ID2D1Layer_iface
;
461 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget
*iface
, ID2D1Mesh
**mesh
)
463 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
464 struct d2d_mesh
*object
;
467 TRACE("iface %p, mesh %p.\n", iface
, mesh
);
469 if (SUCCEEDED(hr
= d2d_mesh_create(render_target
->factory
, &object
)))
470 *mesh
= &object
->ID2D1Mesh_iface
;
475 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawLine(ID2D1RenderTarget
*iface
,
476 D2D1_POINT_2F p0
, D2D1_POINT_2F p1
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
478 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
479 ID2D1PathGeometry
*geometry
;
480 ID2D1GeometrySink
*sink
;
483 TRACE("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p.\n",
484 iface
, p0
.x
, p0
.y
, p1
.x
, p1
.y
, brush
, stroke_width
, stroke_style
);
486 if (FAILED(hr
= ID2D1Factory_CreatePathGeometry(render_target
->factory
, &geometry
)))
488 WARN("Failed to create path geometry, %#x.\n", hr
);
492 if (FAILED(hr
= ID2D1PathGeometry_Open(geometry
, &sink
)))
494 WARN("Open() failed, %#x.\n", hr
);
495 ID2D1PathGeometry_Release(geometry
);
499 ID2D1GeometrySink_BeginFigure(sink
, p0
, D2D1_FIGURE_BEGIN_HOLLOW
);
500 ID2D1GeometrySink_AddLine(sink
, p1
);
501 ID2D1GeometrySink_EndFigure(sink
, D2D1_FIGURE_END_OPEN
);
502 if (FAILED(hr
= ID2D1GeometrySink_Close(sink
)))
503 WARN("Close() failed, %#x.\n", hr
);
504 ID2D1GeometrySink_Release(sink
);
506 ID2D1RenderTarget_DrawGeometry(iface
, (ID2D1Geometry
*)geometry
, brush
, stroke_width
, stroke_style
);
507 ID2D1PathGeometry_Release(geometry
);
510 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget
*iface
,
511 const D2D1_RECT_F
*rect
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
513 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
514 ID2D1RectangleGeometry
*geometry
;
517 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
518 iface
, debug_d2d_rect_f(rect
), brush
, stroke_width
, stroke_style
);
520 if (FAILED(hr
= ID2D1Factory_CreateRectangleGeometry(render_target
->factory
, rect
, &geometry
)))
522 ERR("Failed to create geometry, hr %#x.\n", hr
);
526 ID2D1RenderTarget_DrawGeometry(iface
, (ID2D1Geometry
*)geometry
, brush
, stroke_width
, stroke_style
);
527 ID2D1RectangleGeometry_Release(geometry
);
530 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget
*iface
,
531 const D2D1_RECT_F
*rect
, ID2D1Brush
*brush
)
533 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
534 ID2D1RectangleGeometry
*geometry
;
537 TRACE("iface %p, rect %s, brush %p.\n", iface
, debug_d2d_rect_f(rect
), brush
);
539 if (FAILED(hr
= ID2D1Factory_CreateRectangleGeometry(render_target
->factory
, rect
, &geometry
)))
541 ERR("Failed to create geometry, hr %#x.\n", hr
);
545 ID2D1RenderTarget_FillGeometry(iface
, (ID2D1Geometry
*)geometry
, brush
, NULL
);
546 ID2D1RectangleGeometry_Release(geometry
);
549 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget
*iface
,
550 const D2D1_ROUNDED_RECT
*rect
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
552 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
553 ID2D1RoundedRectangleGeometry
*geometry
;
556 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
557 iface
, rect
, brush
, stroke_width
, stroke_style
);
559 if (FAILED(hr
= ID2D1Factory_CreateRoundedRectangleGeometry(render_target
->factory
, rect
, &geometry
)))
561 ERR("Failed to create geometry, hr %#x.\n", hr
);
565 ID2D1RenderTarget_DrawGeometry(iface
, (ID2D1Geometry
*)geometry
, brush
, stroke_width
, stroke_style
);
566 ID2D1RoundedRectangleGeometry_Release(geometry
);
569 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget
*iface
,
570 const D2D1_ROUNDED_RECT
*rect
, ID2D1Brush
*brush
)
572 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
573 ID2D1RoundedRectangleGeometry
*geometry
;
576 TRACE("iface %p, rect %p, brush %p.\n", iface
, rect
, brush
);
578 if (FAILED(hr
= ID2D1Factory_CreateRoundedRectangleGeometry(render_target
->factory
, rect
, &geometry
)))
580 ERR("Failed to create geometry, hr %#x.\n", hr
);
584 ID2D1RenderTarget_FillGeometry(iface
, (ID2D1Geometry
*)geometry
, brush
, NULL
);
585 ID2D1RoundedRectangleGeometry_Release(geometry
);
588 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget
*iface
,
589 const D2D1_ELLIPSE
*ellipse
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
591 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
592 ID2D1EllipseGeometry
*geometry
;
595 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
596 iface
, ellipse
, brush
, stroke_width
, stroke_style
);
598 if (FAILED(hr
= ID2D1Factory_CreateEllipseGeometry(render_target
->factory
, ellipse
, &geometry
)))
600 ERR("Failed to create geometry, hr %#x.\n", hr
);
604 ID2D1RenderTarget_DrawGeometry(iface
, (ID2D1Geometry
*)geometry
, brush
, stroke_width
, stroke_style
);
605 ID2D1EllipseGeometry_Release(geometry
);
608 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget
*iface
,
609 const D2D1_ELLIPSE
*ellipse
, ID2D1Brush
*brush
)
611 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
612 ID2D1EllipseGeometry
*geometry
;
615 TRACE("iface %p, ellipse %p, brush %p.\n", iface
, ellipse
, brush
);
617 if (FAILED(hr
= ID2D1Factory_CreateEllipseGeometry(render_target
->factory
, ellipse
, &geometry
)))
619 ERR("Failed to create geometry, hr %#x.\n", hr
);
623 ID2D1RenderTarget_FillGeometry(iface
, (ID2D1Geometry
*)geometry
, brush
, NULL
);
624 ID2D1EllipseGeometry_Release(geometry
);
627 static void d2d_rt_draw_geometry(struct d2d_d3d_render_target
*render_target
,
628 const struct d2d_geometry
*geometry
, struct d2d_brush
*brush
, float stroke_width
)
630 ID3D10Buffer
*ib
, *vb
, *vs_cb
, *ps_cb
;
631 D3D10_SUBRESOURCE_DATA buffer_data
;
632 D3D10_BUFFER_DESC buffer_desc
;
633 const D2D1_MATRIX_3X2_F
*w
;
640 float _11
, _21
, _31
, pad0
;
641 float _12
, _22
, _32
, stroke_width
;
642 } transform_geometry
;
643 struct d2d_vec4 transform_rtx
;
644 struct d2d_vec4 transform_rty
;
647 vs_cb_data
.transform_geometry
._11
= geometry
->transform
._11
;
648 vs_cb_data
.transform_geometry
._21
= geometry
->transform
._21
;
649 vs_cb_data
.transform_geometry
._31
= geometry
->transform
._31
;
650 vs_cb_data
.transform_geometry
.pad0
= 0.0f
;
651 vs_cb_data
.transform_geometry
._12
= geometry
->transform
._12
;
652 vs_cb_data
.transform_geometry
._22
= geometry
->transform
._22
;
653 vs_cb_data
.transform_geometry
._32
= geometry
->transform
._32
;
654 vs_cb_data
.transform_geometry
.stroke_width
= stroke_width
;
656 w
= &render_target
->drawing_state
.transform
;
658 tmp_x
= render_target
->desc
.dpiX
/ 96.0f
;
659 vs_cb_data
.transform_rtx
.x
= w
->_11
* tmp_x
;
660 vs_cb_data
.transform_rtx
.y
= w
->_21
* tmp_x
;
661 vs_cb_data
.transform_rtx
.z
= w
->_31
* tmp_x
;
662 vs_cb_data
.transform_rtx
.w
= 2.0f
/ render_target
->pixel_size
.width
;
664 tmp_y
= render_target
->desc
.dpiY
/ 96.0f
;
665 vs_cb_data
.transform_rty
.x
= w
->_12
* tmp_y
;
666 vs_cb_data
.transform_rty
.y
= w
->_22
* tmp_y
;
667 vs_cb_data
.transform_rty
.z
= w
->_32
* tmp_y
;
668 vs_cb_data
.transform_rty
.w
= -2.0f
/ render_target
->pixel_size
.height
;
670 buffer_desc
.ByteWidth
= sizeof(vs_cb_data
);
671 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
672 buffer_desc
.BindFlags
= D3D10_BIND_CONSTANT_BUFFER
;
673 buffer_desc
.CPUAccessFlags
= 0;
674 buffer_desc
.MiscFlags
= 0;
676 buffer_data
.pSysMem
= &vs_cb_data
;
677 buffer_data
.SysMemPitch
= 0;
678 buffer_data
.SysMemSlicePitch
= 0;
680 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vs_cb
)))
682 WARN("Failed to create constant buffer, hr %#x.\n", hr
);
686 if (FAILED(hr
= d2d_brush_get_ps_cb(brush
, NULL
, render_target
, &ps_cb
)))
688 WARN("Failed to get ps constant buffer, hr %#x.\n", hr
);
689 ID3D10Buffer_Release(vs_cb
);
693 if (geometry
->outline
.face_count
)
695 buffer_desc
.ByteWidth
= geometry
->outline
.face_count
* sizeof(*geometry
->outline
.faces
);
696 buffer_desc
.BindFlags
= D3D10_BIND_INDEX_BUFFER
;
697 buffer_data
.pSysMem
= geometry
->outline
.faces
;
699 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &ib
)))
701 WARN("Failed to create index buffer, hr %#x.\n", hr
);
705 buffer_desc
.ByteWidth
= geometry
->outline
.vertex_count
* sizeof(*geometry
->outline
.vertices
);
706 buffer_desc
.BindFlags
= D3D10_BIND_VERTEX_BUFFER
;
707 buffer_data
.pSysMem
= geometry
->outline
.vertices
;
709 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vb
)))
711 ERR("Failed to create vertex buffer, hr %#x.\n", hr
);
712 ID3D10Buffer_Release(ib
);
716 d2d_rt_draw(render_target
, D2D_SHAPE_TYPE_OUTLINE
, ib
, 3 * geometry
->outline
.face_count
, vb
,
717 sizeof(*geometry
->outline
.vertices
), vs_cb
, ps_cb
, brush
, NULL
);
719 ID3D10Buffer_Release(vb
);
720 ID3D10Buffer_Release(ib
);
723 if (geometry
->outline
.bezier_face_count
)
725 buffer_desc
.ByteWidth
= geometry
->outline
.bezier_face_count
* sizeof(*geometry
->outline
.bezier_faces
);
726 buffer_desc
.BindFlags
= D3D10_BIND_INDEX_BUFFER
;
727 buffer_data
.pSysMem
= geometry
->outline
.bezier_faces
;
729 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &ib
)))
731 WARN("Failed to create beziers index buffer, hr %#x.\n", hr
);
735 buffer_desc
.ByteWidth
= geometry
->outline
.bezier_count
* sizeof(*geometry
->outline
.beziers
);
736 buffer_desc
.BindFlags
= D3D10_BIND_VERTEX_BUFFER
;
737 buffer_data
.pSysMem
= geometry
->outline
.beziers
;
739 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vb
)))
741 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr
);
742 ID3D10Buffer_Release(ib
);
746 d2d_rt_draw(render_target
, D2D_SHAPE_TYPE_BEZIER_OUTLINE
, ib
, 3 * geometry
->outline
.bezier_face_count
, vb
,
747 sizeof(*geometry
->outline
.beziers
), vs_cb
, ps_cb
, brush
, NULL
);
749 ID3D10Buffer_Release(vb
);
750 ID3D10Buffer_Release(ib
);
754 ID3D10Buffer_Release(ps_cb
);
755 ID3D10Buffer_Release(vs_cb
);
758 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget
*iface
,
759 ID2D1Geometry
*geometry
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
761 const struct d2d_geometry
*geometry_impl
= unsafe_impl_from_ID2D1Geometry(geometry
);
762 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
763 struct d2d_brush
*brush_impl
= unsafe_impl_from_ID2D1Brush(brush
);
765 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
766 iface
, geometry
, brush
, stroke_width
, stroke_style
);
769 FIXME("Ignoring stoke style %p.\n", stroke_style
);
771 d2d_rt_draw_geometry(render_target
, geometry_impl
, brush_impl
, stroke_width
);
774 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target
*render_target
,
775 const struct d2d_geometry
*geometry
, struct d2d_brush
*brush
, struct d2d_brush
*opacity_brush
)
777 ID3D10Buffer
*ib
, *vb
, *vs_cb
, *ps_cb
;
778 D3D10_SUBRESOURCE_DATA buffer_data
;
779 D3D10_BUFFER_DESC buffer_desc
;
780 D2D1_MATRIX_3X2_F w
, g
;
785 float _11
, _21
, _31
, pad0
;
786 float _12
, _22
, _32
, pad1
;
789 tmp_x
= (2.0f
* render_target
->desc
.dpiX
) / (96.0f
* render_target
->pixel_size
.width
);
790 tmp_y
= -(2.0f
* render_target
->desc
.dpiY
) / (96.0f
* render_target
->pixel_size
.height
);
791 w
= render_target
->drawing_state
.transform
;
794 w
._31
= w
._31
* tmp_x
- 1.0f
;
797 w
._32
= w
._32
* tmp_y
+ 1.0f
;
799 g
= geometry
->transform
;
800 d2d_matrix_multiply(&g
, &w
);
802 transform
._11
= g
._11
;
803 transform
._21
= g
._21
;
804 transform
._31
= g
._31
;
805 transform
.pad0
= 0.0f
;
806 transform
._12
= g
._12
;
807 transform
._22
= g
._22
;
808 transform
._32
= g
._32
;
809 transform
.pad1
= 0.0f
;
811 buffer_desc
.ByteWidth
= sizeof(transform
);
812 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
813 buffer_desc
.BindFlags
= D3D10_BIND_CONSTANT_BUFFER
;
814 buffer_desc
.CPUAccessFlags
= 0;
815 buffer_desc
.MiscFlags
= 0;
817 buffer_data
.pSysMem
= &transform
;
818 buffer_data
.SysMemPitch
= 0;
819 buffer_data
.SysMemSlicePitch
= 0;
821 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vs_cb
)))
823 WARN("Failed to create constant buffer, hr %#x.\n", hr
);
827 if (FAILED(hr
= d2d_brush_get_ps_cb(brush
, opacity_brush
, render_target
, &ps_cb
)))
829 WARN("Failed to get ps constant buffer, hr %#x.\n", hr
);
830 ID3D10Buffer_Release(vs_cb
);
834 if (geometry
->fill
.face_count
)
836 buffer_desc
.ByteWidth
= geometry
->fill
.face_count
* sizeof(*geometry
->fill
.faces
);
837 buffer_desc
.BindFlags
= D3D10_BIND_INDEX_BUFFER
;
838 buffer_data
.pSysMem
= geometry
->fill
.faces
;
840 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &ib
)))
842 WARN("Failed to create index buffer, hr %#x.\n", hr
);
846 buffer_desc
.ByteWidth
= geometry
->fill
.vertex_count
* sizeof(*geometry
->fill
.vertices
);
847 buffer_desc
.BindFlags
= D3D10_BIND_VERTEX_BUFFER
;
848 buffer_data
.pSysMem
= geometry
->fill
.vertices
;
850 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vb
)))
852 ERR("Failed to create vertex buffer, hr %#x.\n", hr
);
853 ID3D10Buffer_Release(ib
);
857 d2d_rt_draw(render_target
, D2D_SHAPE_TYPE_TRIANGLE
, ib
, 3 * geometry
->fill
.face_count
, vb
,
858 sizeof(*geometry
->fill
.vertices
), vs_cb
, ps_cb
, brush
, opacity_brush
);
860 ID3D10Buffer_Release(vb
);
861 ID3D10Buffer_Release(ib
);
864 if (geometry
->fill
.bezier_vertex_count
)
866 buffer_desc
.ByteWidth
= geometry
->fill
.bezier_vertex_count
* sizeof(*geometry
->fill
.bezier_vertices
);
867 buffer_data
.pSysMem
= geometry
->fill
.bezier_vertices
;
869 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vb
)))
871 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr
);
875 d2d_rt_draw(render_target
, D2D_SHAPE_TYPE_BEZIER
, NULL
, geometry
->fill
.bezier_vertex_count
, vb
,
876 sizeof(*geometry
->fill
.bezier_vertices
), vs_cb
, ps_cb
, brush
, opacity_brush
);
878 ID3D10Buffer_Release(vb
);
882 ID3D10Buffer_Release(ps_cb
);
883 ID3D10Buffer_Release(vs_cb
);
886 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget
*iface
,
887 ID2D1Geometry
*geometry
, ID2D1Brush
*brush
, ID2D1Brush
*opacity_brush
)
889 const struct d2d_geometry
*geometry_impl
= unsafe_impl_from_ID2D1Geometry(geometry
);
890 struct d2d_brush
*opacity_brush_impl
= unsafe_impl_from_ID2D1Brush(opacity_brush
);
891 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
892 struct d2d_brush
*brush_impl
= unsafe_impl_from_ID2D1Brush(brush
);
894 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface
, geometry
, brush
, opacity_brush
);
896 if (FAILED(render_target
->error
.code
))
899 if (opacity_brush
&& brush_impl
->type
!= D2D_BRUSH_TYPE_BITMAP
)
901 render_target
->error
.code
= D2DERR_INCOMPATIBLE_BRUSH_TYPES
;
902 render_target
->error
.tag1
= render_target
->drawing_state
.tag1
;
903 render_target
->error
.tag2
= render_target
->drawing_state
.tag2
;
907 d2d_rt_fill_geometry(render_target
, geometry_impl
, brush_impl
, opacity_brush_impl
);
910 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillMesh(ID2D1RenderTarget
*iface
,
911 ID2D1Mesh
*mesh
, ID2D1Brush
*brush
)
913 FIXME("iface %p, mesh %p, brush %p stub!\n", iface
, mesh
, brush
);
916 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget
*iface
,
917 ID2D1Bitmap
*mask
, ID2D1Brush
*brush
, D2D1_OPACITY_MASK_CONTENT content
,
918 const D2D1_RECT_F
*dst_rect
, const D2D1_RECT_F
*src_rect
)
920 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
921 iface
, mask
, brush
, content
, debug_d2d_rect_f(dst_rect
), debug_d2d_rect_f(src_rect
));
924 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget
*iface
,
925 ID2D1Bitmap
*bitmap
, const D2D1_RECT_F
*dst_rect
, float opacity
,
926 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode
, const D2D1_RECT_F
*src_rect
)
928 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc
;
929 D2D1_BRUSH_PROPERTIES brush_desc
;
930 ID2D1BitmapBrush
*brush
;
934 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
935 iface
, bitmap
, debug_d2d_rect_f(dst_rect
), opacity
, interpolation_mode
, debug_d2d_rect_f(src_rect
));
945 size
= ID2D1Bitmap_GetSize(bitmap
);
948 s
.right
= size
.width
;
949 s
.bottom
= size
.height
;
960 d
.right
= s
.right
- s
.left
;
961 d
.bottom
= s
.bottom
- s
.top
;
964 bitmap_brush_desc
.extendModeX
= D2D1_EXTEND_MODE_CLAMP
;
965 bitmap_brush_desc
.extendModeY
= D2D1_EXTEND_MODE_CLAMP
;
966 bitmap_brush_desc
.interpolationMode
= interpolation_mode
;
968 brush_desc
.opacity
= opacity
;
969 brush_desc
.transform
._11
= fabsf((d
.right
- d
.left
) / (s
.right
- s
.left
));
970 brush_desc
.transform
._21
= 0.0f
;
971 brush_desc
.transform
._31
= min(d
.left
, d
.right
) - min(s
.left
, s
.right
) * brush_desc
.transform
._11
;
972 brush_desc
.transform
._12
= 0.0f
;
973 brush_desc
.transform
._22
= fabsf((d
.bottom
- d
.top
) / (s
.bottom
- s
.top
));
974 brush_desc
.transform
._32
= min(d
.top
, d
.bottom
) - min(s
.top
, s
.bottom
) * brush_desc
.transform
._22
;
976 if (FAILED(hr
= ID2D1RenderTarget_CreateBitmapBrush(iface
, bitmap
, &bitmap_brush_desc
, &brush_desc
, &brush
)))
978 ERR("Failed to create bitmap brush, hr %#x.\n", hr
);
982 ID2D1RenderTarget_FillRectangle(iface
, &d
, (ID2D1Brush
*)brush
);
983 ID2D1BitmapBrush_Release(brush
);
986 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawText(ID2D1RenderTarget
*iface
,
987 const WCHAR
*string
, UINT32 string_len
, IDWriteTextFormat
*text_format
, const D2D1_RECT_F
*layout_rect
,
988 ID2D1Brush
*brush
, D2D1_DRAW_TEXT_OPTIONS options
, DWRITE_MEASURING_MODE measuring_mode
)
990 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
991 IDWriteTextLayout
*text_layout
;
992 IDWriteFactory
*dwrite_factory
;
993 D2D1_POINT_2F origin
;
996 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
997 "brush %p, options %#x, measuring_mode %#x.\n",
998 iface
, debugstr_wn(string
, string_len
), string_len
, text_format
, debug_d2d_rect_f(layout_rect
),
999 brush
, options
, measuring_mode
);
1001 if (FAILED(hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
,
1002 &IID_IDWriteFactory
, (IUnknown
**)&dwrite_factory
)))
1004 ERR("Failed to create dwrite factory, hr %#x.\n", hr
);
1008 if (measuring_mode
== DWRITE_MEASURING_MODE_NATURAL
)
1009 hr
= IDWriteFactory_CreateTextLayout(dwrite_factory
, string
, string_len
, text_format
,
1010 layout_rect
->right
- layout_rect
->left
, layout_rect
->bottom
- layout_rect
->top
, &text_layout
);
1012 hr
= IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory
, string
, string_len
, text_format
,
1013 layout_rect
->right
- layout_rect
->left
, layout_rect
->bottom
- layout_rect
->top
, render_target
->desc
.dpiX
/ 96.0f
,
1014 (DWRITE_MATRIX
*)&render_target
->drawing_state
.transform
, measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, &text_layout
);
1015 IDWriteFactory_Release(dwrite_factory
);
1018 ERR("Failed to create text layout, hr %#x.\n", hr
);
1022 d2d_point_set(&origin
, layout_rect
->left
, layout_rect
->top
);
1023 ID2D1RenderTarget_DrawTextLayout(iface
, origin
, text_layout
, brush
, options
);
1024 IDWriteTextLayout_Release(text_layout
);
1027 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget
*iface
,
1028 D2D1_POINT_2F origin
, IDWriteTextLayout
*layout
, ID2D1Brush
*brush
, D2D1_DRAW_TEXT_OPTIONS options
)
1030 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1031 struct d2d_draw_text_layout_ctx ctx
;
1034 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
1035 iface
, origin
.x
, origin
.y
, layout
, brush
, options
);
1038 ctx
.options
= options
;
1040 if (FAILED(hr
= IDWriteTextLayout_Draw(layout
,
1041 &ctx
, &render_target
->IDWriteTextRenderer_iface
, origin
.x
, origin
.y
)))
1042 FIXME("Failed to draw text layout, hr %#x.\n", hr
);
1045 static D2D1_ANTIALIAS_MODE
d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(struct d2d_d3d_render_target
*rt
)
1047 D2D1_ANTIALIAS_MODE prev_antialias_mode
= rt
->drawing_state
.antialiasMode
;
1048 rt
->drawing_state
.antialiasMode
= rt
->drawing_state
.textAntialiasMode
== D2D1_TEXT_ANTIALIAS_MODE_ALIASED
?
1049 D2D1_ANTIALIAS_MODE_ALIASED
: D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
;
1050 return prev_antialias_mode
;
1053 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target
*render_target
,
1054 D2D1_POINT_2F baseline_origin
, const DWRITE_GLYPH_RUN
*glyph_run
, ID2D1Brush
*brush
)
1056 D2D1_MATRIX_3X2_F
*transform
, prev_transform
;
1057 D2D1_ANTIALIAS_MODE prev_antialias_mode
;
1058 ID2D1PathGeometry
*geometry
;
1059 ID2D1GeometrySink
*sink
;
1062 if (FAILED(hr
= ID2D1Factory_CreatePathGeometry(render_target
->factory
, &geometry
)))
1064 ERR("Failed to create geometry, hr %#x.\n", hr
);
1068 if (FAILED(hr
= ID2D1PathGeometry_Open(geometry
, &sink
)))
1070 ERR("Failed to open geometry sink, hr %#x.\n", hr
);
1071 ID2D1PathGeometry_Release(geometry
);
1075 if (FAILED(hr
= IDWriteFontFace_GetGlyphRunOutline(glyph_run
->fontFace
, glyph_run
->fontEmSize
,
1076 glyph_run
->glyphIndices
, glyph_run
->glyphAdvances
, glyph_run
->glyphOffsets
, glyph_run
->glyphCount
,
1077 glyph_run
->isSideways
, glyph_run
->bidiLevel
& 1, (IDWriteGeometrySink
*)sink
)))
1079 ERR("Failed to get glyph run outline, hr %#x.\n", hr
);
1080 ID2D1GeometrySink_Release(sink
);
1081 ID2D1PathGeometry_Release(geometry
);
1085 if (FAILED(hr
= ID2D1GeometrySink_Close(sink
)))
1086 ERR("Failed to close geometry sink, hr %#x.\n", hr
);
1087 ID2D1GeometrySink_Release(sink
);
1089 transform
= &render_target
->drawing_state
.transform
;
1090 prev_transform
= *transform
;
1091 transform
->_31
+= baseline_origin
.x
* transform
->_11
+ baseline_origin
.y
* transform
->_21
;
1092 transform
->_32
+= baseline_origin
.x
* transform
->_12
+ baseline_origin
.y
* transform
->_22
;
1093 prev_antialias_mode
= d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target
);
1094 d2d_rt_fill_geometry(render_target
, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry
*)geometry
),
1095 unsafe_impl_from_ID2D1Brush(brush
), NULL
);
1096 render_target
->drawing_state
.antialiasMode
= prev_antialias_mode
;
1097 *transform
= prev_transform
;
1099 ID2D1PathGeometry_Release(geometry
);
1102 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target
*render_target
,
1103 D2D1_POINT_2F baseline_origin
, const DWRITE_GLYPH_RUN
*glyph_run
, ID2D1Brush
*brush
,
1104 float ppd
, DWRITE_RENDERING_MODE rendering_mode
, DWRITE_MEASURING_MODE measuring_mode
,
1105 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode
)
1107 D2D1_MATRIX_3X2_F prev_transform
, *transform
;
1108 ID2D1RectangleGeometry
*geometry
= NULL
;
1109 ID2D1BitmapBrush
*opacity_brush
= NULL
;
1110 D2D1_BITMAP_PROPERTIES bitmap_desc
;
1111 ID2D1Bitmap
*opacity_bitmap
= NULL
;
1112 IDWriteGlyphRunAnalysis
*analysis
;
1113 DWRITE_TEXTURE_TYPE texture_type
;
1114 D2D1_BRUSH_PROPERTIES brush_desc
;
1115 IDWriteFactory2
*dwrite_factory
;
1116 DWRITE_GLYPH_RUN scaled_run
;
1117 void *opacity_values
= NULL
;
1118 size_t opacity_values_size
;
1119 D2D1_SIZE_U bitmap_size
;
1120 D2D1_RECT_F run_rect
;
1124 if (FAILED(hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
,
1125 &IID_IDWriteFactory2
, (IUnknown
**)&dwrite_factory
)))
1127 ERR("Failed to create dwrite factory, hr %#x.\n", hr
);
1131 scaled_run
= *glyph_run
;
1132 scaled_run
.fontEmSize
*= ppd
;
1133 hr
= IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory
, &scaled_run
,
1134 (DWRITE_MATRIX
*)&render_target
->drawing_state
.transform
, rendering_mode
, measuring_mode
,
1135 DWRITE_GRID_FIT_MODE_DEFAULT
, antialias_mode
, baseline_origin
.x
,
1136 baseline_origin
.y
, &analysis
);
1137 IDWriteFactory2_Release(dwrite_factory
);
1140 ERR("Failed to create glyph run analysis, hr %#x.\n", hr
);
1144 if (rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)
1145 texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
1147 texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
1149 if (FAILED(hr
= IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis
, texture_type
, &bounds
)))
1151 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr
);
1155 d2d_size_set(&bitmap_size
, bounds
.right
- bounds
.left
, bounds
.bottom
- bounds
.top
);
1156 if (!bitmap_size
.width
|| !bitmap_size
.height
)
1158 /* Empty run, nothing to do. */
1162 if (texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
1163 bitmap_size
.width
*= 3;
1164 opacity_values_size
= bitmap_size
.width
* bitmap_size
.height
;
1165 if (!(opacity_values
= HeapAlloc(GetProcessHeap(), 0, opacity_values_size
)))
1167 ERR("Failed to allocate opacity values.\n");
1171 if (FAILED(hr
= IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis
,
1172 texture_type
, &bounds
, opacity_values
, opacity_values_size
)))
1174 ERR("Failed to create alpha texture, hr %#x.\n", hr
);
1178 bitmap_desc
.pixelFormat
.format
= DXGI_FORMAT_A8_UNORM
;
1179 bitmap_desc
.pixelFormat
.alphaMode
= D2D1_ALPHA_MODE_PREMULTIPLIED
;
1180 bitmap_desc
.dpiX
= render_target
->desc
.dpiX
;
1181 if (texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
1182 bitmap_desc
.dpiX
*= 3.0f
;
1183 bitmap_desc
.dpiY
= render_target
->desc
.dpiY
;
1184 if (FAILED(hr
= d2d_d3d_render_target_CreateBitmap(&render_target
->ID2D1RenderTarget_iface
,
1185 bitmap_size
, opacity_values
, bitmap_size
.width
, &bitmap_desc
, &opacity_bitmap
)))
1187 ERR("Failed to create opacity bitmap, hr %#x.\n", hr
);
1191 brush_desc
.opacity
= 1.0f
;
1192 brush_desc
.transform
._11
= 1.0f
;
1193 brush_desc
.transform
._12
= 0.0f
;
1194 brush_desc
.transform
._21
= 0.0f
;
1195 brush_desc
.transform
._22
= 1.0f
;
1196 brush_desc
.transform
._31
= bounds
.left
;
1197 brush_desc
.transform
._32
= bounds
.top
;
1198 if (FAILED(hr
= d2d_d3d_render_target_CreateBitmapBrush(&render_target
->ID2D1RenderTarget_iface
,
1199 opacity_bitmap
, NULL
, &brush_desc
, &opacity_brush
)))
1201 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr
);
1205 d2d_rect_set(&run_rect
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
1206 if (FAILED(hr
= ID2D1Factory_CreateRectangleGeometry(render_target
->factory
, &run_rect
, &geometry
)))
1208 ERR("Failed to create geometry, hr %#x.\n", hr
);
1212 transform
= &render_target
->drawing_state
.transform
;
1213 prev_transform
= *transform
;
1214 *transform
= identity
;
1215 d2d_rt_fill_geometry(render_target
, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry
*)geometry
),
1216 unsafe_impl_from_ID2D1Brush(brush
), unsafe_impl_from_ID2D1Brush((ID2D1Brush
*)opacity_brush
));
1217 *transform
= prev_transform
;
1221 ID2D1RectangleGeometry_Release(geometry
);
1223 ID2D1BitmapBrush_Release(opacity_brush
);
1225 ID2D1Bitmap_Release(opacity_bitmap
);
1226 HeapFree(GetProcessHeap(), 0, opacity_values
);
1227 IDWriteGlyphRunAnalysis_Release(analysis
);
1230 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget
*iface
,
1231 D2D1_POINT_2F baseline_origin
, const DWRITE_GLYPH_RUN
*glyph_run
, ID2D1Brush
*brush
,
1232 DWRITE_MEASURING_MODE measuring_mode
)
1234 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1235 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode
= DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
;
1236 IDWriteRenderingParams
*rendering_params
;
1237 DWRITE_RENDERING_MODE rendering_mode
;
1241 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1242 iface
, baseline_origin
.x
, baseline_origin
.y
, glyph_run
, brush
, measuring_mode
);
1244 rendering_params
= render_target
->text_rendering_params
? render_target
->text_rendering_params
1245 : render_target
->default_text_rendering_params
;
1247 rendering_mode
= IDWriteRenderingParams_GetRenderingMode(rendering_params
);
1249 switch (render_target
->drawing_state
.textAntialiasMode
)
1251 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED
:
1252 if (rendering_mode
== DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
1253 || rendering_mode
== DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
1254 || rendering_mode
== DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
1255 || rendering_mode
== DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC
)
1257 render_target
->error
.code
= E_INVALIDARG
;
1260 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE
:
1261 if (rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
1262 || rendering_mode
== DWRITE_RENDERING_MODE_OUTLINE
)
1264 render_target
->error
.code
= E_INVALIDARG
;
1267 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE
:
1268 if (rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)
1269 render_target
->error
.code
= E_INVALIDARG
;
1275 if (FAILED(render_target
->error
.code
))
1278 rendering_mode
= DWRITE_RENDERING_MODE_DEFAULT
;
1279 switch (render_target
->drawing_state
.textAntialiasMode
)
1281 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT
:
1282 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params
) > 0.0f
)
1283 antialias_mode
= DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
;
1285 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE
:
1286 antialias_mode
= DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
;
1288 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED
:
1289 rendering_mode
= DWRITE_RENDERING_MODE_ALIASED
;
1295 ppd
= max(render_target
->desc
.dpiX
, render_target
->desc
.dpiY
) / 96.0f
;
1296 if (rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
1298 if (FAILED(hr
= IDWriteFontFace_GetRecommendedRenderingMode(glyph_run
->fontFace
, glyph_run
->fontEmSize
,
1299 ppd
, measuring_mode
, rendering_params
, &rendering_mode
)))
1301 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr
);
1302 rendering_mode
= DWRITE_RENDERING_MODE_OUTLINE
;
1306 if (rendering_mode
== DWRITE_RENDERING_MODE_OUTLINE
)
1307 d2d_rt_draw_glyph_run_outline(render_target
, baseline_origin
, glyph_run
, brush
);
1309 d2d_rt_draw_glyph_run_bitmap(render_target
, baseline_origin
, glyph_run
, brush
,
1310 ppd
, rendering_mode
, measuring_mode
, antialias_mode
);
1313 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetTransform(ID2D1RenderTarget
*iface
,
1314 const D2D1_MATRIX_3X2_F
*transform
)
1316 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1318 TRACE("iface %p, transform %p.\n", iface
, transform
);
1320 render_target
->drawing_state
.transform
= *transform
;
1323 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetTransform(ID2D1RenderTarget
*iface
,
1324 D2D1_MATRIX_3X2_F
*transform
)
1326 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1328 TRACE("iface %p, transform %p.\n", iface
, transform
);
1330 *transform
= render_target
->drawing_state
.transform
;
1333 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget
*iface
,
1334 D2D1_ANTIALIAS_MODE antialias_mode
)
1336 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1338 TRACE("iface %p, antialias_mode %#x stub!\n", iface
, antialias_mode
);
1340 render_target
->drawing_state
.antialiasMode
= antialias_mode
;
1343 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE
d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget
*iface
)
1345 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1347 TRACE("iface %p.\n", iface
);
1349 return render_target
->drawing_state
.antialiasMode
;
1352 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget
*iface
,
1353 D2D1_TEXT_ANTIALIAS_MODE antialias_mode
)
1355 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1357 TRACE("iface %p, antialias_mode %#x.\n", iface
, antialias_mode
);
1359 render_target
->drawing_state
.textAntialiasMode
= antialias_mode
;
1362 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE
d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget
*iface
)
1364 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1366 TRACE("iface %p.\n", iface
);
1368 return render_target
->drawing_state
.textAntialiasMode
;
1371 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget
*iface
,
1372 IDWriteRenderingParams
*text_rendering_params
)
1374 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1376 TRACE("iface %p, text_rendering_params %p.\n", iface
, text_rendering_params
);
1378 if (text_rendering_params
)
1379 IDWriteRenderingParams_AddRef(text_rendering_params
);
1380 if (render_target
->text_rendering_params
)
1381 IDWriteRenderingParams_Release(render_target
->text_rendering_params
);
1382 render_target
->text_rendering_params
= text_rendering_params
;
1385 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget
*iface
,
1386 IDWriteRenderingParams
**text_rendering_params
)
1388 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1390 TRACE("iface %p, text_rendering_params %p.\n", iface
, text_rendering_params
);
1392 if ((*text_rendering_params
= render_target
->text_rendering_params
))
1393 IDWriteRenderingParams_AddRef(*text_rendering_params
);
1396 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetTags(ID2D1RenderTarget
*iface
, D2D1_TAG tag1
, D2D1_TAG tag2
)
1398 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1400 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface
, wine_dbgstr_longlong(tag1
), wine_dbgstr_longlong(tag2
));
1402 render_target
->drawing_state
.tag1
= tag1
;
1403 render_target
->drawing_state
.tag2
= tag2
;
1406 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetTags(ID2D1RenderTarget
*iface
, D2D1_TAG
*tag1
, D2D1_TAG
*tag2
)
1408 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1410 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface
, tag1
, tag2
);
1412 *tag1
= render_target
->drawing_state
.tag1
;
1413 *tag2
= render_target
->drawing_state
.tag2
;
1416 static void STDMETHODCALLTYPE
d2d_d3d_render_target_PushLayer(ID2D1RenderTarget
*iface
,
1417 const D2D1_LAYER_PARAMETERS
*layer_parameters
, ID2D1Layer
*layer
)
1419 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface
, layer_parameters
, layer
);
1422 static void STDMETHODCALLTYPE
d2d_d3d_render_target_PopLayer(ID2D1RenderTarget
*iface
)
1424 FIXME("iface %p stub!\n", iface
);
1427 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_Flush(ID2D1RenderTarget
*iface
, D2D1_TAG
*tag1
, D2D1_TAG
*tag2
)
1429 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface
, tag1
, tag2
);
1434 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget
*iface
,
1435 ID2D1DrawingStateBlock
*state_block
)
1437 struct d2d_state_block
*state_block_impl
= unsafe_impl_from_ID2D1DrawingStateBlock(state_block
);
1438 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1440 TRACE("iface %p, state_block %p.\n", iface
, state_block
);
1442 state_block_impl
->drawing_state
= render_target
->drawing_state
;
1443 if (render_target
->text_rendering_params
)
1444 IDWriteRenderingParams_AddRef(render_target
->text_rendering_params
);
1445 if (state_block_impl
->text_rendering_params
)
1446 IDWriteRenderingParams_Release(state_block_impl
->text_rendering_params
);
1447 state_block_impl
->text_rendering_params
= render_target
->text_rendering_params
;
1450 static void STDMETHODCALLTYPE
d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget
*iface
,
1451 ID2D1DrawingStateBlock
*state_block
)
1453 struct d2d_state_block
*state_block_impl
= unsafe_impl_from_ID2D1DrawingStateBlock(state_block
);
1454 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1456 TRACE("iface %p, state_block %p.\n", iface
, state_block
);
1458 render_target
->drawing_state
= state_block_impl
->drawing_state
;
1459 if (state_block_impl
->text_rendering_params
)
1460 IDWriteRenderingParams_AddRef(state_block_impl
->text_rendering_params
);
1461 if (render_target
->text_rendering_params
)
1462 IDWriteRenderingParams_Release(render_target
->text_rendering_params
);
1463 render_target
->text_rendering_params
= state_block_impl
->text_rendering_params
;
1466 static void STDMETHODCALLTYPE
d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget
*iface
,
1467 const D2D1_RECT_F
*clip_rect
, D2D1_ANTIALIAS_MODE antialias_mode
)
1469 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1470 D2D1_RECT_F transformed_rect
;
1471 float x_scale
, y_scale
;
1472 D2D1_POINT_2F point
;
1474 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface
, debug_d2d_rect_f(clip_rect
), antialias_mode
);
1476 if (antialias_mode
!= D2D1_ANTIALIAS_MODE_ALIASED
)
1477 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode
);
1479 x_scale
= render_target
->desc
.dpiX
/ 96.0f
;
1480 y_scale
= render_target
->desc
.dpiY
/ 96.0f
;
1481 d2d_point_transform(&point
, &render_target
->drawing_state
.transform
,
1482 clip_rect
->left
* x_scale
, clip_rect
->top
* y_scale
);
1483 d2d_rect_set(&transformed_rect
, point
.x
, point
.y
, point
.x
, point
.y
);
1484 d2d_point_transform(&point
, &render_target
->drawing_state
.transform
,
1485 clip_rect
->left
* x_scale
, clip_rect
->bottom
* y_scale
);
1486 d2d_rect_expand(&transformed_rect
, &point
);
1487 d2d_point_transform(&point
, &render_target
->drawing_state
.transform
,
1488 clip_rect
->right
* x_scale
, clip_rect
->top
* y_scale
);
1489 d2d_rect_expand(&transformed_rect
, &point
);
1490 d2d_point_transform(&point
, &render_target
->drawing_state
.transform
,
1491 clip_rect
->right
* x_scale
, clip_rect
->bottom
* y_scale
);
1492 d2d_rect_expand(&transformed_rect
, &point
);
1494 if (!d2d_clip_stack_push(&render_target
->clip_stack
, &transformed_rect
))
1495 WARN("Failed to push clip rect.\n");
1498 static void STDMETHODCALLTYPE
d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget
*iface
)
1500 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1502 TRACE("iface %p.\n", iface
);
1504 d2d_clip_stack_pop(&render_target
->clip_stack
);
1507 static void STDMETHODCALLTYPE
d2d_d3d_render_target_Clear(ID2D1RenderTarget
*iface
, const D2D1_COLOR_F
*color
)
1509 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1510 D2D1_COLOR_F c
= {0.0f
, 0.0f
, 0.0f
, 0.0f
};
1511 D3D10_SUBRESOURCE_DATA buffer_data
;
1512 D3D10_BUFFER_DESC buffer_desc
;
1513 ID3D10Buffer
*vs_cb
, *ps_cb
;
1516 static const float transform
[] =
1518 1.0f
, 0.0f
, 0.0f
, 0.0f
,
1519 0.0f
, -1.0f
, 0.0f
, 0.0f
,
1522 TRACE("iface %p, color %p.\n", iface
, color
);
1524 buffer_desc
.ByteWidth
= sizeof(transform
);
1525 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
1526 buffer_desc
.BindFlags
= D3D10_BIND_CONSTANT_BUFFER
;
1527 buffer_desc
.CPUAccessFlags
= 0;
1528 buffer_desc
.MiscFlags
= 0;
1530 buffer_data
.pSysMem
= transform
;
1531 buffer_data
.SysMemPitch
= 0;
1532 buffer_data
.SysMemSlicePitch
= 0;
1534 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vs_cb
)))
1536 WARN("Failed to create constant buffer, hr %#x.\n", hr
);
1542 if (render_target
->desc
.pixelFormat
.alphaMode
== D2D1_ALPHA_MODE_IGNORE
)
1547 buffer_desc
.ByteWidth
= sizeof(c
);
1548 buffer_data
.pSysMem
= &c
;
1550 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &ps_cb
)))
1552 WARN("Failed to create constant buffer, hr %#x.\n", hr
);
1553 ID3D10Buffer_Release(vs_cb
);
1557 d2d_rt_draw(render_target
, D2D_SHAPE_TYPE_TRIANGLE
, render_target
->ib
, 6,
1558 render_target
->vb
, render_target
->vb_stride
, vs_cb
, ps_cb
, NULL
, NULL
);
1560 ID3D10Buffer_Release(ps_cb
);
1561 ID3D10Buffer_Release(vs_cb
);
1564 static void STDMETHODCALLTYPE
d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget
*iface
)
1566 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1568 TRACE("iface %p.\n", iface
);
1570 memset(&render_target
->error
, 0, sizeof(render_target
->error
));
1573 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_EndDraw(ID2D1RenderTarget
*iface
,
1574 D2D1_TAG
*tag1
, D2D1_TAG
*tag2
)
1576 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1578 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface
, tag1
, tag2
);
1581 *tag1
= render_target
->error
.tag1
;
1583 *tag2
= render_target
->error
.tag2
;
1585 return render_target
->error
.code
;
1588 static D2D1_PIXEL_FORMAT
* STDMETHODCALLTYPE
d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget
*iface
,
1589 D2D1_PIXEL_FORMAT
*format
)
1591 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1593 TRACE("iface %p, format %p.\n", iface
, format
);
1595 *format
= render_target
->desc
.pixelFormat
;
1599 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetDpi(ID2D1RenderTarget
*iface
, float dpi_x
, float dpi_y
)
1601 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1603 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface
, dpi_x
, dpi_y
);
1605 if (dpi_x
== 0.0f
&& dpi_y
== 0.0f
)
1610 else if (dpi_x
<= 0.0f
|| dpi_y
<= 0.0f
)
1613 render_target
->desc
.dpiX
= dpi_x
;
1614 render_target
->desc
.dpiY
= dpi_y
;
1617 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetDpi(ID2D1RenderTarget
*iface
, float *dpi_x
, float *dpi_y
)
1619 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1621 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface
, dpi_x
, dpi_y
);
1623 *dpi_x
= render_target
->desc
.dpiX
;
1624 *dpi_y
= render_target
->desc
.dpiY
;
1627 static D2D1_SIZE_F
* STDMETHODCALLTYPE
d2d_d3d_render_target_GetSize(ID2D1RenderTarget
*iface
, D2D1_SIZE_F
*size
)
1629 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1631 TRACE("iface %p, size %p.\n", iface
, size
);
1633 size
->width
= render_target
->pixel_size
.width
/ (render_target
->desc
.dpiX
/ 96.0f
);
1634 size
->height
= render_target
->pixel_size
.height
/ (render_target
->desc
.dpiY
/ 96.0f
);
1638 static D2D1_SIZE_U
* STDMETHODCALLTYPE
d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget
*iface
,
1639 D2D1_SIZE_U
*pixel_size
)
1641 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1643 TRACE("iface %p, pixel_size %p.\n", iface
, pixel_size
);
1645 *pixel_size
= render_target
->pixel_size
;
1649 static UINT32 STDMETHODCALLTYPE
d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget
*iface
)
1651 FIXME("iface %p stub!\n", iface
);
1656 static BOOL STDMETHODCALLTYPE
d2d_d3d_render_target_IsSupported(ID2D1RenderTarget
*iface
,
1657 const D2D1_RENDER_TARGET_PROPERTIES
*desc
)
1659 FIXME("iface %p, desc %p stub!\n", iface
, desc
);
1664 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl
=
1666 d2d_d3d_render_target_QueryInterface
,
1667 d2d_d3d_render_target_AddRef
,
1668 d2d_d3d_render_target_Release
,
1669 d2d_d3d_render_target_GetFactory
,
1670 d2d_d3d_render_target_CreateBitmap
,
1671 d2d_d3d_render_target_CreateBitmapFromWicBitmap
,
1672 d2d_d3d_render_target_CreateSharedBitmap
,
1673 d2d_d3d_render_target_CreateBitmapBrush
,
1674 d2d_d3d_render_target_CreateSolidColorBrush
,
1675 d2d_d3d_render_target_CreateGradientStopCollection
,
1676 d2d_d3d_render_target_CreateLinearGradientBrush
,
1677 d2d_d3d_render_target_CreateRadialGradientBrush
,
1678 d2d_d3d_render_target_CreateCompatibleRenderTarget
,
1679 d2d_d3d_render_target_CreateLayer
,
1680 d2d_d3d_render_target_CreateMesh
,
1681 d2d_d3d_render_target_DrawLine
,
1682 d2d_d3d_render_target_DrawRectangle
,
1683 d2d_d3d_render_target_FillRectangle
,
1684 d2d_d3d_render_target_DrawRoundedRectangle
,
1685 d2d_d3d_render_target_FillRoundedRectangle
,
1686 d2d_d3d_render_target_DrawEllipse
,
1687 d2d_d3d_render_target_FillEllipse
,
1688 d2d_d3d_render_target_DrawGeometry
,
1689 d2d_d3d_render_target_FillGeometry
,
1690 d2d_d3d_render_target_FillMesh
,
1691 d2d_d3d_render_target_FillOpacityMask
,
1692 d2d_d3d_render_target_DrawBitmap
,
1693 d2d_d3d_render_target_DrawText
,
1694 d2d_d3d_render_target_DrawTextLayout
,
1695 d2d_d3d_render_target_DrawGlyphRun
,
1696 d2d_d3d_render_target_SetTransform
,
1697 d2d_d3d_render_target_GetTransform
,
1698 d2d_d3d_render_target_SetAntialiasMode
,
1699 d2d_d3d_render_target_GetAntialiasMode
,
1700 d2d_d3d_render_target_SetTextAntialiasMode
,
1701 d2d_d3d_render_target_GetTextAntialiasMode
,
1702 d2d_d3d_render_target_SetTextRenderingParams
,
1703 d2d_d3d_render_target_GetTextRenderingParams
,
1704 d2d_d3d_render_target_SetTags
,
1705 d2d_d3d_render_target_GetTags
,
1706 d2d_d3d_render_target_PushLayer
,
1707 d2d_d3d_render_target_PopLayer
,
1708 d2d_d3d_render_target_Flush
,
1709 d2d_d3d_render_target_SaveDrawingState
,
1710 d2d_d3d_render_target_RestoreDrawingState
,
1711 d2d_d3d_render_target_PushAxisAlignedClip
,
1712 d2d_d3d_render_target_PopAxisAlignedClip
,
1713 d2d_d3d_render_target_Clear
,
1714 d2d_d3d_render_target_BeginDraw
,
1715 d2d_d3d_render_target_EndDraw
,
1716 d2d_d3d_render_target_GetPixelFormat
,
1717 d2d_d3d_render_target_SetDpi
,
1718 d2d_d3d_render_target_GetDpi
,
1719 d2d_d3d_render_target_GetSize
,
1720 d2d_d3d_render_target_GetPixelSize
,
1721 d2d_d3d_render_target_GetMaximumBitmapSize
,
1722 d2d_d3d_render_target_IsSupported
,
1725 static inline struct d2d_d3d_render_target
*impl_from_IDWriteTextRenderer(IDWriteTextRenderer
*iface
)
1727 return CONTAINING_RECORD(iface
, struct d2d_d3d_render_target
, IDWriteTextRenderer_iface
);
1730 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_QueryInterface(IDWriteTextRenderer
*iface
, REFIID iid
, void **out
)
1732 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1734 if (IsEqualGUID(iid
, &IID_IDWriteTextRenderer
)
1735 || IsEqualGUID(iid
, &IID_IDWritePixelSnapping
)
1736 || IsEqualGUID(iid
, &IID_IUnknown
))
1738 IDWriteTextRenderer_AddRef(iface
);
1743 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
1746 return E_NOINTERFACE
;
1749 static ULONG STDMETHODCALLTYPE
d2d_text_renderer_AddRef(IDWriteTextRenderer
*iface
)
1751 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1753 TRACE("iface %p.\n", iface
);
1755 return d2d_d3d_render_target_AddRef(&render_target
->ID2D1RenderTarget_iface
);
1758 static ULONG STDMETHODCALLTYPE
d2d_text_renderer_Release(IDWriteTextRenderer
*iface
)
1760 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1762 TRACE("iface %p.\n", iface
);
1764 return d2d_d3d_render_target_Release(&render_target
->ID2D1RenderTarget_iface
);
1767 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer
*iface
,
1768 void *ctx
, BOOL
*disabled
)
1770 struct d2d_draw_text_layout_ctx
*context
= ctx
;
1772 TRACE("iface %p, ctx %p, disabled %p.\n", iface
, ctx
, disabled
);
1774 *disabled
= context
->options
& D2D1_DRAW_TEXT_OPTIONS_NO_SNAP
;
1779 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer
*iface
,
1780 void *ctx
, DWRITE_MATRIX
*transform
)
1782 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1784 TRACE("iface %p, ctx %p, transform %p.\n", iface
, ctx
, transform
);
1786 ID2D1RenderTarget_GetTransform(&render_target
->ID2D1RenderTarget_iface
, (D2D1_MATRIX_3X2_F
*)transform
);
1791 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer
*iface
, void *ctx
, float *ppd
)
1793 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1795 TRACE("iface %p, ctx %p, ppd %p.\n", iface
, ctx
, ppd
);
1797 *ppd
= render_target
->desc
.dpiY
/ 96.0f
;
1802 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer
*iface
, void *ctx
,
1803 float baseline_origin_x
, float baseline_origin_y
, DWRITE_MEASURING_MODE measuring_mode
,
1804 const DWRITE_GLYPH_RUN
*glyph_run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*desc
, IUnknown
*effect
)
1806 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1807 D2D1_POINT_2F baseline_origin
= {baseline_origin_x
, baseline_origin_y
};
1808 struct d2d_draw_text_layout_ctx
*context
= ctx
;
1809 BOOL color_font
= FALSE
;
1812 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1813 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1814 iface
, ctx
, baseline_origin_x
, baseline_origin_y
,
1815 measuring_mode
, glyph_run
, desc
, effect
);
1818 WARN("Ignoring glyph run description %p.\n", desc
);
1819 if (context
->options
& ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP
| D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT
))
1820 FIXME("Ignoring options %#x.\n", context
->options
);
1822 brush
= d2d_draw_get_text_brush(context
, effect
);
1824 TRACE("%s\n", debugstr_wn(desc
->string
, desc
->stringLength
));
1826 if (context
->options
& D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT
)
1828 IDWriteFontFace2
*fontface
;
1830 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run
->fontFace
,
1831 &IID_IDWriteFontFace2
, (void **)&fontface
)))
1833 color_font
= IDWriteFontFace2_IsColorFont(fontface
);
1834 IDWriteFontFace2_Release(fontface
);
1840 IDWriteColorGlyphRunEnumerator
*layers
;
1841 IDWriteFactory2
*dwrite_factory
;
1844 if (FAILED(hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, &IID_IDWriteFactory2
,
1845 (IUnknown
**)&dwrite_factory
)))
1847 ERR("Failed to create dwrite factory, hr %#x.\n", hr
);
1848 ID2D1Brush_Release(brush
);
1852 hr
= IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory
, baseline_origin_x
, baseline_origin_y
,
1853 glyph_run
, desc
, measuring_mode
, (DWRITE_MATRIX
*)&render_target
->drawing_state
.transform
, 0, &layers
);
1854 IDWriteFactory2_Release(dwrite_factory
);
1857 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr
);
1858 ID2D1Brush_Release(brush
);
1864 const DWRITE_COLOR_GLYPH_RUN
*color_run
;
1865 ID2D1Brush
*color_brush
;
1866 D2D1_POINT_2F origin
;
1867 BOOL has_run
= FALSE
;
1869 if (FAILED(hr
= IDWriteColorGlyphRunEnumerator_MoveNext(layers
, &has_run
)))
1871 ERR("Failed to switch color glyph layer, hr %#x.\n", hr
);
1878 if (FAILED(hr
= IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers
, &color_run
)))
1880 ERR("Failed to get current color run, hr %#x.\n", hr
);
1884 if (color_run
->paletteIndex
== 0xffff)
1885 color_brush
= brush
;
1888 if (FAILED(hr
= ID2D1RenderTarget_CreateSolidColorBrush(&render_target
->ID2D1RenderTarget_iface
,
1889 &color_run
->runColor
, NULL
, (ID2D1SolidColorBrush
**)&color_brush
)))
1891 ERR("Failed to create solid color brush, hr %#x.\n", hr
);
1896 origin
.x
= color_run
->baselineOriginX
;
1897 origin
.y
= color_run
->baselineOriginY
;
1898 ID2D1RenderTarget_DrawGlyphRun(&render_target
->ID2D1RenderTarget_iface
,
1899 origin
, &color_run
->glyphRun
, color_brush
, measuring_mode
);
1901 if (color_brush
!= brush
)
1902 ID2D1Brush_Release(color_brush
);
1905 IDWriteColorGlyphRunEnumerator_Release(layers
);
1908 ID2D1RenderTarget_DrawGlyphRun(&render_target
->ID2D1RenderTarget_iface
,
1909 baseline_origin
, glyph_run
, brush
, measuring_mode
);
1911 ID2D1Brush_Release(brush
);
1916 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_DrawUnderline(IDWriteTextRenderer
*iface
, void *ctx
,
1917 float baseline_origin_x
, float baseline_origin_y
, const DWRITE_UNDERLINE
*underline
, IUnknown
*effect
)
1919 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1920 const D2D1_MATRIX_3X2_F
*m
= &render_target
->drawing_state
.transform
;
1921 struct d2d_draw_text_layout_ctx
*context
= ctx
;
1922 D2D1_ANTIALIAS_MODE prev_antialias_mode
;
1923 D2D1_POINT_2F start
, end
;
1927 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1928 iface
, ctx
, baseline_origin_x
, baseline_origin_y
, underline
, effect
);
1930 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1931 thickness
= max(96.0f
/ (render_target
->desc
.dpiY
* sqrtf(m
->_21
* m
->_21
+ m
->_22
* m
->_22
)),
1932 underline
->thickness
);
1934 brush
= d2d_draw_get_text_brush(context
, effect
);
1936 start
.x
= baseline_origin_x
;
1937 start
.y
= baseline_origin_y
+ underline
->offset
+ thickness
/ 2.0f
;
1938 end
.x
= start
.x
+ underline
->width
;
1940 prev_antialias_mode
= d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target
);
1941 d2d_d3d_render_target_DrawLine(&render_target
->ID2D1RenderTarget_iface
, start
, end
, brush
, thickness
, NULL
);
1942 render_target
->drawing_state
.antialiasMode
= prev_antialias_mode
;
1944 ID2D1Brush_Release(brush
);
1949 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer
*iface
, void *ctx
,
1950 float baseline_origin_x
, float baseline_origin_y
, const DWRITE_STRIKETHROUGH
*strikethrough
, IUnknown
*effect
)
1952 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1953 const D2D1_MATRIX_3X2_F
*m
= &render_target
->drawing_state
.transform
;
1954 struct d2d_draw_text_layout_ctx
*context
= ctx
;
1955 D2D1_ANTIALIAS_MODE prev_antialias_mode
;
1956 D2D1_POINT_2F start
, end
;
1960 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
1961 iface
, ctx
, baseline_origin_x
, baseline_origin_y
, strikethrough
, effect
);
1963 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1964 thickness
= max(96.0f
/ (render_target
->desc
.dpiY
* sqrtf(m
->_21
* m
->_21
+ m
->_22
* m
->_22
)),
1965 strikethrough
->thickness
);
1967 brush
= d2d_draw_get_text_brush(context
, effect
);
1969 start
.x
= baseline_origin_x
;
1970 start
.y
= baseline_origin_y
+ strikethrough
->offset
+ thickness
/ 2.0f
;
1971 end
.x
= start
.x
+ strikethrough
->width
;
1973 prev_antialias_mode
= d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target
);
1974 d2d_d3d_render_target_DrawLine(&render_target
->ID2D1RenderTarget_iface
, start
, end
, brush
, thickness
, NULL
);
1975 render_target
->drawing_state
.antialiasMode
= prev_antialias_mode
;
1977 ID2D1Brush_Release(brush
);
1982 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer
*iface
, void *ctx
,
1983 float origin_x
, float origin_y
, IDWriteInlineObject
*object
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*effect
)
1985 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1986 iface
, ctx
, origin_x
, origin_y
, object
, is_sideways
, is_rtl
, effect
);
1988 return IDWriteInlineObject_Draw(object
, ctx
, iface
, origin_x
, origin_y
, is_sideways
, is_rtl
, effect
);
1991 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl
=
1993 d2d_text_renderer_QueryInterface
,
1994 d2d_text_renderer_AddRef
,
1995 d2d_text_renderer_Release
,
1996 d2d_text_renderer_IsPixelSnappingDisabled
,
1997 d2d_text_renderer_GetCurrentTransform
,
1998 d2d_text_renderer_GetPixelsPerDip
,
1999 d2d_text_renderer_DrawGlyphRun
,
2000 d2d_text_renderer_DrawUnderline
,
2001 d2d_text_renderer_DrawStrikethrough
,
2002 d2d_text_renderer_DrawInlineObject
,
2005 static inline struct d2d_d3d_render_target
*impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget
*iface
)
2007 return CONTAINING_RECORD(iface
, struct d2d_d3d_render_target
, ID2D1GdiInteropRenderTarget_iface
);
2010 static HRESULT STDMETHODCALLTYPE
d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget
*iface
,
2011 REFIID iid
, void **out
)
2013 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1GdiInteropRenderTarget(iface
);
2015 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
2017 return IUnknown_QueryInterface(render_target
->outer_unknown
, iid
, out
);
2020 static ULONG STDMETHODCALLTYPE
d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget
*iface
)
2022 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1GdiInteropRenderTarget(iface
);
2024 TRACE("iface %p.\n", iface
);
2026 return IUnknown_AddRef(render_target
->outer_unknown
);
2029 static ULONG STDMETHODCALLTYPE
d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget
*iface
)
2031 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1GdiInteropRenderTarget(iface
);
2033 TRACE("iface %p.\n", iface
);
2035 return IUnknown_Release(render_target
->outer_unknown
);
2038 static HRESULT
d2d_d3d_render_target_get_surface(struct d2d_d3d_render_target
*render_target
, IDXGISurface1
**surface
)
2040 ID3D10Resource
*resource
;
2043 ID3D10RenderTargetView_GetResource(render_target
->view
, &resource
);
2044 hr
= ID3D10Resource_QueryInterface(resource
, &IID_IDXGISurface1
, (void **)surface
);
2045 ID3D10Resource_Release(resource
);
2049 WARN("Failed to get DXGI surface, %#x.\n", hr
);
2056 static HRESULT STDMETHODCALLTYPE
d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget
*iface
,
2057 D2D1_DC_INITIALIZE_MODE mode
, HDC
*dc
)
2059 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1GdiInteropRenderTarget(iface
);
2060 IDXGISurface1
*surface
;
2063 TRACE("iface %p, mode %d, dc %p.\n", iface
, mode
, dc
);
2065 if (FAILED(hr
= d2d_d3d_render_target_get_surface(render_target
, &surface
)))
2068 hr
= IDXGISurface1_GetDC(surface
, mode
!= D2D1_DC_INITIALIZE_MODE_COPY
, dc
);
2069 IDXGISurface1_Release(surface
);
2074 static HRESULT STDMETHODCALLTYPE
d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget
*iface
,
2077 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1GdiInteropRenderTarget(iface
);
2078 IDXGISurface1
*surface
;
2082 TRACE("iface %p, update rect %s.\n", iface
, wine_dbgstr_rect(update
));
2084 if (FAILED(hr
= d2d_d3d_render_target_get_surface(render_target
, &surface
)))
2088 update_rect
= *update
;
2089 hr
= IDXGISurface1_ReleaseDC(surface
, update
? &update_rect
: NULL
);
2090 IDXGISurface1_Release(surface
);
2095 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl
=
2097 d2d_gdi_interop_render_target_QueryInterface
,
2098 d2d_gdi_interop_render_target_AddRef
,
2099 d2d_gdi_interop_render_target_Release
,
2100 d2d_gdi_interop_render_target_GetDC
,
2101 d2d_gdi_interop_render_target_ReleaseDC
,
2104 static HRESULT
d2d_d3d_render_target_init(struct d2d_d3d_render_target
*render_target
, ID2D1Factory
*factory
,
2105 IDXGISurface
*surface
, IUnknown
*outer_unknown
, const D2D1_RENDER_TARGET_PROPERTIES
*desc
)
2107 D3D10_SUBRESOURCE_DATA buffer_data
;
2108 D3D10_STATE_BLOCK_MASK state_mask
;
2109 DXGI_SURFACE_DESC surface_desc
;
2110 IDWriteFactory
*dwrite_factory
;
2111 D3D10_RASTERIZER_DESC rs_desc
;
2112 D3D10_BUFFER_DESC buffer_desc
;
2113 D3D10_BLEND_DESC blend_desc
;
2114 ID3D10Resource
*resource
;
2115 unsigned int i
, j
, k
;
2118 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline
[] =
2120 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 0, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2121 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 8, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2122 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 16, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2124 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle
[] =
2126 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 0, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2128 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier_outline
[] =
2130 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 0, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2131 {"P", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 8, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2132 {"P", 1, DXGI_FORMAT_R32G32_FLOAT
, 0, 16, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2133 {"P", 2, DXGI_FORMAT_R32G32_FLOAT
, 0, 24, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2134 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 32, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2135 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 40, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2137 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier
[] =
2139 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 0, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2140 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT
, 0, 8, D3D10_INPUT_PER_VERTEX_DATA
, 0},
2142 static const DWORD vs_code_outline
[] =
2145 float3x2 transform_geometry
;
2147 float4 transform_rtx
;
2148 float4 transform_rty
;
2150 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2152 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2156 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2158 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2159 float4
main(float2 position
: POSITION
, float2 prev
: PREV
, float2 next
: NEXT
) : SV_POSITION
2161 float2 q_prev
, q_next
, v_p
, q_i
;
2164 q_prev
= float2(dot(prev
, transform_geometry
._11_21
), dot(prev
, transform_geometry
._12_22
));
2165 q_prev
= normalize(q_prev
);
2167 q_next
= float2(dot(next
, transform_geometry
._11_21
), dot(next
, transform_geometry
._12_22
));
2168 q_next
= normalize(q_next
);
2170 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2171 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2172 v_p
= float2(-q_prev
.y
, q_prev
.x
);
2173 l
= -dot(v_p
, q_next
) / (1.0f
+ dot(q_prev
, q_next
));
2174 q_i
= l
* q_prev
+ v_p
;
2175 position
= mul(float3(position
, 1.0f
), transform_geometry
) + stroke_width
* 0.5f
* q_i
;
2177 return float4(mul(float2x3(transform_rtx
.xyz
* transform_rtx
.w
, transform_rty
.xyz
* transform_rty
.w
),
2178 float3(position
.xy
, 1.0f
)) + float2(-1.0f
, 1.0f
), 0.0f
, 1.0f
);
2181 0x43425844, 0xe88f7af5, 0x480b101b, 0xfd80f66b, 0xd878e0b8, 0x00000001, 0x0000047c, 0x00000003,
2182 0x0000002c, 0x00000098, 0x000000cc, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2183 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2184 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2185 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x0000002c,
2186 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f,
2187 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x000003a8, 0x00010040, 0x000000ea, 0x04000059,
2188 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032,
2189 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
2190 0x02000068, 0x00000003, 0x0800000f, 0x00100012, 0x00000000, 0x00101046, 0x00000002, 0x00208046,
2191 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000002, 0x00208046,
2192 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
2193 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032,
2194 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001,
2195 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000001,
2196 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000,
2197 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a,
2198 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001,
2199 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042,
2200 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000,
2201 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a,
2202 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041,
2203 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000,
2204 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a,
2205 0x00000000, 0x00000001, 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046,
2206 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
2207 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
2208 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032,
2209 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x09000038,
2210 0x00100072, 0x00000001, 0x00208ff6, 0x00000000, 0x00000002, 0x00208246, 0x00000000, 0x00000002,
2211 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x07000010, 0x00100012, 0x00000001,
2212 0x00100246, 0x00000001, 0x00100246, 0x00000000, 0x09000038, 0x00100072, 0x00000002, 0x00208ff6,
2213 0x00000000, 0x00000003, 0x00208246, 0x00000000, 0x00000003, 0x07000010, 0x00100022, 0x00000001,
2214 0x00100246, 0x00000002, 0x00100246, 0x00000000, 0x0a000000, 0x00102032, 0x00000000, 0x00100046,
2215 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
2216 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
2218 static const DWORD vs_code_triangle
[] =
2220 /* float3x2 transform;
2222 * float4 main(float4 position : POSITION) : SV_POSITION
2224 * return float4(mul(position.xyw, transform), position.zw);
2226 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
2227 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2228 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
2229 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
2230 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
2231 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
2232 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
2233 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
2234 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
2235 0x00000000, 0x0100003e,
2245 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2246 * ⎣p2.x-p0.x p2.y-p0.y⎦
2254 static const DWORD vs_code_bezier_outline
[] =
2257 float3x2 transform_geometry
;
2259 float4 transform_rtx
;
2260 float4 transform_rty
;
2262 float4
main(float2 position
: POSITION
, float2 p0
: P0
, float2 p1
: P1
, float2 p2
: P2
,
2263 float2 prev
: PREV
, float2 next
: NEXT
, out float4 texcoord
: UV
,
2264 out float2x2 stroke_transform
: STROKE_TRANSFORM
) : SV_POSITION
2266 float2 q_prev
, q_next
, v_p
, q_i
, p
;
2270 geom
= float2x2(transform_geometry
._11_21
, transform_geometry
._12_22
);
2271 rt
= float2x2(transform_rtx
.xy
, transform_rty
.xy
);
2272 stroke_transform
= rt
* stroke_width
* 0.5f
;
2274 p
= mul(geom
, position
);
2283 q_prev
= normalize(mul(geom
, prev
));
2284 q_next
= normalize(mul(geom
, next
));
2286 v_p
= float2(-q_prev
.y
, q_prev
.x
);
2287 l
= -dot(v_p
, q_next
) / (1.0f
+ dot(q_prev
, q_next
));
2288 q_i
= l
* q_prev
+ v_p
;
2289 p
+= stroke_width
* q_i
;
2292 v_p
= normalize(float2(-v_p
.y
, v_p
.x
));
2293 if (abs(dot(mul(rt
, p1
), v_p
)) < 1.0f
)
2295 texcoord
.xzw
= float3(0.0f
, 0.0f
, 0.0f
);
2296 texcoord
.y
= dot(mul(rt
, p
), v_p
);
2300 texcoord
.zw
= sign(dot(mul(rt
, p1
), v_p
)) * v_p
;
2301 v_p
= -float2(-p
.y
, p
.x
) / dot(float2(-p1
.y
, p1
.x
), p2
);
2302 texcoord
.x
= dot(v_p
, p1
- 0.5f
* p2
);
2303 texcoord
.y
= dot(v_p
, p1
);
2306 position
= mul(geom
, position
)
2307 + float2(transform_geometry
._31
, transform_geometry
._32
) + stroke_width
* q_i
;
2308 position
= mul(rt
, position
) + float2(transform_rtx
.z
, transform_rty
.z
);
2309 position
= position
* float2(transform_rtx
.w
, transform_rty
.w
) + float2(-1.0f
, 1.0f
);
2311 return float4(position
, 0.0f
, 1.0f
);
2314 0x43425844, 0x2b43c2df, 0x861ad5cd, 0x32b8fe33, 0x2d50f992, 0x00000001, 0x00000a9c, 0x00000003,
2315 0x0000002c, 0x000000e4, 0x00000174, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
2316 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
2317 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
2318 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
2319 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
2320 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
2321 0xababab00, 0x4e47534f, 0x00000088, 0x00000004, 0x00000008, 0x00000068, 0x00000000, 0x00000001,
2322 0x00000003, 0x00000000, 0x0000000f, 0x00000074, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
2323 0x0000000f, 0x00000077, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000077,
2324 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x505f5653, 0x5449534f, 0x004e4f49,
2325 0x53005655, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x52444853, 0x00000920, 0x00010040,
2326 0x00000248, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2327 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x0300005f, 0x00101032,
2328 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f, 0x00101032, 0x00000005, 0x04000067,
2329 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032,
2330 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x02000068, 0x00000005, 0x0800000f, 0x00100012,
2331 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022,
2332 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042,
2333 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000,
2334 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046,
2335 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046,
2336 0x00000004, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046,
2337 0x00000004, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001,
2338 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001,
2339 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556,
2340 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046,
2341 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000,
2342 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e,
2343 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032,
2344 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001,
2345 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000,
2346 0x08000000, 0x00100012, 0x00000002, 0x0010000a, 0x00000001, 0x0020802a, 0x00000000, 0x00000000,
2347 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000,
2348 0x08000000, 0x00100022, 0x00000002, 0x0010001a, 0x00000001, 0x0020802a, 0x00000000, 0x00000001,
2349 0x0a000032, 0x001000c2, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x00100406, 0x00000000,
2350 0x00100406, 0x00000002, 0x0800000f, 0x00100042, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2351 0x00100ae6, 0x00000000, 0x0800000f, 0x00100042, 0x00000000, 0x00208046, 0x00000000, 0x00000003,
2352 0x00100ae6, 0x00000000, 0x08000000, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x0020802a,
2353 0x00000000, 0x00000003, 0x08000038, 0x00100022, 0x00000002, 0x0010002a, 0x00000000, 0x0020803a,
2354 0x00000000, 0x00000003, 0x08000000, 0x00100042, 0x00000000, 0x0010002a, 0x00000001, 0x0020802a,
2355 0x00000000, 0x00000002, 0x08000038, 0x00100012, 0x00000002, 0x0010002a, 0x00000000, 0x0020803a,
2356 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000000, 0x00100046, 0x00000002, 0x00004002,
2357 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002,
2358 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046,
2359 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000002, 0x00208046,
2360 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x001000c2, 0x00000000, 0x00100406,
2361 0x00000001, 0x80100406, 0x00000041, 0x00000002, 0x0a000032, 0x00100032, 0x00000000, 0x00208ff6,
2362 0x00000000, 0x00000001, 0x00100046, 0x00000000, 0x00100ae6, 0x00000000, 0x0800000f, 0x00100012,
2363 0x00000001, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f, 0x00100022,
2364 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f, 0x00100012,
2365 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f, 0x00100022,
2366 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000, 0x001000c2,
2367 0x00000001, 0x80100406, 0x00000041, 0x00000002, 0x00100406, 0x00000003, 0x0800000f, 0x00100082,
2368 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000001, 0x06000036, 0x00100042,
2369 0x00000002, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000002, 0x00208046,
2370 0x00000000, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000000, 0x00100ae6,
2371 0x00000002, 0x00100ae6, 0x00000002, 0x05000044, 0x00100082, 0x00000000, 0x0010003a, 0x00000000,
2372 0x07000038, 0x001000c2, 0x00000002, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000002, 0x0700000f,
2373 0x00100022, 0x00000003, 0x00100046, 0x00000001, 0x00100ae6, 0x00000002, 0x06000036, 0x00100042,
2374 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046,
2375 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00208046,
2376 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000004, 0x80100046,
2377 0x00000041, 0x00000002, 0x00100046, 0x00000001, 0x06000036, 0x00100042, 0x00000004, 0x8010001a,
2378 0x00000041, 0x00000004, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000004, 0x00100ae6,
2379 0x00000001, 0x0d000032, 0x00100032, 0x00000001, 0x80100ae6, 0x00000041, 0x00000001, 0x00004002,
2380 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000004, 0x0800000e, 0x00100032,
2381 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f, 0x00100012,
2382 0x00000001, 0x00100046, 0x00000000, 0x00100046, 0x00000001, 0x0700000f, 0x00100022, 0x00000001,
2383 0x00100046, 0x00000000, 0x00100046, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
2384 0x00000000, 0x00000002, 0x00100046, 0x00000004, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
2385 0x00000000, 0x00000003, 0x00100046, 0x00000004, 0x0700000f, 0x00100012, 0x00000000, 0x00100046,
2386 0x00000000, 0x00100ae6, 0x00000002, 0x07000031, 0x00100022, 0x00000000, 0x00004001, 0x00000000,
2387 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2388 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000, 0x00004001,
2389 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0010002a,
2390 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038, 0x001000c2,
2391 0x00000001, 0x00100ea6, 0x00000002, 0x00100556, 0x00000000, 0x08000036, 0x001000d2, 0x00000003,
2392 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2, 0x00000001,
2393 0x00100006, 0x00000000, 0x00100e46, 0x00000003, 0x00100e46, 0x00000001, 0x06000036, 0x00100032,
2394 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000, 0x00208406,
2395 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6,
2396 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000, 0x00004002,
2397 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002, 0x00100086,
2398 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x0100003e,
2400 static const DWORD vs_code_bezier
[] =
2405 float4
main(float4 position
: POSITION
,
2406 inout float3 texcoord
: TEXCOORD0
) : SV_POSITION
2408 return float4(mul(position
.xyw
, transform
), position
.zw
);
2411 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
2412 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
2413 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
2414 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
2415 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
2416 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
2417 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
2418 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
2419 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
2420 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
2421 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
2422 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
2423 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
2425 static const DWORD ps_code_triangle_solid
[] =
2429 * float4 main(float4 position : SV_POSITION) : SV_Target
2433 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
2434 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2435 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
2436 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2437 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
2438 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
2439 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2441 static const DWORD ps_code_triangle_solid_bitmap
[] =
2453 float4
main(float4 position
: SV_POSITION
) : SV_Target
2458 texcoord
.x
= position
.x
* transform
._11
+ position
.y
* transform
._21
+ transform
._31
;
2459 texcoord
.y
= position
.x
* transform
._12
+ position
.y
* transform
._22
+ transform
._32
;
2460 ret
= t
.Sample(s
, texcoord
) * opacity
;
2464 return color
* ret
.a
;
2467 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
2468 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2469 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2470 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2471 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
2472 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
2473 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2474 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2475 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
2476 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
2477 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
2478 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
2479 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
2480 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
2481 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
2482 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
2483 0x00000000, 0x0100003e,
2485 static const DWORD ps_code_triangle_bitmap
[] =
2495 float4
main(float4 position
: SV_POSITION
) : SV_Target
2500 texcoord
.x
= position
.x
* transform
._11
+ position
.y
* transform
._21
+ transform
._31
;
2501 texcoord
.y
= position
.x
* transform
._12
+ position
.y
* transform
._22
+ transform
._32
;
2502 ret
= t
.Sample(s
, texcoord
) * opacity
;
2509 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
2510 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2511 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2512 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2513 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
2514 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
2515 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2516 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2517 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
2518 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
2519 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
2520 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
2521 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
2522 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
2523 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
2524 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
2526 static const DWORD ps_code_triangle_bitmap_solid
[] =
2538 float4
main(float4 position
: SV_POSITION
) : SV_Target
2543 texcoord
.x
= position
.x
* transform
._11
+ position
.y
* transform
._21
+ transform
._31
;
2544 texcoord
.y
= position
.x
* transform
._12
+ position
.y
* transform
._22
+ transform
._32
;
2545 ret
= t
.Sample(s
, texcoord
) * opacity
;
2549 return ret
* color
.a
;
2552 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
2553 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2554 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2555 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2556 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
2557 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
2558 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2559 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2560 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
2561 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
2562 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
2563 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
2564 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
2565 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
2566 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
2567 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
2568 0x00000003, 0x0100003e,
2570 static const DWORD ps_code_triangle_bitmap_bitmap
[] =
2580 SamplerState s0
, s1
;
2583 float4
main(float4 position
: SV_POSITION
) : SV_Target
2589 texcoord
.x
= position
.x
* brush0
.transform
._11
+ position
.y
* brush0
.transform
._21
+ brush0
.transform
._31
;
2590 texcoord
.y
= position
.x
* brush0
.transform
._12
+ position
.y
* brush0
.transform
._22
+ brush0
.transform
._32
;
2591 ret
= t0
.Sample(s0
, texcoord
) * brush0
.opacity
;
2592 if (brush0
.ignore_alpha
)
2593 ret
.a
= brush0
.opacity
;
2595 texcoord
.x
= position
.x
* brush1
.transform
._11
+ position
.y
* brush1
.transform
._21
+ brush1
.transform
._31
;
2596 texcoord
.y
= position
.x
* brush1
.transform
._12
+ position
.y
* brush1
.transform
._22
+ brush1
.transform
._32
;
2597 opacity
= t1
.Sample(s1
, texcoord
).a
* brush1
.opacity
;
2598 if (brush1
.ignore_alpha
)
2599 opacity
= brush1
.opacity
;
2601 return ret
* opacity
;
2604 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
2605 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2606 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2607 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2608 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
2609 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
2610 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
2611 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
2612 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
2613 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
2614 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
2615 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
2616 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
2617 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
2618 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
2619 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
2620 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
2621 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
2622 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
2623 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
2624 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
2625 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
2626 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
2627 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
2628 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
2630 /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
2631 * using the screen-space partial derivatives to convert the calculated
2632 * distance to object space.
2634 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
2635 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
2636 * f(x, y) = u(x, y)² - v(x, y)
2637 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
2638 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
2639 static const DWORD ps_code_bezier_solid_outline
[] =
2644 float4
main(float4 position
: SV_POSITION
, float4 uv
: UV
,
2645 nointerpolation float2x2 stroke_transform
: STROKE_TRANSFORM
) : SV_Target
2649 du
= float2(ddx(uv
.x
), ddy(uv
.x
));
2650 dv
= float2(ddx(uv
.y
), ddy(uv
.y
));
2651 df
= 2.0f
* uv
.x
* du
- dv
;
2653 clip(dot(df
, uv
.zw
));
2654 clip(length(mul(stroke_transform
, df
)) - abs(uv
.x
* uv
.x
- uv
.y
));
2658 0x43425844, 0x9da521d4, 0x4c86449e, 0x4f2c1641, 0x6f798508, 0x00000001, 0x000002f4, 0x00000003,
2659 0x0000002c, 0x000000bc, 0x000000f0, 0x4e475349, 0x00000088, 0x00000004, 0x00000008, 0x00000068,
2660 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000074, 0x00000000, 0x00000000,
2661 0x00000003, 0x00000001, 0x00000f0f, 0x00000077, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2662 0x00000303, 0x00000077, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x505f5653,
2663 0x5449534f, 0x004e4f49, 0x53005655, 0x4b4f5254, 0x52545f45, 0x46534e41, 0x004d524f, 0x4e47534f,
2664 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
2665 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000001fc, 0x00000040, 0x0000007f,
2666 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x001010f2, 0x00000001, 0x03000862,
2667 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003, 0x03000065, 0x001020f2, 0x00000000,
2668 0x02000068, 0x00000002, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
2669 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x07000000, 0x00100012, 0x00000001, 0x0010100a,
2670 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x00100032, 0x00000000, 0x00100006, 0x00000001,
2671 0x00100086, 0x00000000, 0x801005d6, 0x00000041, 0x00000000, 0x0700000f, 0x00100042, 0x00000000,
2672 0x00100046, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100042, 0x00000000, 0x0010002a,
2673 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010002a, 0x00000000, 0x07000038, 0x00100062,
2674 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100032, 0x00000000,
2675 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596, 0x00000000, 0x0700000f, 0x00100012,
2676 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
2677 0x0010000a, 0x00000000, 0x0a000032, 0x00100022, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a,
2678 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012, 0x00000000, 0x8010001a,
2679 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012, 0x00000000, 0x0010000a,
2680 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x06000036, 0x001020f2,
2681 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2683 /* The basic idea here is to evaluate the implicit form of the curve in
2684 * texture space. "t.z" determines which side of the curve is shaded. */
2685 static const DWORD ps_code_bezier_solid
[] =
2690 float4
main(float4 position
: SV_POSITION
, float3 t
: TEXCOORD0
) : SV_Target
2692 clip((t
.x
* t
.x
- t
.y
) * t
.z
);
2696 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
2697 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
2698 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
2699 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
2700 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
2701 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
2702 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
2703 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
2704 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
2705 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
2706 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
2707 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2709 static const struct brush_shader
2711 const void *byte_code
;
2712 size_t byte_code_size
;
2713 enum d2d_shape_type shape_type
;
2714 enum d2d_brush_type brush_type
;
2715 enum d2d_brush_type opacity_brush_type
;
2719 {ps_code_triangle_solid
, sizeof(ps_code_triangle_solid
),
2720 D2D_SHAPE_TYPE_TRIANGLE
, D2D_BRUSH_TYPE_SOLID
, D2D_BRUSH_TYPE_COUNT
},
2721 {ps_code_triangle_solid_bitmap
, sizeof(ps_code_triangle_solid_bitmap
),
2722 D2D_SHAPE_TYPE_TRIANGLE
, D2D_BRUSH_TYPE_SOLID
, D2D_BRUSH_TYPE_BITMAP
},
2723 {ps_code_triangle_bitmap
, sizeof(ps_code_triangle_bitmap
),
2724 D2D_SHAPE_TYPE_TRIANGLE
, D2D_BRUSH_TYPE_BITMAP
, D2D_BRUSH_TYPE_COUNT
},
2725 {ps_code_triangle_bitmap_solid
, sizeof(ps_code_triangle_bitmap_solid
),
2726 D2D_SHAPE_TYPE_TRIANGLE
, D2D_BRUSH_TYPE_BITMAP
, D2D_BRUSH_TYPE_SOLID
},
2727 {ps_code_triangle_bitmap_bitmap
, sizeof(ps_code_triangle_bitmap_bitmap
),
2728 D2D_SHAPE_TYPE_TRIANGLE
, D2D_BRUSH_TYPE_BITMAP
, D2D_BRUSH_TYPE_BITMAP
},
2729 {ps_code_bezier_solid
, sizeof(ps_code_bezier_solid
),
2730 D2D_SHAPE_TYPE_BEZIER
, D2D_BRUSH_TYPE_SOLID
, D2D_BRUSH_TYPE_COUNT
},
2731 {ps_code_bezier_solid_outline
, sizeof(ps_code_bezier_solid_outline
),
2732 D2D_SHAPE_TYPE_BEZIER_OUTLINE
, D2D_BRUSH_TYPE_SOLID
, D2D_BRUSH_TYPE_COUNT
},
2745 static const UINT16 indices
[] = {0, 1, 2, 2, 1, 3};
2751 if (dpi_x
== 0.0f
&& dpi_y
== 0.0f
)
2756 else if (dpi_x
<= 0.0f
|| dpi_y
<= 0.0f
)
2757 return E_INVALIDARG
;
2759 if (desc
->type
!= D2D1_RENDER_TARGET_TYPE_DEFAULT
&& desc
->type
!= D2D1_RENDER_TARGET_TYPE_HARDWARE
)
2760 WARN("Ignoring render target type %#x.\n", desc
->type
);
2761 if (desc
->usage
!= D2D1_RENDER_TARGET_USAGE_NONE
)
2762 FIXME("Ignoring render target usage %#x.\n", desc
->usage
);
2763 if (desc
->minLevel
!= D2D1_FEATURE_LEVEL_DEFAULT
)
2764 WARN("Ignoring feature level %#x.\n", desc
->minLevel
);
2766 render_target
->ID2D1RenderTarget_iface
.lpVtbl
= &d2d_d3d_render_target_vtbl
;
2767 render_target
->ID2D1GdiInteropRenderTarget_iface
.lpVtbl
= &d2d_gdi_interop_render_target_vtbl
;
2768 render_target
->IDWriteTextRenderer_iface
.lpVtbl
= &d2d_text_renderer_vtbl
;
2769 render_target
->refcount
= 1;
2770 render_target
->factory
= factory
;
2771 ID2D1Factory_AddRef(render_target
->factory
);
2773 render_target
->outer_unknown
= outer_unknown
? outer_unknown
:
2774 (IUnknown
*)&render_target
->ID2D1RenderTarget_iface
;
2776 if (FAILED(hr
= IDXGISurface_GetDevice(surface
, &IID_ID3D10Device
, (void **)&render_target
->device
)))
2778 WARN("Failed to get device interface, hr %#x.\n", hr
);
2779 ID2D1Factory_Release(render_target
->factory
);
2783 if (FAILED(hr
= IDXGISurface_QueryInterface(surface
, &IID_ID3D10Resource
, (void **)&resource
)))
2785 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr
);
2789 hr
= ID3D10Device_CreateRenderTargetView(render_target
->device
, resource
, NULL
, &render_target
->view
);
2790 ID3D10Resource_Release(resource
);
2793 WARN("Failed to create rendertarget view, hr %#x.\n", hr
);
2797 if (FAILED(hr
= D3D10StateBlockMaskEnableAll(&state_mask
)))
2799 WARN("Failed to create stateblock mask, hr %#x.\n", hr
);
2803 if (FAILED(hr
= D3D10CreateStateBlock(render_target
->device
, &state_mask
, &render_target
->stateblock
)))
2805 WARN("Failed to create stateblock, hr %#x.\n", hr
);
2809 if (FAILED(hr
= ID3D10Device_CreateInputLayout(render_target
->device
, il_desc_outline
,
2810 ARRAY_SIZE(il_desc_outline
), vs_code_outline
, sizeof(vs_code_outline
),
2811 &render_target
->shape_resources
[D2D_SHAPE_TYPE_OUTLINE
].il
)))
2813 WARN("Failed to create outline input layout, hr %#x.\n", hr
);
2817 if (FAILED(hr
= ID3D10Device_CreateInputLayout(render_target
->device
, il_desc_triangle
,
2818 ARRAY_SIZE(il_desc_triangle
), vs_code_triangle
, sizeof(vs_code_triangle
),
2819 &render_target
->shape_resources
[D2D_SHAPE_TYPE_TRIANGLE
].il
)))
2821 WARN("Failed to create triangle input layout, hr %#x.\n", hr
);
2825 if (FAILED(hr
= ID3D10Device_CreateInputLayout(render_target
->device
, il_desc_bezier_outline
,
2826 ARRAY_SIZE(il_desc_bezier_outline
), vs_code_bezier_outline
, sizeof(vs_code_bezier_outline
),
2827 &render_target
->shape_resources
[D2D_SHAPE_TYPE_BEZIER_OUTLINE
].il
)))
2829 WARN("Failed to create bezier outline input layout, hr %#x.\n", hr
);
2833 if (FAILED(hr
= ID3D10Device_CreateInputLayout(render_target
->device
, il_desc_bezier
,
2834 ARRAY_SIZE(il_desc_bezier
), vs_code_bezier
, sizeof(vs_code_bezier
),
2835 &render_target
->shape_resources
[D2D_SHAPE_TYPE_BEZIER
].il
)))
2837 WARN("Failed to create bezier input layout, hr %#x.\n", hr
);
2841 if (FAILED(hr
= ID3D10Device_CreateVertexShader(render_target
->device
, vs_code_outline
,
2842 sizeof(vs_code_outline
), &render_target
->shape_resources
[D2D_SHAPE_TYPE_OUTLINE
].vs
)))
2844 WARN("Failed to create outline vertex shader, hr %#x.\n", hr
);
2848 if (FAILED(hr
= ID3D10Device_CreateVertexShader(render_target
->device
, vs_code_bezier_outline
,
2849 sizeof(vs_code_bezier_outline
), &render_target
->shape_resources
[D2D_SHAPE_TYPE_BEZIER_OUTLINE
].vs
)))
2851 WARN("Failed to create bezier outline vertex shader, hr %#x.\n", hr
);
2855 if (FAILED(hr
= ID3D10Device_CreateVertexShader(render_target
->device
, vs_code_triangle
,
2856 sizeof(vs_code_triangle
), &render_target
->shape_resources
[D2D_SHAPE_TYPE_TRIANGLE
].vs
)))
2858 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr
);
2862 if (FAILED(hr
= ID3D10Device_CreateVertexShader(render_target
->device
, vs_code_bezier
,
2863 sizeof(vs_code_bezier
), &render_target
->shape_resources
[D2D_SHAPE_TYPE_BEZIER
].vs
)))
2865 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr
);
2869 for (i
= 0; i
< ARRAY_SIZE(brush_shaders
); ++i
)
2871 const struct brush_shader
*bs
= &brush_shaders
[i
];
2872 if (FAILED(hr
= ID3D10Device_CreatePixelShader(render_target
->device
, bs
->byte_code
, bs
->byte_code_size
,
2873 &render_target
->shape_resources
[bs
->shape_type
].ps
[bs
->brush_type
][bs
->opacity_brush_type
])))
2875 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
2876 bs
->shape_type
, bs
->brush_type
, bs
->opacity_brush_type
);
2881 for (j
= 0; j
< D2D_BRUSH_TYPE_COUNT
; ++j
)
2883 for (k
= 0; k
< D2D_BRUSH_TYPE_COUNT
+ 1; ++k
)
2885 struct d2d_shape_resources
*outline
= &render_target
->shape_resources
[D2D_SHAPE_TYPE_OUTLINE
];
2886 struct d2d_shape_resources
*triangle
= &render_target
->shape_resources
[D2D_SHAPE_TYPE_TRIANGLE
];
2888 if (triangle
->ps
[j
][k
])
2889 ID3D10PixelShader_AddRef(outline
->ps
[j
][k
] = triangle
->ps
[j
][k
]);
2893 buffer_desc
.ByteWidth
= sizeof(indices
);
2894 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
2895 buffer_desc
.BindFlags
= D3D10_BIND_INDEX_BUFFER
;
2896 buffer_desc
.CPUAccessFlags
= 0;
2897 buffer_desc
.MiscFlags
= 0;
2899 buffer_data
.pSysMem
= indices
;
2900 buffer_data
.SysMemPitch
= 0;
2901 buffer_data
.SysMemSlicePitch
= 0;
2903 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
,
2904 &buffer_desc
, &buffer_data
, &render_target
->ib
)))
2906 WARN("Failed to create clear index buffer, hr %#x.\n", hr
);
2910 buffer_desc
.ByteWidth
= sizeof(quad
);
2911 buffer_desc
.BindFlags
= D3D10_BIND_VERTEX_BUFFER
;
2912 buffer_data
.pSysMem
= quad
;
2914 render_target
->vb_stride
= sizeof(*quad
);
2915 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
,
2916 &buffer_desc
, &buffer_data
, &render_target
->vb
)))
2918 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr
);
2922 rs_desc
.FillMode
= D3D10_FILL_SOLID
;
2923 rs_desc
.CullMode
= D3D10_CULL_NONE
;
2924 rs_desc
.FrontCounterClockwise
= FALSE
;
2925 rs_desc
.DepthBias
= 0;
2926 rs_desc
.DepthBiasClamp
= 0.0f
;
2927 rs_desc
.SlopeScaledDepthBias
= 0.0f
;
2928 rs_desc
.DepthClipEnable
= TRUE
;
2929 rs_desc
.ScissorEnable
= TRUE
;
2930 rs_desc
.MultisampleEnable
= FALSE
;
2931 rs_desc
.AntialiasedLineEnable
= FALSE
;
2932 if (FAILED(hr
= ID3D10Device_CreateRasterizerState(render_target
->device
, &rs_desc
, &render_target
->rs
)))
2934 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr
);
2938 memset(&blend_desc
, 0, sizeof(blend_desc
));
2939 blend_desc
.BlendEnable
[0] = TRUE
;
2940 blend_desc
.SrcBlend
= D3D10_BLEND_ONE
;
2941 blend_desc
.DestBlend
= D3D10_BLEND_INV_SRC_ALPHA
;
2942 blend_desc
.BlendOp
= D3D10_BLEND_OP_ADD
;
2943 if (desc
->pixelFormat
.alphaMode
== D2D1_ALPHA_MODE_IGNORE
)
2945 blend_desc
.SrcBlendAlpha
= D3D10_BLEND_ZERO
;
2946 blend_desc
.DestBlendAlpha
= D3D10_BLEND_ONE
;
2950 blend_desc
.SrcBlendAlpha
= D3D10_BLEND_ONE
;
2951 blend_desc
.DestBlendAlpha
= D3D10_BLEND_INV_SRC_ALPHA
;
2953 blend_desc
.BlendOpAlpha
= D3D10_BLEND_OP_ADD
;
2954 blend_desc
.RenderTargetWriteMask
[0] = D3D10_COLOR_WRITE_ENABLE_ALL
;
2955 if (FAILED(hr
= ID3D10Device_CreateBlendState(render_target
->device
, &blend_desc
, &render_target
->bs
)))
2957 WARN("Failed to create blend state, hr %#x.\n", hr
);
2961 if (FAILED(hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
,
2962 &IID_IDWriteFactory
, (IUnknown
**)&dwrite_factory
)))
2964 ERR("Failed to create dwrite factory, hr %#x.\n", hr
);
2968 hr
= IDWriteFactory_CreateRenderingParams(dwrite_factory
, &render_target
->default_text_rendering_params
);
2969 IDWriteFactory_Release(dwrite_factory
);
2972 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr
);
2976 if (FAILED(hr
= IDXGISurface_GetDesc(surface
, &surface_desc
)))
2978 WARN("Failed to get surface desc, hr %#x.\n", hr
);
2982 render_target
->desc
.pixelFormat
= desc
->pixelFormat
;
2983 render_target
->pixel_size
.width
= surface_desc
.Width
;
2984 render_target
->pixel_size
.height
= surface_desc
.Height
;
2985 render_target
->drawing_state
.transform
= identity
;
2987 if (!d2d_clip_stack_init(&render_target
->clip_stack
))
2989 WARN("Failed to initialize clip stack.\n");
2994 render_target
->desc
.dpiX
= dpi_x
;
2995 render_target
->desc
.dpiY
= dpi_y
;
3000 if (render_target
->default_text_rendering_params
)
3001 IDWriteRenderingParams_Release(render_target
->default_text_rendering_params
);
3002 if (render_target
->bs
)
3003 ID3D10BlendState_Release(render_target
->bs
);
3004 if (render_target
->rs
)
3005 ID3D10RasterizerState_Release(render_target
->rs
);
3006 if (render_target
->vb
)
3007 ID3D10Buffer_Release(render_target
->vb
);
3008 if (render_target
->ib
)
3009 ID3D10Buffer_Release(render_target
->ib
);
3010 for (i
= 0; i
< D2D_SHAPE_TYPE_COUNT
; ++i
)
3012 for (j
= 0; j
< D2D_BRUSH_TYPE_COUNT
; ++j
)
3014 for (k
= 0; k
< D2D_BRUSH_TYPE_COUNT
+ 1; ++k
)
3016 if (render_target
->shape_resources
[i
].ps
[j
][k
])
3017 ID3D10PixelShader_Release(render_target
->shape_resources
[i
].ps
[j
][k
]);
3020 if (render_target
->shape_resources
[i
].vs
)
3021 ID3D10VertexShader_Release(render_target
->shape_resources
[i
].vs
);
3022 if (render_target
->shape_resources
[i
].il
)
3023 ID3D10InputLayout_Release(render_target
->shape_resources
[i
].il
);
3025 if (render_target
->stateblock
)
3026 render_target
->stateblock
->lpVtbl
->Release(render_target
->stateblock
);
3027 if (render_target
->view
)
3028 ID3D10RenderTargetView_Release(render_target
->view
);
3029 if (render_target
->device
)
3030 ID3D10Device_Release(render_target
->device
);
3031 ID2D1Factory_Release(render_target
->factory
);
3035 HRESULT
d2d_d3d_create_render_target(ID2D1Factory
*factory
, IDXGISurface
*surface
, IUnknown
*outer_unknown
,
3036 const D2D1_RENDER_TARGET_PROPERTIES
*desc
, ID2D1RenderTarget
**render_target
)
3038 struct d2d_d3d_render_target
*object
;
3041 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
3042 return E_OUTOFMEMORY
;
3044 if (FAILED(hr
= d2d_d3d_render_target_init(object
, factory
, surface
, outer_unknown
, desc
)))
3046 WARN("Failed to initialize render target, hr %#x.\n", hr
);
3047 HeapFree(GetProcessHeap(), 0, object
);
3051 TRACE("Created render target %p.\n", object
);
3052 *render_target
= &object
->ID2D1RenderTarget_iface
;
3057 HRESULT
d2d_d3d_render_target_create_rtv(ID2D1RenderTarget
*iface
, IDXGISurface1
*surface
)
3059 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
3060 DXGI_SURFACE_DESC surface_desc
;
3061 ID3D10RenderTargetView
*view
;
3062 ID3D10Resource
*resource
;
3067 ID3D10RenderTargetView_Release(render_target
->view
);
3068 render_target
->view
= NULL
;
3072 if (FAILED(hr
= IDXGISurface1_GetDesc(surface
, &surface_desc
)))
3074 WARN("Failed to get surface desc, hr %#x.\n", hr
);
3078 if (FAILED(hr
= IDXGISurface1_QueryInterface(surface
, &IID_ID3D10Resource
, (void **)&resource
)))
3080 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr
);
3084 hr
= ID3D10Device_CreateRenderTargetView(render_target
->device
, resource
, NULL
, &view
);
3085 ID3D10Resource_Release(resource
);
3088 WARN("Failed to create rendertarget view, hr %#x.\n", hr
);
3092 render_target
->pixel_size
.width
= surface_desc
.Width
;
3093 render_target
->pixel_size
.height
= surface_desc
.Height
;
3094 if (render_target
->view
)
3095 ID3D10RenderTargetView_Release(render_target
->view
);
3096 render_target
->view
= view
;