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 static inline struct d2d_gradient
*impl_from_ID2D1GradientStopCollection(ID2D1GradientStopCollection
*iface
)
28 return CONTAINING_RECORD(iface
, struct d2d_gradient
, ID2D1GradientStopCollection_iface
);
31 static HRESULT STDMETHODCALLTYPE
d2d_gradient_QueryInterface(ID2D1GradientStopCollection
*iface
,
32 REFIID iid
, void **out
)
34 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
36 if (IsEqualGUID(iid
, &IID_ID2D1GradientStopCollection
)
37 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
38 || IsEqualGUID(iid
, &IID_IUnknown
))
40 ID2D1GradientStopCollection_AddRef(iface
);
45 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
51 static ULONG STDMETHODCALLTYPE
d2d_gradient_AddRef(ID2D1GradientStopCollection
*iface
)
53 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
54 ULONG refcount
= InterlockedIncrement(&gradient
->refcount
);
56 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
61 static ULONG STDMETHODCALLTYPE
d2d_gradient_Release(ID2D1GradientStopCollection
*iface
)
63 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
64 ULONG refcount
= InterlockedDecrement(&gradient
->refcount
);
66 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
70 HeapFree(GetProcessHeap(), 0, gradient
->stops
);
71 ID2D1Factory_Release(gradient
->factory
);
72 HeapFree(GetProcessHeap(), 0, gradient
);
78 static void STDMETHODCALLTYPE
d2d_gradient_GetFactory(ID2D1GradientStopCollection
*iface
, ID2D1Factory
**factory
)
80 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
82 TRACE("iface %p, factory %p.\n", iface
, factory
);
84 ID2D1Factory_AddRef(*factory
= gradient
->factory
);
87 static UINT32 STDMETHODCALLTYPE
d2d_gradient_GetGradientStopCount(ID2D1GradientStopCollection
*iface
)
89 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
91 TRACE("iface %p.\n", iface
);
93 return gradient
->stop_count
;
96 static void STDMETHODCALLTYPE
d2d_gradient_GetGradientStops(ID2D1GradientStopCollection
*iface
,
97 D2D1_GRADIENT_STOP
*stops
, UINT32 stop_count
)
99 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
101 TRACE("iface %p, stops %p, stop_count %u.\n", iface
, stops
, stop_count
);
103 memcpy(stops
, gradient
->stops
, min(gradient
->stop_count
, stop_count
) * sizeof(*stops
));
104 if (stop_count
> gradient
->stop_count
)
105 memset(stops
, 0, (stop_count
- gradient
->stop_count
) * sizeof(*stops
));
108 static D2D1_GAMMA STDMETHODCALLTYPE
d2d_gradient_GetColorInterpolationGamma(ID2D1GradientStopCollection
*iface
)
110 FIXME("iface %p stub!\n", iface
);
112 return D2D1_GAMMA_1_0
;
115 static D2D1_EXTEND_MODE STDMETHODCALLTYPE
d2d_gradient_GetExtendMode(ID2D1GradientStopCollection
*iface
)
117 FIXME("iface %p stub!\n", iface
);
119 return D2D1_EXTEND_MODE_CLAMP
;
122 static const struct ID2D1GradientStopCollectionVtbl d2d_gradient_vtbl
=
124 d2d_gradient_QueryInterface
,
126 d2d_gradient_Release
,
127 d2d_gradient_GetFactory
,
128 d2d_gradient_GetGradientStopCount
,
129 d2d_gradient_GetGradientStops
,
130 d2d_gradient_GetColorInterpolationGamma
,
131 d2d_gradient_GetExtendMode
,
134 HRESULT
d2d_gradient_init(struct d2d_gradient
*gradient
, ID2D1Factory
*factory
,
135 const D2D1_GRADIENT_STOP
*stops
, UINT32 stop_count
, D2D1_GAMMA gamma
, D2D1_EXTEND_MODE extend_mode
)
137 FIXME("Ignoring gradient properties.\n");
139 gradient
->ID2D1GradientStopCollection_iface
.lpVtbl
= &d2d_gradient_vtbl
;
140 gradient
->refcount
= 1;
141 ID2D1Factory_AddRef(gradient
->factory
= factory
);
143 gradient
->stop_count
= stop_count
;
144 if (!(gradient
->stops
= HeapAlloc(GetProcessHeap(), 0, stop_count
* sizeof(*stops
))))
145 return E_OUTOFMEMORY
;
146 memcpy(gradient
->stops
, stops
, stop_count
* sizeof(*stops
));
151 static void d2d_brush_destroy(struct d2d_brush
*brush
)
153 ID2D1Factory_Release(brush
->factory
);
154 HeapFree(GetProcessHeap(), 0, brush
);
157 static void d2d_brush_init(struct d2d_brush
*brush
, ID2D1Factory
*factory
,
158 enum d2d_brush_type type
, const D2D1_BRUSH_PROPERTIES
*desc
, const struct ID2D1BrushVtbl
*vtbl
)
160 static const D2D1_MATRIX_3X2_F identity
=
167 brush
->ID2D1Brush_iface
.lpVtbl
= vtbl
;
169 ID2D1Factory_AddRef(brush
->factory
= factory
);
170 brush
->opacity
= desc
? desc
->opacity
: 1.0f
;
171 brush
->transform
= desc
? desc
->transform
: identity
;
175 static inline struct d2d_brush
*impl_from_ID2D1SolidColorBrush(ID2D1SolidColorBrush
*iface
)
177 return CONTAINING_RECORD(iface
, struct d2d_brush
, ID2D1Brush_iface
);
180 static HRESULT STDMETHODCALLTYPE
d2d_solid_color_brush_QueryInterface(ID2D1SolidColorBrush
*iface
,
181 REFIID iid
, void **out
)
183 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
185 if (IsEqualGUID(iid
, &IID_ID2D1SolidColorBrush
)
186 || IsEqualGUID(iid
, &IID_ID2D1Brush
)
187 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
188 || IsEqualGUID(iid
, &IID_IUnknown
))
190 ID2D1SolidColorBrush_AddRef(iface
);
195 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
198 return E_NOINTERFACE
;
201 static ULONG STDMETHODCALLTYPE
d2d_solid_color_brush_AddRef(ID2D1SolidColorBrush
*iface
)
203 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
204 ULONG refcount
= InterlockedIncrement(&brush
->refcount
);
206 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
211 static ULONG STDMETHODCALLTYPE
d2d_solid_color_brush_Release(ID2D1SolidColorBrush
*iface
)
213 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
214 ULONG refcount
= InterlockedDecrement(&brush
->refcount
);
216 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
219 d2d_brush_destroy(brush
);
224 static void STDMETHODCALLTYPE
d2d_solid_color_brush_GetFactory(ID2D1SolidColorBrush
*iface
, ID2D1Factory
**factory
)
226 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
228 TRACE("iface %p, factory %p.\n", iface
, factory
);
230 ID2D1Factory_AddRef(*factory
= brush
->factory
);
233 static void STDMETHODCALLTYPE
d2d_solid_color_brush_SetOpacity(ID2D1SolidColorBrush
*iface
, float opacity
)
235 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
237 TRACE("iface %p, opacity %.8e.\n", iface
, opacity
);
239 brush
->opacity
= opacity
;
242 static void STDMETHODCALLTYPE
d2d_solid_color_brush_SetTransform(ID2D1SolidColorBrush
*iface
,
243 const D2D1_MATRIX_3X2_F
*transform
)
245 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
247 TRACE("iface %p, transform %p.\n", iface
, transform
);
249 brush
->transform
= *transform
;
252 static float STDMETHODCALLTYPE
d2d_solid_color_brush_GetOpacity(ID2D1SolidColorBrush
*iface
)
254 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
256 TRACE("iface %p.\n", iface
);
258 return brush
->opacity
;
261 static void STDMETHODCALLTYPE
d2d_solid_color_brush_GetTransform(ID2D1SolidColorBrush
*iface
,
262 D2D1_MATRIX_3X2_F
*transform
)
264 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
266 TRACE("iface %p, transform %p.\n", iface
, transform
);
268 *transform
= brush
->transform
;
271 static void STDMETHODCALLTYPE
d2d_solid_color_brush_SetColor(ID2D1SolidColorBrush
*iface
, const D2D1_COLOR_F
*color
)
273 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
275 TRACE("iface %p, color %p.\n", iface
, color
);
277 brush
->u
.solid
.color
= *color
;
280 static D2D1_COLOR_F
* STDMETHODCALLTYPE
d2d_solid_color_brush_GetColor(ID2D1SolidColorBrush
*iface
, D2D1_COLOR_F
*color
)
282 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
284 TRACE("iface %p, color %p.\n", iface
, color
);
286 *color
= brush
->u
.solid
.color
;
290 static const struct ID2D1SolidColorBrushVtbl d2d_solid_color_brush_vtbl
=
292 d2d_solid_color_brush_QueryInterface
,
293 d2d_solid_color_brush_AddRef
,
294 d2d_solid_color_brush_Release
,
295 d2d_solid_color_brush_GetFactory
,
296 d2d_solid_color_brush_SetOpacity
,
297 d2d_solid_color_brush_SetTransform
,
298 d2d_solid_color_brush_GetOpacity
,
299 d2d_solid_color_brush_GetTransform
,
300 d2d_solid_color_brush_SetColor
,
301 d2d_solid_color_brush_GetColor
,
304 void d2d_solid_color_brush_init(struct d2d_brush
*brush
, ID2D1Factory
*factory
,
305 const D2D1_COLOR_F
*color
, const D2D1_BRUSH_PROPERTIES
*desc
)
307 d2d_brush_init(brush
, factory
, D2D_BRUSH_TYPE_SOLID
, desc
,
308 (ID2D1BrushVtbl
*)&d2d_solid_color_brush_vtbl
);
309 brush
->u
.solid
.color
= *color
;
312 static inline struct d2d_brush
*impl_from_ID2D1LinearGradientBrush(ID2D1LinearGradientBrush
*iface
)
314 return CONTAINING_RECORD(iface
, struct d2d_brush
, ID2D1Brush_iface
);
317 static HRESULT STDMETHODCALLTYPE
d2d_linear_gradient_brush_QueryInterface(ID2D1LinearGradientBrush
*iface
,
318 REFIID iid
, void **out
)
320 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
322 if (IsEqualGUID(iid
, &IID_ID2D1LinearGradientBrush
)
323 || IsEqualGUID(iid
, &IID_ID2D1Brush
)
324 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
325 || IsEqualGUID(iid
, &IID_IUnknown
))
327 ID2D1LinearGradientBrush_AddRef(iface
);
332 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
335 return E_NOINTERFACE
;
338 static ULONG STDMETHODCALLTYPE
d2d_linear_gradient_brush_AddRef(ID2D1LinearGradientBrush
*iface
)
340 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
341 ULONG refcount
= InterlockedIncrement(&brush
->refcount
);
343 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
348 static ULONG STDMETHODCALLTYPE
d2d_linear_gradient_brush_Release(ID2D1LinearGradientBrush
*iface
)
350 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
351 ULONG refcount
= InterlockedDecrement(&brush
->refcount
);
353 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
356 d2d_brush_destroy(brush
);
361 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetFactory(ID2D1LinearGradientBrush
*iface
,
362 ID2D1Factory
**factory
)
364 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
366 TRACE("iface %p, factory %p.\n", iface
, factory
);
368 ID2D1Factory_AddRef(*factory
= brush
->factory
);
371 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_SetOpacity(ID2D1LinearGradientBrush
*iface
, float opacity
)
373 FIXME("iface %p, opacity %.8e stub!\n", iface
, opacity
);
376 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_SetTransform(ID2D1LinearGradientBrush
*iface
,
377 const D2D1_MATRIX_3X2_F
*transform
)
379 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
381 TRACE("iface %p, transform %p.\n", iface
, transform
);
383 brush
->transform
= *transform
;
386 static float STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetOpacity(ID2D1LinearGradientBrush
*iface
)
388 FIXME("iface %p stub!\n", iface
);
393 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetTransform(ID2D1LinearGradientBrush
*iface
,
394 D2D1_MATRIX_3X2_F
*transform
)
396 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
398 TRACE("iface %p, transform %p.\n", iface
, transform
);
400 *transform
= brush
->transform
;
403 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_SetStartPoint(ID2D1LinearGradientBrush
*iface
,
404 D2D1_POINT_2F start_point
)
406 FIXME("iface %p, start_point {%.8e, %.8e} stub!\n", iface
, start_point
.x
, start_point
.y
);
409 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_SetEndPoint(ID2D1LinearGradientBrush
*iface
,
410 D2D1_POINT_2F end_point
)
412 FIXME("iface %p, end_point {%.8e, %.8e} stub!\n", iface
, end_point
.x
, end_point
.y
);
415 static D2D1_POINT_2F
* STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetStartPoint(ID2D1LinearGradientBrush
*iface
,
416 D2D1_POINT_2F
*point
)
418 FIXME("iface %p, point %p stub!\n", iface
, point
);
425 static D2D1_POINT_2F
* STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetEndPoint(ID2D1LinearGradientBrush
*iface
,
426 D2D1_POINT_2F
*point
)
428 FIXME("iface %p, point %p stub!\n", iface
, point
);
435 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetGradientStopCollection(ID2D1LinearGradientBrush
*iface
,
436 ID2D1GradientStopCollection
**gradient
)
438 FIXME("iface %p, gradient %p stub!\n", iface
, gradient
);
443 static const struct ID2D1LinearGradientBrushVtbl d2d_linear_gradient_brush_vtbl
=
445 d2d_linear_gradient_brush_QueryInterface
,
446 d2d_linear_gradient_brush_AddRef
,
447 d2d_linear_gradient_brush_Release
,
448 d2d_linear_gradient_brush_GetFactory
,
449 d2d_linear_gradient_brush_SetOpacity
,
450 d2d_linear_gradient_brush_SetTransform
,
451 d2d_linear_gradient_brush_GetOpacity
,
452 d2d_linear_gradient_brush_GetTransform
,
453 d2d_linear_gradient_brush_SetStartPoint
,
454 d2d_linear_gradient_brush_SetEndPoint
,
455 d2d_linear_gradient_brush_GetStartPoint
,
456 d2d_linear_gradient_brush_GetEndPoint
,
457 d2d_linear_gradient_brush_GetGradientStopCollection
,
460 void d2d_linear_gradient_brush_init(struct d2d_brush
*brush
, ID2D1Factory
*factory
,
461 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES
*gradient_brush_desc
, const D2D1_BRUSH_PROPERTIES
*brush_desc
,
462 ID2D1GradientStopCollection
*gradient
)
464 FIXME("Ignoring brush properties.\n");
466 d2d_brush_init(brush
, factory
, D2D_BRUSH_TYPE_LINEAR
, brush_desc
,
467 (ID2D1BrushVtbl
*)&d2d_linear_gradient_brush_vtbl
);
470 static inline struct d2d_brush
*impl_from_ID2D1BitmapBrush(ID2D1BitmapBrush
*iface
)
472 return CONTAINING_RECORD(iface
, struct d2d_brush
, ID2D1Brush_iface
);
475 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_brush_QueryInterface(ID2D1BitmapBrush
*iface
,
476 REFIID iid
, void **out
)
478 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
480 if (IsEqualGUID(iid
, &IID_ID2D1BitmapBrush
)
481 || IsEqualGUID(iid
, &IID_ID2D1Brush
)
482 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
483 || IsEqualGUID(iid
, &IID_IUnknown
))
485 ID2D1BitmapBrush_AddRef(iface
);
490 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
493 return E_NOINTERFACE
;
496 static ULONG STDMETHODCALLTYPE
d2d_bitmap_brush_AddRef(ID2D1BitmapBrush
*iface
)
498 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
499 ULONG refcount
= InterlockedIncrement(&brush
->refcount
);
501 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
506 static ULONG STDMETHODCALLTYPE
d2d_bitmap_brush_Release(ID2D1BitmapBrush
*iface
)
508 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
509 ULONG refcount
= InterlockedDecrement(&brush
->refcount
);
511 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
515 if (brush
->u
.bitmap
.sampler_state
)
516 ID3D10SamplerState_Release(brush
->u
.bitmap
.sampler_state
);
517 if (brush
->u
.bitmap
.bitmap
)
518 ID2D1Bitmap_Release(&brush
->u
.bitmap
.bitmap
->ID2D1Bitmap_iface
);
519 d2d_brush_destroy(brush
);
525 static void STDMETHODCALLTYPE
d2d_bitmap_brush_GetFactory(ID2D1BitmapBrush
*iface
,
526 ID2D1Factory
**factory
)
528 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
530 TRACE("iface %p, factory %p.\n", iface
, factory
);
532 ID2D1Factory_AddRef(*factory
= brush
->factory
);
535 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetOpacity(ID2D1BitmapBrush
*iface
, float opacity
)
537 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
539 TRACE("iface %p, opacity %.8e.\n", iface
, opacity
);
541 brush
->opacity
= opacity
;
544 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetTransform(ID2D1BitmapBrush
*iface
,
545 const D2D1_MATRIX_3X2_F
*transform
)
547 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
549 TRACE("iface %p, transform %p.\n", iface
, transform
);
551 brush
->transform
= *transform
;
554 static float STDMETHODCALLTYPE
d2d_bitmap_brush_GetOpacity(ID2D1BitmapBrush
*iface
)
556 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
558 TRACE("iface %p.\n", iface
);
560 return brush
->opacity
;
563 static void STDMETHODCALLTYPE
d2d_bitmap_brush_GetTransform(ID2D1BitmapBrush
*iface
,
564 D2D1_MATRIX_3X2_F
*transform
)
566 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
568 TRACE("iface %p, transform %p.\n", iface
, transform
);
570 *transform
= brush
->transform
;
573 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetExtendModeX(ID2D1BitmapBrush
*iface
, D2D1_EXTEND_MODE mode
)
575 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
577 TRACE("iface %p, mode %#x.\n", iface
, mode
);
579 brush
->u
.bitmap
.extend_mode_x
= mode
;
580 if (brush
->u
.bitmap
.sampler_state
)
582 ID3D10SamplerState_Release(brush
->u
.bitmap
.sampler_state
);
583 brush
->u
.bitmap
.sampler_state
= NULL
;
587 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetExtendModeY(ID2D1BitmapBrush
*iface
, D2D1_EXTEND_MODE mode
)
589 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
591 TRACE("iface %p, mode %#x.\n", iface
, mode
);
593 brush
->u
.bitmap
.extend_mode_y
= mode
;
594 if (brush
->u
.bitmap
.sampler_state
)
596 ID3D10SamplerState_Release(brush
->u
.bitmap
.sampler_state
);
597 brush
->u
.bitmap
.sampler_state
= NULL
;
601 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetInterpolationMode(ID2D1BitmapBrush
*iface
,
602 D2D1_BITMAP_INTERPOLATION_MODE mode
)
604 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
606 TRACE("iface %p, mode %#x.\n", iface
, mode
);
608 brush
->u
.bitmap
.interpolation_mode
= mode
;
609 if (brush
->u
.bitmap
.sampler_state
)
611 ID3D10SamplerState_Release(brush
->u
.bitmap
.sampler_state
);
612 brush
->u
.bitmap
.sampler_state
= NULL
;
616 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetBitmap(ID2D1BitmapBrush
*iface
, ID2D1Bitmap
*bitmap
)
618 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
620 TRACE("iface %p, bitmap %p.\n", iface
, bitmap
);
623 ID2D1Bitmap_AddRef(bitmap
);
624 if (brush
->u
.bitmap
.bitmap
)
625 ID2D1Bitmap_Release(&brush
->u
.bitmap
.bitmap
->ID2D1Bitmap_iface
);
626 brush
->u
.bitmap
.bitmap
= unsafe_impl_from_ID2D1Bitmap(bitmap
);
629 static D2D1_EXTEND_MODE STDMETHODCALLTYPE
d2d_bitmap_brush_GetExtendModeX(ID2D1BitmapBrush
*iface
)
631 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
633 TRACE("iface %p.\n", iface
);
635 return brush
->u
.bitmap
.extend_mode_x
;
638 static D2D1_EXTEND_MODE STDMETHODCALLTYPE
d2d_bitmap_brush_GetExtendModeY(ID2D1BitmapBrush
*iface
)
640 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
642 TRACE("iface %p.\n", iface
);
644 return brush
->u
.bitmap
.extend_mode_y
;
647 static D2D1_BITMAP_INTERPOLATION_MODE STDMETHODCALLTYPE
d2d_bitmap_brush_GetInterpolationMode(ID2D1BitmapBrush
*iface
)
649 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
651 TRACE("iface %p.\n", iface
);
653 return brush
->u
.bitmap
.interpolation_mode
;
656 static void STDMETHODCALLTYPE
d2d_bitmap_brush_GetBitmap(ID2D1BitmapBrush
*iface
, ID2D1Bitmap
**bitmap
)
658 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
660 TRACE("iface %p, bitmap %p.\n", iface
, bitmap
);
662 if ((*bitmap
= &brush
->u
.bitmap
.bitmap
->ID2D1Bitmap_iface
))
663 ID2D1Bitmap_AddRef(*bitmap
);
666 static const struct ID2D1BitmapBrushVtbl d2d_bitmap_brush_vtbl
=
668 d2d_bitmap_brush_QueryInterface
,
669 d2d_bitmap_brush_AddRef
,
670 d2d_bitmap_brush_Release
,
671 d2d_bitmap_brush_GetFactory
,
672 d2d_bitmap_brush_SetOpacity
,
673 d2d_bitmap_brush_SetTransform
,
674 d2d_bitmap_brush_GetOpacity
,
675 d2d_bitmap_brush_GetTransform
,
676 d2d_bitmap_brush_SetExtendModeX
,
677 d2d_bitmap_brush_SetExtendModeY
,
678 d2d_bitmap_brush_SetInterpolationMode
,
679 d2d_bitmap_brush_SetBitmap
,
680 d2d_bitmap_brush_GetExtendModeX
,
681 d2d_bitmap_brush_GetExtendModeY
,
682 d2d_bitmap_brush_GetInterpolationMode
,
683 d2d_bitmap_brush_GetBitmap
,
686 void d2d_bitmap_brush_init(struct d2d_brush
*brush
, ID2D1Factory
*factory
, ID2D1Bitmap
*bitmap
,
687 const D2D1_BITMAP_BRUSH_PROPERTIES
*bitmap_brush_desc
, const D2D1_BRUSH_PROPERTIES
*brush_desc
)
689 d2d_brush_init(brush
, factory
, D2D_BRUSH_TYPE_BITMAP
,
690 brush_desc
, (ID2D1BrushVtbl
*)&d2d_bitmap_brush_vtbl
);
691 if ((brush
->u
.bitmap
.bitmap
= unsafe_impl_from_ID2D1Bitmap(bitmap
)))
692 ID2D1Bitmap_AddRef(&brush
->u
.bitmap
.bitmap
->ID2D1Bitmap_iface
);
693 if (bitmap_brush_desc
)
695 brush
->u
.bitmap
.extend_mode_x
= bitmap_brush_desc
->extendModeX
;
696 brush
->u
.bitmap
.extend_mode_y
= bitmap_brush_desc
->extendModeY
;
697 brush
->u
.bitmap
.interpolation_mode
= bitmap_brush_desc
->interpolationMode
;
701 brush
->u
.bitmap
.extend_mode_x
= D2D1_EXTEND_MODE_CLAMP
;
702 brush
->u
.bitmap
.extend_mode_y
= D2D1_EXTEND_MODE_CLAMP
;
703 brush
->u
.bitmap
.interpolation_mode
= D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
;
707 struct d2d_brush
*unsafe_impl_from_ID2D1Brush(ID2D1Brush
*iface
)
711 assert(iface
->lpVtbl
== (const ID2D1BrushVtbl
*)&d2d_solid_color_brush_vtbl
712 || iface
->lpVtbl
== (const ID2D1BrushVtbl
*)&d2d_linear_gradient_brush_vtbl
713 || iface
->lpVtbl
== (const ID2D1BrushVtbl
*)&d2d_bitmap_brush_vtbl
);
714 return CONTAINING_RECORD(iface
, struct d2d_brush
, ID2D1Brush_iface
);
717 static D3D10_TEXTURE_ADDRESS_MODE
texture_address_mode_from_extend_mode(D2D1_EXTEND_MODE mode
)
721 case D2D1_EXTEND_MODE_CLAMP
:
722 return D3D10_TEXTURE_ADDRESS_CLAMP
;
723 case D2D1_EXTEND_MODE_WRAP
:
724 return D3D10_TEXTURE_ADDRESS_WRAP
;
725 case D2D1_EXTEND_MODE_MIRROR
:
726 return D3D10_TEXTURE_ADDRESS_MIRROR
;
728 FIXME("Unhandled extend mode %#x.\n", mode
);
729 return D3D10_TEXTURE_ADDRESS_CLAMP
;
733 HRESULT
d2d_brush_get_ps_cb(struct d2d_brush
*brush
, struct d2d_d3d_render_target
*render_target
,
734 ID3D10Buffer
**ps_cb
)
736 D3D10_SUBRESOURCE_DATA buffer_data
;
737 D3D10_BUFFER_DESC buffer_desc
;
740 float _11
, _21
, _31
, pad0
;
741 float _12
, _22
, _32
, opacity
;
747 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
748 buffer_desc
.BindFlags
= D3D10_BIND_CONSTANT_BUFFER
;
749 buffer_desc
.CPUAccessFlags
= 0;
750 buffer_desc
.MiscFlags
= 0;
752 buffer_data
.SysMemPitch
= 0;
753 buffer_data
.SysMemSlicePitch
= 0;
755 if (brush
->type
== D2D_BRUSH_TYPE_SOLID
)
757 color
= brush
->u
.solid
.color
;
758 color
.a
*= brush
->opacity
;
763 buffer_desc
.ByteWidth
= sizeof(color
);
764 buffer_data
.pSysMem
= &color
;
766 else if (brush
->type
== D2D_BRUSH_TYPE_BITMAP
)
768 struct d2d_bitmap
*bitmap
= brush
->u
.bitmap
.bitmap
;
769 D2D_MATRIX_3X2_F w
, b
;
773 w
= render_target
->drawing_state
.transform
;
774 dpi_scale
= render_target
->dpi_x
/ 96.0f
;
778 dpi_scale
= render_target
->dpi_y
/ 96.0f
;
783 /* Scale for bitmap size and dpi. */
784 b
= brush
->transform
;
785 dpi_scale
= bitmap
->pixel_size
.width
* (96.0f
/ bitmap
->dpi_x
);
788 dpi_scale
= bitmap
->pixel_size
.height
* (96.0f
/ bitmap
->dpi_y
);
792 d2d_matrix_multiply(&b
, &w
);
794 /* Invert the matrix. (Because the matrix is applied to the sampling
795 * coordinates. I.e., to scale the bitmap by 2 we need to divide the
796 * coordinates by 2.) */
797 d
= b
._11
* b
._22
- b
._21
* b
._12
;
800 bitmap_brush_cb
._11
= b
._22
/ d
;
801 bitmap_brush_cb
._21
= -b
._21
/ d
;
802 bitmap_brush_cb
._31
= (b
._21
* b
._32
- b
._31
* b
._22
) / d
;
803 bitmap_brush_cb
._12
= -b
._12
/ d
;
804 bitmap_brush_cb
._22
= b
._11
/ d
;
805 bitmap_brush_cb
._32
= -(b
._11
* b
._32
- b
._31
* b
._12
) / d
;
807 bitmap_brush_cb
.opacity
= brush
->opacity
;
808 bitmap_brush_cb
.ignore_alpha
= bitmap
->format
.alphaMode
== D2D1_ALPHA_MODE_IGNORE
;
810 buffer_desc
.ByteWidth
= sizeof(bitmap_brush_cb
);
811 buffer_data
.pSysMem
= &bitmap_brush_cb
;
815 FIXME("Unhandled brush type %#x.\n", brush
->type
);
819 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, ps_cb
)))
820 ERR("Failed to create constant buffer, hr %#x.\n", hr
);
825 void d2d_brush_bind_resources(struct d2d_brush
*brush
, struct d2d_d3d_render_target
*render_target
,
826 enum d2d_shape_type shape_type
)
828 static const float blend_factor
[] = {1.0f
, 1.0f
, 1.0f
, 1.0f
};
829 ID3D10Device
*device
= render_target
->device
;
830 ID3D10PixelShader
*ps
;
833 ID3D10Device_OMSetBlendState(device
, render_target
->bs
, blend_factor
, D3D10_DEFAULT_SAMPLE_MASK
);
834 if (!(ps
= render_target
->shape_resources
[shape_type
].ps
[brush
->type
]))
835 FIXME("No pixel shader for shape type %#x and brush type %#x.\n", shape_type
, brush
->type
);
836 ID3D10Device_PSSetShader(device
, ps
);
838 if (brush
->type
== D2D_BRUSH_TYPE_BITMAP
)
840 ID3D10Device_PSSetShaderResources(device
, 0, 1, &brush
->u
.bitmap
.bitmap
->view
);
841 if (!brush
->u
.bitmap
.sampler_state
)
843 D3D10_SAMPLER_DESC sampler_desc
;
845 if (brush
->u
.bitmap
.interpolation_mode
== D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
)
846 sampler_desc
.Filter
= D3D10_FILTER_MIN_MAG_MIP_POINT
;
848 sampler_desc
.Filter
= D3D10_FILTER_MIN_MAG_MIP_LINEAR
;
849 sampler_desc
.AddressU
= texture_address_mode_from_extend_mode(brush
->u
.bitmap
.extend_mode_x
);
850 sampler_desc
.AddressV
= texture_address_mode_from_extend_mode(brush
->u
.bitmap
.extend_mode_y
);
851 sampler_desc
.AddressW
= D3D10_TEXTURE_ADDRESS_CLAMP
;
852 sampler_desc
.MipLODBias
= 0.0f
;
853 sampler_desc
.MaxAnisotropy
= 0;
854 sampler_desc
.ComparisonFunc
= D3D10_COMPARISON_NEVER
;
855 sampler_desc
.BorderColor
[0] = 0.0f
;
856 sampler_desc
.BorderColor
[1] = 0.0f
;
857 sampler_desc
.BorderColor
[2] = 0.0f
;
858 sampler_desc
.BorderColor
[3] = 0.0f
;
859 sampler_desc
.MinLOD
= 0.0f
;
860 sampler_desc
.MaxLOD
= 0.0f
;
862 if (FAILED(hr
= ID3D10Device_CreateSamplerState(device
,
863 &sampler_desc
, &brush
->u
.bitmap
.sampler_state
)))
864 ERR("Failed to create sampler state, hr %#x.\n", hr
);
866 ID3D10Device_PSSetSamplers(device
, 0, 1, &brush
->u
.bitmap
.sampler_state
);
868 else if (brush
->type
!= D2D_BRUSH_TYPE_SOLID
)
870 FIXME("Unhandled brush type %#x.\n", brush
->type
);