1 module directx.d2d1_1helper;
2 /*=========================================================================*\
3 
4     Copyright (c) Microsoft Corporation.  All rights reserved.
5 
6     File: D2D1_1Helper.h
7 
8     Module Name: D2D
9 
10     Description: Helper files over the D2D interfaces and APIs.
11 
12 \*=========================================================================*/
13 
14 version(Windows):
15 
16 public import directx.d2d1_1;
17 import directx.d2d1helper;
18 
19 template TypeTraits(T : INT32)
20 {
21     alias Point =  D2D1_POINT_2L;
22     alias Rect = D2D1_RECT_L;
23 }
24 
25 template TypeTraits(T : LONG)
26 {
27     alias Point = D2D1_POINT_2L;
28     alias Rect = D2D1_RECT_L;
29 }
30 
31 struct Matrix4x3F // : D2D1_MATRIX_4X3_F
32 {
33     D2D1_MATRIX_4X3_F matrix;
34     alias matrix this;
35 
36     nothrow this(D2D1_MATRIX_4X3_F m) { matrix = m; }
37     nothrow this(
38         FLOAT m11, FLOAT m12, FLOAT m13,
39         FLOAT m21, FLOAT m22, FLOAT m23,
40         FLOAT m31, FLOAT m32, FLOAT m33,
41         FLOAT m41, FLOAT m42, FLOAT m43
42         )
43     {
44         _11 = m11;
45         _12 = m12;
46         _13 = m13;
47 
48         _21 = m21;
49         _22 = m22;
50         _23 = m23;
51 
52         _31 = m31;
53         _32 = m32;
54         _33 = m33;
55 
56         _41 = m41;
57         _42 = m42;
58         _43 = m43;
59     }
60 
61     // this()
62     /// Use this instead of default constructor
63     static @property nothrow Identity()
64     {
65         return Matrix4x3F(
66             1, 0, 0,
67             0, 1, 0,
68             0, 0, 1,
69             0, 0, 0
70         );
71     }
72 }
73 
74 struct Matrix4x4F // : public D2D1_MATRIX_4X4_F
75 {
76     D2D1_MATRIX_4X4_F matrix;
77     alias matrix this;
78 
79     nothrow this(D2D1_MATRIX_4X4_F m) { matrix = m; }
80     nothrow this(
81         FLOAT m11, FLOAT m12, FLOAT m13, FLOAT m14,
82         FLOAT m21, FLOAT m22, FLOAT m23, FLOAT m24,
83         FLOAT m31, FLOAT m32, FLOAT m33, FLOAT m34,
84         FLOAT m41, FLOAT m42, FLOAT m43, FLOAT m44
85         )
86     {
87         _11 = m11;
88         _12 = m12;
89         _13 = m13;
90         _14 = m14;
91 
92         _21 = m21;
93         _22 = m22;
94         _23 = m23;
95         _24 = m24;
96 
97         _31 = m31;
98         _32 = m32;
99         _33 = m33;
100         _34 = m34;
101 
102         _41 = m41;
103         _42 = m42;
104         _43 = m43;
105         _44 = m44;
106     }
107 
108     // this()
109     /// Use this instead of default constructor
110     static nothrow @property Identity()
111     {
112         return Matrix4x4F(
113             1, 0, 0, 0,
114             0, 1, 0, 0,
115             0, 0, 1, 0,
116             0, 0, 0, 1
117         );
118     }
119 
120     bool opEquals(
121         const Matrix4x4F r
122         ) const
123     {
124         return _11 == r._11 && _12 == r._12 && _13 == r._13 && _14 == r._14 &&
125                 _21 == r._21 && _22 == r._22 && _23 == r._23 && _24 == r._24 &&
126                 _31 == r._31 && _32 == r._32 && _33 == r._33 && _34 == r._34 &&
127                 _41 == r._41 && _42 == r._42 && _43 == r._43 && _44 == r._44;
128     }
129 
130     static
131     Matrix4x4F
132     Translation(FLOAT x, FLOAT y, FLOAT z)
133     {
134         Matrix4x4F translation;
135 
136         translation._11 = 1.0; translation._12 = 0.0; translation._13 = 0.0; translation._14 = 0.0;
137         translation._21 = 0.0; translation._22 = 1.0; translation._23 = 0.0; translation._24 = 0.0;
138         translation._31 = 0.0; translation._32 = 0.0; translation._33 = 1.0; translation._34 = 0.0;
139         translation._41 = x;   translation._42 = y;   translation._43 = z;   translation._44 = 1.0;
140 
141         return translation;
142     }
143 
144     static
145     Matrix4x4F
146     Scale(FLOAT x, FLOAT y, FLOAT z)
147     {
148         Matrix4x4F scale;
149 
150         scale._11 = x;   scale._12 = 0.0; scale._13 = 0.0; scale._14 = 0.0;
151         scale._21 = 0.0; scale._22 = y;   scale._23 = 0.0; scale._24 = 0.0;
152         scale._31 = 0.0; scale._32 = 0.0; scale._33 = z;   scale._34 = 0.0;
153         scale._41 = 0.0; scale._42 = 0.0; scale._43 = 0.0; scale._44 = 1.0;
154 
155         return scale;
156     }
157 
158     static
159     Matrix4x4F
160     RotationX(FLOAT degreeX)
161     {
162         FLOAT angleInRadian = degreeX * (3.141592654f / 180.0f);
163 
164         FLOAT sinAngle = 0.0;
165         FLOAT cosAngle = 0.0;
166         D2D1SinCos(angleInRadian, &sinAngle, &cosAngle);
167 
168         return Matrix4x4F(
169             1, 0,         0,        0,
170             0, cosAngle,  sinAngle, 0,
171             0, -sinAngle, cosAngle, 0,
172             0, 0,         0,        1
173             );
174     }
175 
176     static
177     Matrix4x4F
178     RotationY(FLOAT degreeY)
179     {
180         FLOAT angleInRadian = degreeY * (3.141592654f / 180.0f);
181 
182         FLOAT sinAngle = 0.0;
183         FLOAT cosAngle = 0.0;
184         D2D1SinCos(angleInRadian, &sinAngle, &cosAngle);
185 
186         return Matrix4x4F(
187             cosAngle, 0, -sinAngle, 0,
188             0,        1, 0,         0,
189             sinAngle, 0, cosAngle,  0,
190             0,        0, 0,         1
191             );
192     }
193 
194     static
195     Matrix4x4F
196     RotationZ(FLOAT degreeZ)
197     {
198         FLOAT angleInRadian = degreeZ * (3.141592654f / 180.0f);
199 
200         FLOAT sinAngle = 0.0;
201         FLOAT cosAngle = 0.0;
202         D2D1SinCos(angleInRadian, &sinAngle, &cosAngle);
203 
204         return Matrix4x4F(
205             cosAngle,  sinAngle, 0, 0,
206             -sinAngle, cosAngle, 0, 0,
207             0,         0,        1, 0,
208             0,         0,        0, 1
209             );
210     }
211 
212     //
213     // 3D Rotation matrix for an arbitrary axis specified by x, y and z
214     //
215     static
216     Matrix4x4F
217     RotationArbitraryAxis(FLOAT x, FLOAT y, FLOAT z, FLOAT degree)
218     {
219         // Normalize the vector represented by x, y, and z
220         FLOAT magnitude = D2D1Vec3Length(x, y, z);
221         x /= magnitude;
222         y /= magnitude;
223         z /= magnitude;
224 
225         FLOAT angleInRadian = degree * (3.141592654f / 180.0f);
226 
227         FLOAT sinAngle = 0.0;
228         FLOAT cosAngle = 0.0;
229         D2D1SinCos(angleInRadian, &sinAngle, &cosAngle);
230 
231         FLOAT oneMinusCosAngle = 1 - cosAngle;
232 
233         return Matrix4x4F(
234             1             + oneMinusCosAngle * (x * x - 1),
235             z  * sinAngle + oneMinusCosAngle *  x * y,
236             -y * sinAngle + oneMinusCosAngle *  x * z,
237             0,
238 
239             -z * sinAngle + oneMinusCosAngle *  y * x,
240             1             + oneMinusCosAngle * (y * y - 1),
241             x  * sinAngle + oneMinusCosAngle *  y * z,
242             0,
243 
244             y  * sinAngle + oneMinusCosAngle *  z * x,
245             -x * sinAngle + oneMinusCosAngle *  z * y,
246             1             + oneMinusCosAngle * (z * z - 1) ,
247             0,
248 
249             0, 0, 0, 1
250             );
251     }
252 
253     static
254     Matrix4x4F
255     SkewX(FLOAT degreeX)
256     {
257         FLOAT angleInRadian = degreeX * (3.141592654f / 180.0f);
258 
259         FLOAT tanAngle = D2D1Tan(angleInRadian);
260 
261         return Matrix4x4F(
262             1,          0,  0, 0,
263             tanAngle,   1,  0, 0,
264             0,          0,  1, 0,
265             0,          0,  0, 1
266             );
267     }
268 
269     static
270     Matrix4x4F
271     SkewY(FLOAT degreeY)
272     {
273         FLOAT angleInRadian = degreeY * (3.141592654f / 180.0f);
274 
275         FLOAT tanAngle = D2D1Tan(angleInRadian);
276 
277         return Matrix4x4F(
278             1,  tanAngle,   0, 0,
279             0,  1,          0, 0,
280             0,  0,          1, 0,
281             0,  0,          0, 1
282             );
283     }
284 
285 
286     static
287     Matrix4x4F
288     PerspectiveProjection(FLOAT depth)
289     {
290         float proj = 0;
291 
292         if (depth > 0)
293         {
294             proj = -1/depth;
295         }
296 
297         return Matrix4x4F(
298             1, 0, 0, 0,
299             0, 1, 0, 0,
300             0, 0, 1, proj,
301             0, 0, 0, 1
302             );
303     }
304 
305     //
306     // Functions for convertion from the base D2D1_MATRIX_4X4_f to
307     // this type without making a copy
308     //
309     static
310     const(Matrix4x4F)*
311     ReinterpretBaseType(const(D2D1_MATRIX_4X4_F)* pMatrix)
312     {
313         return cast(const(Matrix4x4F)*)pMatrix;
314     }
315 
316     static
317     nothrow
318     Matrix4x4F*
319     ReinterpretBaseType(D2D1_MATRIX_4X4_F *pMatrix)
320     {
321         return cast(Matrix4x4F*)(pMatrix);
322     }
323 
324     nothrow
325     FLOAT
326     Determinant() const
327     {
328         FLOAT minor1 = _41 * (_12 * (_23 * _34 - _33 * _24) - _13 * (_22 * _34 - _24 * _32) + _14 * (_22 * _33 - _23 * _32));
329         FLOAT minor2 = _42 * (_11 * (_21 * _34 - _31 * _24) - _13 * (_21 * _34 - _24 * _31) + _14 * (_21 * _33 - _23 * _31));
330         FLOAT minor3 = _43 * (_11 * (_22 * _34 - _32 * _24) - _12 * (_21 * _34 - _24 * _31) + _14 * (_21 * _32 - _22 * _31));
331         FLOAT minor4 = _44 * (_11 * (_22 * _33 - _32 * _23) - _12 * (_21 * _33 - _23 * _31) + _13 * (_21 * _32 - _22 * _31));
332 
333         return minor1 - minor2 + minor3 - minor4;
334     }
335 
336     nothrow
337     bool
338     IsIdentity() const
339     {
340         return _11 == 1.0f && _12 == 0.0f && _13 == 0.0f && _14 == 0.0f
341             && _21 == 0.0f && _22 == 1.0f && _23 == 0.0f && _24 == 0.0f
342             && _31 == 0.0f && _32 == 0.0f && _33 == 1.0f && _34 == 0.0f
343             && _41 == 0.0f && _42 == 0.0f && _43 == 0.0f && _44 == 1.0f;
344     }
345 
346     nothrow
347     void
348     SetProduct(const Matrix4x4F a, const Matrix4x4F b)
349     {
350         _11 = a._11 * b._11 + a._12 * b._21 + a._13 * b._31 + a._14 * b._41;
351         _12 = a._11 * b._12 + a._12 * b._22 + a._13 * b._32 + a._14 * b._42;
352         _13 = a._11 * b._13 + a._12 * b._23 + a._13 * b._33 + a._14 * b._43;
353         _14 = a._11 * b._14 + a._12 * b._24 + a._13 * b._34 + a._14 * b._44;
354 
355         _21 = a._21 * b._11 + a._22 * b._21 + a._23 * b._31 + a._24 * b._41;
356         _22 = a._21 * b._12 + a._22 * b._22 + a._23 * b._32 + a._24 * b._42;
357         _23 = a._21 * b._13 + a._22 * b._23 + a._23 * b._33 + a._24 * b._43;
358         _24 = a._21 * b._14 + a._22 * b._24 + a._23 * b._34 + a._24 * b._44;
359 
360         _31 = a._31 * b._11 + a._32 * b._21 + a._33 * b._31 + a._34 * b._41;
361         _32 = a._31 * b._12 + a._32 * b._22 + a._33 * b._32 + a._34 * b._42;
362         _33 = a._31 * b._13 + a._32 * b._23 + a._33 * b._33 + a._34 * b._43;
363         _34 = a._31 * b._14 + a._32 * b._24 + a._33 * b._34 + a._34 * b._44;
364 
365         _41 = a._41 * b._11 + a._42 * b._21 + a._43 * b._31 + a._44 * b._41;
366         _42 = a._41 * b._12 + a._42 * b._22 + a._43 * b._32 + a._44 * b._42;
367         _43 = a._41 * b._13 + a._42 * b._23 + a._43 * b._33 + a._44 * b._43;
368         _44 = a._41 * b._14 + a._42 * b._24 + a._43 * b._34 + a._44 * b._44;
369     }
370 
371     nothrow
372     Matrix4x4F
373     opBinary(string op)(const Matrix4x4F matrix) const if(op == "*")
374     {
375         Matrix4x4F result;
376 
377         result.SetProduct(*this, matrix);
378 
379         return result;
380     }
381 }
382 
383 
384 struct Matrix5x4F // : D2D1_MATRIX_5X4_F
385 {
386     D2D1_MATRIX_5X4_F matrix;
387     alias matrix this;
388 
389     nothrow this(D2D1_MATRIX_5X4_F m) { matrix = m; }
390     nothrow this(
391         FLOAT m11, FLOAT m12, FLOAT m13, FLOAT m14,
392         FLOAT m21, FLOAT m22, FLOAT m23, FLOAT m24,
393         FLOAT m31, FLOAT m32, FLOAT m33, FLOAT m34,
394         FLOAT m41, FLOAT m42, FLOAT m43, FLOAT m44,
395         FLOAT m51, FLOAT m52, FLOAT m53, FLOAT m54
396         )
397     {
398         _11 = m11;
399         _12 = m12;
400         _13 = m13;
401         _14 = m14;
402 
403         _21 = m21;
404         _22 = m22;
405         _23 = m23;
406         _24 = m24;
407 
408         _31 = m31;
409         _32 = m32;
410         _33 = m33;
411         _34 = m34;
412 
413         _41 = m41;
414         _42 = m42;
415         _43 = m43;
416         _44 = m44;
417 
418         _51 = m51;
419         _52 = m52;
420         _53 = m53;
421         _54 = m54;
422     }
423 
424     // this()
425     /// Use this instead of default constructor
426     static nothrow @property Identity()
427     {
428         return Matrix5x4F(
429             1, 0, 0, 0,
430             0, 1, 0, 0,
431             0, 0, 1, 0,
432             0, 0, 0, 1,
433             0, 0, 0, 0
434         );
435     }
436 }
437 
438 D2D1_COLOR_F
439 ConvertColorSpace(
440     D2D1_COLOR_SPACE sourceColorSpace,
441     D2D1_COLOR_SPACE destinationColorSpace,
442     const D2D1_COLOR_F color
443     )
444 {
445     return D2D1ConvertColorSpace(
446         sourceColorSpace,
447         destinationColorSpace,
448         &color
449         );
450 }
451 
452 D2D1_DRAWING_STATE_DESCRIPTION1
453 DrawingStateDescription1(
454     D2D1_ANTIALIAS_MODE antialiasMode = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
455     D2D1_TEXT_ANTIALIAS_MODE textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
456     D2D1_TAG tag1 = 0,
457     D2D1_TAG tag2 = 0,
458     const D2D1_MATRIX_3X2_F transform = D2D1.IdentityMatrix(),
459     D2D1_PRIMITIVE_BLEND primitiveBlend = D2D1_PRIMITIVE_BLEND_SOURCE_OVER,
460     D2D1_UNIT_MODE unitMode = D2D1_UNIT_MODE_DIPS
461     )
462 {
463     D2D1_DRAWING_STATE_DESCRIPTION1 drawingStateDescription1;
464 
465     drawingStateDescription1.antialiasMode = antialiasMode;
466     drawingStateDescription1.textAntialiasMode = textAntialiasMode;
467     drawingStateDescription1.tag1 = tag1;
468     drawingStateDescription1.tag2 = tag2;
469     drawingStateDescription1.transform = transform;
470     drawingStateDescription1.primitiveBlend = primitiveBlend;
471     drawingStateDescription1.unitMode = unitMode;
472 
473     return drawingStateDescription1;
474 }
475 
476 D2D1_DRAWING_STATE_DESCRIPTION1
477 DrawingStateDescription1(
478     const D2D1_DRAWING_STATE_DESCRIPTION desc,
479     D2D1_PRIMITIVE_BLEND primitiveBlend = D2D1_PRIMITIVE_BLEND_SOURCE_OVER,
480     D2D1_UNIT_MODE unitMode = D2D1_UNIT_MODE_DIPS
481     )
482 {
483     D2D1_DRAWING_STATE_DESCRIPTION1 drawingStateDescription1;
484 
485     drawingStateDescription1.antialiasMode = desc.antialiasMode;
486     drawingStateDescription1.textAntialiasMode = desc.textAntialiasMode;
487     drawingStateDescription1.tag1 = desc.tag1;
488     drawingStateDescription1.tag2 = desc.tag2;
489     drawingStateDescription1.transform = desc.transform;
490     drawingStateDescription1.primitiveBlend = primitiveBlend;
491     drawingStateDescription1.unitMode = unitMode;
492 
493     return drawingStateDescription1;
494 }
495 
496 D2D1_BITMAP_PROPERTIES1
497 BitmapProperties1(
498     D2D1_BITMAP_OPTIONS bitmapOptions = D2D1_BITMAP_OPTIONS_NONE,
499     const D2D1_PIXEL_FORMAT pixelFormat = D2D1.PixelFormat(),
500     FLOAT dpiX = 96.0f,
501     FLOAT dpiY = 96.0f,
502     ID2D1ColorContext colorContext = null
503     )
504 {
505     D2D1_BITMAP_PROPERTIES1 bitmapProperties =
506     {
507         pixelFormat,
508         dpiX, dpiY,
509         bitmapOptions,
510         colorContext
511     };
512 
513     return bitmapProperties;
514 }    
515 
516 D2D1_LAYER_PARAMETERS1
517 LayerParameters1(
518     const D2D1_RECT_F contentBounds = D2D1.InfiniteRect(),
519     ID2D1Geometry geometricMask = NULL,
520     D2D1_ANTIALIAS_MODE maskAntialiasMode = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
521     D2D1_MATRIX_3X2_F maskTransform = D2D1.IdentityMatrix(),
522     FLOAT opacity = 1.0,
523     ID2D1Brush opacityBrush = NULL,
524     D2D1_LAYER_OPTIONS1 layerOptions = D2D1_LAYER_OPTIONS1_NONE
525     )
526 {
527     D2D1_LAYER_PARAMETERS1 layerParameters;
528 
529     layerParameters.contentBounds = contentBounds;
530     layerParameters.geometricMask = geometricMask;
531     layerParameters.maskAntialiasMode = maskAntialiasMode;
532     layerParameters.maskTransform = maskTransform;
533     layerParameters.opacity = opacity;
534     layerParameters.opacityBrush = opacityBrush;
535     layerParameters.layerOptions = layerOptions;
536 
537     return layerParameters;
538 }
539 
540 D2D1_STROKE_STYLE_PROPERTIES1
541 StrokeStyleProperties1(
542     D2D1_CAP_STYLE startCap = D2D1_CAP_STYLE_FLAT,
543     D2D1_CAP_STYLE endCap = D2D1_CAP_STYLE_FLAT,
544     D2D1_CAP_STYLE dashCap = D2D1_CAP_STYLE_FLAT,
545     D2D1_LINE_JOIN lineJoin = D2D1_LINE_JOIN_MITER,
546     FLOAT miterLimit = 10.0f,
547     D2D1_DASH_STYLE dashStyle = D2D1_DASH_STYLE_SOLID,
548     FLOAT dashOffset = 0.0f,
549     D2D1_STROKE_TRANSFORM_TYPE transformType = D2D1_STROKE_TRANSFORM_TYPE_NORMAL
550     )
551 {
552     D2D1_STROKE_STYLE_PROPERTIES1 strokeStyleProperties;
553 
554     strokeStyleProperties.startCap = startCap;
555     strokeStyleProperties.endCap = endCap;
556     strokeStyleProperties.dashCap = dashCap;
557     strokeStyleProperties.lineJoin = lineJoin;
558     strokeStyleProperties.miterLimit = miterLimit;
559     strokeStyleProperties.dashStyle = dashStyle;
560     strokeStyleProperties.dashOffset = dashOffset;
561     strokeStyleProperties.transformType = transformType;
562 
563     return strokeStyleProperties;
564 }
565 
566 D2D1_IMAGE_BRUSH_PROPERTIES
567 ImageBrushProperties(
568     D2D1_RECT_F sourceRectangle,
569     D2D1_EXTEND_MODE extendModeX = D2D1_EXTEND_MODE_CLAMP,
570     D2D1_EXTEND_MODE extendModeY = D2D1_EXTEND_MODE_CLAMP,
571     D2D1_INTERPOLATION_MODE interpolationMode = D2D1_INTERPOLATION_MODE_LINEAR
572     )
573 {
574     D2D1_IMAGE_BRUSH_PROPERTIES imageBrushProperties;
575 
576     imageBrushProperties.extendModeX = extendModeX;
577     imageBrushProperties.extendModeY = extendModeY;
578     imageBrushProperties.interpolationMode = interpolationMode;
579     imageBrushProperties.sourceRectangle = sourceRectangle;
580 
581     return imageBrushProperties;
582 }
583 
584 D2D1_BITMAP_BRUSH_PROPERTIES1
585 BitmapBrushProperties1(
586     D2D1_EXTEND_MODE extendModeX = D2D1_EXTEND_MODE_CLAMP,
587     D2D1_EXTEND_MODE extendModeY = D2D1_EXTEND_MODE_CLAMP,
588     D2D1_INTERPOLATION_MODE interpolationMode = D2D1_INTERPOLATION_MODE_LINEAR
589     )
590 {
591     D2D1_BITMAP_BRUSH_PROPERTIES1 bitmapBrush1Properties;
592 
593     bitmapBrush1Properties.extendModeX = extendModeX;
594     bitmapBrush1Properties.extendModeY = extendModeY;
595     bitmapBrush1Properties.interpolationMode = interpolationMode;
596 
597     return bitmapBrush1Properties;
598 }
599 
600 D2D1_PRINT_CONTROL_PROPERTIES
601 PrintControlProperties(
602     D2D1_PRINT_FONT_SUBSET_MODE fontSubsetMode = D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT,
603     FLOAT rasterDpi = 150.0f,
604     D2D1_COLOR_SPACE colorSpace = D2D1_COLOR_SPACE_SRGB
605     )
606 {
607     D2D1_PRINT_CONTROL_PROPERTIES printControlProps;
608 
609     printControlProps.fontSubset = fontSubsetMode;
610     printControlProps.rasterDPI = rasterDpi;
611     printControlProps.colorSpace = colorSpace;
612 
613     return printControlProps;
614 }
615 
616 D2D1_RENDERING_CONTROLS
617 RenderingControls(
618     D2D1_BUFFER_PRECISION bufferPrecision,
619     D2D1_SIZE_U tileSize
620     )
621 {
622     D2D1_RENDERING_CONTROLS renderingControls;
623 
624     renderingControls.bufferPrecision = bufferPrecision;
625     renderingControls.tileSize = tileSize;
626 
627     return renderingControls;
628 }
629 
630 D2D1_EFFECT_INPUT_DESCRIPTION
631 EffectInputDescription(
632     ID2D1Effect effect,
633     UINT32 inputIndex,
634     D2D1_RECT_F inputRectangle
635     )
636 {
637     D2D1_EFFECT_INPUT_DESCRIPTION description;
638 
639     description.effect = effect;
640     description.inputIndex = inputIndex;
641     description.inputRectangle = inputRectangle;
642 
643     return description;
644 }
645 
646 D2D1_CREATION_PROPERTIES
647 CreationProperties(
648     D2D1_THREADING_MODE threadingMode,
649     D2D1_DEBUG_LEVEL debugLevel,
650     D2D1_DEVICE_CONTEXT_OPTIONS options
651     )
652 {
653     D2D1_CREATION_PROPERTIES creationProperties;
654 
655     creationProperties.threadingMode = threadingMode;
656     creationProperties.debugLevel = debugLevel;
657     creationProperties.options = options;
658 
659     return creationProperties;
660 }
661 
662 D2D1_VECTOR_2F
663 Vector2F(
664     FLOAT x = 0.0f,
665     FLOAT y = 0.0f
666     )
667 {
668     D2D1_VECTOR_2F vec2 = {x, y};
669     return vec2;
670 }
671 
672 D2D1_VECTOR_3F
673 Vector3F(
674     FLOAT x = 0.0f,
675     FLOAT y = 0.0f,
676     FLOAT z = 0.0f
677     )
678 {
679     D2D1_VECTOR_3F vec3 = {x, y, z};
680     return vec3;
681 }
682 
683 D2D1_VECTOR_4F
684 Vector4F(
685     FLOAT x = 0.0f,
686     FLOAT y = 0.0f,
687     FLOAT z = 0.0f,
688     FLOAT w = 0.0f
689     )
690 {
691     D2D1_VECTOR_4F vec4 = {x, y, z, w};
692     return vec4;
693 }
694 
695 D2D1_POINT_2L
696 Point2L(
697     INT32 x = 0,
698     INT32 y = 0
699     )
700 {
701     return D2D1_POINT_2L(x, y);
702 }
703 
704 D2D1_RECT_L
705 RectL(
706     INT32 left = 0,
707     INT32 top = 0,
708     INT32 right = 0,
709     INT32 bottom = 0
710     )
711 {
712     return D2D1_RECT_L(left, top, right, bottom);
713 }
714 
715 ///
716 /// Sets a bitmap as an effect input, while inserting a DPI compensation effect
717 /// to preserve visual appearance as the device context's DPI changes.
718 /// 
719 HRESULT
720 SetDpiCompensatedEffectInput(
721     ID2D1DeviceContext deviceContext,
722     ID2D1Effect effect,
723     UINT32 inputIndex,
724     ID2D1Bitmap inputBitmap,
725     D2D1_INTERPOLATION_MODE interpolationMode = D2D1_INTERPOLATION_MODE_LINEAR,
726     D2D1_BORDER_MODE borderMode = D2D1_BORDER_MODE_HARD
727     )
728 {
729     HRESULT hr = S_OK;
730     ID2D1Effect dpiCompensationEffect = null;
731 
732     if (inputBitmap is null)
733     {
734         effect.SetInput(inputIndex, null);
735         return hr;
736     }
737 
738     hr = deviceContext.CreateEffect(&CLSID_D2D1DpiCompensation, &dpiCompensationEffect);
739 
740     if (SUCCEEDED(hr))
741     {
742             if (SUCCEEDED(hr))
743             {
744                 dpiCompensationEffect.SetInput(0, inputBitmap);
745 
746                 D2D1_POINT_2F bitmapDpi;
747                 inputBitmap.GetDpi(bitmapDpi.x, bitmapDpi.y);
748                 hr = dpiCompensationEffect.SetValue(D2D1_DPICOMPENSATION_PROP_INPUT_DPI, bitmapDpi);
749             }
750 
751             if (SUCCEEDED(hr))
752             {
753                 hr = dpiCompensationEffect.SetValue(D2D1_DPICOMPENSATION_PROP_INTERPOLATION_MODE, interpolationMode);
754             }
755 
756             if (SUCCEEDED(hr))
757             {
758                 hr = dpiCompensationEffect.SetValue(D2D1_DPICOMPENSATION_PROP_BORDER_MODE, borderMode);
759             }
760 
761             if (SUCCEEDED(hr))
762             {
763                 effect.SetInputEffect(inputIndex, dpiCompensationEffect);
764             }
765 
766             if (dpiCompensationEffect !is null)
767             {
768                 dpiCompensationEffect.Release();
769             }
770     }
771 
772     return hr;
773 }