diff --git a/src/Performance/FunctionPointers.cs b/src/Performance/FunctionPointers.cs
index b2a3c60d..ce34a9bb 100644
--- a/src/Performance/FunctionPointers.cs
+++ b/src/Performance/FunctionPointers.cs
@@ -15,14 +15,14 @@ namespace Performance
[MemoryDiagnoser]
public unsafe class FunctionPointers
{
- private IUnknown* _punk;
+ private Unknown* _punk;
private string _path;
[GlobalSetup]
public void GlobalSetup()
{
_path = Path.Join(Path.GetTempPath(), Path.GetRandomFileName());
- _punk = (IUnknown*)CreateStorage(_path, InterfaceIds.IID_IStorage);
+ _punk = (Unknown*)CreateStorage(_path, InterfaceIds.IID_IStorage);
}
[GlobalCleanup]
diff --git a/src/Performance/Performance.csproj b/src/Performance/Performance.csproj
index 638d88f0..62781c30 100644
--- a/src/Performance/Performance.csproj
+++ b/src/Performance/Performance.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Samples/CoreWindows/Direct2dDemo/CombineGeometries.cs b/src/Samples/CoreWindows/Direct2dDemo/CombineGeometries.cs
new file mode 100644
index 00000000..1e2b5de8
--- /dev/null
+++ b/src/Samples/CoreWindows/Direct2dDemo/CombineGeometries.cs
@@ -0,0 +1,94 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Drawing;
+using System.Numerics;
+using WInterop.Direct2d;
+using WInterop.DirectX;
+using WInterop.Windows;
+
+namespace Direct2dDemo
+{
+ // https://docs.microsoft.com/windows/win32/direct2d/how-to-combine-geometries
+ public class CombineGeometries : DirectXWindowClass
+ {
+ private readonly EllipseGeometry _circleGeometry1;
+ private readonly EllipseGeometry _circleGeometry2;
+ private readonly PathGeometry _geometryUnion;
+ private readonly PathGeometry _geometryIntersect;
+ private readonly PathGeometry _geometryXOR;
+ private readonly PathGeometry _geometryExclude;
+ private SolidColorBrush _brush;
+ private SolidColorBrush _strokeBrush;
+ private SolidColorBrush _fillBrush;
+
+ public CombineGeometries() : base()
+ {
+ _circleGeometry1 = Direct2dFactory.CreateEllipseGeometry(new((75.0f, 75.0f), 50.0f, 50.0f));
+ _circleGeometry2 = Direct2dFactory.CreateEllipseGeometry(new((125.0f, 75.0f), 50.0f, 50.0f));
+ _geometryUnion = Direct2dFactory.CreatePathGeometry();
+ using (var sink = _geometryUnion.Open())
+ {
+ _circleGeometry1.CombineWithGeometry(_circleGeometry2, CombineMode.Union, sink);
+ }
+
+ _geometryIntersect = Direct2dFactory.CreatePathGeometry();
+ using (var sink = _geometryIntersect.Open())
+ {
+ _circleGeometry1.CombineWithGeometry(_circleGeometry2, CombineMode.Intersect, sink);
+ }
+
+ _geometryXOR = Direct2dFactory.CreatePathGeometry();
+ using (var sink = _geometryXOR.Open())
+ {
+ _circleGeometry1.CombineWithGeometry(_circleGeometry2, CombineMode.XOr, sink);
+ }
+
+ _geometryExclude = Direct2dFactory.CreatePathGeometry();
+ using (var sink = _geometryExclude.Open())
+ {
+ _circleGeometry1.CombineWithGeometry(_circleGeometry2, CombineMode.Exclude, sink);
+ }
+ }
+
+ protected override void CreateResources()
+ {
+ _brush = RenderTarget.CreateSolidColorBrush(Color.Black);
+ _strokeBrush = RenderTarget.CreateSolidColorBrush(Color.Blue);
+ _fillBrush = RenderTarget.CreateSolidColorBrush(new(Color.CornflowerBlue, 0.5f));
+ }
+
+ protected override void OnPaint(WindowHandle window)
+ {
+ RenderTarget.Transform = Matrix3x2.Identity;
+ RenderTarget.Clear(Color.White);
+
+ RenderTarget.Transform = Matrix3x2.CreateTranslation(new(20, 100));
+ RenderTarget.FillGeometry(_circleGeometry1, _fillBrush);
+ RenderTarget.DrawGeometry(_circleGeometry1, _strokeBrush);
+ RenderTarget.FillGeometry(_circleGeometry2, _fillBrush);
+ RenderTarget.DrawGeometry(_circleGeometry2, _strokeBrush);
+ RenderTarget.Transform = Matrix3x2.Identity;
+
+ RenderTarget.Transform = Matrix3x2.CreateTranslation(new(300, 0));
+ RenderTarget.FillGeometry(_geometryUnion, _fillBrush);
+ RenderTarget.DrawGeometry(_geometryUnion, _strokeBrush);
+ RenderTarget.Transform = Matrix3x2.Identity;
+
+ RenderTarget.Transform = Matrix3x2.CreateTranslation(new(550, 0));
+ RenderTarget.FillGeometry(_geometryIntersect, _fillBrush);
+ RenderTarget.DrawGeometry(_geometryIntersect, _strokeBrush);
+ RenderTarget.Transform = Matrix3x2.Identity;
+
+ RenderTarget.Transform = Matrix3x2.CreateTranslation(new(300, 200));
+ RenderTarget.FillGeometry(_geometryXOR, _fillBrush);
+ RenderTarget.DrawGeometry(_geometryXOR, _strokeBrush);
+ RenderTarget.Transform = Matrix3x2.Identity;
+
+ RenderTarget.Transform = Matrix3x2.CreateTranslation(new(550, 200));
+ RenderTarget.FillGeometry(_geometryExclude, _fillBrush);
+ RenderTarget.DrawGeometry(_geometryExclude, _strokeBrush);
+ RenderTarget.Transform = Matrix3x2.Identity;
+ }
+ }
+}
diff --git a/src/Samples/CoreWindows/Direct2dDemo/Direct2dDemo.cs b/src/Samples/CoreWindows/Direct2dDemo/Direct2dDemo.cs
index 11bf326a..1bb470d2 100644
--- a/src/Samples/CoreWindows/Direct2dDemo/Direct2dDemo.cs
+++ b/src/Samples/CoreWindows/Direct2dDemo/Direct2dDemo.cs
@@ -2,17 +2,21 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Drawing;
+using System.Numerics;
using WInterop.Direct2d;
using WInterop.DirectX;
using WInterop.Windows;
namespace Direct2dDemo
{
- // https://docs.microsoft.com/en-us/windows/desktop/Direct2D/direct2d-quickstart
+ ///
+ /// Implementation of the
+ /// Simple Direct2D Application.
+ ///
public class Direct2dDemo : DirectXWindowClass
{
- private ISolidColorBrush _lightSlateGrayBrush;
- private ISolidColorBrush _cornflowerBlueBrush;
+ private SolidColorBrush _lightSlateGrayBrush;
+ private SolidColorBrush _cornflowerBlueBrush;
protected override void CreateResources()
{
@@ -22,16 +26,14 @@ protected override void CreateResources()
protected override void OnPaint(WindowHandle window)
{
- RenderTarget.SetTransform();
+ RenderTarget.Transform = Matrix3x2.Identity;
RenderTarget.Clear(Color.White);
- Size size = RenderTarget.GetSize().ToSize();
-
- _lightSlateGrayBrush.GetColor(out ColorF color);
+ Size size = RenderTarget.Size.ToSize();
for (int x = 0; x < size.Width; x += 10)
{
RenderTarget.DrawLine(
- new Point(x, 0), new Point(x, size.Height),
+ (x, 0), (x, size.Height),
_lightSlateGrayBrush, 0.5f);
}
diff --git a/src/Samples/CoreWindows/Direct2dDemo/DrawEllipse.cs b/src/Samples/CoreWindows/Direct2dDemo/DrawEllipse.cs
index bb1e19a7..8cb2ae7b 100644
--- a/src/Samples/CoreWindows/Direct2dDemo/DrawEllipse.cs
+++ b/src/Samples/CoreWindows/Direct2dDemo/DrawEllipse.cs
@@ -8,16 +8,19 @@
namespace Direct2dDemo
{
- // https://docs.microsoft.com/en-us/windows/desktop/Direct2D/how-to-draw-an-ellipse
+ // https://docs.microsoft.com/windows/desktop/Direct2D/how-to-draw-an-ellipse
public class DrawEllipse : DirectXWindowClass
{
- private ISolidColorBrush _blackBrush;
- private ISolidColorBrush _silverBrush;
- private readonly IStrokeStyle _dashDotDotStyle;
+ private SolidColorBrush _blackBrush;
+ private SolidColorBrush _silverBrush;
+ private readonly StrokeStyle _dashDotDotStyle;
public DrawEllipse() : base()
{
- StrokeStyleProperties style = new StrokeStyleProperties(dashCap: CapStyle.Triangle, miterLimit: 10.0f, dashStyle: DashStyle.DashDotDot);
+ StrokeStyleProperties style = new(
+ dashCap: CapStyle.Triangle,
+ miterLimit: 10.0f,
+ dashStyle: DashStyle.DashDotDot);
_dashDotDotStyle = Direct2dFactory.CreateStrokeStyle(style);
}
@@ -31,19 +34,26 @@ protected override void OnPaint(WindowHandle window)
{
RenderTarget.Clear(Color.White);
- Ellipse ellipse = new Ellipse(new PointF(100.0f, 100.0f), 75.0f, 50.0f);
+ Ellipse ellipse = new((100.0f, 100.0f), 75.0f, 50.0f);
RenderTarget.DrawEllipse(ellipse, _blackBrush, 10.0f);
- Ellipse ellipse2 = new Ellipse(new PointF(300.0f, 100.0f), 75.0f, 50.0f);
+ Ellipse ellipse2 = new((300.0f, 100.0f), 75.0f, 50.0f);
RenderTarget.DrawEllipse(ellipse2, _blackBrush, 10.0f, _dashDotDotStyle);
- Ellipse ellipse3 = new Ellipse(new PointF(500.0f, 100.0f), 75.0f, 50.0f);
+ Ellipse ellipse3 = new((500.0f, 100.0f), 75.0f, 50.0f);
RenderTarget.DrawEllipse(ellipse3, _blackBrush, 10.0f, _dashDotDotStyle);
RenderTarget.FillEllipse(ellipse3, _silverBrush);
- Ellipse ellipse4 = new Ellipse(new PointF(700.0f, 100.0f), 75.0f, 50.0f);
+ Ellipse ellipse4 = new((700.0f, 100.0f), 75.0f, 50.0f);
RenderTarget.FillEllipse(ellipse4, _silverBrush);
RenderTarget.DrawEllipse(ellipse4, _blackBrush, 10.0f, _dashDotDotStyle);
}
+
+ protected override void Dispose(bool disposing)
+ {
+ _blackBrush.Dispose();
+ _silverBrush.Dispose();
+ _dashDotDotStyle.Dispose();
+ }
}
}
diff --git a/src/Samples/CoreWindows/Direct2dDemo/PathGeometries.cs b/src/Samples/CoreWindows/Direct2dDemo/PathGeometries.cs
index 1b329f1f..a1b6fe85 100644
--- a/src/Samples/CoreWindows/Direct2dDemo/PathGeometries.cs
+++ b/src/Samples/CoreWindows/Direct2dDemo/PathGeometries.cs
@@ -6,20 +6,19 @@
using System.Numerics;
using WInterop.Direct2d;
using WInterop.DirectX;
-using WInterop.Errors;
using WInterop.Windows;
namespace Direct2dDemo
{
public class PathGeometries : DirectXWindowClass
{
- private readonly IPathGeometry _leftMountainGeometry;
- private readonly IPathGeometry _rightMountainGeometry;
- private readonly IPathGeometry _sunGeometry;
- private readonly IPathGeometry _riverGeometry;
- private ISolidColorBrush _sceneBrush;
- private IBitmapBrush _gridPatternBrush;
- private IRadialGradientBrush _radialGradientBrush;
+ private readonly PathGeometry _leftMountainGeometry;
+ private readonly PathGeometry _rightMountainGeometry;
+ private readonly PathGeometry _sunGeometry;
+ private readonly PathGeometry _riverGeometry;
+ private SolidColorBrush _sceneBrush;
+ private BitmapBrush _gridPatternBrush;
+ private RadialGradientBrush _radialGradientBrush;
public PathGeometries() : base()
{
@@ -27,17 +26,17 @@ public PathGeometries() : base()
_leftMountainGeometry = Direct2dFactory.CreatePathGeometry();
var sink = _leftMountainGeometry.Open();
sink.SetFillMode(FillMode.Winding);
- sink.BeginFigure(new PointF(346, 255), FigureBegin.Filled);
- Span lines = stackalloc PointF[]
- {
- new PointF(267, 177),
- new PointF(236, 192),
- new PointF(212, 160),
- new PointF(156, 255),
- new PointF(346, 255)
- };
-
- sink.AddLines(lines);
+ sink.BeginFigure((346, 255), FigureBegin.Filled);
+
+ sink.AddLines(
+ stackalloc PointF[]
+ {
+ new(267, 177),
+ new(236, 192),
+ new(212, 160),
+ new(156, 255),
+ new(346, 255)
+ });
sink.EndFigure(FigureEnd.Closed);
sink.Close();
@@ -45,19 +44,20 @@ public PathGeometries() : base()
_rightMountainGeometry = Direct2dFactory.CreatePathGeometry();
sink = _rightMountainGeometry.Open();
sink.SetFillMode(FillMode.Winding);
- sink.BeginFigure(new PointF(575, 263), FigureBegin.Filled);
- lines = stackalloc PointF[]
- {
- new PointF(481, 146),
- new PointF(449, 181),
- new PointF(433, 159),
- new PointF(401, 214),
- new PointF(381, 199),
- new PointF(323, 263),
- new PointF(575, 263)
- };
-
- sink.AddLines(lines);
+ sink.BeginFigure((575, 263), FigureBegin.Filled);
+
+ sink.AddLines(
+ stackalloc PointF[]
+ {
+ new(481, 146),
+ new(449, 181),
+ new(433, 159),
+ new(401, 214),
+ new(381, 199),
+ new(323, 263),
+ new(575, 263)
+ });
+
sink.EndFigure(FigureEnd.Closed);
sink.Close();
@@ -65,33 +65,33 @@ public PathGeometries() : base()
_sunGeometry = Direct2dFactory.CreatePathGeometry();
sink = _sunGeometry.Open();
sink.SetFillMode(FillMode.Winding);
- sink.BeginFigure(new PointF(270, 255), FigureBegin.Filled);
- sink.AddArc(new ArcSegment(new PointF(440, 255), new SizeF(85, 85)));
+ sink.BeginFigure((270, 255), FigureBegin.Filled);
+ sink.AddArc(new((440, 255), (85, 85)));
sink.EndFigure(FigureEnd.Closed);
- sink.BeginFigure(new PointF(299, 182), FigureBegin.Hollow);
- sink.AddBezier((299, 182), (294, 176), (285, 178));
- sink.AddBezier((276, 179), (272, 173), (272, 173));
+ sink.BeginFigure((299, 182), FigureBegin.Hollow);
+ sink.AddBezier(new((299, 182), (294, 176), (285, 178)));
+ sink.AddBezier(new((276, 179), (272, 173), (272, 173)));
sink.EndFigure(FigureEnd.Open);
- sink.BeginFigure(new PointF(354, 156), FigureBegin.Hollow);
- sink.AddBezier((354, 156), (358, 149), (354, 142));
- sink.AddBezier((349, 134), (354, 127), (354, 127));
+ sink.BeginFigure((354, 156), FigureBegin.Hollow);
+ sink.AddBezier(new((354, 156), (358, 149), (354, 142)));
+ sink.AddBezier(new((349, 134), (354, 127), (354, 127)));
sink.EndFigure(FigureEnd.Open);
- sink.BeginFigure(new PointF(322, 164), FigureBegin.Hollow);
- sink.AddBezier((322, 164), (322, 156), (314, 152));
- sink.AddBezier((306, 149), (305, 141), (305, 141));
+ sink.BeginFigure((322, 164), FigureBegin.Hollow);
+ sink.AddBezier(new((322, 164), (322, 156), (314, 152)));
+ sink.AddBezier(new((306, 149), (305, 141), (305, 141)));
sink.EndFigure(FigureEnd.Open);
- sink.BeginFigure(new PointF(385, 164), FigureBegin.Hollow);
- sink.AddBezier((385, 164), (392, 161), (394,152));
- sink.AddBezier((395, 144), (402, 141), (402, 142));
+ sink.BeginFigure((385, 164), FigureBegin.Hollow);
+ sink.AddBezier(new((385, 164), (392, 161), (394, 152)));
+ sink.AddBezier(new((395, 144), (402, 141), (402, 142)));
sink.EndFigure(FigureEnd.Open);
- sink.BeginFigure(new PointF(408, 182), FigureBegin.Hollow);
- sink.AddBezier((408, 182), (416, 184), (422, 178));
- sink.AddBezier((428, 171), (435, 173), (435, 173));
+ sink.BeginFigure((408, 182), FigureBegin.Hollow);
+ sink.AddBezier(new((408, 182), (416, 184), (422, 178)));
+ sink.AddBezier(new((428, 171), (435, 173), (435, 173)));
sink.EndFigure(FigureEnd.Open);
sink.Close();
@@ -100,11 +100,11 @@ public PathGeometries() : base()
_riverGeometry = Direct2dFactory.CreatePathGeometry();
sink = _riverGeometry.Open();
sink.SetFillMode(FillMode.Winding);
- sink.BeginFigure(new PointF(183, 392), FigureBegin.Filled);
- sink.AddBezier((238, 284), (472, 345), (356, 303));
- sink.AddBezier((237, 261), (333, 256), (333, 256));
- sink.AddBezier((335, 257), (241, 261), (411, 306));
- sink.AddBezier((574, 350), (288, 324), (296, 392));
+ sink.BeginFigure((183, 392), FigureBegin.Filled);
+ sink.AddBezier(new((238, 284), (472, 345), (356, 303)));
+ sink.AddBezier(new((237, 261), (333, 256), (333, 256)));
+ sink.AddBezier(new((335, 257), (241, 261), (411, 306)));
+ sink.AddBezier(new((574, 350), (288, 324), (296, 392)));
sink.EndFigure(FigureEnd.Open);
sink.Close();
}
@@ -114,54 +114,55 @@ protected override void CreateResources()
_sceneBrush = RenderTarget.CreateSolidColorBrush(Color.Black);
// Background grid brush
- var bitmapTarget = RenderTarget.CreateCompatibleRenderTarget(new SizeF(10, 10));
- var gridBrush = bitmapTarget.CreateSolidColorBrush(new ColorF(.93f, .94f, .96f));
+ var bitmapTarget = RenderTarget.CreateCompatibleRenderTarget((10, 10));
+ var gridBrush = bitmapTarget.CreateSolidColorBrush(.93f, .94f, .96f);
bitmapTarget.BeginDraw();
- bitmapTarget.FillRectangle(RectangleF.FromLTRB(0, 0, 10, 1), gridBrush);
- bitmapTarget.FillRectangle(RectangleF.FromLTRB(0, 0, 1, 10), gridBrush);
- bitmapTarget.EndDraw().ThrowIfFailed();
- IBitmap bitmap = bitmapTarget.GetBitmap();
- _gridPatternBrush = RenderTarget.CreateBitmapBrush(bitmap, new BitmapBrushProperties(ExtendMode.Wrap, ExtendMode.Wrap));
+ bitmapTarget.FillRectangle((0, 0, 10, 1), gridBrush);
+ bitmapTarget.FillRectangle((0, 0, 1, 10), gridBrush);
+ bitmapTarget.EndDraw();
+ Bitmap bitmap = bitmapTarget.Bitmap;
+ _gridPatternBrush = RenderTarget.CreateBitmapBrush(bitmap, new(ExtendMode.Wrap, ExtendMode.Wrap));
// Gradient brush
- Span stops = stackalloc[]
- {
- new GradientStop(0.0f, Color.Gold),
- new GradientStop(0.85f, new ColorF(Color.Orange, 0.8f)),
- new GradientStop(1.0f, new ColorF(Color.OrangeRed, 0.7f))
- };
+ using var gradientStops = RenderTarget.CreateGradientStopCollection(
+ stackalloc GradientStop[]
+ {
+ new(0.0f, Color.Gold),
+ new(0.85f, new(Color.Orange, 0.8f)),
+ new(1.0f, new(Color.OrangeRed, 0.7f))
+ });
_radialGradientBrush = RenderTarget.CreateRadialGradientBrush(
- new RadialGradientBrushProperties(new PointF(330, 330), new PointF(140, 140), 140, 140),
- RenderTarget.CreateGradienStopCollection(stops));
+ new((330, 330), (140, 140), 140, 140),
+ gradientStops);
}
protected override void OnPaint(WindowHandle window)
{
- SizeF targetSize = RenderTarget.GetSize();
+ SizeF targetSize = RenderTarget.Size;
- RenderTarget.SetTransform();
+ RenderTarget.Transform = Matrix3x2.Identity;
RenderTarget.Clear(Color.White);
- RenderTarget.FillRectangle(RenderTarget.GetSize(), _gridPatternBrush);
- RenderTarget.SetTransform(Matrix3x2.CreateScale(Math.Min(targetSize.Width / 840.0f, targetSize.Height / 700.0f) * 1.4f));
+ RenderTarget.FillRectangle(new(RenderTarget.Size), _gridPatternBrush);
+ RenderTarget.Transform = Matrix3x2.CreateScale(Math.Min(targetSize.Width / 840.0f, targetSize.Height / 700.0f) * 1.4f);
RenderTarget.FillGeometry(_sunGeometry, _radialGradientBrush);
- _sceneBrush.SetColor(Color.Black);
+ _sceneBrush.Color = Color.Black;
RenderTarget.DrawGeometry(_sunGeometry, _sceneBrush);
- _sceneBrush.SetColor(Color.OliveDrab);
+ _sceneBrush.Color = Color.OliveDrab;
RenderTarget.FillGeometry(_leftMountainGeometry, _sceneBrush);
- _sceneBrush.SetColor(Color.Black);
+ _sceneBrush.Color = Color.Black;
RenderTarget.DrawGeometry(_leftMountainGeometry, _sceneBrush);
- _sceneBrush.SetColor(Color.LightSkyBlue);
+ _sceneBrush.Color = Color.LightSkyBlue;
RenderTarget.FillGeometry(_riverGeometry, _sceneBrush);
- _sceneBrush.SetColor(Color.Black);
+ _sceneBrush.Color = Color.Black;
RenderTarget.DrawGeometry(_riverGeometry, _sceneBrush);
- _sceneBrush.SetColor(Color.YellowGreen);
+ _sceneBrush.Color = Color.YellowGreen;
RenderTarget.FillGeometry(_rightMountainGeometry, _sceneBrush);
- _sceneBrush.SetColor(Color.Black);
+ _sceneBrush.Color = Color.Black;
RenderTarget.DrawGeometry(_rightMountainGeometry, _sceneBrush);
}
}
diff --git a/src/Samples/CoreWindows/Direct2dDemo/Program.cs b/src/Samples/CoreWindows/Direct2dDemo/Program.cs
index 5e7c295b..5390cec2 100644
--- a/src/Samples/CoreWindows/Direct2dDemo/Program.cs
+++ b/src/Samples/CoreWindows/Direct2dDemo/Program.cs
@@ -11,6 +11,7 @@ internal static class Program
[STAThread]
private static void Main()
{
+ Windows.CreateMainWindowAndRun(new CombineGeometries(), "Combine geometries");
Windows.CreateMainWindowAndRun(new Direct2dDemo(), "Direct2d Sample App");
Windows.CreateMainWindowAndRun(new DrawEllipse(), "Drawing ellipses");
Windows.CreateMainWindowAndRun(new PathGeometries(), "Path geometries");
diff --git a/src/Samples/CoreWindows/DirectWriteDemo/CustomText.cs b/src/Samples/CoreWindows/DirectWriteDemo/CustomText.cs
index 52ea69b6..edd9c67c 100644
--- a/src/Samples/CoreWindows/DirectWriteDemo/CustomText.cs
+++ b/src/Samples/CoreWindows/DirectWriteDemo/CustomText.cs
@@ -11,8 +11,8 @@ namespace DirectWriteDemo
// https://docs.microsoft.com/en-us/windows/desktop/DirectWrite/how-to-implement-a-custom-text-renderer
public class CustomText : HelloWorld
{
- private IRadialGradientBrush _radialGradientBrush;
- private CustomTextRenderer _textRenderer;
+ private RadialGradientBrush _radialGradientBrush;
+ private SampleTextRenderer _textRenderer;
protected override void CreateResources()
{
@@ -28,15 +28,15 @@ protected override void CreateResources()
_radialGradientBrush = RenderTarget.CreateRadialGradientBrush(
new RadialGradientBrushProperties(new PointF(330, 330), new PointF(140, 140), 140, 140),
- RenderTarget.CreateGradienStopCollection(stops));
+ RenderTarget.CreateGradientStopCollection(stops));
- _textRenderer = new CustomTextRenderer(Direct2dFactory, RenderTarget, _blackBrush, _radialGradientBrush);
+ _textRenderer = new SampleTextRenderer(Direct2dFactory, RenderTarget, _blackBrush, _radialGradientBrush);
}
protected override void OnPaint(WindowHandle window)
{
RenderTarget.Clear(Color.AntiqueWhite);
- _textLayout.Draw(IntPtr.Zero, _textRenderer, 0, 0);
+ _textLayout.Draw(IntPtr.Zero, _textRenderer, default);
}
}
}
diff --git a/src/Samples/CoreWindows/DirectWriteDemo/CustomTextRenderer.cs b/src/Samples/CoreWindows/DirectWriteDemo/CustomTextRenderer.cs
deleted file mode 100644
index ba4dc7be..00000000
--- a/src/Samples/CoreWindows/DirectWriteDemo/CustomTextRenderer.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-using WInterop;
-using WInterop.Direct2d;
-using WInterop.DirectWrite;
-
-namespace DirectWriteDemo
-{
- public class CustomTextRenderer : ITextRenderer
- {
- private readonly IRenderTarget _renderTarget;
- private readonly IBrush _outlineBrush;
- private readonly IBrush _fillBrush;
- private readonly WInterop.Direct2d.IFactory _factory;
-
- public CustomTextRenderer(
- WInterop.Direct2d.IFactory factory,
- IRenderTarget renderTarget,
- IBrush outlineBrush,
- IBrush fillBrush)
- {
- _renderTarget = renderTarget;
- _factory = factory;
- _outlineBrush = outlineBrush;
- _fillBrush = fillBrush;
- }
-
- public IntBoolean IsPixelSnappingDisabled(IntPtr clientDrawingContext) => false;
-
- public Matrix3x2 GetCurrentTransform(IntPtr clientDrawingContext)
- {
- _renderTarget.GetTransform(out Matrix3x2 transform);
- return transform;
- }
-
- public float GetPixelsPerDip(IntPtr clientDrawingContext)
- {
- _renderTarget.GetDpi(out float x, out _);
- return x / 96;
- }
-
- public unsafe void DrawGlyphRun(
- IntPtr clientDrawingContext,
- float baselineOriginX,
- float baselineOriginY,
- MeasuringMode measuringMode,
- in GlyphRun glyphRun,
- in GlyphRunDescription glyphRunDescription,
- [MarshalAs(UnmanagedType.IUnknown)] object clientDrawingEffect)
- {
- IPathGeometry geometry = _factory.CreatePathGeometry();
- IGeometrySink sink = geometry.Open();
- glyphRun.FontFace.GetGlyphRunOutline(
- glyphRun.FontEmSize,
- glyphRun.GlyphIndices,
- glyphRun.GlyphAdvances,
- glyphRun.GlyphOffsets,
- glyphRun.GlyphCount,
- glyphRun.IsSideways,
- glyphRun.BidiLevel % 2 > 0,
- sink);
- sink.Close();
-
- Matrix3x2 matrix = new Matrix3x2(1, 0, 0, 1, baselineOriginX, baselineOriginY);
- ITransformedGeometry transformedGeometry = _factory.CreateTransformedGeometry(geometry, ref matrix);
-
- _renderTarget.DrawGeometry(transformedGeometry, _outlineBrush);
- _renderTarget.FillGeometry(transformedGeometry, _fillBrush);
- }
-
- public void DrawUnderline(
- IntPtr clientDrawingContext,
- float baselineOriginX,
- float baselineOriginY,
- in Underline underline,
- [MarshalAs(UnmanagedType.IUnknown)] object clientDrawingEffect)
- {
- IRectangleGeometry geometry = _factory.CreateRectangleGeometry(RectangleF.FromLTRB(
- 0, underline.Offset, underline.Width, underline.Offset + underline.Thickness));
-
- Matrix3x2 matrix = new Matrix3x2(1, 0, 0, 1, baselineOriginX, baselineOriginY);
- ITransformedGeometry transformedGeometry = _factory.CreateTransformedGeometry(geometry, ref matrix);
-
- _renderTarget.DrawGeometry(transformedGeometry, _outlineBrush);
- _renderTarget.FillGeometry(transformedGeometry, _fillBrush);
- }
-
- public void DrawStrikethrough(
- IntPtr clientDrawingContext,
- float baselineOriginX,
- float baselineOriginY,
- in Strikethrough strikethrough,
- [MarshalAs(UnmanagedType.IUnknown)] object clientDrawingEffect)
- {
- IRectangleGeometry geometry = _factory.CreateRectangleGeometry(RectangleF.FromLTRB(
- 0, strikethrough.Offset, strikethrough.Width, strikethrough.Offset + strikethrough.Thickness));
-
- Matrix3x2 matrix = new Matrix3x2(1, 0, 0, 1, baselineOriginX, baselineOriginY);
- ITransformedGeometry transformedGeometry = _factory.CreateTransformedGeometry(geometry, ref matrix);
-
- _renderTarget.DrawGeometry(transformedGeometry, _outlineBrush);
- _renderTarget.FillGeometry(transformedGeometry, _fillBrush);
- }
-
- public void DrawInlineObject(
- IntPtr clientDrawingContext,
- float originX,
- float originY,
- IInlineObject inlineObject,
- IntBoolean isSideways,
- IntBoolean isRightToLeft,
- [MarshalAs(UnmanagedType.IUnknown)] object clientDrawingEffect)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/src/Samples/CoreWindows/DirectWriteDemo/HelloWorld.cs b/src/Samples/CoreWindows/DirectWriteDemo/HelloWorld.cs
index 3dff7ec9..739e8f59 100644
--- a/src/Samples/CoreWindows/DirectWriteDemo/HelloWorld.cs
+++ b/src/Samples/CoreWindows/DirectWriteDemo/HelloWorld.cs
@@ -12,24 +12,24 @@ namespace DirectWriteDemo
// https://docs.microsoft.com/en-us/windows/desktop/DirectWrite/getting-started-with-directwrite
public class HelloWorld : DirectXWindowClass
{
- protected ITextFormat _textFormat;
- protected ITextLayout _textLayout;
- protected ITypography _typography;
+ protected TextFormat _textFormat;
+ protected TextLayout _textLayout;
+ protected Typography _typography;
- protected ISolidColorBrush _blackBrush;
+ protected SolidColorBrush _blackBrush;
public HelloWorld() : base()
{
_textFormat = DirectWriteFactory.CreateTextFormat("Gabriola", fontSize: 64);
- _textFormat.SetTextAlignment(TextAlignment.Center);
- _textFormat.SetParagraphAlignment(ParagraphAlignment.Center);
+ _textFormat.TextAlignment = TextAlignment.Center;
+ _textFormat.ParagraphAlignment = ParagraphAlignment.Center;
}
protected override void CreateResources()
{
string text = "Hello World From ... DirectWrite!";
_blackBrush = RenderTarget.CreateSolidColorBrush(Color.Black);
- _textLayout = DirectWriteFactory.CreateTextLayout(text, _textFormat, RenderTarget.GetSize());
+ _textLayout = DirectWriteFactory.CreateTextLayout(text, _textFormat, RenderTarget.Size);
// (21, 12) is the range around "DirectWrite!"
_textLayout.SetFontSize(100, (21, 12));
diff --git a/src/Samples/CoreWindows/DirectWriteDemo/SampleTextRenderer.cs b/src/Samples/CoreWindows/DirectWriteDemo/SampleTextRenderer.cs
new file mode 100644
index 00000000..c479bbb9
--- /dev/null
+++ b/src/Samples/CoreWindows/DirectWriteDemo/SampleTextRenderer.cs
@@ -0,0 +1,107 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using WInterop.Direct2d;
+using WInterop.DirectWrite;
+
+namespace DirectWriteDemo
+{
+ public class SampleTextRenderer : ManagedTextRenderer
+ {
+ private readonly IRenderTarget _renderTarget;
+ private readonly Brush _outlineBrush;
+ private readonly Brush _fillBrush;
+ private readonly Factory _factory;
+
+ public SampleTextRenderer(
+ Factory factory,
+ IRenderTarget renderTarget,
+ Brush outlineBrush,
+ Brush fillBrush)
+ {
+ _renderTarget = renderTarget;
+ _factory = factory;
+ _outlineBrush = outlineBrush;
+ _fillBrush = fillBrush;
+ }
+
+ public override Matrix3x2 GetCurrentTransform(IntPtr clientDrawingContext)
+ => _renderTarget.Transform;
+
+ public override float GetPixelsPerDip(IntPtr clientDrawingContext)
+ => _renderTarget.Dpi.X / 96;
+
+ public override void DrawGlyphRun(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ MeasuringMode measuringMode,
+ GlyphRun glyphRun,
+ GlyphRunDescription glyphRunDescription,
+ IntPtr clientDrawingEffect)
+ {
+ using PathGeometry geometry = _factory.CreatePathGeometry();
+ using GeometrySink sink = geometry.Open();
+ glyphRun.FontFace.GetGlyphRunOutline(
+ glyphRun.FontEmSize,
+ glyphRun.GlyphIndices,
+ glyphRun.GlyphAdvances,
+ glyphRun.GlyphOffsets,
+ glyphRun.IsSideways,
+ glyphRun.BidiLevel % 2 > 0,
+ sink);
+ sink.Close();
+
+ Matrix3x2 matrix = new(1, 0, 0, 1, baselineOrigin.X, baselineOrigin.Y);
+ using TransformedGeometry transformedGeometry = _factory.CreateTransformedGeometry(geometry, matrix);
+
+ _renderTarget.DrawGeometry(transformedGeometry, _outlineBrush);
+ _renderTarget.FillGeometry(transformedGeometry, _fillBrush);
+ }
+
+ public override void DrawUnderline(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ Underline underline,
+ IntPtr clientDrawingEffect)
+ {
+ using RectangleGeometry geometry = _factory.CreateRectangleGeometry(RectangleF.FromLTRB(
+ 0, underline.Offset, underline.Width, underline.Offset + underline.Thickness));
+
+ Matrix3x2 matrix = new(1, 0, 0, 1, baselineOrigin.X, baselineOrigin.Y);
+ TransformedGeometry transformedGeometry = _factory.CreateTransformedGeometry(geometry, matrix);
+
+ _renderTarget.DrawGeometry(transformedGeometry, _outlineBrush);
+ _renderTarget.FillGeometry(transformedGeometry, _fillBrush);
+ }
+
+ public override void DrawStrikethrough(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ Strikethrough strikethrough,
+ IntPtr clientDrawingEffect)
+ {
+ using RectangleGeometry geometry = _factory.CreateRectangleGeometry(RectangleF.FromLTRB(
+ 0, strikethrough.Offset, strikethrough.Width, strikethrough.Offset + strikethrough.Thickness));
+
+ Matrix3x2 matrix = new(1, 0, 0, 1, baselineOrigin.X, baselineOrigin.Y);
+ TransformedGeometry transformedGeometry = _factory.CreateTransformedGeometry(geometry, matrix);
+
+ _renderTarget.DrawGeometry(transformedGeometry, _outlineBrush);
+ _renderTarget.FillGeometry(transformedGeometry, _fillBrush);
+ }
+
+ public override void DrawInlineObject(
+ IntPtr clientDrawingContext,
+ PointF origin,
+ InlineObject inlineObject,
+ bool isSideways,
+ bool isRightToLeft,
+ IntPtr clientDrawingEffect)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Tests/WInterop.Tests/Direct2d/Factory.cs b/src/Tests/WInterop.Tests/Direct2d/Factory.cs
deleted file mode 100644
index 1d644b37..00000000
--- a/src/Tests/WInterop.Tests/Direct2d/Factory.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using WInterop.Direct2d;
-using WInterop.Direct2d.Native;
-using WInterop.Errors;
-using Xunit;
-
-namespace Direct2dTests
-{
- public class Factory
- {
- [Fact]
- public void Initialize()
- {
- HResult result = Imports.D2D1CreateFactory(
- FactoryType.SingleThreaded, new Guid(InterfaceIds.IID_ID2D1Factory), DebugLevel.None, out IFactory factory);
-
- Ellipse ellipse = new Ellipse(new PointF(1.0f, 2.0f), 3.0f, 4.0f);
- var ellipseGeometry = factory.CreateEllipseGeometry(in ellipse);
- ellipseGeometry.GetEllipse(out Ellipse newEllipse);
- }
-
- [Fact]
- public void GetDpi()
- {
- IFactory factory = Direct2d.CreateFactory();
-
- factory.GetDesktopDpi(out float x, out float y);
- }
- }
-}
diff --git a/src/Tests/WInterop.Tests/Direct2d/FactoryTests.cs b/src/Tests/WInterop.Tests/Direct2d/FactoryTests.cs
new file mode 100644
index 00000000..fb880c2a
--- /dev/null
+++ b/src/Tests/WInterop.Tests/Direct2d/FactoryTests.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using FluentAssertions;
+using System.Drawing;
+using WInterop.Direct2d;
+using Xunit;
+
+namespace Direct2dTests
+{
+ public class FactoryTests
+ {
+ [Fact]
+ public void Initialize()
+ {
+ using Factory factory = Direct2d.CreateFactory();
+
+ Ellipse ellipse = new(new PointF(1.0f, 2.0f), 3.0f, 4.0f);
+ using EllipseGeometry ellipseGeometry = factory.CreateEllipseGeometry(ellipse);
+ ellipseGeometry.GetEllipse().Should().Be(ellipse);
+ }
+
+ [Fact]
+ public void GetDpi()
+ {
+ using Factory factory = Direct2d.CreateFactory();
+ SizeF dpi = factory.GetDesktopDpi();
+ }
+ }
+}
diff --git a/src/Tests/WInterop.Tests/Direct2d/RenderTarget.cs b/src/Tests/WInterop.Tests/Direct2d/RenderTarget.cs
index 3eae6f2f..73bbcc20 100644
--- a/src/Tests/WInterop.Tests/Direct2d/RenderTarget.cs
+++ b/src/Tests/WInterop.Tests/Direct2d/RenderTarget.cs
@@ -12,205 +12,205 @@
namespace Direct2dTests
{
- public class RenderTarget : IClassFixture
- {
- private readonly RenderTargetFixture _fixture;
- public RenderTarget(RenderTargetFixture fixture)
- {
- _fixture = fixture;
- }
-
- public class RenderTargetFixture : IDisposable
- {
- private readonly IFactory _factory;
- // private DeviceContext _dc;
- private readonly WindowHandle _window;
- private readonly WindowClass _windowClass;
-
- public RenderTargetFixture()
- {
- _factory = Direct2d.CreateFactory(FactoryType.SingleThreaded, DebugLevel.None);
-
- // Create a memory only copy of the primary monitor DC
- // _dc = Gdi.CreateCompatibleDeviceContext(Gdi.GetDeviceContext());
-
- _windowClass = new WindowClass(backgroundBrush: BrushHandle.NoBrush);
- _windowClass.Register();
- _window = _windowClass.CreateWindow(Windows.DefaultBounds, "RenderTargetTest");
- RenderTarget = _factory.CreateWindowRenderTarget(default,
- new WindowRenderTargetProperties(_window, _window.GetClientRectangle().Size));
- }
-
- public void Dispose()
- {
- // Nothing
- }
-
- public IRenderTarget RenderTarget { get; private set; }
- }
-
- [Fact]
- public void GetFactory()
- {
- _fixture.RenderTarget.GetFactory(out IFactory factory);
- factory.Should().NotBeNull();
- }
-
- [Fact]
- public void CreateBitmap()
- {
- IBitmap bitmap = _fixture.RenderTarget.CreateBitmap(new Size(100, 100),
- new BitmapProperties(new PixelFormat(WInterop.Dxgi.Format.DXGI_FORMAT_R32G32B32A32_FLOAT, AlphaMode.Ignore), 72, 72));
-
- bitmap.Should().NotBeNull();
- }
-
- [Fact]
- public unsafe void CreateBitmapBrush()
- {
- IBitmap bitmap = _fixture.RenderTarget.CreateBitmap(new Size(10, 10),
- new BitmapProperties(new PixelFormat(WInterop.Dxgi.Format.DXGI_FORMAT_R32G32B32A32_FLOAT, AlphaMode.Ignore), 72, 72));
-
- IBitmapBrush brush = _fixture.RenderTarget.CreateBitmapBrush(bitmap, null, null);
- brush.Should().NotBeNull();
- }
-
- [Fact]
- public unsafe void CreateSolidColorBrush()
- {
- ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Bisque);
- brush.Should().NotBeNull();
- brush.GetColor(out ColorF color);
- ((Color)color).ToArgb().Should().Be(Color.Bisque.ToArgb());
- }
-
- [Fact]
- public unsafe void DrawLine()
- {
- ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Maroon);
- _fixture.RenderTarget.BeginDraw();
- _fixture.RenderTarget.DrawLine(default, new Point(10, 10), brush);
- _fixture.RenderTarget.EndDraw(out _, out _);
- }
-
- [Fact]
- public unsafe void DrawRectangle()
- {
- ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Gold);
- _fixture.RenderTarget.BeginDraw();
- _fixture.RenderTarget.DrawRectangle(new Rectangle(0, 0, 10, 10), brush);
- _fixture.RenderTarget.EndDraw(out _, out _);
- }
-
- [Fact]
- public unsafe void FillRectangle()
- {
- ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Blue);
- _fixture.RenderTarget.BeginDraw();
- _fixture.RenderTarget.FillRectangle(new Rectangle(0, 0, 10, 10), brush);
- _fixture.RenderTarget.EndDraw(out _, out _);
- }
-
- [Fact]
- public unsafe void DrawRoundedRectangle()
- {
- ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.White);
- _fixture.RenderTarget.BeginDraw();
- _fixture.RenderTarget.DrawRoundedRectangle(new RoundedRectangle(new Rectangle(0, 0, 10, 10), 3, 3), brush);
- _fixture.RenderTarget.EndDraw(out _, out _);
- }
-
- [Fact]
- public unsafe void FillRoundedRectangle()
- {
- ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.BurlyWood);
- _fixture.RenderTarget.BeginDraw();
- _fixture.RenderTarget.FillRoundedRectangle(new RoundedRectangle(new Rectangle(0, 0, 10, 10), 3, 3), brush);
- _fixture.RenderTarget.EndDraw(out _, out _);
- }
-
- [Fact]
- public unsafe void DrawEllipse()
- {
- ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Chocolate);
- _fixture.RenderTarget.BeginDraw();
- _fixture.RenderTarget.DrawEllipse(new Ellipse(new Point(5,5), 6, 7), brush);
- _fixture.RenderTarget.EndDraw(out _, out _);
- }
-
- [Fact]
- public unsafe void FillEllipse()
- {
- ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Honeydew);
- _fixture.RenderTarget.BeginDraw();
- _fixture.RenderTarget.FillEllipse(new Ellipse(new Point(5, 5), 6, 7), brush);
- _fixture.RenderTarget.EndDraw(out _, out _);
- }
-
- [Fact]
- public unsafe void Tags()
- {
- _fixture.RenderTarget.SetTags(2001, 2010);
- _fixture.RenderTarget.GetTags(out ulong tag1, out ulong tag2);
- tag1.Should().Be(2001);
- tag2.Should().Be(2010);
- _fixture.RenderTarget.BeginDraw();
- _fixture.RenderTarget.EndDraw(out tag2, out tag1);
-
- // These are 0 if there are no errors, a value will tell you the tag state when
- // a drawing operation failed.
- tag2.Should().Be(0);
- tag1.Should().Be(0);
- }
-
- [Fact]
- public unsafe void Dpi()
- {
- _fixture.RenderTarget.SetDpi(72.0f, 72.0f);
- _fixture.RenderTarget.GetDpi(out float dpiX, out float dpiY);
- dpiX.Should().Be(72.0f);
- dpiY.Should().Be(72.0f);
- }
-
- [Fact]
- public void GetSize()
- {
- _fixture.RenderTarget.GetSize(out SizeF size);
- size.Width.Should().BeGreaterThan(0);
- }
-
- [Fact]
- public void GetPixelSize()
- {
- _fixture.RenderTarget.GetPixelSize(out SizeU size);
- size.Width.Should().BeGreaterThan(0);
- }
-
- [Fact]
- public void GetPixelFormat()
- {
- _fixture.RenderTarget.GetPixelFormat(out PixelFormat pixelFormat);
- // BGRA
- pixelFormat.Format.Should().Be(WInterop.Dxgi.Format.DXGI_FORMAT_B8G8R8A8_UNORM);
- }
-
- [Fact]
- public void AntialiasModes()
- {
- AntialiasMode existing = _fixture.RenderTarget.GetAntialiasMode();
- _fixture.RenderTarget.SetAntialiasMode(AntialiasMode.Aliased);
- _fixture.RenderTarget.GetAntialiasMode().Should().Be(AntialiasMode.Aliased);
- _fixture.RenderTarget.SetAntialiasMode(existing);
- }
-
- [Fact]
- public void Transforms()
- {
- _fixture.RenderTarget.GetTransform(out Matrix3x2 transform);
- _fixture.RenderTarget.SetTransform();
- _fixture.RenderTarget.GetTransform(out Matrix3x2 newTransform);
- newTransform.IsIdentity.Should().BeTrue();
- _fixture.RenderTarget.SetTransform(ref transform);
- }
- }
+ //public class RenderTarget : IClassFixture
+ //{
+ // private readonly RenderTargetFixture _fixture;
+ // public RenderTarget(RenderTargetFixture fixture)
+ // {
+ // _fixture = fixture;
+ // }
+
+ // public class RenderTargetFixture : IDisposable
+ // {
+ // private readonly IFactory _factory;
+ // // private DeviceContext _dc;
+ // private readonly WindowHandle _window;
+ // private readonly WindowClass _windowClass;
+
+ // public RenderTargetFixture()
+ // {
+ // _factory = Direct2d.CreateFactory(FactoryType.SingleThreaded, DebugLevel.None);
+
+ // // Create a memory only copy of the primary monitor DC
+ // // _dc = Gdi.CreateCompatibleDeviceContext(Gdi.GetDeviceContext());
+
+ // _windowClass = new WindowClass(backgroundBrush: BrushHandle.NoBrush);
+ // _windowClass.Register();
+ // _window = _windowClass.CreateWindow(Windows.DefaultBounds, "RenderTargetTest");
+ // RenderTarget = _factory.CreateWindowRenderTarget(default,
+ // new WindowRenderTargetProperties(_window, _window.GetClientRectangle().Size));
+ // }
+
+ // public void Dispose()
+ // {
+ // // Nothing
+ // }
+
+ // public IRenderTarget RenderTarget { get; private set; }
+ // }
+
+ // [Fact]
+ // public void GetFactory()
+ // {
+ // _fixture.RenderTarget.GetFactory(out IFactory factory);
+ // factory.Should().NotBeNull();
+ // }
+
+ // [Fact]
+ // public void CreateBitmap()
+ // {
+ // IBitmap bitmap = _fixture.RenderTarget.CreateBitmap(new Size(100, 100),
+ // new BitmapProperties(new PixelFormat(WInterop.Dxgi.Format.DXGI_FORMAT_R32G32B32A32_FLOAT, AlphaMode.Ignore), 72, 72));
+
+ // bitmap.Should().NotBeNull();
+ // }
+
+ // [Fact]
+ // public unsafe void CreateBitmapBrush()
+ // {
+ // IBitmap bitmap = _fixture.RenderTarget.CreateBitmap(new Size(10, 10),
+ // new BitmapProperties(new PixelFormat(WInterop.Dxgi.Format.DXGI_FORMAT_R32G32B32A32_FLOAT, AlphaMode.Ignore), 72, 72));
+
+ // IBitmapBrush brush = _fixture.RenderTarget.CreateBitmapBrush(bitmap, null, null);
+ // brush.Should().NotBeNull();
+ // }
+
+ // [Fact]
+ // public unsafe void CreateSolidColorBrush()
+ // {
+ // ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Bisque);
+ // brush.Should().NotBeNull();
+ // brush.GetColor(out ColorF color);
+ // ((Color)color).ToArgb().Should().Be(Color.Bisque.ToArgb());
+ // }
+
+ // [Fact]
+ // public unsafe void DrawLine()
+ // {
+ // ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Maroon);
+ // _fixture.RenderTarget.BeginDraw();
+ // _fixture.RenderTarget.DrawLine(default, new Point(10, 10), brush);
+ // _fixture.RenderTarget.EndDraw(out _, out _);
+ // }
+
+ // [Fact]
+ // public unsafe void DrawRectangle()
+ // {
+ // ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Gold);
+ // _fixture.RenderTarget.BeginDraw();
+ // _fixture.RenderTarget.DrawRectangle(new Rectangle(0, 0, 10, 10), brush);
+ // _fixture.RenderTarget.EndDraw(out _, out _);
+ // }
+
+ // [Fact]
+ // public unsafe void FillRectangle()
+ // {
+ // ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Blue);
+ // _fixture.RenderTarget.BeginDraw();
+ // _fixture.RenderTarget.FillRectangle(new Rectangle(0, 0, 10, 10), brush);
+ // _fixture.RenderTarget.EndDraw(out _, out _);
+ // }
+
+ // [Fact]
+ // public unsafe void DrawRoundedRectangle()
+ // {
+ // ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.White);
+ // _fixture.RenderTarget.BeginDraw();
+ // _fixture.RenderTarget.DrawRoundedRectangle(new RoundedRectangle(new Rectangle(0, 0, 10, 10), 3, 3), brush);
+ // _fixture.RenderTarget.EndDraw(out _, out _);
+ // }
+
+ // [Fact]
+ // public unsafe void FillRoundedRectangle()
+ // {
+ // ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.BurlyWood);
+ // _fixture.RenderTarget.BeginDraw();
+ // _fixture.RenderTarget.FillRoundedRectangle(new RoundedRectangle(new Rectangle(0, 0, 10, 10), 3, 3), brush);
+ // _fixture.RenderTarget.EndDraw(out _, out _);
+ // }
+
+ // [Fact]
+ // public unsafe void DrawEllipse()
+ // {
+ // ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Chocolate);
+ // _fixture.RenderTarget.BeginDraw();
+ // _fixture.RenderTarget.DrawEllipse(new Ellipse(new Point(5,5), 6, 7), brush);
+ // _fixture.RenderTarget.EndDraw(out _, out _);
+ // }
+
+ // [Fact]
+ // public unsafe void FillEllipse()
+ // {
+ // ISolidColorBrush brush = _fixture.RenderTarget.CreateSolidColorBrush(Color.Honeydew);
+ // _fixture.RenderTarget.BeginDraw();
+ // _fixture.RenderTarget.FillEllipse(new Ellipse(new Point(5, 5), 6, 7), brush);
+ // _fixture.RenderTarget.EndDraw(out _, out _);
+ // }
+
+ // [Fact]
+ // public unsafe void Tags()
+ // {
+ // _fixture.RenderTarget.SetTags(2001, 2010);
+ // _fixture.RenderTarget.GetTags(out ulong tag1, out ulong tag2);
+ // tag1.Should().Be(2001);
+ // tag2.Should().Be(2010);
+ // _fixture.RenderTarget.BeginDraw();
+ // _fixture.RenderTarget.EndDraw(out tag2, out tag1);
+
+ // // These are 0 if there are no errors, a value will tell you the tag state when
+ // // a drawing operation failed.
+ // tag2.Should().Be(0);
+ // tag1.Should().Be(0);
+ // }
+
+ // [Fact]
+ // public unsafe void Dpi()
+ // {
+ // _fixture.RenderTarget.SetDpi(72.0f, 72.0f);
+ // _fixture.RenderTarget.GetDpi(out float dpiX, out float dpiY);
+ // dpiX.Should().Be(72.0f);
+ // dpiY.Should().Be(72.0f);
+ // }
+
+ // [Fact]
+ // public void GetSize()
+ // {
+ // _fixture.RenderTarget.GetSize(out SizeF size);
+ // size.Width.Should().BeGreaterThan(0);
+ // }
+
+ // [Fact]
+ // public void GetPixelSize()
+ // {
+ // _fixture.RenderTarget.GetPixelSize(out SizeU size);
+ // size.Width.Should().BeGreaterThan(0);
+ // }
+
+ // [Fact]
+ // public void GetPixelFormat()
+ // {
+ // _fixture.RenderTarget.GetPixelFormat(out PixelFormat pixelFormat);
+ // // BGRA
+ // pixelFormat.Format.Should().Be(WInterop.Dxgi.Format.DXGI_FORMAT_B8G8R8A8_UNORM);
+ // }
+
+ // [Fact]
+ // public void AntialiasModes()
+ // {
+ // AntialiasMode existing = _fixture.RenderTarget.GetAntialiasMode();
+ // _fixture.RenderTarget.SetAntialiasMode(AntialiasMode.Aliased);
+ // _fixture.RenderTarget.GetAntialiasMode().Should().Be(AntialiasMode.Aliased);
+ // _fixture.RenderTarget.SetAntialiasMode(existing);
+ // }
+
+ // [Fact]
+ // public void Transforms()
+ // {
+ // _fixture.RenderTarget.GetTransform(out Matrix3x2 transform);
+ // _fixture.RenderTarget.SetTransform();
+ // _fixture.RenderTarget.GetTransform(out Matrix3x2 newTransform);
+ // newTransform.IsIdentity.Should().BeTrue();
+ // _fixture.RenderTarget.SetTransform(ref transform);
+ // }
+ //}
}
diff --git a/src/WInterop.Desktop/Com/Native/IDataObject.cs b/src/WInterop.Desktop/Com/Native/IDataObject.cs
index 8b59b997..526ed3e8 100644
--- a/src/WInterop.Desktop/Com/Native/IDataObject.cs
+++ b/src/WInterop.Desktop/Com/Native/IDataObject.cs
@@ -96,15 +96,15 @@ private static unsafe HResult QueryInterface(void* @this, Guid* iid, void* ppObj
return HResult.E_NOINTERFACE;
}
- Lifetime.AddRef(@this);
+ Lifetime.AddRef(@this);
return HResult.S_OK;
}
[UnmanagedCallersOnly]
- private static unsafe uint AddRef(void* @this) => Lifetime.AddRef(@this);
+ private static unsafe uint AddRef(void* @this) => Lifetime.AddRef(@this);
[UnmanagedCallersOnly]
- private static unsafe uint Release(void* @this) => Lifetime.Release(@this);
+ private static unsafe uint Release(void* @this) => Lifetime.Release(@this);
[UnmanagedCallersOnly]
#pragma warning disable IDE0060 // Remove unused parameter
diff --git a/src/WInterop.Desktop/Com/Native/IDropSource.CCW.cs b/src/WInterop.Desktop/Com/Native/IDropSource.CCW.cs
index ebc561f6..9d4479cf 100644
--- a/src/WInterop.Desktop/Com/Native/IDropSource.CCW.cs
+++ b/src/WInterop.Desktop/Com/Native/IDropSource.CCW.cs
@@ -29,7 +29,7 @@ public static class CCW
}
public static unsafe IntPtr CreateInstance(Managed.IDropSource @object)
- => (IntPtr)Lifetime.Allocate(@object, CCWVTable);
+ => (IntPtr)Lifetime.Allocate(@object, CCWVTable);
[UnmanagedCallersOnly]
private static unsafe HResult QueryInterface(void* @this, Guid* iid, void* ppObject)
@@ -44,20 +44,20 @@ private static unsafe HResult QueryInterface(void* @this, Guid* iid, void* ppObj
return HResult.E_NOINTERFACE;
}
- Lifetime.AddRef(@this);
+ Lifetime.AddRef(@this);
return HResult.S_OK;
}
[UnmanagedCallersOnly]
- private static unsafe uint AddRef(void* @this) => Lifetime.AddRef(@this);
+ private static unsafe uint AddRef(void* @this) => Lifetime.AddRef(@this);
[UnmanagedCallersOnly]
- private static unsafe uint Release(void* @this) => Lifetime.Release(@this);
+ private static unsafe uint Release(void* @this) => Lifetime.Release(@this);
[UnmanagedCallersOnly]
private static unsafe HResult QueryContinueDrag(void* @this, int fEscapePressed, KeyState grfKeyState)
{
- var lifetime = (Lifetime*)@this;
+ var lifetime = (Lifetime*)@this;
var dropSource = GCHandle.FromIntPtr((IntPtr)lifetime->Handle).Target as Managed.IDropSource;
return dropSource?.QueryContinueDrag(fEscapePressed.FromBOOL(), grfKeyState) ?? HResult.E_FAIL;
}
@@ -65,7 +65,7 @@ private static unsafe HResult QueryContinueDrag(void* @this, int fEscapePressed,
[UnmanagedCallersOnly]
private static unsafe HResult GiveFeedback(void* @this, DropEffect dwEffect)
{
- var lifetime = (Lifetime*)@this;
+ var lifetime = (Lifetime*)@this;
var dropSource = GCHandle.FromIntPtr((IntPtr)lifetime->Handle).Target as Managed.IDropSource;
return dropSource?.GiveFeedback(dwEffect) ?? HResult.E_FAIL;
}
diff --git a/src/WInterop.Desktop/Com/Native/IUnknown.CCW.cs b/src/WInterop.Desktop/Com/Native/IUnknown.CCW.cs
index 1022624a..169710c4 100644
--- a/src/WInterop.Desktop/Com/Native/IUnknown.CCW.cs
+++ b/src/WInterop.Desktop/Com/Native/IUnknown.CCW.cs
@@ -27,7 +27,7 @@ public static class CCW
}
public static unsafe IntPtr CreateInstance(object @object)
- => (IntPtr)Lifetime.Allocate(@object, CCWVTable);
+ => (IntPtr)Lifetime.Allocate(@object, CCWVTable);
[UnmanagedCallersOnly]
private static unsafe HResult QueryInterface(void* @this, Guid* iid, void* ppObject)
@@ -42,15 +42,15 @@ private static unsafe HResult QueryInterface(void* @this, Guid* iid, void* ppObj
return HResult.E_NOINTERFACE;
}
- Lifetime.AddRef(@this);
+ Lifetime.AddRef(@this);
return HResult.S_OK;
}
[UnmanagedCallersOnly]
- private static unsafe uint AddRef(void* @this) => Lifetime.AddRef(@this);
+ private static unsafe uint AddRef(void* @this) => Lifetime.AddRef(@this);
[UnmanagedCallersOnly]
- private static unsafe uint Release(void* @this) => Lifetime.Release(@this);
+ private static unsafe uint Release(void* @this) => Lifetime.Release(@this);
}
}
}
\ No newline at end of file
diff --git a/src/WInterop.Desktop/Com/Native/Lifetime.cs b/src/WInterop.Desktop/Com/Native/Lifetime.cs
index 7fa67efd..ef6b0861 100644
--- a/src/WInterop.Desktop/Com/Native/Lifetime.cs
+++ b/src/WInterop.Desktop/Com/Native/Lifetime.cs
@@ -9,18 +9,18 @@
namespace WInterop.Com.Native
{
- public unsafe struct Lifetime where TVTable : unmanaged
+ public unsafe struct Lifetime where TVTable : unmanaged
{
public TVTable* VTable;
public void* Handle;
public uint RefCount;
public static unsafe uint AddRef(void* @this)
- => Interlocked.Increment(ref ((Lifetime*)@this)->RefCount);
+ => Interlocked.Increment(ref ((Lifetime*)@this)->RefCount);
public static unsafe uint Release(void* @this)
{
- var lifetime = (Lifetime*)@this;
+ var lifetime = (Lifetime*)@this;
Debug.Assert(lifetime->RefCount > 0);
uint count = Interlocked.Decrement(ref lifetime->RefCount);
if (count == 0)
@@ -32,9 +32,23 @@ public static unsafe uint Release(void* @this)
return count;
}
- public static unsafe Lifetime* Allocate(object @object, TVTable* vtable)
+ ///
+ /// Allocate a lifetime wrapper for the given with the given
+ /// .
+ ///
+ ///
+ ///
+ /// This creates a to root the until ref
+ /// counting has gone to zero.
+ ///
+ ///
+ /// The should be fixed, typically as a static. Com calls always
+ /// include the "this" pointer as the first argument.
+ ///
+ ///
+ public static unsafe Lifetime* Allocate(TObject @object, TVTable* vtable)
{
- var wrapper = (Lifetime*)CoTaskAllocate((nuint)sizeof(Lifetime));
+ var wrapper = (Lifetime*)CoTaskAllocate((nuint)sizeof(Lifetime));
// Create the wrapper instance.
wrapper->VTable = vtable;
@@ -43,5 +57,11 @@ public static unsafe uint Release(void* @this)
return wrapper;
}
+
+ public static TObject? GetObject(void* @this)
+ {
+ var lifetime = (Lifetime*)@this;
+ return (TObject?)GCHandle.FromIntPtr((IntPtr)lifetime->Handle).Target;
+ }
}
}
\ No newline at end of file
diff --git a/src/WInterop.Desktop/Windows/Classes/WindowClass.cs b/src/WInterop.Desktop/Windows/Classes/WindowClass.cs
index 81542218..26bce03d 100644
--- a/src/WInterop.Desktop/Windows/Classes/WindowClass.cs
+++ b/src/WInterop.Desktop/Windows/Classes/WindowClass.cs
@@ -11,13 +11,14 @@
namespace WInterop.Windows
{
- public class WindowClass
+ public class WindowClass : IDisposable
{
// Stash the delegate to keep it from being collected
private readonly WindowProcedure _windowProcedure;
private WNDCLASSEX _wndClass;
private readonly string _className;
private readonly string _menuName;
+ private bool _disposedValue;
public Atom Atom { get; private set; }
public WindowHandle MainWindow { get; private set; }
@@ -190,5 +191,28 @@ protected virtual LResult WindowProcedure(WindowHandle window, MessageType messa
return Windows.DefaultWindowProcedure(window, message, wParam, lParam);
}
+
+ protected virtual void Dispose(bool disposing)
+ {
+ }
+
+ ~WindowClass()
+ {
+ if (!_disposedValue)
+ {
+ _disposedValue = true;
+ Dispose(disposing: false);
+ }
+ }
+
+ public void Dispose()
+ {
+ GC.SuppressFinalize(this);
+ if (!_disposedValue)
+ {
+ _disposedValue = true;
+ Dispose(disposing: true);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/WInterop.DirectX/Direct2d/AlphaMode.cs b/src/WInterop.DirectX/Direct2d/AlphaMode.cs
index 112c6d3c..49695d8a 100644
--- a/src/WInterop.DirectX/Direct2d/AlphaMode.cs
+++ b/src/WInterop.DirectX/Direct2d/AlphaMode.cs
@@ -14,21 +14,21 @@ public enum AlphaMode : uint
/// or imply this information in which case alpha must be specified.
/// [D2D1_ALPHA_MODE_UNKNOWN]
///
- Unknown = 0,
+ Unknown = D2D1_ALPHA_MODE.D2D1_ALPHA_MODE_UNKNOWN,
///
/// Treat the alpha as premultipled. [D2D1_ALPHA_MODE_PREMULTIPLIED]
///
- Premultiplied = 1,
+ Premultiplied = D2D1_ALPHA_MODE.D2D1_ALPHA_MODE_PREMULTIPLIED,
///
/// Opacity is in the 'A' component only. [D2D1_ALPHA_MODE_STRAIGHT]
///
- Straight = 2,
+ Straight = D2D1_ALPHA_MODE.D2D1_ALPHA_MODE_STRAIGHT,
///
/// Ignore any alpha channel information. [D2D1_ALPHA_MODE_IGNORE]
///
- Ignore = 3,
+ Ignore = D2D1_ALPHA_MODE.D2D1_ALPHA_MODE_IGNORE,
}
}
diff --git a/src/WInterop.DirectX/Direct2d/AntialiasMode.cs b/src/WInterop.DirectX/Direct2d/AntialiasMode.cs
index c1a64721..fd8b0432 100644
--- a/src/WInterop.DirectX/Direct2d/AntialiasMode.cs
+++ b/src/WInterop.DirectX/Direct2d/AntialiasMode.cs
@@ -11,11 +11,11 @@ public enum AntialiasMode : uint
///
/// The edges of each primitive are antialiased sequentially. [D2D1_ANTIALIAS_MODE_PER_PRIMITIVE]
///
- PerPrimitive = 0,
+ PerPrimitive = D2D1_ANTIALIAS_MODE.D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
///
/// Each pixel is rendered if its pixel center is contained by the geometry. [D2D1_ANTIALIAS_MODE_ALIASED]
///
- Aliased = 1
+ Aliased = D2D1_ANTIALIAS_MODE.D2D1_ANTIALIAS_MODE_ALIASED
}
}
diff --git a/src/WInterop.DirectX/Direct2d/ArcSegment.cs b/src/WInterop.DirectX/Direct2d/ArcSegment.cs
index 3ca3c52e..e867ea86 100644
--- a/src/WInterop.DirectX/Direct2d/ArcSegment.cs
+++ b/src/WInterop.DirectX/Direct2d/ArcSegment.cs
@@ -10,11 +10,11 @@ namespace WInterop.Direct2d
///
public readonly struct ArcSegment
{
- public readonly PointF Point;
- public readonly SizeF Size;
- public readonly float RotationAngle;
- public readonly SweepDirection SweepDirection;
- public readonly ArcSize ArcSize;
+ public PointF Point { get; }
+ public SizeF Size { get; }
+ public float RotationAngle { get; }
+ public SweepDirection SweepDirection { get; }
+ public ArcSize ArcSize { get; }
public ArcSegment(
PointF point,
@@ -29,5 +29,19 @@ public ArcSegment(
SweepDirection = sweepDirection;
ArcSize = arcSize;
}
+
+ public ArcSegment(
+ (float X, float Y) point,
+ (float X, float Y) size,
+ float rotationAngle = 0.0f,
+ SweepDirection sweepDirection = SweepDirection.Clockwise,
+ ArcSize arcSize = ArcSize.Small)
+ {
+ Point = new(point.X, point.Y);
+ Size = new(size.X, size.Y);
+ RotationAngle = rotationAngle;
+ SweepDirection = sweepDirection;
+ ArcSize = arcSize;
+ }
}
}
diff --git a/src/WInterop.DirectX/Direct2d/ArcSize.cs b/src/WInterop.DirectX/Direct2d/ArcSize.cs
index 6727dfb3..b8348c6f 100644
--- a/src/WInterop.DirectX/Direct2d/ArcSize.cs
+++ b/src/WInterop.DirectX/Direct2d/ArcSize.cs
@@ -12,11 +12,11 @@ public enum ArcSize : uint
///
/// [D2D1_ARC_SIZE_SMALL]
///
- Small = 0,
+ Small = D2D1_ARC_SIZE.D2D1_ARC_SIZE_SMALL,
///
/// [D2D1_ARC_SIZE_LARGE]
///
- Large = 1,
+ Large = D2D1_ARC_SIZE.D2D1_ARC_SIZE_LARGE,
}
}
diff --git a/src/WInterop.DirectX/Direct2d/BezierSegment.cs b/src/WInterop.DirectX/Direct2d/BezierSegment.cs
index d88f9ffc..1b47ed1b 100644
--- a/src/WInterop.DirectX/Direct2d/BezierSegment.cs
+++ b/src/WInterop.DirectX/Direct2d/BezierSegment.cs
@@ -10,9 +10,9 @@ namespace WInterop.Direct2d
///
public readonly struct BezierSegment
{
- public readonly PointF Point1;
- public readonly PointF Point2;
- public readonly PointF Point3;
+ public PointF Point1 { get; }
+ public PointF Point2 { get; }
+ public PointF Point3 { get; }
public BezierSegment(PointF point1, PointF point2, PointF point3)
{
@@ -23,9 +23,9 @@ public BezierSegment(PointF point1, PointF point2, PointF point3)
public BezierSegment((float X, float Y) point1, (float X, float Y) point2, (float X, float Y) point3)
{
- Point1 = new PointF(point1.X, point1.Y);
- Point2 = new PointF(point2.X, point2.Y);
- Point3 = new PointF(point3.X, point3.Y);
+ Point1 = new(point1.X, point1.Y);
+ Point2 = new(point2.X, point2.Y);
+ Point3 = new(point3.X, point3.Y);
}
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Bitmap.cs b/src/WInterop.DirectX/Direct2d/Bitmap.cs
new file mode 100644
index 00000000..9344045d
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/Bitmap.cs
@@ -0,0 +1,110 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Root bitmap resource, linearly scaled on a draw call. [ID2D1Bitmap]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1Bitmap)]
+ public readonly unsafe struct Bitmap : Bitmap.Interface, IDisposable
+ {
+ internal readonly ID2D1Bitmap* _handle;
+
+ internal Bitmap(ID2D1Bitmap* handle) => _handle = handle;
+
+ public unsafe Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public SizeF Size => _handle->GetSize().ToSizeF();
+
+ public SizeU PixelSize => new(_handle->GetPixelSize());
+
+ public PixelFormat PixelFormat => new(_handle->GetPixelFormat());
+
+ public PointF Dpi
+ {
+ get
+ {
+ float x;
+ float y;
+ _handle->GetDpi(&x, &y);
+ return new(x, y);
+ }
+ }
+
+ public void CopyFromBitmap(PointU destinationPoint, Bitmap bitmap, Rectangle sourceRectangle)
+ {
+ var rect = sourceRectangle.ToD2D();
+ _handle->CopyFromBitmap(
+ (D2D_POINT_2U*)&destinationPoint,
+ bitmap._handle,
+ &rect).ThrowIfFailed();
+ }
+
+ public void CopyFromRenderTarget(PointU destinationPoint, IRenderTarget renderTarget, Rectangle sourceRectangle)
+ {
+ var rect = sourceRectangle.ToD2D();
+ _handle->CopyFromRenderTarget(
+ (D2D_POINT_2U*)&destinationPoint,
+ ((IResource)renderTarget).Handle,
+ &rect).ThrowIfFailed();
+ }
+
+ public void CopyFromMemory(Rectangle destinationRectangle, void* sourceData, uint pitch)
+ {
+ var rect = destinationRectangle.ToD2D();
+ _handle->CopyFromMemory(
+ &rect,
+ sourceData,
+ pitch).ThrowIfFailed();
+ }
+
+ public void Dispose() => _handle->Release();
+
+
+ public static implicit operator Image(Bitmap bitmap) => new((ID2D1Image*)bitmap._handle);
+
+ internal interface Interface : Resource.Interface
+ {
+ ///
+ /// Returns the size of the bitmap in resolution independent units.
+ ///
+ SizeF Size { get; }
+
+ ///
+ /// Returns the size of the bitmap in resolution dependent units, (pixels).
+ ///
+ SizeU PixelSize { get; }
+
+ ///
+ /// Retrieve the format of the bitmap.
+ ///
+ PixelFormat PixelFormat { get; }
+
+ ///
+ /// Return the DPI of the bitmap.
+ ///
+ PointF Dpi { get; }
+
+ void CopyFromBitmap(
+ PointU destinationPoint,
+ Bitmap bitmap,
+ Rectangle sourceRectangle);
+
+ void CopyFromRenderTarget(
+ PointU destinationPoint,
+ IRenderTarget renderTarget,
+ Rectangle sourceRectangle);
+
+ void CopyFromMemory(
+ Rectangle destinationRectangle,
+ void* sourceData,
+ uint pitch);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/BitmapBrush.cs b/src/WInterop.DirectX/Direct2d/BitmapBrush.cs
new file mode 100644
index 00000000..ea0cbbbc
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/BitmapBrush.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// A bitmap brush allows a bitmap to be used to fill a geometry. [ID2D1BitmapBrush]
+ ///
+ [Guid(InterfaceIds.IID_ID2D1BitmapBrush)]
+ public readonly unsafe struct BitmapBrush : BitmapBrush.Interface
+ {
+ private readonly ID2D1BitmapBrush* _handle;
+
+ internal BitmapBrush(ID2D1BitmapBrush* handle) => _handle = handle;
+
+ public unsafe Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public float Opacity
+ {
+ get => Brush.From(this).Opacity;
+ set => Brush.From(this).Opacity = value;
+ }
+
+ public Matrix3x2 Transform
+ {
+ get => Brush.From(this).Transform;
+ set => Brush.From(this).Transform = value;
+ }
+
+ public ExtendMode ExtendModeX
+ {
+ get => (ExtendMode)_handle->GetExtendModeX();
+ set => _handle->SetExtendModeX((D2D1_EXTEND_MODE)value);
+ }
+
+ public ExtendMode ExtendModeY
+ {
+ get => (ExtendMode)_handle->GetExtendModeY();
+ set => _handle->SetExtendModeY((D2D1_EXTEND_MODE)value);
+ }
+
+ public Bitmap Bitmap
+ {
+ get
+ {
+ ID2D1Bitmap* bitmap;
+ _handle->GetBitmap(&bitmap);
+ return new(bitmap);
+ }
+ set => _handle->SetBitmap(value._handle);
+ }
+
+ public BitmapInterpolationMode InterpolationMode
+ {
+ get => (BitmapInterpolationMode)_handle->GetInterpolationMode();
+ set => _handle->SetInterpolationMode((D2D1_BITMAP_INTERPOLATION_MODE)value);
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public static implicit operator Brush(BitmapBrush brush) => new((ID2D1Brush*)brush._handle);
+
+ internal interface Interface : Brush.Interface
+ {
+ ///
+ /// How the bitmap is to be treated outside of its natural extent on the X axis.
+ ///
+ ExtendMode ExtendModeX { get; set; }
+
+ ///
+ /// How the bitmap is to be treated outside of its natural extent on the Y axis.
+ ///
+ ExtendMode ExtendModeY { get; set; }
+
+ ///
+ /// Sets the bitmap associated as the source of this brush.
+ ///
+ Bitmap Bitmap { get; set; }
+
+ ///
+ /// The interpolation mode used when this brush is used.
+ ///
+ BitmapInterpolationMode InterpolationMode { get; set; }
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/BitmapBrushProperties.cs b/src/WInterop.DirectX/Direct2d/BitmapBrushProperties.cs
index d24ff008..fc1645c3 100644
--- a/src/WInterop.DirectX/Direct2d/BitmapBrushProperties.cs
+++ b/src/WInterop.DirectX/Direct2d/BitmapBrushProperties.cs
@@ -1,17 +1,19 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System.Runtime.CompilerServices;
+
namespace WInterop.Direct2d
{
///
- /// Describes the extend modes and the interpolation mode of an .
+ /// Describes the extend modes and the interpolation mode of an .
/// [D2D1_BITMAP_BRUSH_PROPERTIES]
///
- public readonly struct BitmapBrushProperties
+ public struct BitmapBrushProperties
{
- public readonly ExtendMode ExtendModeX;
- public readonly ExtendMode ExtendModeY;
- public readonly BitmapInterpolationMode InterpolationMode;
+ public ExtendMode ExtendModeX;
+ public ExtendMode ExtendModeY;
+ public BitmapInterpolationMode InterpolationMode;
public BitmapBrushProperties(
ExtendMode extendModeX = ExtendMode.Clamp,
@@ -22,5 +24,11 @@ public BitmapBrushProperties(
ExtendModeY = extendModeY;
InterpolationMode = interpolationMode;
}
+
+ public static implicit operator BitmapBrushProperties(in D2D1_BITMAP_BRUSH_PROPERTIES properties)
+ => Unsafe.As(ref Unsafe.AsRef(properties));
+
+ public static implicit operator D2D1_BITMAP_BRUSH_PROPERTIES(in BitmapBrushProperties properties)
+ => Unsafe.As(ref Unsafe.AsRef(properties));
}
}
diff --git a/src/WInterop.DirectX/Direct2d/BitmapRenderTarget.cs b/src/WInterop.DirectX/Direct2d/BitmapRenderTarget.cs
new file mode 100644
index 00000000..5151085b
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/BitmapRenderTarget.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Renders to an intermediate texture created by the CreateCompatibleRenderTarget method.
+ /// [ID2D1BitmapRenderTarget]
+ ///
+ internal unsafe class BitmapRenderTarget : RenderTarget, IBitmapRenderTarget
+ {
+ private readonly ID2D1BitmapRenderTarget* _handle;
+
+ internal BitmapRenderTarget(ID2D1BitmapRenderTarget* handle)
+ : base ((ID2D1RenderTarget*)handle)
+ => _handle = handle;
+
+ public Bitmap Bitmap
+ {
+ get
+ {
+ ID2D1Bitmap* bitmap;
+ _handle->GetBitmap(&bitmap).ThrowIfFailed();
+ return new(bitmap);
+ }
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/Brush.cs b/src/WInterop.DirectX/Direct2d/Brush.cs
new file mode 100644
index 00000000..dd023149
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/Brush.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// The root brush interface. All brushes can be used to fill or pen a geometry.
+ /// [ID2D1Brush]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1Brush)]
+ public readonly unsafe struct Brush : Brush.Interface, IDisposable
+ {
+ internal readonly ID2D1Brush* Handle { get; }
+
+ internal Brush(ID2D1Brush* handle) => Handle = handle;
+
+ public unsafe Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public float Opacity
+ {
+ get => Handle->GetOpacity();
+ set => Handle->SetOpacity(value);
+ }
+
+ public Matrix3x2 Transform
+ {
+ get
+ {
+ Matrix3x2 matrix;
+ Handle->GetTransform((D2D_MATRIX_3X2_F*)&matrix);
+ return matrix;
+ }
+ set => Handle->SetTransform((D2D_MATRIX_3X2_F*)&value);
+ }
+
+ internal static ref Brush From(in TFrom from)
+ where TFrom : unmanaged, Interface
+ => ref Unsafe.AsRef(Unsafe.AsPointer(ref Unsafe.AsRef(from)));
+
+ public void Dispose() => Handle->Release();
+
+ internal interface Interface : Resource.Interface
+ {
+ ///
+ /// Sets the opacity for when the brush is drawn over the entire fill of the brush.
+ ///
+ float Opacity { get; set; }
+
+ ///
+ /// Sets the transform that applies to everything drawn by the brush.
+ ///
+ Matrix3x2 Transform { get; set; }
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/BrushProperties.cs b/src/WInterop.DirectX/Direct2d/BrushProperties.cs
index 4b3efa0b..123fbd7e 100644
--- a/src/WInterop.DirectX/Direct2d/BrushProperties.cs
+++ b/src/WInterop.DirectX/Direct2d/BrushProperties.cs
@@ -2,21 +2,30 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Numerics;
+using System.Runtime.CompilerServices;
namespace WInterop.Direct2d
{
///
/// Describes the opacity and transformation of a brush. [D2D1_BRUSH_PROPERTIES]
///
- public readonly struct BrushProperties
+ public struct BrushProperties
{
public readonly float Opacity;
public readonly Matrix3x2 Transform;
- public BrushProperties(float opacity)
+ public static BrushProperties Default { get; } = new(1.0f, Matrix3x2.Identity);
+
+ public BrushProperties(float opacity, Matrix3x2 transform)
{
Opacity = opacity;
- Transform = Matrix3x2.Identity;
+ Transform = transform;
}
+
+ public static implicit operator BrushProperties(in D2D1_BRUSH_PROPERTIES properties)
+ => Unsafe.As(ref Unsafe.AsRef(properties));
+
+ public static implicit operator D2D1_BRUSH_PROPERTIES(in BrushProperties properties)
+ => Unsafe.As(ref Unsafe.AsRef(properties));
}
}
diff --git a/src/WInterop.DirectX/Direct2d/CapStyle.cs b/src/WInterop.DirectX/Direct2d/CapStyle.cs
index 32e2bce4..8d88164f 100644
--- a/src/WInterop.DirectX/Direct2d/CapStyle.cs
+++ b/src/WInterop.DirectX/Direct2d/CapStyle.cs
@@ -12,21 +12,21 @@ public enum CapStyle : uint
///
/// Flat line cap. [D2D1_CAP_STYLE_FLAT]
///
- Flat = 0,
+ Flat = D2D1_CAP_STYLE.D2D1_CAP_STYLE_FLAT,
///
/// Square line cap. [D2D1_CAP_STYLE_SQUARE]
///
- Square = 1,
+ Square = D2D1_CAP_STYLE.D2D1_CAP_STYLE_SQUARE,
///
/// Round line cap. [D2D1_CAP_STYLE_ROUND]
///
- Round = 2,
+ Round = D2D1_CAP_STYLE.D2D1_CAP_STYLE_ROUND,
///
/// Triangle line cap. [D2D1_CAP_STYLE_TRIANGLE]
///
- Triangle = 3
+ Triangle = D2D1_CAP_STYLE.D2D1_CAP_STYLE_TRIANGLE
}
}
diff --git a/src/WInterop.DirectX/Direct2d/ColorF.cs b/src/WInterop.DirectX/Direct2d/ColorF.cs
index 5bed64b5..c211067a 100644
--- a/src/WInterop.DirectX/Direct2d/ColorF.cs
+++ b/src/WInterop.DirectX/Direct2d/ColorF.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Drawing;
+using System.Runtime.CompilerServices;
namespace WInterop.Direct2d
{
@@ -31,10 +32,16 @@ public ColorF(Color color, float a = 1.0f)
A = a;
}
+ public static implicit operator ColorF(in DXGI_RGBA color)
+ => Unsafe.As(ref Unsafe.AsRef(color));
+
+ public static implicit operator DXGI_RGBA(in ColorF color)
+ => Unsafe.As(ref Unsafe.AsRef(color));
+
public static implicit operator Color(ColorF color)
=> Color.FromArgb((int)(color.A * 255), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255));
public static implicit operator ColorF(Color color)
- => new ColorF(color, color.A / 255.0f);
+ => new(color, color.A / 255.0f);
}
}
diff --git a/src/WInterop.DirectX/Direct2d/DashStyle.cs b/src/WInterop.DirectX/Direct2d/DashStyle.cs
index dfacb9de..9c27f003 100644
--- a/src/WInterop.DirectX/Direct2d/DashStyle.cs
+++ b/src/WInterop.DirectX/Direct2d/DashStyle.cs
@@ -12,31 +12,31 @@ public enum DashStyle : uint
///
/// [D2D1_DASH_STYLE_SOLID]
///
- Solid = 0,
+ Solid = D2D1_DASH_STYLE.D2D1_DASH_STYLE_SOLID,
///
/// [D2D1_DASH_STYLE_DASH]
///
- Dash = 1,
+ Dash = D2D1_DASH_STYLE.D2D1_DASH_STYLE_DASH,
///
/// [D2D1_DASH_STYLE_DOT]
///
- Dot = 2,
+ Dot = D2D1_DASH_STYLE.D2D1_DASH_STYLE_DOT,
///
/// [D2D1_DASH_STYLE_DASH_DOT]
///
- DashDot = 3,
+ DashDot = D2D1_DASH_STYLE.D2D1_DASH_STYLE_DASH_DOT,
///
/// [D2D1_DASH_STYLE_DASH_DOT_DOT]
///
- DashDotDot = 4,
+ DashDotDot = D2D1_DASH_STYLE.D2D1_DASH_STYLE_DASH_DOT_DOT,
///
/// [D2D1_DASH_STYLE_CUSTOM]
///
- Custom = 5
+ Custom = D2D1_DASH_STYLE.D2D1_DASH_STYLE_CUSTOM
}
}
diff --git a/src/WInterop.DirectX/Direct2d/DebugLevel.cs b/src/WInterop.DirectX/Direct2d/DebugLevel.cs
index 1440df7b..cc9c040d 100644
--- a/src/WInterop.DirectX/Direct2d/DebugLevel.cs
+++ b/src/WInterop.DirectX/Direct2d/DebugLevel.cs
@@ -12,21 +12,21 @@ public enum DebugLevel : uint
///
/// [D2D1_DEBUG_LEVEL_NONE]
///
- None,
+ None = D2D1_DEBUG_LEVEL.D2D1_DEBUG_LEVEL_NONE,
///
/// [D2D1_DEBUG_LEVEL_ERROR]
///
- Error,
+ Error = D2D1_DEBUG_LEVEL.D2D1_DEBUG_LEVEL_ERROR,
///
/// [D2D1_DEBUG_LEVEL_WARNING]
///
- Warning,
+ Warning = D2D1_DEBUG_LEVEL.D2D1_DEBUG_LEVEL_WARNING,
///
/// [D2D1_DEBUG_LEVEL_INFORMATION]
///
- Information
+ Information = D2D1_DEBUG_LEVEL.D2D1_DEBUG_LEVEL_INFORMATION
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Direct2d.cs b/src/WInterop.DirectX/Direct2d/Direct2d.cs
index ae4f33a9..8a330407 100644
--- a/src/WInterop.DirectX/Direct2d/Direct2d.cs
+++ b/src/WInterop.DirectX/Direct2d/Direct2d.cs
@@ -1,23 +1,24 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-using System;
using WInterop.Errors;
-using WInterop.Direct2d.Native;
namespace WInterop.Direct2d
{
public static class Direct2d
{
- public static IFactory CreateFactory(
+ public unsafe static Factory CreateFactory(
FactoryType factoryType = FactoryType.SingleThreaded,
DebugLevel debugLevel = DebugLevel.None)
{
- Imports.D2D1CreateFactory(
- factoryType, new Guid(InterfaceIds.IID_ID2D1Factory), debugLevel, out IFactory factory)
- .ThrowIfFailed();
+ ID2D1Factory* factory;
+ HResult result = TerraFX.Interop.DirectX.DirectX.D2D1CreateFactory(
+ (D2D1_FACTORY_TYPE)factoryType,
+ (D2D1_FACTORY_OPTIONS*)&debugLevel,
+ (void**)&factory).ToHResult();
- return factory;
+ result.ThrowIfFailed();
+ return new(factory);
}
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Ellipse.cs b/src/WInterop.DirectX/Direct2d/Ellipse.cs
index b31a4eda..5153f663 100644
--- a/src/WInterop.DirectX/Direct2d/Ellipse.cs
+++ b/src/WInterop.DirectX/Direct2d/Ellipse.cs
@@ -12,9 +12,9 @@ namespace WInterop.Direct2d
///
public readonly struct Ellipse
{
- public readonly PointF Point;
- public readonly float RadiusX;
- public readonly float RadiusY;
+ public PointF Point { get; }
+ public float RadiusX { get; }
+ public float RadiusY { get; }
public Ellipse(PointF point, float radiusX, float radiusY)
{
@@ -22,5 +22,12 @@ public Ellipse(PointF point, float radiusX, float radiusY)
RadiusX = radiusX;
RadiusY = radiusY;
}
+
+ public unsafe Ellipse((float X, float Y) point, float radiusX, float radiusY)
+ {
+ Point = *(PointF*)&point;
+ RadiusX = radiusX;
+ RadiusY = radiusY;
+ }
}
}
diff --git a/src/WInterop.DirectX/Direct2d/EllipseGeometry.cs b/src/WInterop.DirectX/Direct2d/EllipseGeometry.cs
new file mode 100644
index 00000000..07c72296
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/EllipseGeometry.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// [ID2D1EllipseGeometry]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1ElipseGeometry)]
+ public readonly unsafe struct EllipseGeometry : EllipseGeometry.Interface, IDisposable
+ {
+ internal readonly ID2D1EllipseGeometry* _handle;
+
+ internal EllipseGeometry(ID2D1EllipseGeometry* handle) => _handle = handle;
+
+ public RectangleF GetBounds() => Geometry.From(this).GetBounds();
+
+ public RectangleF GetBounds(Matrix3x2 worldTransform)
+ => Geometry.From(this).GetBounds(worldTransform);
+
+ public void CombineWithGeometry(Geometry inputGeometry, CombineMode combineMode, SimplifiedGeometrySink geometrySink)
+ => Geometry.From(this).CombineWithGeometry(inputGeometry, combineMode, geometrySink);
+
+ public Ellipse GetEllipse()
+ {
+ Ellipse ellipse;
+ _handle->GetEllipse((D2D1_ELLIPSE*)&ellipse);
+ return ellipse;
+ }
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public void Dispose() => _handle->Release();
+
+ public static implicit operator Geometry(EllipseGeometry geometry) => new((ID2D1Geometry*)geometry._handle);
+
+ internal unsafe interface Interface : Geometry.Interface
+ {
+ Ellipse GetEllipse();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/ExtendMode.cs b/src/WInterop.DirectX/Direct2d/ExtendMode.cs
index afe5cd13..a7878df7 100644
--- a/src/WInterop.DirectX/Direct2d/ExtendMode.cs
+++ b/src/WInterop.DirectX/Direct2d/ExtendMode.cs
@@ -12,18 +12,18 @@ public enum ExtendMode : uint
/// Extend the edges of the source out by clamping sample points outside the source
/// to the edges. [D2D1_EXTEND_MODE_CLAMP]
///
- Clamp = 0,
+ Clamp = D2D1_EXTEND_MODE.D2D1_EXTEND_MODE_CLAMP,
///
/// The base tile is drawn untransformed and the remainder are filled by repeating
/// the base tile. [D2D1_EXTEND_MODE_WRAP]
///
- Wrap = 1,
+ Wrap = D2D1_EXTEND_MODE.D2D1_EXTEND_MODE_WRAP,
///
/// The same as wrap, but alternate tiles are flipped The base tile is drawn
/// untransformed. [D2D1_EXTEND_MODE_MIRROR]
///
- Mirror = 2
+ Mirror = D2D1_EXTEND_MODE.D2D1_EXTEND_MODE_MIRROR
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Factory.cs b/src/WInterop.DirectX/Direct2d/Factory.cs
new file mode 100644
index 00000000..5d8e284f
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/Factory.cs
@@ -0,0 +1,164 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// [ID2D1Factory]
+ ///
+ ///
+ /// https://docs.microsoft.com/windows/win32/api/d2d1/nn-d2d1-id2d1factory
+ ///
+ public readonly unsafe struct Factory : Factory.Interface, IDisposable
+ {
+ private readonly ID2D1Factory* _handle;
+
+ internal Factory(ID2D1Factory* factory) => _handle = factory;
+
+ public EllipseGeometry CreateEllipseGeometry(Ellipse ellipse)
+ {
+ ID2D1EllipseGeometry* geometry;
+ _handle->CreateEllipseGeometry((D2D1_ELLIPSE*)&ellipse, &geometry).ThrowIfFailed();
+ return new(geometry);
+ }
+
+ public GeometryGroup CreateGeometryGroup(FillMode fillMode, ReadOnlySpan geometries)
+ {
+ fixed (Geometry* g = geometries)
+ {
+ ID2D1GeometryGroup* group;
+ _handle->CreateGeometryGroup(
+ (D2D1_FILL_MODE)fillMode,
+ (ID2D1Geometry**)&g,
+ (uint)geometries.Length,
+ &group).ThrowIfFailed();
+
+ return new(group);
+ }
+ }
+
+ public PathGeometry CreatePathGeometry()
+ {
+ ID2D1PathGeometry* geometry;
+ _handle->CreatePathGeometry(&geometry).ThrowIfFailed();
+ return new(geometry);
+ }
+
+ public RectangleGeometry CreateRectangleGeometry(RectangleF rectangle)
+ {
+ ID2D1RectangleGeometry* geometry;
+ var rect = rectangle.ToD2D();
+ _handle->CreateRectangleGeometry(&rect, &geometry).ThrowIfFailed();
+ return new(geometry);
+ }
+
+ public RoundedRectangleGeometry CreateRoundedRectangleGeometry(RoundedRectangle roundedRectangle)
+ {
+ ID2D1RoundedRectangleGeometry* geometry;
+ _handle->CreateRoundedRectangleGeometry((D2D1_ROUNDED_RECT*)&roundedRectangle, &geometry).ThrowIfFailed();
+ return new(geometry);
+ }
+
+ public StrokeStyle CreateStrokeStyle(StrokeStyleProperties strokeStyleProperties, ReadOnlySpan dashes = default)
+ {
+ ID2D1StrokeStyle* style;
+ fixed(float* d = dashes)
+ {
+ _handle->CreateStrokeStyle(
+ (D2D1_STROKE_STYLE_PROPERTIES*)&strokeStyleProperties,
+ d,
+ (uint)dashes.Length,
+ &style).ThrowIfFailed();
+
+ return new(style);
+ }
+ }
+
+ public TransformedGeometry CreateTransformedGeometry(Geometry sourceGeometry, Matrix3x2 transform)
+ {
+ ID2D1TransformedGeometry* geometry;
+ _handle->CreateTransformedGeometry(
+ sourceGeometry._handle,
+ (D2D_MATRIX_3X2_F*)&transform,
+ &geometry).ThrowIfFailed();
+
+ return new(geometry);
+ }
+
+ public IWindowRenderTarget CreateWindowRenderTarget(
+ RenderTargetProperties renderTargetProperties,
+ WindowRenderTargetProperties hwndRenderTargetProperties)
+ {
+ ID2D1HwndRenderTarget* target;
+ _handle->CreateHwndRenderTarget(
+ (D2D1_RENDER_TARGET_PROPERTIES*)&renderTargetProperties,
+ (D2D1_HWND_RENDER_TARGET_PROPERTIES*)&hwndRenderTargetProperties,
+ &target).ThrowIfFailed();
+
+ return new WindowRenderTarget(target);
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public SizeF GetDesktopDpi()
+ {
+ float x;
+ float y;
+ _handle->GetDesktopDpi(&x, &y);
+ return new(x, y);
+ }
+
+ public void ReloadSystemMetrics() => _handle->ReloadSystemMetrics().ThrowIfFailed();
+
+ internal unsafe interface Interface
+ {
+ RectangleGeometry CreateRectangleGeometry(RectangleF rectangle);
+
+ RoundedRectangleGeometry CreateRoundedRectangleGeometry(RoundedRectangle roundedRectangle);
+
+ EllipseGeometry CreateEllipseGeometry(Ellipse ellipse);
+
+ GeometryGroup CreateGeometryGroup(
+ FillMode fillMode,
+ ReadOnlySpan geometries);
+
+ TransformedGeometry CreateTransformedGeometry(
+ Geometry sourceGeometry,
+ Matrix3x2 transform);
+
+ ///
+ /// Returns an initially empty path geometry interface. A geometry sink is created
+ /// off the interface to populate it.
+ ///
+ PathGeometry CreatePathGeometry();
+
+ ///
+ /// Allows a non-default stroke style to be specified for a given geometry at draw time.
+ ///
+ StrokeStyle CreateStrokeStyle(
+ StrokeStyleProperties strokeStyleProperties,
+ ReadOnlySpan dashes = default);
+
+ ///
+ /// Creates a render target that appears on the display. [CreateHwndRenderTarget]
+ ///
+ IWindowRenderTarget CreateWindowRenderTarget(
+ RenderTargetProperties renderTargetProperties,
+ WindowRenderTargetProperties hwndRenderTargetProperties);
+
+ ///
+ /// Gets the current desktop DPI.
+ ///
+ SizeF GetDesktopDpi();
+
+ ///
+ /// Forces the factory to refresh any system defaults that it might have changed since factory creation.
+ ///
+ void ReloadSystemMetrics();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/FactoryType.cs b/src/WInterop.DirectX/Direct2d/FactoryType.cs
index 8a3cbfca..c2276e2d 100644
--- a/src/WInterop.DirectX/Direct2d/FactoryType.cs
+++ b/src/WInterop.DirectX/Direct2d/FactoryType.cs
@@ -14,11 +14,11 @@ public enum FactoryType : uint
///
/// [D2D1_FACTORY_TYPE_SINGLE_THREADED]
///
- SingleThreaded,
+ SingleThreaded = D2D1_FACTORY_TYPE.D2D1_FACTORY_TYPE_SINGLE_THREADED,
///
/// [D2D1_FACTORY_TYPE_MULTI_THREADED]
///
- MultiThreaded
+ MultiThreaded = D2D1_FACTORY_TYPE.D2D1_FACTORY_TYPE_MULTI_THREADED
}
}
diff --git a/src/WInterop.DirectX/Direct2d/FigureBegin.cs b/src/WInterop.DirectX/Direct2d/FigureBegin.cs
index 9d37d69f..e2247b55 100644
--- a/src/WInterop.DirectX/Direct2d/FigureBegin.cs
+++ b/src/WInterop.DirectX/Direct2d/FigureBegin.cs
@@ -11,11 +11,11 @@ public enum FigureBegin : uint
///
/// [D2D1_FIGURE_BEGIN_FILLED]
///
- Filled = 0,
+ Filled = D2D1_FIGURE_BEGIN.D2D1_FIGURE_BEGIN_FILLED,
///
/// [D2D1_FIGURE_BEGIN_HOLLOW]
///
- Hollow = 1
+ Hollow = D2D1_FIGURE_BEGIN.D2D1_FIGURE_BEGIN_HOLLOW
}
}
diff --git a/src/WInterop.DirectX/Direct2d/FigureEnd.cs b/src/WInterop.DirectX/Direct2d/FigureEnd.cs
index e2237856..61e02fa8 100644
--- a/src/WInterop.DirectX/Direct2d/FigureEnd.cs
+++ b/src/WInterop.DirectX/Direct2d/FigureEnd.cs
@@ -11,11 +11,11 @@ public enum FigureEnd : uint
///
/// [D2D1_FIGURE_END_OPEN]
///
- Open = 0,
+ Open = D2D1_FIGURE_END.D2D1_FIGURE_END_OPEN,
///
/// [D2D1_FIGURE_END_CLOSED]
///
- Closed = 1
+ Closed = D2D1_FIGURE_END.D2D1_FIGURE_END_CLOSED
}
}
diff --git a/src/WInterop.DirectX/Direct2d/FillMode.cs b/src/WInterop.DirectX/Direct2d/FillMode.cs
index f163f0a0..32e76393 100644
--- a/src/WInterop.DirectX/Direct2d/FillMode.cs
+++ b/src/WInterop.DirectX/Direct2d/FillMode.cs
@@ -12,11 +12,11 @@ public enum FillMode : uint
///
/// [D2D1_FILL_MODE_ALTERNATE]
///
- Alternate = 0,
+ Alternate = D2D1_FILL_MODE.D2D1_FILL_MODE_ALTERNATE,
///
/// [D2D1_FILL_MODE_WINDING]
///
- Winding = 1
+ Winding = D2D1_FILL_MODE.D2D1_FILL_MODE_WINDING
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Gamma.cs b/src/WInterop.DirectX/Direct2d/Gamma.cs
index 71697beb..fe625993 100644
--- a/src/WInterop.DirectX/Direct2d/Gamma.cs
+++ b/src/WInterop.DirectX/Direct2d/Gamma.cs
@@ -11,11 +11,11 @@ public enum Gamma : uint
///
/// Colors are manipulated in 2.2 gamma color space. [D2D1_GAMMA_2_2]
///
- ColorSpace_2_2 = 0,
+ ColorSpace_2_2 = D2D1_GAMMA.D2D1_GAMMA_2_2,
///
/// Colors are manipulated in 1.0 gamma color space. [D2D1_GAMMA_1_0]
///
- ColorSpace_1_0 = 1,
+ ColorSpace_1_0 = D2D1_GAMMA.D2D1_GAMMA_1_0,
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Geometry.cs b/src/WInterop.DirectX/Direct2d/Geometry.cs
new file mode 100644
index 00000000..2b5293b2
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/Geometry.cs
@@ -0,0 +1,182 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ [Guid(InterfaceIds.IID_ID2D1Geometry)]
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly unsafe struct Geometry : Geometry.Interface, IDisposable
+ {
+ internal readonly ID2D1Geometry* _handle;
+
+ internal Geometry(ID2D1Geometry* handle) => _handle = handle;
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public RectangleF GetBounds()
+ {
+ D2D_RECT_F rect;
+ _handle->GetBounds(null, &rect).ThrowIfFailed();
+ return rect.ToRectangleF();
+ }
+
+ public RectangleF GetBounds(Matrix3x2 worldTransform)
+ {
+ D2D_RECT_F rect;
+ _handle->GetBounds((D2D_MATRIX_3X2_F*)&worldTransform, &rect).ThrowIfFailed();
+ return rect.ToRectangleF();
+ }
+
+ public unsafe void CombineWithGeometry(
+ Geometry inputGeometry,
+ CombineMode combineMode,
+ SimplifiedGeometrySink geometrySink)
+ {
+ _handle->CombineWithGeometry(
+ inputGeometry._handle,
+ (D2D1_COMBINE_MODE)combineMode,
+ null,
+ geometrySink.Handle);
+ }
+
+ internal static ref Geometry From(in TFrom from)
+ where TFrom : unmanaged, Interface
+ => ref Unsafe.AsRef(Unsafe.AsPointer(ref Unsafe.AsRef(from)));
+
+ public void Dispose() => _handle->Release();
+
+ ///
+ /// [ID2D1Geometry]
+ ///
+ internal unsafe interface Interface : Resource.Interface
+ {
+ ///
+ /// Retrieve the bounds of the geometry.
+ ///
+ RectangleF GetBounds();
+
+ ///
+ /// Retrieve the bounds of the geometry with the applied .
+ ///
+ RectangleF GetBounds(Matrix3x2 worldTransform);
+
+ /*
+ ///
+ /// Get the bounds of the corresponding geometry after it has been widened or have
+ /// an optional pen style applied.
+ ///
+ RectangleF GetWidenedBounds(
+ float strokeWidth,
+ StrokeStyle* strokeStyle,
+ Matrix3x2* worldTransform,
+ float flatteningTolerance);
+
+ ///
+ /// Checks to see whether the corresponding penned and widened geometry contains the
+ /// given point.
+ ///
+ bool StrokeContainsPoint(
+ PointF point,
+ float strokeWidth,
+ StrokeStyle* strokeStyle,
+ Matrix3x2* worldTransform,
+ float flatteningTolerance);
+
+ ///
+ /// Test whether the given fill of this geometry would contain this point.
+ ///
+ IntBoolean FillContainsPoint(
+ PointF point,
+ Matrix3x2* worldTransform,
+ float flatteningTolerance);
+
+ ///
+ /// Compare how one geometry intersects or contains another geometry.
+ ///
+ GeometryRelation CompareWithGeometry(
+ Geometry* inputGeometry,
+ Matrix3x2* inputGeometryTransform,
+ float flatteningTolerance);
+
+ ///
+ /// Converts a geometry to a simplified geometry that has arcs and quadratic beziers
+ /// removed.
+ ///
+ void Simplify(
+ GeometrySimplificationOption simplificationOption,
+ Matrix3x2* worldTransform,
+ float flatteningTolerance,
+ ISimplifiedGeometrySink geometrySink);
+
+ ///
+ /// Tessellates a geometry into triangles.
+ ///
+ void Tessellate(
+ Matrix3x2* worldTransform,
+ float flatteningTolerance,
+ ITesselationSink tessellationSink);
+ */
+
+ ///
+ /// Performs a combine operation between the two geometries to produce a resulting geometry.
+ ///
+ void CombineWithGeometry(
+ Geometry inputGeometry,
+ CombineMode combineMode,
+ //Matrix3x2? inputGeometryTransform,
+ //float? flatteningTolerance,
+ SimplifiedGeometrySink geometrySink);
+
+ /*
+ ///
+ /// Computes the outline of the geometry. The result is written back into a
+ /// simplified geometry sink.
+ ///
+ void Outline(
+ Matrix3x2* worldTransform,
+ float flatteningTolerance,
+ ISimplifiedGeometrySink geometrySink);
+
+ ///
+ /// Computes the area of the geometry.
+ ///
+ float ComputeArea(
+ Matrix3x2* worldTransform,
+ float flatteningTolerance);
+
+ ///
+ /// Computes the length of the geometry.
+ ///
+ float ComputeLength(
+ Matrix3x2* worldTransform,
+ float flatteningTolerance);
+
+ ///
+ /// Computes the point and tangent a given distance along the path.
+ ///
+ void ComputePointAtLength(
+ float length,
+ Matrix3x2* worldTransform,
+ float flatteningTolerance,
+ PointF* point,
+ PointF* unitTangentVector);
+
+ ///
+ /// Get the geometry and widen it as well as apply an optional pen style.
+ ///
+ void Widen(
+ float strokeWidth,
+ IStrokeStyle strokeStyle,
+ Matrix3x2* worldTransform,
+ float flatteningTolerance,
+ ISimplifiedGeometrySink geometrySink);
+ */
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/GeometryGroup.cs b/src/WInterop.DirectX/Direct2d/GeometryGroup.cs
new file mode 100644
index 00000000..82eea4b8
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/GeometryGroup.cs
@@ -0,0 +1,58 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// [ID2D1GeometryGroup]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1GeometryGroup)]
+ public readonly unsafe struct GeometryGroup : GeometryGroup.Interface, IDisposable
+ {
+ internal readonly ID2D1GeometryGroup* _handle;
+
+ internal GeometryGroup(ID2D1GeometryGroup* handle) => _handle = handle;
+
+ public RectangleF GetBounds() => Geometry.From(this).GetBounds();
+
+ public RectangleF GetBounds(Matrix3x2 worldTransform)
+ => Geometry.From(this).GetBounds(worldTransform);
+
+ public void CombineWithGeometry(Geometry inputGeometry, CombineMode combineMode, SimplifiedGeometrySink geometrySink)
+ => Geometry.From(this).CombineWithGeometry(inputGeometry, combineMode, geometrySink);
+
+ public Factory GetFactory() => Geometry.From(this).GetFactory();
+
+ public FillMode GetFillMode() => (FillMode)_handle->GetFillMode();
+
+ public void GetSourceGeometries(Span geometries)
+ {
+ fixed(void* g = geometries)
+ {
+ _handle->GetSourceGeometries((ID2D1Geometry**)&g, (uint)geometries.Length);
+ }
+ }
+
+ public uint GetSourceGeometryCount() => _handle->GetSourceGeometryCount();
+
+ public void Dispose() => _handle->Release();
+
+ public static implicit operator Geometry(GeometryGroup geometry) => new((ID2D1Geometry*)geometry._handle);
+
+ internal unsafe interface Interface : Geometry.Interface
+ {
+ FillMode GetFillMode();
+
+ uint GetSourceGeometryCount();
+
+ unsafe void GetSourceGeometries(Span geometries);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/GeometryRelation.cs b/src/WInterop.DirectX/Direct2d/GeometryRelation.cs
index 136a4298..dbe2bf87 100644
--- a/src/WInterop.DirectX/Direct2d/GeometryRelation.cs
+++ b/src/WInterop.DirectX/Direct2d/GeometryRelation.cs
@@ -4,8 +4,7 @@
namespace WInterop.Direct2d
{
///
- /// Describes how one geometry object is spatially related to another geometry
- /// object.
+ /// Describes how one geometry object is spatially related to another geometry object.
///
public enum GeometryRelation : uint
{
diff --git a/src/WInterop.DirectX/Direct2d/GeometrySink.cs b/src/WInterop.DirectX/Direct2d/GeometrySink.cs
new file mode 100644
index 00000000..04d1d782
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/GeometrySink.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Describes a geometric path that can contain lines, arcs, cubic Bezier curves,
+ /// and quadratic Bezier curves. [ID2D1GeometrySink]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1GeometrySink)]
+ public readonly unsafe struct GeometrySink : GeometrySink.Interface, IDisposable
+ {
+ internal ID2D1GeometrySink* Handle { get; }
+
+ public void AddArc(ArcSegment arc) => Handle->AddArc((D2D1_ARC_SEGMENT*)&arc);
+
+ public void AddBezier(BezierSegment bezier) => Handle->AddBezier((D2D1_BEZIER_SEGMENT*)&bezier);
+
+ public void AddBeziers(ReadOnlySpan beziers)
+ {
+ fixed(BezierSegment* b = beziers)
+ {
+ Handle->AddBeziers((D2D1_BEZIER_SEGMENT*)b, (uint)beziers.Length);
+ }
+ }
+
+ public void AddLine(PointF point) => Handle->AddLine(point.ToD2D());
+
+ public void AddLine((float X, float Y) point) => Handle->AddLine(new(point.X, point.Y));
+
+ public void AddLines(ReadOnlySpan points)
+ => SimplifiedGeometrySink.From(this).AddLines(points);
+
+ public void AddQuadraticBezier(QuadraticBezierSegment bezier)
+ => Handle->AddQuadraticBezier((D2D1_QUADRATIC_BEZIER_SEGMENT*)&bezier);
+
+ public void AddQuadraticBeziers(ReadOnlySpan beziers)
+ {
+ fixed(QuadraticBezierSegment* b = beziers)
+ {
+ Handle->AddQuadraticBeziers((D2D1_QUADRATIC_BEZIER_SEGMENT*)b, (uint)beziers.Length);
+ }
+ }
+ public void BeginFigure(PointF startPoint, FigureBegin figureBegin)
+ => SimplifiedGeometrySink.From(this).BeginFigure(startPoint, figureBegin);
+
+ public void BeginFigure((float X, float Y) startPoint, FigureBegin figureBegin)
+ => SimplifiedGeometrySink.From(this).BeginFigure(startPoint, figureBegin);
+
+ public void Close() => SimplifiedGeometrySink.From(this).Close();
+
+ public void EndFigure(FigureEnd figureEnd)
+ => SimplifiedGeometrySink.From(this).EndFigure(figureEnd);
+
+ public void SetFillMode(FillMode fillMode)
+ => SimplifiedGeometrySink.From(this).SetFillMode(fillMode);
+
+ public void SetSegmentFlags(PathSegment vertexFlags)
+ => SimplifiedGeometrySink.From(this).SetSegmentFlags(vertexFlags);
+
+ public static implicit operator SimplifiedGeometrySink(GeometrySink sink)
+ => new((ID2D1SimplifiedGeometrySink*)sink.Handle);
+
+ internal static ref GeometrySink From(in TFrom from)
+ where TFrom : unmanaged, Interface
+ => ref Unsafe.AsRef(Unsafe.AsPointer(ref Unsafe.AsRef(from)));
+
+ public void Dispose()
+ {
+ Handle->Close();
+ Handle->Release();
+ }
+
+ internal interface Interface : SimplifiedGeometrySink.Interface
+ {
+ void AddLine(PointF point);
+
+ void AddBezier(BezierSegment bezier);
+
+ void AddQuadraticBezier(QuadraticBezierSegment bezier);
+
+ void AddQuadraticBeziers(ReadOnlySpan beziers);
+
+ void AddArc(ArcSegment arc);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/GradientStopCollection.cs b/src/WInterop.DirectX/Direct2d/GradientStopCollection.cs
new file mode 100644
index 00000000..8e3c91c6
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/GradientStopCollection.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Represents an collection of gradient stops that can then be the source resource
+ /// for either a linear or radial gradient brush. [ID2D1GradientStopCollection]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1GradientStopCollection)]
+ public readonly unsafe struct GradientStopCollection : GradientStopCollection.Interface, IDisposable
+ {
+ internal readonly ID2D1GradientStopCollection* _handle;
+
+ internal GradientStopCollection(ID2D1GradientStopCollection* collection) => _handle = collection;
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public Gamma GetColorInterpolationGamma() => (Gamma)_handle->GetColorInterpolationGamma();
+
+ public ExtendMode GetExtendMode() => (ExtendMode)_handle->GetExtendMode();
+
+ public uint GetGradientStopCount() => _handle->GetGradientStopCount();
+
+ public void GetGradientStops(Span gradientStops)
+ {
+ fixed(GradientStop* g = gradientStops)
+ {
+ _handle->GetGradientStops((D2D1_GRADIENT_STOP*)g, (uint)gradientStops.Length);
+ }
+ }
+
+ public void Dispose() => _handle->Release();
+
+ internal interface Interface : Resource.Interface
+ {
+ ///
+ /// Returns the number of stops in the gradient.
+ ///
+ uint GetGradientStopCount();
+
+ ///
+ /// Copies the gradient stops from the collection into the caller's interface. The
+ /// returned colors have straight alpha.
+ ///
+ unsafe void GetGradientStops(Span gradientStops);
+
+ ///
+ /// Returns whether the interpolation occurs with 1.0 or 2.2 gamma.
+ ///
+ Gamma GetColorInterpolationGamma();
+
+ ExtendMode GetExtendMode();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/IBitmap.cs b/src/WInterop.DirectX/Direct2d/IBitmap.cs
deleted file mode 100644
index 2ca4a478..00000000
--- a/src/WInterop.DirectX/Direct2d/IBitmap.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System.Drawing;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Root bitmap resource, linearly scaled on a draw call. [ID2D1Bitmap]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1Bitmap),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IBitmap : IImage
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- ///
- /// Returns the size of the bitmap in resolution independent units.
- ///
- [PreserveSig]
- SizeF GetSize();
-
- ///
- /// Returns the size of the bitmap in resolution dependent units, (pixels).
- ///
- [PreserveSig]
- SizeU GetPixelSize();
-
- ///
- /// Retrieve the format of the bitmap.
- ///
- [PreserveSig]
- PixelFormat GetPixelFormat();
-
- ///
- /// Return the DPI of the bitmap.
- ///
- [PreserveSig]
- void GetDpi(
- out float dpiX,
- out float dpiY);
-
- unsafe void CopyFromBitmap(
- PointU* destPoint,
- IBitmap bitmap,
- LtrbRectangleU* srcRect);
-
- unsafe void CopyFromRenderTarget(
- PointU* destPoint,
- IRenderTarget renderTarget,
- LtrbRectangleU* srcRect);
-
- unsafe void CopyFromMemory(
- LtrbRectangleU* dstRect,
- void* srcData,
- uint pitch);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IBitmapBrush.cs b/src/WInterop.DirectX/Direct2d/IBitmapBrush.cs
deleted file mode 100644
index da0a3365..00000000
--- a/src/WInterop.DirectX/Direct2d/IBitmapBrush.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// A bitmap brush allows a bitmap to be used to fill a geometry. [ID2D1BitmapBrush]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1BitmapBrush),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IBitmapBrush : IBrush
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Brush
- ///
- /// Sets the opacity for when the brush is drawn over the entire fill of the brush.
- ///
- [PreserveSig]
- new void SetOpacity(
- float opacity);
-
- ///
- /// Sets the transform that applies to everything drawn by the brush.
- ///
- [PreserveSig]
- new void SetTransform(
- ref Matrix3x2 transform);
-
- [PreserveSig]
- new float GetOpacity();
-
- [PreserveSig]
- new void GetTransform(
- out Matrix3x2 transform);
- #endregion
-
- ///
- /// Sets how the bitmap is to be treated outside of its natural extent on the X
- /// axis.
- ///
- [PreserveSig]
- void SetExtendModeX(
- ExtendMode extendModeX);
-
- ///
- /// Sets how the bitmap is to be treated outside of its natural extent on the X
- /// axis.
- ///
- [PreserveSig]
- void SetExtendModeY(
- ExtendMode extendModeY);
-
- ///
- /// Sets the interpolation mode used when this brush is used.
- ///
- [PreserveSig]
- void SetInterpolationMode(
- BitmapInterpolationMode interpolationMode);
-
- ///
- /// Sets the bitmap associated as the source of this brush.
- ///
- [PreserveSig]
- void SetBitmap(
- IBitmap bitmap);
-
- [PreserveSig]
- ExtendMode GetExtendModeX();
-
- [PreserveSig]
- ExtendMode GetExtendModeY();
-
- [PreserveSig]
- BitmapInterpolationMode GetInterpolationMode();
-
- [PreserveSig]
- void GetBitmap(
- out IBitmap bitmap);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IBitmapRenderTarget.cs b/src/WInterop.DirectX/Direct2d/IBitmapRenderTarget.cs
index c08eb37f..685ae5b2 100644
--- a/src/WInterop.DirectX/Direct2d/IBitmapRenderTarget.cs
+++ b/src/WInterop.DirectX/Direct2d/IBitmapRenderTarget.cs
@@ -1,450 +1,10 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-using WInterop.DirectWrite;
-
namespace WInterop.Direct2d
{
- ///
- /// Renders to an intermediate texture created by the CreateCompatibleRenderTarget method.
- /// [ID2D1BitmapRenderTarget]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1BitmapRenderTarget),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IBitmapRenderTarget : IRenderTarget
{
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1RenderTarget
- ///
- /// Create a D2D bitmap by copying from memory, or create uninitialized.
- ///
- new unsafe IBitmap CreateBitmap(
- SizeU size,
- void* srcData,
- uint pitch,
- in BitmapProperties bitmapProperties);
-
- ///
- /// Create a D2D bitmap by copying a WIC bitmap.
- ///
- new unsafe IBitmap CreateBitmapFromWicBitmap(
- object wicBitmapSource, // IWICBitmapSource
- BitmapProperties* bitmapProperties);
-
- ///
- /// Create a D2D bitmap by sharing bits from another resource. The bitmap must be
- /// compatible with the render target for the call to succeed. For example, an
- /// IWICBitmap can be shared with a software target, or a DXGI surface can be shared
- /// with a DXGI render target.
- ///
- new unsafe IBitmap CreateSharedBitmap(
- in Guid riid,
- void* data,
- BitmapProperties* bitmapProperties);
-
- ///
- /// Creates a bitmap brush. The bitmap is scaled, rotated, skewed or tiled to fill
- /// or pen a geometry.
- ///
- new unsafe IBitmapBrush CreateBitmapBrush(
- IBitmap bitmap,
- BitmapBrushProperties* bitmapBrushProperties,
- BrushProperties* brushProperties);
-
- new unsafe ISolidColorBrush CreateSolidColorBrush(
- in ColorF color,
- BrushProperties* brushProperties);
-
- ///
- /// A gradient stop collection represents a set of stops in an ideal unit length.
- /// This is the source resource for a linear gradient and radial gradient brush.
- ///
- /// Specifies which space the color
- /// interpolation occurs in.
- /// Specifies how the gradient will be extended outside of
- /// the unit length.
- new unsafe IGradientStopCollection CreateGradientStopCollection(
- GradientStop* gradientStops,
- uint gradientStopsCount,
- Gamma colorInterpolationGamma,
- ExtendMode extendMode);
-
- new void CreateLinearGradientBrushSTUB();
- //STDMETHOD(CreateLinearGradientBrush)(
- // _In_ CONST D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *linearGradientBrushProperties,
- // _In_opt_ CONST D2D1_BRUSH_PROPERTIES* brushProperties,
- // _In_ ID2D1GradientStopCollection* gradientStopCollection,
- // _COM_Outptr_ ID2D1LinearGradientBrush** linearGradientBrush
- // ) PURE;
-
- new unsafe IRadialGradientBrush CreateRadialGradientBrush(
- in RadialGradientBrushProperties radialGradientBrushProperties,
- BrushProperties* brushProperties,
- IGradientStopCollection gradientStopCollection);
-
- ///
- /// Creates a bitmap render target whose bitmap can be used as a source for
- /// rendering in the API.
- ///
- /// The requested size of the target in DIPs. If the pixel
- /// size is not specified, the DPI is inherited from the parent target. However, the
- /// render target will never contain a fractional number of pixels.
- /// The requested size of the render target in
- /// pixels. If the DIP size is also specified, the DPI is calculated from these two
- /// values. If the desired size is not specified, the DPI is inherited from the
- /// parent render target. If neither value is specified, the compatible render
- /// target will be the same size and have the same DPI as the parent target.
- /// The desired pixel format. The format must be
- /// compatible with the parent render target type. If the format is not specified,
- /// it will be inherited from the parent render target.
- /// Allows the caller to retrieve a GDI compatible render
- /// target.
- /// The returned bitmap render target.
- new unsafe IBitmapRenderTarget CreateCompatibleRenderTarget(
- SizeF* desiredSize,
- SizeU* desiredPixelSize,
- PixelFormat* desiredFormat,
- CompatibleRenderTargetOptions options);
-
- ///
- /// Creates a layer resource that can be used on any target and which will resize
- /// under the covers if necessary.
- ///
- /// The resolution independent minimum size hint for the layer
- /// resource. Specify this to prevent unwanted reallocation of the layer backing
- /// store. The size is in DIPs, but, it is unaffected by the current world
- /// transform. If the size is unspecified, the returned resource is a placeholder
- /// and the backing store will be allocated to be the minimum size that can hold the
- /// content when the layer is pushed.
- new void CreateLayerStub();
- //STDMETHOD(CreateLayer)(
- // _In_opt_ CONST D2D1_SIZE_F *size,
- // _COM_Outptr_ ID2D1Layer **layer
- // ) PURE;
-
- ///
- /// Create a D2D mesh.
- ///
- new void CreateMeshSTUB();
- //STDMETHOD(CreateMesh)(
- // _COM_Outptr_ ID2D1Mesh ** mesh
- // ) PURE;
-
- [PreserveSig]
- new void DrawLine(
- PointF point0,
- PointF point1,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void DrawRectangle(
- in LtrbRectangleF rect,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillRectangle(
- in LtrbRectangleF rect,
- IBrush brush);
-
- [PreserveSig]
- new void DrawRoundedRectangle(
- in RoundedRectangle roundedRect,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillRoundedRectangle(
- in RoundedRectangle roundedRect,
- IBrush brush);
-
- [PreserveSig]
- new void DrawEllipse(
- in Ellipse ellipse,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillEllipse(
- in Ellipse ellipse,
- IBrush brush);
-
- [PreserveSig]
- new void DrawGeometry(
- IGeometry geometry,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- /// An optionally specified opacity brush. Only the alpha
- /// channel of the corresponding brush will be sampled and will be applied to the
- /// entire fill of the geometry. If this brush is specified, the fill brush must be
- /// a bitmap brush with an extend mode of D2D1_EXTEND_MODE_CLAMP.
- [PreserveSig]
- new void FillGeometry(
- IGeometry geometry,
- IBrush brush,
- IBrush opacityBrush = null);
-
- ///
- /// Fill a mesh. Since meshes can only render aliased content, the render target
- /// antialiasing mode must be set to aliased.
- ///
- new void FillMeshSTUB();
- //STDMETHOD_(void, FillMesh)(
- // _In_ ID2D1Mesh * mesh,
- // _In_ ID2D1Brush* brush
- // ) PURE;
-
- ///
- /// Fill using the alpha channel of the supplied opacity mask bitmap. The brush
- /// opacity will be modulated by the mask. The render target antialiasing mode must
- /// be set to aliased.
- ///
- new void FillOpacityMaskSTUB();
- //STDMETHOD_(void, FillOpacityMask)(
- // _In_ ID2D1Bitmap * opacityMask,
- // _In_ ID2D1Brush* brush,
- // D2D1_OPACITY_MASK_CONTENT content,
- // _In_opt_ CONST D2D1_RECT_F* destinationRectangle = NULL,
- // _In_opt_ CONST D2D1_RECT_F *sourceRectangle = NULL
- // ) PURE;
-
- [PreserveSig]
- new unsafe void DrawBitmap(
- IBitmap bitmap,
- LtrbRectangleF* destinationRectangle = null,
- float opacity = 1.0f,
- BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.Linear,
- LtrbRectangleF* sourceRectangle = null);
-
- ///
- /// Draws the text within the given layout rectangle and by default also performs
- /// baseline snapping.
- ///
- [PreserveSig]
- new unsafe void DrawText(
- char* @string,
- uint stringLength,
- ITextFormat textFormat,
- in LtrbRectangleF layoutRect,
- IBrush defaultFillBrush,
- DrawTextOptions options = DrawTextOptions.None,
- MeasuringMode measuringMode = MeasuringMode.Natural);
-
- ///
- /// Draw a text layout object. If the layout is not subsequently changed, this can
- /// be more efficient than DrawText when drawing the same layout repeatedly.
- ///
- ///
- /// The specified text options. If is used, the text
- /// is clipped to the layout bounds. These bounds are derived from the origin and the
- /// layout bounds of the corresponding object.
- ///
- [PreserveSig]
- new void DrawTextLayout(
- PointF origin,
- ITextLayout textLayout,
- IBrush defaultFillBrush,
- DrawTextOptions options = DrawTextOptions.None);
-
- [PreserveSig]
- new void DrawGlyphRun(
- PointF baselineOrigin,
- in GlyphRun glyphRun,
- IBrush foregroundBrush,
- MeasuringMode measuringMode = MeasuringMode.Natural);
-
- [PreserveSig]
- new void SetTransform(
- ref Matrix3x2 transform);
-
- [PreserveSig]
- new void GetTransform(
- out Matrix3x2 transform);
-
- [PreserveSig]
- new void SetAntialiasMode(
- AntialiasMode antialiasMode);
-
- [PreserveSig]
- new AntialiasMode GetAntialiasMode();
-
- [PreserveSig]
- new void SetTextAntialiasMode(
- TextAntialiasMode textAntialiasMode);
-
- [PreserveSig]
- new TextAntialiasMode GetTextAntialiasMode();
-
- [PreserveSig]
- new void SetTextRenderingParams(
- DirectWrite.IRenderingParams textRenderingParams = null);
-
- ///
- /// Retrieve the text render parameters. NOTE: If NULL is specified to
- /// SetTextRenderingParameters, NULL will be returned.
- ///
- [PreserveSig]
- new void GetTextRenderingParams(
- out DirectWrite.IRenderingParams textRenderingParams);
-
- ///
- /// Set a tag to correspond to the succeeding primitives. If an error occurs
- /// rendering a primitive, the tags can be returned from the Flush or EndDraw call.
- ///
- [PreserveSig]
- new void SetTags(
- ulong tag1,
- ulong tag2);
-
- ///
- /// Retrieves the currently set tags. This does not retrieve the tags corresponding
- /// to any primitive that is in error.
- ///
- [PreserveSig]
- new void GetTags(
- out ulong tag1,
- out ulong tag2);
-
- ///
- /// Start a layer of drawing calls. The way in which the layer must be resolved is
- /// specified first as well as the logical resource that stores the layer
- /// parameters. The supplied layer resource might grow if the specified content
- /// cannot fit inside it. The layer will grow monotonically on each axis. If a NULL
- /// ID2D1Layer is provided, then a layer resource will be allocated automatically.
- ///
- new void PushLayerSTUB();
- //STDMETHOD_(void, PushLayer)(
- // _In_ CONST D2D1_LAYER_PARAMETERS *layerParameters,
- //_In_opt_ ID2D1Layer *layer
- //) PURE;
-
- ///
- /// Ends a layer that was defined with particular layer resources.
- ///
- [PreserveSig]
- new void PopLayer();
-
- new void Flush(
- out ulong tag1,
- out ulong tag2);
-
- ///
- /// Gets the current drawing state and saves it into the supplied
- /// IDrawingStatckBlock.
- ///
- [PreserveSig]
- new void SaveDrawingState(
- IDrawingStateBlock drawingStateBlock);
-
- ///
- /// Copies the state stored in the block interface.
- ///
- [PreserveSig]
- new void RestoreDrawingState(
- IDrawingStateBlock drawingStateBlock);
-
- ///
- /// Pushes a clip. The clip can be antialiased. The clip must be axis aligned. If
- /// the current world transform is not axis preserving, then the bounding box of the
- /// transformed clip rect will be used. The clip will remain in effect until a
- /// PopAxisAligned clip call is made.
- ///
- [PreserveSig]
- new void PushAxisAlignedClip(
- in LtrbRectangleF clipRect,
- AntialiasMode antialiasMode);
-
- [PreserveSig]
- new void PopAxisAlignedClip();
-
- [PreserveSig]
- new unsafe void Clear(
- ColorF* clearColor = null);
-
- ///
- /// Start drawing on this render target. Draw calls can only be issued between a
- /// BeginDraw and EndDraw call.
- ///
- [PreserveSig]
- new void BeginDraw();
-
- ///
- /// Ends drawing on the render target, error results can be retrieved at this time,
- /// or when calling flush.
- ///
- new void EndDraw(
- out ulong tag1,
- out ulong tag2);
-
- [PreserveSig]
- new void GetPixelFormat(out PixelFormat pixelFormat);
-
- ///
- /// Sets the DPI on the render target. This results in the render target being
- /// interpreted to a different scale. Neither DPI can be negative. If zero is
- /// specified for both, the system DPI is chosen. If one is zero and the other
- /// unspecified, the DPI is not changed.
- ///
- [PreserveSig]
- new void SetDpi(
- float dpiX,
- float dpiY);
-
- ///
- /// Return the current DPI from the target.
- ///
- [PreserveSig]
- new void GetDpi(
- out float dpiX,
- out float dpiY);
-
- ///
- /// Returns the size of the render target in DIPs.
- ///
- [PreserveSig]
- new void GetSize(out SizeF size);
-
- ///
- /// Returns the size of the render target in pixels.
- ///
- [PreserveSig]
- new SizeU GetPixelSize(out SizeU pixelSize);
-
- ///
- /// Returns the maximum bitmap and render target size that is guaranteed to be
- /// supported by the render target.
- ///
- [PreserveSig]
- new uint GetMaximumBitmapSize();
-
- ///
- /// Returns true if the given properties are supported by this render target. The
- /// DPI is ignored. NOTE: If the render target type is software, then neither
- /// D2D1_FEATURE_LEVEL_9 nor D2D1_FEATURE_LEVEL_10 will be considered to be
- /// supported.
- ///
- [PreserveSig]
- new IntBoolean IsSupported(
- in RenderTargetProperties renderTargetProperties);
- #endregion
-
- IBitmap GetBitmap();
+ Bitmap Bitmap { get; }
}
}
diff --git a/src/WInterop.DirectX/Direct2d/IBrush.cs b/src/WInterop.DirectX/Direct2d/IBrush.cs
deleted file mode 100644
index 7c93ccb4..00000000
--- a/src/WInterop.DirectX/Direct2d/IBrush.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// The root brush interface. All brushes can be used to fill or pen a geometry.
- /// [ID2D1Brush]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1Brush),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IBrush : IResource
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- ///
- /// Sets the opacity for when the brush is drawn over the entire fill of the brush.
- ///
- [PreserveSig]
- void SetOpacity(
- float opacity);
-
- ///
- /// Sets the transform that applies to everything drawn by the brush.
- ///
- [PreserveSig]
- void SetTransform(
- ref Matrix3x2 transform);
-
- [PreserveSig]
- float GetOpacity();
-
- [PreserveSig]
- void GetTransform(
- out Matrix3x2 transform);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IDeviceContextRenderTarget.cs b/src/WInterop.DirectX/Direct2d/IDeviceContextRenderTarget.cs
index c7cec489..2297fc3e 100644
--- a/src/WInterop.DirectX/Direct2d/IDeviceContextRenderTarget.cs
+++ b/src/WInterop.DirectX/Direct2d/IDeviceContextRenderTarget.cs
@@ -1,443 +1,17 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-using System;
using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-using WInterop.DirectWrite;
using WInterop.Gdi;
using WInterop.Gdi.Native;
namespace WInterop.Direct2d
{
- // ID2D1DCRenderTarget
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1DCRenderTarget),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDeviceContextRenderTarget : IRenderTarget
{
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1RenderTarget
- ///
- /// Create a D2D bitmap by copying from memory, or create uninitialized.
- ///
- new unsafe IBitmap CreateBitmap(
- SizeU size,
- void* srcData,
- uint pitch,
- in BitmapProperties bitmapProperties);
-
- ///
- /// Create a D2D bitmap by copying a WIC bitmap.
- ///
- new unsafe IBitmap CreateBitmapFromWicBitmap(
- object wicBitmapSource, // IWICBitmapSource
- BitmapProperties* bitmapProperties);
-
- ///
- /// Create a D2D bitmap by sharing bits from another resource. The bitmap must be compatible with the render
- /// target for the call to succeed. For example, an IWICBitmap can be shared with a software target, or a
- /// DXGI surface can be shared with a DXGI render target.
- ///
- new unsafe IBitmap CreateSharedBitmap(
- in Guid riid,
- void* data,
- BitmapProperties* bitmapProperties);
-
- ///
- /// Creates a bitmap brush. The bitmap is scaled, rotated, skewed or tiled to fill or pen a geometry.
- ///
- new unsafe IBitmapBrush CreateBitmapBrush(
- IBitmap bitmap,
- BitmapBrushProperties* bitmapBrushProperties,
- BrushProperties* brushProperties);
-
- new unsafe ISolidColorBrush CreateSolidColorBrush(
- in ColorF color,
- BrushProperties* brushProperties);
-
- ///
- /// A gradient stop collection represents a set of stops in an ideal unit length. This is the source resource
- /// for a linear gradient and radial gradient brush.
- ///
- /// Specifies which space the color interpolation occurs in.
- /// Specifies how the gradient will be extended outside of the unit length.
- new unsafe IGradientStopCollection CreateGradientStopCollection(
- GradientStop* gradientStops,
- uint gradientStopsCount,
- Gamma colorInterpolationGamma,
- ExtendMode extendMode);
-
- new void CreateLinearGradientBrushSTUB();
- //STDMETHOD(CreateLinearGradientBrush)(
- // _In_ CONST D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *linearGradientBrushProperties,
- // _In_opt_ CONST D2D1_BRUSH_PROPERTIES* brushProperties,
- // _In_ ID2D1GradientStopCollection* gradientStopCollection,
- // _COM_Outptr_ ID2D1LinearGradientBrush** linearGradientBrush
- // ) PURE;
-
- new unsafe IRadialGradientBrush CreateRadialGradientBrush(
- in RadialGradientBrushProperties radialGradientBrushProperties,
- BrushProperties* brushProperties,
- IGradientStopCollection gradientStopCollection);
-
- ///
- /// Creates a bitmap render target whose bitmap can be used as a source for rendering in the API.
- ///
- ///
- /// The requested size of the target in DIPs. If the pixel size is not specified, the DPI is inherited from
- /// the parent target. However, the render target will never contain a fractional number of pixels.
- ///
- ///
- /// The requested size of the render target in pixels. If the DIP size is also specified, the DPI is
- /// calculated from these two values. If the desired size is not specified, the DPI is inherited from the
- /// parent render target. If neither value is specified, the compatible render target will be the same size
- /// and have the same DPI as the parent target.
- ///
- ///
- /// The desired pixel format. The format must be compatible with the parent render target type. If the format
- /// is not specified, it will be inherited from the parent render target.
- ///
- /// Allows the caller to retrieve a GDI compatible render target.
- /// The returned bitmap render target.
- new unsafe IBitmapRenderTarget CreateCompatibleRenderTarget(
- SizeF* desiredSize,
- SizeU* desiredPixelSize,
- PixelFormat* desiredFormat,
- CompatibleRenderTargetOptions options);
-
- ///
- /// Creates a layer resource that can be used on any target and which will resize under the covers if necessary.
- ///
- ///
- /// The resolution independent minimum size hint for the layer resource. Specify this to prevent unwanted
- /// reallocation of the layer backing store. The size is in DIPs, but, it is unaffected by the current world
- /// transform. If the size is unspecified, the returned resource is a placeholder and the backing store will
- /// be allocated to be the minimum size that can hold the content when the layer is pushed.
- ///
- new void CreateLayerStub();
- //STDMETHOD(CreateLayer)(
- // _In_opt_ CONST D2D1_SIZE_F *size,
- // _COM_Outptr_ ID2D1Layer **layer
- // ) PURE;
-
- ///
- /// Create a D2D mesh.
- ///
- new void CreateMeshSTUB();
- //STDMETHOD(CreateMesh)(
- // _COM_Outptr_ ID2D1Mesh ** mesh
- // ) PURE;
-
- [PreserveSig]
- new void DrawLine(
- PointF point0,
- PointF point1,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void DrawRectangle(
- in LtrbRectangleF rect,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillRectangle(
- in LtrbRectangleF rect,
- IBrush brush);
-
- [PreserveSig]
- new void DrawRoundedRectangle(
- in RoundedRectangle roundedRect,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillRoundedRectangle(
- in RoundedRectangle roundedRect,
- IBrush brush);
-
- [PreserveSig]
- new void DrawEllipse(
- in Ellipse ellipse,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillEllipse(
- in Ellipse ellipse,
- IBrush brush);
-
- [PreserveSig]
- new void DrawGeometry(
- IGeometry geometry,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- ///
- /// An optionally specified opacity brush. Only the alpha channel of the corresponding brush will be sampled
- /// and will be applied to the entire fill of the geometry. If this brush is specified, the fill brush must be
- /// a bitmap brush with an extend mode of D2D1_EXTEND_MODE_CLAMP.
- ///
- [PreserveSig]
- new void FillGeometry(
- IGeometry geometry,
- IBrush brush,
- IBrush opacityBrush = null);
-
- ///
- /// Fill a mesh. Since meshes can only render aliased content, the render target antialiasing mode must be
- /// set to aliased.
- ///
- new void FillMeshSTUB();
- //STDMETHOD_(void, FillMesh)(
- // _In_ ID2D1Mesh * mesh,
- // _In_ ID2D1Brush* brush
- // ) PURE;
-
- ///
- /// Fill using the alpha channel of the supplied opacity mask bitmap. The brush opacity will be modulated by
- /// the mask. The render target antialiasing mode must be set to aliased.
- ///
- new void FillOpacityMaskSTUB();
- //STDMETHOD_(void, FillOpacityMask)(
- // _In_ ID2D1Bitmap * opacityMask,
- // _In_ ID2D1Brush* brush,
- // D2D1_OPACITY_MASK_CONTENT content,
- // _In_opt_ CONST D2D1_RECT_F* destinationRectangle = NULL,
- // _In_opt_ CONST D2D1_RECT_F *sourceRectangle = NULL
- // ) PURE;
-
- [PreserveSig]
- new unsafe void DrawBitmap(
- IBitmap bitmap,
- LtrbRectangleF* destinationRectangle = null,
- float opacity = 1.0f,
- BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.Linear,
- LtrbRectangleF* sourceRectangle = null);
-
- ///
- /// Draws the text within the given layout rectangle and by default also performs baseline snapping.
- ///
- ///
- /// Draws the text within the given layout rectangle and by default also performs baseline snapping.
- ///
- [PreserveSig]
- new unsafe void DrawText(
- char* @string,
- uint stringLength,
- ITextFormat textFormat,
- in LtrbRectangleF layoutRect,
- IBrush defaultFillBrush,
- DrawTextOptions options = DrawTextOptions.None,
- MeasuringMode measuringMode = MeasuringMode.Natural);
-
- ///
- /// Draw a text layout object. If the layout is not subsequently changed, this can be more efficient than
- /// DrawText when drawing the same layout repeatedly.
- ///
- ///
- /// The specified text options. If is used, the text is clipped to the
- /// layout bounds. These bounds are derived from the origin and the layout bounds of the corresponding
- /// object.
- ///
- [PreserveSig]
- new void DrawTextLayout(
- PointF origin,
- ITextLayout textLayout,
- IBrush defaultFillBrush,
- DrawTextOptions options = DrawTextOptions.None);
-
- [PreserveSig]
- new void DrawGlyphRun(
- PointF baselineOrigin,
- in GlyphRun glyphRun,
- IBrush foregroundBrush,
- MeasuringMode measuringMode = MeasuringMode.Natural);
-
- [PreserveSig]
- new void SetTransform(
- ref Matrix3x2 transform);
-
- [PreserveSig]
- new void GetTransform(
- out Matrix3x2 transform);
-
- [PreserveSig]
- new void SetAntialiasMode(
- AntialiasMode antialiasMode);
-
- [PreserveSig]
- new AntialiasMode GetAntialiasMode();
-
- [PreserveSig]
- new void SetTextAntialiasMode(
- TextAntialiasMode textAntialiasMode);
-
- [PreserveSig]
- new TextAntialiasMode GetTextAntialiasMode();
-
- [PreserveSig]
- new void SetTextRenderingParams(
- DirectWrite.IRenderingParams textRenderingParams = null);
-
- ///
- /// Retrieve the text render parameters. NOTE: If NULL is specified to SetTextRenderingParameters, NULL
- /// will be returned.
- ///
- [PreserveSig]
- new void GetTextRenderingParams(
- out DirectWrite.IRenderingParams textRenderingParams);
-
- ///
- /// Set a tag to correspond to the succeeding primitives. If an error occurs rendering a primitive, the tags
- /// can be returned from the Flush or EndDraw call.
- ///
- [PreserveSig]
- new void SetTags(
- ulong tag1,
- ulong tag2);
-
- ///
- /// Retrieves the currently set tags. This does not retrieve the tags corresponding to any primitive that
- /// is in error.
- ///
- [PreserveSig]
- new void GetTags(
- out ulong tag1,
- out ulong tag2);
-
- ///
- /// Start a layer of drawing calls. The way in which the layer must be resolved is specified first as well as
- /// the logical resource that stores the layer parameters. The supplied layer resource might grow if the
- /// specified content cannot fit inside it. The layer will grow monotonically on each axis. If a NULL
- /// ID2D1Layer is provided, then a layer resource will be allocated automatically.
- ///
- new void PushLayerSTUB();
- //STDMETHOD_(void, PushLayer)(
- // _In_ CONST D2D1_LAYER_PARAMETERS *layerParameters,
- //_In_opt_ ID2D1Layer *layer
- //) PURE;
-
- ///
- /// Ends a layer that was defined with particular layer resources.
- ///
- [PreserveSig]
- new void PopLayer();
-
- new void Flush(
- out ulong tag1,
- out ulong tag2);
-
- ///
- /// Gets the current drawing state and saves it into the supplied IDrawingStatckBlock.
- ///
- [PreserveSig]
- new void SaveDrawingState(
- IDrawingStateBlock drawingStateBlock);
-
- ///
- /// Copies the state stored in the block interface.
- ///
- [PreserveSig]
- new void RestoreDrawingState(
- IDrawingStateBlock drawingStateBlock);
-
- ///
- /// Pushes a clip. The clip can be antialiased. The clip must be axis aligned. If the current world transform
- /// is not axis preserving, then the bounding box of the transformed clip rect will be used. The clip will
- /// remain in effect until a PopAxisAligned clip call is made.
- ///
- [PreserveSig]
- new void PushAxisAlignedClip(
- in LtrbRectangleF clipRect,
- AntialiasMode antialiasMode);
-
- [PreserveSig]
- new void PopAxisAlignedClip();
-
- [PreserveSig]
- new unsafe void Clear(
- ColorF* clearColor = null);
-
- ///
- /// Start drawing on this render target. Draw calls can only be issued between a BeginDraw and EndDraw call.
- ///
- [PreserveSig]
- new void BeginDraw();
-
- ///
- /// Ends drawing on the render target, error results can be retrieved at this time, or when calling flush.
- ///
- new void EndDraw(
- out ulong tag1,
- out ulong tag2);
-
- [PreserveSig]
- new void GetPixelFormat(out PixelFormat pixelFormat);
-
- ///
- /// Sets the DPI on the render target. This results in the render target being interpreted to a different
- /// scale. Neither DPI can be negative. If zero is specified for both, the system DPI is chosen. If one is
- /// zero and the other unspecified, the DPI is not changed.
- ///
- [PreserveSig]
- new void SetDpi(
- float dpiX,
- float dpiY);
-
- ///
- /// Return the current DPI from the target.
- ///
- [PreserveSig]
- new void GetDpi(
- out float dpiX,
- out float dpiY);
-
- ///
- /// Returns the size of the render target in DIPs.
- ///
- [PreserveSig]
- new void GetSize(out SizeF size);
-
- ///
- /// Returns the size of the render target in pixels.
- ///
- [PreserveSig]
- new SizeU GetPixelSize(out SizeU pixelSize);
-
- ///
- /// Returns the maximum bitmap and render target size that is guaranteed to be supported by the render target.
- ///
- [PreserveSig]
- new uint GetMaximumBitmapSize();
-
- ///
- /// Returns true if the given properties are supported by this render target. The DPI is ignored. NOTE: If
- /// the render target type is software, then neither D2D1_FEATURE_LEVEL_9 nor D2D1_FEATURE_LEVEL_10 will be
- /// considered to be supported.
- ///
- [PreserveSig]
- new IntBoolean IsSupported(
- in RenderTargetProperties renderTargetProperties);
- #endregion
-
- [PreserveSig]
void BindDC(
- HDC hDC,
- in Rect pSubRect);
+ HDC deviceContext,
+ Rect subRectangle);
}
public static class DeviceContextRenderTargetExtensions
diff --git a/src/WInterop.DirectX/Direct2d/IDrawingStateBlock.cs b/src/WInterop.DirectX/Direct2d/IDrawingStateBlock.cs
index 680697e1..d71f0e9f 100644
--- a/src/WInterop.DirectX/Direct2d/IDrawingStateBlock.cs
+++ b/src/WInterop.DirectX/Direct2d/IDrawingStateBlock.cs
@@ -11,45 +11,50 @@ namespace WInterop.Direct2d
/// Represents the drawing state of a render target: the antialiasing mode,
/// transform, tags, and text-rendering options. [ID2D1DrawingStateBlock]
///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1DrawingStateBlock),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IDrawingStateBlock : IResource
+ [Guid(InterfaceIds.IID_ID2D1DrawingStateBlock)]
+ public readonly unsafe struct DrawingStateBlock : DrawingStateBlock.Interface, IDisposable
{
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- ///
- /// Retrieves the state currently contained within this state block resource.
- ///
- [PreserveSig]
- void GetDescription(
- out DrawingStateDescription stateDescription);
-
- ///
- /// Sets the state description of this state block resource.
- ///
- [PreserveSig]
- void SetDescription(
- in DrawingStateDescription stateDescription);
-
- ///
- /// Sets the text rendering parameters of this state block resource.
- ///
- [PreserveSig]
- void SetTextRenderingParams(
- IRenderingParams textRenderingParams);
-
- ///
- /// Retrieves the text rendering parameters contained within this state block
- /// resource. If a NULL text rendering parameter was specified, NULL will be
- /// returned.
- ///
- [PreserveSig]
- void GetTextRenderingParams(
- out IRenderingParams textRenderingParams);
+ private readonly ID2D1DrawingStateBlock* _handle;
+
+ internal DrawingStateBlock(ID2D1DrawingStateBlock* handle) => _handle = handle;
+
+ public DrawingStateDescription Description
+ {
+ get
+ {
+ DrawingStateDescription description;
+ _handle->GetDescription((D2D1_DRAWING_STATE_DESCRIPTION*)&description);
+ return description;
+ }
+ set => _handle->SetDescription((D2D1_DRAWING_STATE_DESCRIPTION*)&value);
+ }
+
+ public RenderingParams TextRenderingParams
+ {
+ get
+ {
+ IDWriteRenderingParams* rendering;
+ _handle->GetTextRenderingParams(&rendering);
+ return new(rendering);
+ }
+ set => _handle->SetTextRenderingParams(value.Handle);
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ internal interface Interface : Resource.Interface
+ {
+ ///
+ /// Gets/sets the state description of this state block resource.
+ ///
+ DrawingStateDescription Description { get; set; }
+
+ ///
+ /// Gets/Sets the text rendering parameters of this state block resource.
+ ///
+ RenderingParams TextRenderingParams { get; set; }
+ }
}
}
diff --git a/src/WInterop.DirectX/Direct2d/IEllipseGeometry.cs b/src/WInterop.DirectX/Direct2d/IEllipseGeometry.cs
deleted file mode 100644
index b74b7c2b..00000000
--- a/src/WInterop.DirectX/Direct2d/IEllipseGeometry.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Runtime.InteropServices;
-using System.Numerics;
-
-namespace WInterop.Direct2d
-{
- ///
- /// [ID2D1EllipseGeometry]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1ElipseGeometry),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public unsafe interface IEllipseGeometry : IGeometry
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Geometry
- ///
- /// Retrieve the bounds of the geometry, with an optional applied transform.
- ///
- new LtrbRectangleF GetBounds(
- Matrix3x2* worldTransform);
-
- ///
- /// Get the bounds of the corresponding geometry after it has been widened or have
- /// an optional pen style applied.
- ///
- new LtrbRectangleF GetWidenedBounds(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Checks to see whether the corresponding penned and widened geometry contains the
- /// given point.
- ///
- new IntBoolean StrokeContainsPoint(
- PointF point,
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Test whether the given fill of this geometry would contain this point.
- ///
- new IntBoolean FillContainsPoint(
- PointF point,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Compare how one geometry intersects or contains another geometry.
- ///
- new GeometryRelation CompareWithGeometry(
- IGeometry inputGeometry,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance);
-
- ///
- /// Converts a geometry to a simplified geometry that has arcs and quadratic beziers
- /// removed.
- ///
- new void Simplify(
- GeometrySimplificationOption simplificationOption,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Tessellates a geometry into triangles.
- ///
- new void Tessellate(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ITesselationSink tessellationSink);
-
- ///
- /// Performs a combine operation between the two geometries to produce a resulting
- /// geometry.
- ///
- new void CombineWithGeometry(
- IGeometry inputGeometry,
- CombineMode combineMode,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the outline of the geometry. The result is written back into a
- /// simplified geometry sink.
- ///
- new void Outline(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the area of the geometry.
- ///
- new float ComputeArea(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the length of the geometry.
- ///
- new float ComputeLength(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the point and tangent a given distance along the path.
- ///
- new void ComputePointAtLength(
- float length,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- PointF* point,
- PointF* unitTangentVector);
-
- ///
- /// Get the geometry and widen it as well as apply an optional pen style.
- ///
- new void Widen(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
- #endregion
-
- [PreserveSig]
- void GetEllipse(out Ellipse ellipse);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IFactory.cs b/src/WInterop.DirectX/Direct2d/IFactory.cs
deleted file mode 100644
index 8b0981ed..00000000
--- a/src/WInterop.DirectX/Direct2d/IFactory.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Numerics;
-using System.Runtime.InteropServices;
-using WInterop.DirectWrite;
-
-namespace WInterop.Direct2d
-{
- ///
- /// [ID2D1Factory]
- ///
- ///
- ///
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1Factory),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IFactory
- {
- ///
- /// Cause the factory to refresh any system metrics that it might have been snapped
- /// on factory creation.
- ///
- void ReloadSystemMetrics();
-
- ///
- /// Retrieves the current desktop DPI. To refresh this, call ReloadSystemMetrics.
- /// Note: this method is deprecated. Use DisplayProperties::LogicalDpi for Windows
- /// Store Apps and GetDpiForWindow for Win32 Apps.
- ///
- [PreserveSig]
- void GetDesktopDpi(
- out float dpiX,
- out float dpiY);
-
- IRectangleGeometry CreateRectangleGeometry(
- in LtrbRectangleF rectangle);
-
- IRoundedRectangleGeometry CreateRoundedRectangleGeometry(
- in RoundedRectangle roundedRectangle);
-
- IEllipseGeometry CreateEllipseGeometry(
- in Ellipse ellipse);
-
- ///
- /// Create a geometry which holds other geometries.
- ///
- IGeometryGroup CreateGeometryGroup(
- FillMode fillMode,
- IGeometry[] geometries,
- uint geometriesCount);
-
- ITransformedGeometry CreateTransformedGeometry(
- IGeometry sourceGeometry,
- ref Matrix3x2 transform);
-
- ///
- /// Returns an initially empty path geometry interface. A geometry sink is created
- /// off the interface to populate it.
- ///
- IPathGeometry CreatePathGeometry();
-
- ///
- /// Allows a non-default stroke style to be specified for a given geometry at draw
- /// time.
- ///
- unsafe IStrokeStyle CreateStrokeStyle(
- in StrokeStyleProperties strokeStyleProperties,
- float* dashes,
- uint dashesCount);
-
- ///
- /// Creates a new drawing state block, this can be used in subsequent
- /// SaveDrawingState and RestoreDrawingState operations on the render target.
- ///
- IDrawingStateBlock CreateDrawingStateBlock(
- in DrawingStateDescription drawingStateDescription,
- IRenderingParams textRenderingParams);
-
- ///
- /// Creates a render target which is a source of bitmaps.
- ///
- void CreateWicBitmapRenderTargetSTUB();
- //STDMETHOD(CreateWicBitmapRenderTarget)(
- // _In_ IWICBitmap * target,
- // _In_ CONST D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties,
- //_COM_Outptr_ ID2D1RenderTarget **renderTarget
- //) PURE;
-
- ///
- /// Creates a render target that appears on the display. [CreateHwndRenderTarget]
- ///
- IWindowRenderTarget CreateWindowRenderTarget(
- in RenderTargetProperties renderTargetProperties,
- in WindowRenderTargetProperties hwndRenderTargetProperties);
-
- ///
- /// Creates a render target that draws to a DXGI Surface. The device that owns the
- /// surface is used for rendering.
- ///
- void CreateDxgiSurfaceRenderTargetSTUB();
- //STDMETHOD(CreateDxgiSurfaceRenderTarget)(
- // _In_ IDXGISurface * dxgiSurface,
- // _In_ CONST D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties,
- // _COM_Outptr_ ID2D1RenderTarget **renderTarget
- // ) PURE;
-
- // TODO: really ID2D1DCRenderTarget
- ///
- /// Creates a render target that draws to a GDI device context.
- ///
- IRenderTarget CreateDCRenderTarget(
- in RenderTargetProperties renderTargetProperties);
- }
-
- public static class FactoryExtensions
- {
- public unsafe static IStrokeStyle CreateStrokeStyle(
- this IFactory factory,
- in StrokeStyleProperties strokeStyleProperties)
- => factory.CreateStrokeStyle(strokeStyleProperties, null, 0);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IGeometry.cs b/src/WInterop.DirectX/Direct2d/IGeometry.cs
deleted file mode 100644
index c92eede8..00000000
--- a/src/WInterop.DirectX/Direct2d/IGeometry.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// [ID2D1Geometry]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1Geometry),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public unsafe interface IGeometry : IResource
- {
- // ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
-
- ///
- /// Retrieve the bounds of the geometry, with an optional applied transform.
- ///
- LtrbRectangleF GetBounds(
- Matrix3x2* worldTransform);
-
- ///
- /// Get the bounds of the corresponding geometry after it has been widened or have
- /// an optional pen style applied.
- ///
- LtrbRectangleF GetWidenedBounds(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Checks to see whether the corresponding penned and widened geometry contains the
- /// given point.
- ///
- IntBoolean StrokeContainsPoint(
- PointF point,
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Test whether the given fill of this geometry would contain this point.
- ///
- IntBoolean FillContainsPoint(
- PointF point,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Compare how one geometry intersects or contains another geometry.
- ///
- GeometryRelation CompareWithGeometry(
- IGeometry inputGeometry,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance);
-
- ///
- /// Converts a geometry to a simplified geometry that has arcs and quadratic beziers
- /// removed.
- ///
- void Simplify(
- GeometrySimplificationOption simplificationOption,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Tessellates a geometry into triangles.
- ///
- void Tessellate(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ITesselationSink tessellationSink);
-
- ///
- /// Performs a combine operation between the two geometries to produce a resulting
- /// geometry.
- ///
- void CombineWithGeometry(
- IGeometry inputGeometry,
- CombineMode combineMode,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the outline of the geometry. The result is written back into a
- /// simplified geometry sink.
- ///
- void Outline(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the area of the geometry.
- ///
- float ComputeArea(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the length of the geometry.
- ///
- float ComputeLength(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the point and tangent a given distance along the path.
- ///
- void ComputePointAtLength(
- float length,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- PointF* point,
- PointF* unitTangentVector);
-
- ///
- /// Get the geometry and widen it as well as apply an optional pen style.
- ///
- void Widen(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
- }
-
- public static class GeometryExtensions
- {
- ///
- /// Retrieve the bounds of the geometry.
- ///
- public static unsafe RectangleF GetBounds(this IGeometry geometry) => geometry.GetBounds(null);
-
- ///
- /// Retrieve the bounds of the geometry with a transform.
- ///
- public static unsafe RectangleF GetBounds(this IGeometry geometry, Matrix3x2 worldTransform)
- => geometry.GetBounds(&worldTransform);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IGeometryGroup.cs b/src/WInterop.DirectX/Direct2d/IGeometryGroup.cs
deleted file mode 100644
index 96295fa0..00000000
--- a/src/WInterop.DirectX/Direct2d/IGeometryGroup.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// [ID2D1GeometryGroup]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1GeometryGroup),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public unsafe interface IGeometryGroup : IGeometry
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Geometry
- ///
- /// Retrieve the bounds of the geometry, with an optional applied transform.
- ///
- new LtrbRectangleF GetBounds(
- Matrix3x2* worldTransform);
-
- ///
- /// Get the bounds of the corresponding geometry after it has been widened or have
- /// an optional pen style applied.
- ///
- new LtrbRectangleF GetWidenedBounds(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Checks to see whether the corresponding penned and widened geometry contains the
- /// given point.
- ///
- new IntBoolean StrokeContainsPoint(
- PointF point,
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Test whether the given fill of this geometry would contain this point.
- ///
- new IntBoolean FillContainsPoint(
- PointF point,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Compare how one geometry intersects or contains another geometry.
- ///
- new GeometryRelation CompareWithGeometry(
- IGeometry inputGeometry,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance);
-
- ///
- /// Converts a geometry to a simplified geometry that has arcs and quadratic beziers
- /// removed.
- ///
- new void Simplify(
- GeometrySimplificationOption simplificationOption,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Tessellates a geometry into triangles.
- ///
- new void Tessellate(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ITesselationSink tessellationSink);
-
- ///
- /// Performs a combine operation between the two geometries to produce a resulting
- /// geometry.
- ///
- new void CombineWithGeometry(
- IGeometry inputGeometry,
- CombineMode combineMode,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the outline of the geometry. The result is written back into a
- /// simplified geometry sink.
- ///
- new void Outline(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the area of the geometry.
- ///
- new float ComputeArea(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the length of the geometry.
- ///
- new float ComputeLength(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the point and tangent a given distance along the path.
- ///
- new void ComputePointAtLength(
- float length,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- PointF* point,
- PointF* unitTangentVector);
-
- ///
- /// Get the geometry and widen it as well as apply an optional pen style.
- ///
- new void Widen(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
- #endregion
-
- [PreserveSig]
- FillMode GetFillMode();
-
- [PreserveSig]
- uint GetSourceGeometryCount();
-
- [PreserveSig]
- unsafe void GetSourceGeometries(
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
- out IGeometry[] geometries,
- uint geometriesCount);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IGeometrySink.cs b/src/WInterop.DirectX/Direct2d/IGeometrySink.cs
deleted file mode 100644
index 684cabe1..00000000
--- a/src/WInterop.DirectX/Direct2d/IGeometrySink.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Describes a geometric path that can contain lines, arcs, cubic Bezier curves,
- /// and quadratic Bezier curves. [ID2D1GeometrySink]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1GeometrySink),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IGeometrySink : ISimplifiedGeometrySink
- {
- #region ID2D1SimplifiedGeometrySink
- [PreserveSig]
- new void SetFillMode(
- FillMode fillMode);
-
- [PreserveSig]
- new void SetSegmentFlags(
- PathSegment vertexFlags);
-
- [PreserveSig]
- new void BeginFigure(
- PointF startPoint,
- FigureBegin figureBegin);
-
- [PreserveSig]
- unsafe new void AddLines(
- PointF* points,
- uint pointsCount);
-
- [PreserveSig]
- unsafe new void AddBeziers(
- BezierSegment* beziers,
- uint beziersCount);
-
- [PreserveSig]
- new void EndFigure(
- FigureEnd figureEnd);
-
- [PreserveSig]
- new void Close();
- #endregion
-
- [PreserveSig]
- void AddLine(
- PointF point);
-
- [PreserveSig]
- void AddBezier(
- in BezierSegment bezier);
-
- [PreserveSig]
- void AddQuadraticBezier(
- in QuadraticBezierSegment bezier);
-
- [PreserveSig]
- void AddQuadraticBeziers(
- in QuadraticBezierSegment bezier,
- uint beziersCount);
-
- [PreserveSig]
- void AddArc(
- in ArcSegment arc);
- }
-
- public static class GeometrySinkExtensions
- {
- public unsafe static void AddBezier(this IGeometrySink sink, (float X, float Y) point1, (float X, float Y) point2, (float X, float Y) point3)
- => sink.AddBezier(new BezierSegment(point1, point2, point3));
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IGradientStopCollection.cs b/src/WInterop.DirectX/Direct2d/IGradientStopCollection.cs
deleted file mode 100644
index 32b8c60d..00000000
--- a/src/WInterop.DirectX/Direct2d/IGradientStopCollection.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Represents an collection of gradient stops that can then be the source resource
- /// for either a linear or radial gradient brush. [ID2D1GradientStopCollection]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1GradientStopCollection),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IGradientStopCollection : IResource
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- ///
- /// Returns the number of stops in the gradient.
- ///
- [PreserveSig]
- uint GetGradientStopCount();
-
- ///
- /// Copies the gradient stops from the collection into the caller's interface. The
- /// returned colors have straight alpha.
- ///
- [PreserveSig]
- unsafe void GetGradientStops(
- GradientStop* gradientStops,
- uint gradientStopsCount);
-
- ///
- /// Returns whether the interpolation occurs with 1.0 or 2.2 gamma.
- ///
- [PreserveSig]
- Gamma GetColorInterpolationGamma();
-
- [PreserveSig]
- ExtendMode GetExtendMode();
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IImage.cs b/src/WInterop.DirectX/Direct2d/IImage.cs
deleted file mode 100644
index 8a3661cc..00000000
--- a/src/WInterop.DirectX/Direct2d/IImage.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Represents a producer of pixels that can fill an arbitrary 2D plane. [ID2D1Image]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1Image),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IImage : IResource
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IPathGeometry.cs b/src/WInterop.DirectX/Direct2d/IPathGeometry.cs
deleted file mode 100644
index d2d27bee..00000000
--- a/src/WInterop.DirectX/Direct2d/IPathGeometry.cs
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Represents a complex shape that may be composed of arcs, curves, and lines. [ID2D1PathGeometry]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1PathGeometry),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public unsafe interface IPathGeometry : IGeometry
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Geometry
- ///
- /// Retrieve the bounds of the geometry, with an optional applied transform.
- ///
- new LtrbRectangleF GetBounds(
- Matrix3x2* worldTransform);
-
- ///
- /// Get the bounds of the corresponding geometry after it has been widened or have
- /// an optional pen style applied.
- ///
- new LtrbRectangleF GetWidenedBounds(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Checks to see whether the corresponding penned and widened geometry contains the
- /// given point.
- ///
- new IntBoolean StrokeContainsPoint(
- PointF point,
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Test whether the given fill of this geometry would contain this point.
- ///
- new IntBoolean FillContainsPoint(
- PointF point,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Compare how one geometry intersects or contains another geometry.
- ///
- new GeometryRelation CompareWithGeometry(
- IGeometry inputGeometry,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance);
-
- ///
- /// Converts a geometry to a simplified geometry that has arcs and quadratic beziers
- /// removed.
- ///
- new void Simplify(
- GeometrySimplificationOption simplificationOption,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Tessellates a geometry into triangles.
- ///
- new void Tessellate(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ITesselationSink tessellationSink);
-
- ///
- /// Performs a combine operation between the two geometries to produce a resulting
- /// geometry.
- ///
- new void CombineWithGeometry(
- IGeometry inputGeometry,
- CombineMode combineMode,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the outline of the geometry. The result is written back into a
- /// simplified geometry sink.
- ///
- new void Outline(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the area of the geometry.
- ///
- new float ComputeArea(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the length of the geometry.
- ///
- new float ComputeLength(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the point and tangent a given distance along the path.
- ///
- new void ComputePointAtLength(
- float length,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- PointF* point,
- PointF* unitTangentVector);
-
- ///
- /// Get the geometry and widen it as well as apply an optional pen style.
- ///
- new void Widen(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
- #endregion
-
- ///
- /// Opens a geometry sink that will be used to create this path geometry.
- ///
- IGeometrySink Open();
-
- ///
- /// Retrieve the contents of this geometry. The caller passes an implementation of a
- /// ID2D1GeometrySink interface to receive the data.
- ///
- void Stream(
- IGeometrySink geometrySink);
-
- uint GetSegmentCount();
-
- uint GetFigureCount();
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IRadialGradientBrush.cs b/src/WInterop.DirectX/Direct2d/IRadialGradientBrush.cs
deleted file mode 100644
index cee9bb3f..00000000
--- a/src/WInterop.DirectX/Direct2d/IRadialGradientBrush.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Paints an area with a radial gradient. [ID2D1RadialGradientBrush]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1RadialGradientBrush),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IRadialGradientBrush : IBrush
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Brush
- ///
- /// Sets the opacity for when the brush is drawn over the entire fill of the brush.
- ///
- [PreserveSig]
- new void SetOpacity(
- float opacity);
-
- ///
- /// Sets the transform that applies to everything drawn by the brush.
- ///
- [PreserveSig]
- new void SetTransform(
- ref Matrix3x2 transform);
-
- [PreserveSig]
- new float GetOpacity();
-
- [PreserveSig]
- new void GetTransform(
- out Matrix3x2 transform);
- #endregion
-
- ///
- /// Sets the center of the radial gradient. This will be in local coordinates and
- /// will not depend on the geometry being filled.
- ///
- [PreserveSig]
- void SetCenter(PointF center);
-
- ///
- /// Sets offset of the origin relative to the radial gradient center.
- ///
- [PreserveSig]
- void SetGradientOriginOffset(PointF gradientOriginOffset);
-
- [PreserveSig]
- void SetRadiusX(float radiusX);
-
- [PreserveSig]
- void SetRadiusY(float radiusY);
-
- // TODO: Bug in COM interop, should return PointF
- [PreserveSig]
- void GetCenter(out PointF center);
-
- // TODO: Bug in COM interop, should return PointF
- [PreserveSig]
- void GetGradientOriginOffset(out PointF offset);
-
- [PreserveSig]
- float GetRadiusX();
-
- [PreserveSig]
- float GetRadiusY();
-
- [PreserveSig]
- void GetGradientStopCollection(out IGradientStopCollection gradientStopCollection);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IRectangleGeometry.cs b/src/WInterop.DirectX/Direct2d/IRectangleGeometry.cs
deleted file mode 100644
index 7fae1471..00000000
--- a/src/WInterop.DirectX/Direct2d/IRectangleGeometry.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1RectangleGeometry),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public unsafe interface IRectangleGeometry : IGeometry
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Geometry
- ///
- /// Retrieve the bounds of the geometry, with an optional applied transform.
- ///
- new LtrbRectangleF GetBounds(
- Matrix3x2* worldTransform);
-
- ///
- /// Get the bounds of the corresponding geometry after it has been widened or have
- /// an optional pen style applied.
- ///
- new LtrbRectangleF GetWidenedBounds(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Checks to see whether the corresponding penned and widened geometry contains the
- /// given point.
- ///
- new IntBoolean StrokeContainsPoint(
- PointF point,
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Test whether the given fill of this geometry would contain this point.
- ///
- new IntBoolean FillContainsPoint(
- PointF point,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Compare how one geometry intersects or contains another geometry.
- ///
- new GeometryRelation CompareWithGeometry(
- IGeometry inputGeometry,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance);
-
- ///
- /// Converts a geometry to a simplified geometry that has arcs and quadratic beziers
- /// removed.
- ///
- new void Simplify(
- GeometrySimplificationOption simplificationOption,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Tessellates a geometry into triangles.
- ///
- new void Tessellate(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ITesselationSink tessellationSink);
-
- ///
- /// Performs a combine operation between the two geometries to produce a resulting
- /// geometry.
- ///
- new void CombineWithGeometry(
- IGeometry inputGeometry,
- CombineMode combineMode,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the outline of the geometry. The result is written back into a
- /// simplified geometry sink.
- ///
- new void Outline(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the area of the geometry.
- ///
- new float ComputeArea(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the length of the geometry.
- ///
- new float ComputeLength(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the point and tangent a given distance along the path.
- ///
- new void ComputePointAtLength(
- float length,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- PointF* point,
- PointF* unitTangentVector);
-
- ///
- /// Get the geometry and widen it as well as apply an optional pen style.
- ///
- new void Widen(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
- #endregion
-
- [PreserveSig]
- void GetRect(out LtrbRectangleF rect);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IRenderTarget.cs b/src/WInterop.DirectX/Direct2d/IRenderTarget.cs
index cb5a0084..8ccc0b18 100644
--- a/src/WInterop.DirectX/Direct2d/IRenderTarget.cs
+++ b/src/WInterop.DirectX/Direct2d/IRenderTarget.cs
@@ -4,250 +4,125 @@
using System;
using System.Drawing;
using System.Numerics;
-using System.Runtime.InteropServices;
using WInterop.DirectWrite;
-using WInterop.Errors;
namespace WInterop.Direct2d
{
- ///
- /// Represents an object that can receive drawing commands. Interfaces that inherit
- /// from render the drawing commands they receive in different
- /// ways. [ID2D1RenderTarget]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1RenderTarget),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IRenderTarget : IResource
+ public interface IRenderTarget : IResource, IDisposable
{
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
+ SolidColorBrush CreateSolidColorBrush(ColorF color);
///
- /// Create a D2D bitmap by copying from memory, or create uninitialized.
+ /// Creates a bitmap brush. The bitmap is scaled, rotated, skewed or tiled to fill or pen a geometry.
///
- /// Byte count of each scanline, ignored if is null.
- unsafe IBitmap CreateBitmap(
- SizeU size,
- void* srcData,
- uint pitch,
- in BitmapProperties bitmapProperties);
+ BitmapBrush CreateBitmapBrush(
+ Bitmap bitmap,
+ BitmapBrushProperties bitmapBrushProperties,
+ BrushProperties brushProperties);
- ///
- /// Create a D2D bitmap by copying a WIC bitmap.
- ///
- unsafe IBitmap CreateBitmapFromWicBitmap(
- object wicBitmapSource, // IWICBitmapSource
- BitmapProperties* bitmapProperties);
-
- ///
- /// Create a D2D bitmap by sharing bits from another resource. The bitmap must be
- /// compatible with the render target for the call to succeed. For example, an
- /// IWICBitmap can be shared with a software target, or a DXGI surface can be shared
- /// with a DXGI render target.
- ///
- unsafe IBitmap CreateSharedBitmap(
- in Guid riid,
- void* data,
- BitmapProperties* bitmapProperties);
-
- ///
- /// Creates a bitmap brush. The bitmap is scaled, rotated, skewed or tiled to fill
- /// or pen a geometry.
- ///
- unsafe IBitmapBrush CreateBitmapBrush(
- IBitmap bitmap,
- BitmapBrushProperties* bitmapBrushProperties,
- BrushProperties* brushProperties);
-
- unsafe ISolidColorBrush CreateSolidColorBrush(
- in ColorF color,
- BrushProperties* brushProperties);
+ SolidColorBrush CreateSolidColorBrush(
+ ColorF color,
+ BrushProperties brushProperties);
///
/// A gradient stop collection represents a set of stops in an ideal unit length.
/// This is the source resource for a linear gradient and radial gradient brush.
///
- /// Specifies which space the color
- /// interpolation occurs in.
- /// Specifies how the gradient will be extended outside of
- /// the unit length.
- unsafe IGradientStopCollection CreateGradientStopCollection(
- GradientStop* gradientStops,
- uint gradientStopsCount,
- Gamma colorInterpolationGamma,
- ExtendMode extendMode);
-
- void CreateLinearGradientBrushSTUB();
- //STDMETHOD(CreateLinearGradientBrush)(
- // _In_ CONST D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *linearGradientBrushProperties,
- // _In_opt_ CONST D2D1_BRUSH_PROPERTIES* brushProperties,
- // _In_ ID2D1GradientStopCollection* gradientStopCollection,
- // _COM_Outptr_ ID2D1LinearGradientBrush** linearGradientBrush
- // ) PURE;
-
- unsafe IRadialGradientBrush CreateRadialGradientBrush(
- in RadialGradientBrushProperties radialGradientBrushProperties,
- BrushProperties* brushProperties,
- IGradientStopCollection gradientStopCollection);
-
- ///
- /// Creates a bitmap render target whose bitmap can be used as a source for
- /// rendering in the API.
- ///
- /// The requested size of the target in DIPs. If the pixel
- /// size is not specified, the DPI is inherited from the parent target. However, the
- /// render target will never contain a fractional number of pixels.
- /// The requested size of the render target in
- /// pixels. If the DIP size is also specified, the DPI is calculated from these two
- /// values. If the desired size is not specified, the DPI is inherited from the
- /// parent render target. If neither value is specified, the compatible render
- /// target will be the same size and have the same DPI as the parent target.
- /// The desired pixel format. The format must be
- /// compatible with the parent render target type. If the format is not specified,
- /// it will be inherited from the parent render target.
- /// Allows the caller to retrieve a GDI compatible render
- /// target.
- /// The returned bitmap render target.
- unsafe IBitmapRenderTarget CreateCompatibleRenderTarget(
- SizeF* desiredSize,
- SizeU* desiredPixelSize,
- PixelFormat* desiredFormat,
- CompatibleRenderTargetOptions options);
+ ///
+ /// Specifies which space the color interpolation occurs in.
+ ///
+ ///
+ /// Specifies how the gradient will be extended outside of the unit length.
+ ///
+ GradientStopCollection CreateGradientStopCollection(
+ ReadOnlySpan gradientStops,
+ Gamma colorInterpolationGamma = Gamma.ColorSpace_2_2,
+ ExtendMode extendMode = ExtendMode.Clamp);
- ///
- /// Creates a layer resource that can be used on any target and which will resize
- /// under the covers if necessary.
- ///
- /// The resolution independent minimum size hint for the layer
- /// resource. Specify this to prevent unwanted reallocation of the layer backing
- /// store. The size is in DIPs, but, it is unaffected by the current world
- /// transform. If the size is unspecified, the returned resource is a placeholder
- /// and the backing store will be allocated to be the minimum size that can hold the
- /// content when the layer is pushed.
- void CreateLayerStub();
- //STDMETHOD(CreateLayer)(
- // _In_opt_ CONST D2D1_SIZE_F *size,
- // _COM_Outptr_ ID2D1Layer **layer
- // ) PURE;
+ RadialGradientBrush CreateRadialGradientBrush(
+ RadialGradientBrushProperties radialGradientBrushProperties,
+ BrushProperties brushProperties,
+ GradientStopCollection gradientStopCollection);
///
- /// Create a D2D mesh.
+ /// Creates a bitmap render target whose bitmap can be used as a source for rendering in the API.
///
- void CreateMeshSTUB();
- //STDMETHOD(CreateMesh)(
- // _COM_Outptr_ ID2D1Mesh ** mesh
- // ) PURE;
+ ///
+ /// The requested size of the target in DIPs. If the pixel size is not specified, the DPI is inherited from
+ /// the parent target. However, the render target will never contain a fractional number of pixels.
+ ///
+ ///
+ /// The requested size of the render target in pixels. If the DIP size is also specified, the DPI is
+ /// calculated from these two values. If the desired size is not specified, the DPI is inherited from the
+ /// parent render target. If neither value is specified, the compatible render target will be the same size
+ /// and have the same DPI as the parent target.
+ ///
+ ///
+ /// The desired pixel format. The format must be compatible with the parent render target type. If the format
+ /// is not specified, it will be inherited from the parent render target.
+ ///
+ ///
+ /// Allows the caller to retrieve a GDI compatible render target.
+ ///
+ /// The bitmap render target.
+ IBitmapRenderTarget CreateCompatibleRenderTarget(
+ SizeF? desiredSize = default,
+ SizeU? desiredPixelSize = default,
+ PixelFormat? desiredFormat = default,
+ CompatibleRenderTargetOptions options = CompatibleRenderTargetOptions.None);
- [PreserveSig]
void DrawLine(
PointF point0,
PointF point1,
- IBrush brush,
+ Brush brush,
float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
+ StrokeStyle strokeStyle = default);
- [PreserveSig]
void DrawRectangle(
- in LtrbRectangleF rect,
- IBrush brush,
+ LtrbRectangleF rectangle,
+ Brush brush,
float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
+ StrokeStyle strokeStyle = default);
- [PreserveSig]
void FillRectangle(
- in LtrbRectangleF rect,
- IBrush brush);
+ LtrbRectangleF rectangle,
+ Brush brush);
- [PreserveSig]
void DrawRoundedRectangle(
- in RoundedRectangle roundedRect,
- IBrush brush,
+ RoundedRectangle roundedRectangle,
+ Brush brush,
float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
+ StrokeStyle strokeStyle = default);
- [PreserveSig]
void FillRoundedRectangle(
- in RoundedRectangle roundedRect,
- IBrush brush);
+ RoundedRectangle roundedRectangle,
+ Brush brush);
- [PreserveSig]
void DrawEllipse(
- in Ellipse ellipse,
- IBrush brush,
+ Ellipse ellipse,
+ Brush brush,
float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
+ StrokeStyle strokeStyle = default);
- [PreserveSig]
void FillEllipse(
- in Ellipse ellipse,
- IBrush brush);
+ Ellipse ellipse,
+ Brush brush);
- [PreserveSig]
void DrawGeometry(
- IGeometry geometry,
- IBrush brush,
+ Geometry geometry,
+ Brush brush,
float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
+ StrokeStyle strokeStyle = default);
- /// An optionally specified opacity brush. Only the alpha
- /// channel of the corresponding brush will be sampled and will be applied to the
- /// entire fill of the geometry. If this brush is specified, the fill brush must be
- /// a bitmap brush with an extend mode of D2D1_EXTEND_MODE_CLAMP.
- [PreserveSig]
+ ///
+ /// An optionally specified opacity brush. Only the alpha channel of the corresponding brush will be sampled
+ /// and will be applied to the entire fill of the geometry. If this brush is specified, the fill brush must be
+ /// a bitmap brush with an extend mode of .
+ ///
void FillGeometry(
- IGeometry geometry,
- IBrush brush,
- IBrush opacityBrush = null);
-
- ///
- /// Fill a mesh. Since meshes can only render aliased content, the render target
- /// antialiasing mode must be set to aliased.
- ///
- void FillMeshSTUB();
- //STDMETHOD_(void, FillMesh)(
- // _In_ ID2D1Mesh * mesh,
- // _In_ ID2D1Brush* brush
- // ) PURE;
-
- ///
- /// Fill using the alpha channel of the supplied opacity mask bitmap. The brush
- /// opacity will be modulated by the mask. The render target antialiasing mode must
- /// be set to aliased.
- ///
- void FillOpacityMaskSTUB();
- //STDMETHOD_(void, FillOpacityMask)(
- // _In_ ID2D1Bitmap * opacityMask,
- // _In_ ID2D1Brush* brush,
- // D2D1_OPACITY_MASK_CONTENT content,
- // _In_opt_ CONST D2D1_RECT_F* destinationRectangle = NULL,
- // _In_opt_ CONST D2D1_RECT_F *sourceRectangle = NULL
- // ) PURE;
-
- [PreserveSig]
- unsafe void DrawBitmap(
- IBitmap bitmap,
- LtrbRectangleF* destinationRectangle = null,
- float opacity = 1.0f,
- BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.Linear,
- LtrbRectangleF* sourceRectangle = null);
-
- ///
- /// Draws the text within the given layout rectangle and by default also performs
- /// baseline snapping.
- ///
- [PreserveSig]
- unsafe void DrawText(
- char* @string,
- uint stringLength,
- ITextFormat textFormat,
- in LtrbRectangleF layoutRect,
- IBrush defaultFillBrush,
- DrawTextOptions options = DrawTextOptions.None,
- MeasuringMode measuringMode = MeasuringMode.Natural);
+ Geometry geometry,
+ Brush brush,
+ Brush opacityBrush = default);
///
/// Draw a text layout object. If the layout is not subsequently changed, this can
@@ -256,111 +131,42 @@ unsafe void DrawText(
///
/// The specified text options. If is used, the text
/// is clipped to the layout bounds. These bounds are derived from the origin and the
- /// layout bounds of the corresponding object.
+ /// layout bounds of the corresponding object.
///
- [PreserveSig]
void DrawTextLayout(
PointF origin,
- ITextLayout textLayout,
- IBrush defaultFillBrush,
+ TextLayout textLayout,
+ Brush defaultFillBrush,
DrawTextOptions options = DrawTextOptions.None);
- [PreserveSig]
+ /*
void DrawGlyphRun(
PointF baselineOrigin,
- in GlyphRun glyphRun,
- IBrush foregroundBrush,
+ GlyphRun glyphRun,
+ Brush foregroundBrush,
MeasuringMode measuringMode = MeasuringMode.Natural);
+ */
- [PreserveSig]
- void SetTransform(
- ref Matrix3x2 transform);
+ Matrix3x2 Transform { get; set; }
- [PreserveSig]
- void GetTransform(
- out Matrix3x2 transform);
+ AntialiasMode AntialiasMode { get; set; }
- [PreserveSig]
- void SetAntialiasMode(
- AntialiasMode antialiasMode);
-
- [PreserveSig]
- AntialiasMode GetAntialiasMode();
-
- [PreserveSig]
- void SetTextAntialiasMode(
- TextAntialiasMode textAntialiasMode);
-
- [PreserveSig]
- TextAntialiasMode GetTextAntialiasMode();
-
- [PreserveSig]
- void SetTextRenderingParams(
- DirectWrite.IRenderingParams textRenderingParams = null);
-
- ///
- /// Retrieve the text render parameters. NOTE: If NULL is specified to
- /// SetTextRenderingParameters, NULL will be returned.
- ///
- [PreserveSig]
- void GetTextRenderingParams(
- out DirectWrite.IRenderingParams textRenderingParams);
+ TextAntialiasMode TextAntialiasMode { get; set; }
///
/// Set a tag to correspond to the succeeding primitives. If an error occurs
/// rendering a primitive, the tags can be returned from the Flush or EndDraw call.
+ ///
+ /// This does not retrieve the tags corresponding to any primitive that is in error.
///
- [PreserveSig]
- void SetTags(
- ulong tag1,
- ulong tag2);
-
- ///
- /// Retrieves the currently set tags. This does not retrieve the tags corresponding
- /// to any primitive that is in error.
- ///
- [PreserveSig]
- void GetTags(
- out ulong tag1,
- out ulong tag2);
-
- ///
- /// Start a layer of drawing calls. The way in which the layer must be resolved is
- /// specified first as well as the logical resource that stores the layer
- /// parameters. The supplied layer resource might grow if the specified content
- /// cannot fit inside it. The layer will grow monotonically on each axis. If a NULL
- /// ID2D1Layer is provided, then a layer resource will be allocated automatically.
- ///
- void PushLayerSTUB();
- //STDMETHOD_(void, PushLayer)(
- // _In_ CONST D2D1_LAYER_PARAMETERS *layerParameters,
- //_In_opt_ ID2D1Layer *layer
- //) PURE;
+ public Tags Tags { get; set; }
///
/// Ends a layer that was defined with particular layer resources.
///
- [PreserveSig]
void PopLayer();
- void Flush(
- out ulong tag1,
- out ulong tag2);
-
- ///
- /// Gets the current drawing state and saves it into the supplied
- /// IDrawingStatckBlock.
- ///
- [PreserveSig]
- void SaveDrawingState(
- IDrawingStateBlock drawingStateBlock);
-
- ///
- /// Copies the state stored in the block interface.
- ///
- [PreserveSig]
- void RestoreDrawingState(
- IDrawingStateBlock drawingStateBlock);
+ Tags Flush();
///
/// Pushes a clip. The clip can be antialiased. The clip must be axis aligned. If
@@ -368,74 +174,53 @@ void RestoreDrawingState(
/// transformed clip rect will be used. The clip will remain in effect until a
/// PopAxisAligned clip call is made.
///
- [PreserveSig]
void PushAxisAlignedClip(
- in LtrbRectangleF clipRect,
+ LtrbRectangleF clipRect,
AntialiasMode antialiasMode);
- [PreserveSig]
void PopAxisAlignedClip();
- [PreserveSig]
- unsafe void Clear(
- ColorF* clearColor = null);
+ void Clear();
+
+ void Clear(ColorF clearColor);
///
/// Start drawing on this render target. Draw calls can only be issued between a
/// BeginDraw and EndDraw call.
///
- [PreserveSig]
void BeginDraw();
///
/// Ends drawing on the render target, error results can be retrieved at this time,
/// or when calling flush.
///
- [PreserveSig]
- HResult EndDraw(
- out ulong tag1,
- out ulong tag2);
+ Tags EndDraw(out bool recreateTarget);
- [PreserveSig]
- void GetPixelFormat(out PixelFormat pixelFormat);
+ PixelFormat PixelFormat { get; }
///
- /// Sets the DPI on the render target. This results in the render target being
+ /// The DPI on the render target. This results in the render target being
/// interpreted to a different scale. Neither DPI can be negative. If zero is
/// specified for both, the system DPI is chosen. If one is zero and the other
/// unspecified, the DPI is not changed.
///
- [PreserveSig]
- void SetDpi(
- float dpiX,
- float dpiY);
-
- ///
- /// Return the current DPI from the target.
- ///
- [PreserveSig]
- void GetDpi(
- out float dpiX,
- out float dpiY);
+ PointF Dpi { get; set; }
///
/// Returns the size of the render target in DIPs.
///
- [PreserveSig]
- void GetSize(out SizeF size);
+ SizeF Size { get; }
///
/// Returns the size of the render target in pixels.
///
- [PreserveSig]
- void GetPixelSize(out SizeU pixelSize);
+ SizeU PixelSize { get; }
///
/// Returns the maximum bitmap and render target size that is guaranteed to be
/// supported by the render target.
///
- [PreserveSig]
- uint GetMaximumBitmapSize();
+ uint MaximumBitmapSize { get; }
///
/// Returns true if the given properties are supported by this render target. The
@@ -443,76 +228,6 @@ void GetDpi(
/// D2D1_FEATURE_LEVEL_9 nor D2D1_FEATURE_LEVEL_10 will be considered to be
/// supported.
///
- [PreserveSig]
- IntBoolean IsSupported(
- in RenderTargetProperties renderTargetProperties);
- }
-
- public static class RenderTargetExtensions
- {
- public unsafe static IBitmap CreateBitmap(this IRenderTarget renderTarget, Size size, in BitmapProperties properties)
- => renderTarget.CreateBitmap(size, null, 0, properties);
-
- public unsafe static ISolidColorBrush CreateSolidColorBrush(this IRenderTarget renderTarget, in ColorF color)
- => renderTarget.CreateSolidColorBrush(color, null);
-
- public unsafe static ISolidColorBrush CreateSolidColorBrush(
- this IRenderTarget renderTarget, in ColorF color, in BrushProperties properties)
- {
- fixed (BrushProperties* p = &properties)
- return renderTarget.CreateSolidColorBrush(color, p);
- }
-
- public unsafe static IBitmapRenderTarget CreateCompatibleRenderTarget(this IRenderTarget renderTarget, SizeF desiredSize)
- => renderTarget.CreateCompatibleRenderTarget(&desiredSize, null, null, CompatibleRenderTargetOptions.None);
-
- public unsafe static IBitmapBrush CreateBitmapBrush(this IRenderTarget renderTarget, IBitmap bitmap, BitmapBrushProperties bitmapBrushProperties)
- => renderTarget.CreateBitmapBrush(bitmap, &bitmapBrushProperties, null);
-
- public unsafe static IRadialGradientBrush CreateRadialGradientBrush(
- this IRenderTarget renderTarget,
- in RadialGradientBrushProperties properties,
- IGradientStopCollection gradientStopCollection)
- {
- return renderTarget.CreateRadialGradientBrush(properties, null, gradientStopCollection);
- }
-
- public unsafe static IGradientStopCollection CreateGradienStopCollection(
- this IRenderTarget renderTarget,
- ReadOnlySpan gradientStops,
- Gamma gamma = Gamma.ColorSpace_2_2,
- ExtendMode extendMode = ExtendMode.Clamp)
- {
- fixed (GradientStop* gs = &MemoryMarshal.GetReference(gradientStops))
- {
- return renderTarget.CreateGradientStopCollection(gs, (uint)gradientStops.Length, gamma, extendMode);
- }
- }
-
- public unsafe static void Clear(this IRenderTarget renderTarget)
- => renderTarget.Clear(null);
-
- public unsafe static void Clear(this IRenderTarget renderTarget, in ColorF color)
- {
- fixed (ColorF* c = &color)
- renderTarget.Clear(c);
- }
-
- public static SizeF GetSize(this IRenderTarget renderTarget)
- {
- renderTarget.GetSize(out SizeF size);
- return size;
- }
-
- ///
- /// Set the transform to identity.
- ///
- public static void SetTransform(this IRenderTarget renderTarget)
- {
- Matrix3x2 identity = Matrix3x2.Identity;
- renderTarget.SetTransform(ref identity);
- }
-
- public static HResult EndDraw(this IRenderTarget renderTarget) => renderTarget.EndDraw(out _, out _);
+ bool IsSupported(RenderTargetProperties renderTargetProperties);
}
}
diff --git a/src/WInterop.DirectX/Direct2d/IResource.cs b/src/WInterop.DirectX/Direct2d/IResource.cs
deleted file mode 100644
index 56d303ec..00000000
--- a/src/WInterop.DirectX/Direct2d/IResource.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// [ID2D1Resource]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1Resource),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IResource
- {
- [PreserveSig]
- void GetFactory(
- out IFactory factory);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IRoundedRectangleGeometry.cs b/src/WInterop.DirectX/Direct2d/IRoundedRectangleGeometry.cs
deleted file mode 100644
index f2306eb2..00000000
--- a/src/WInterop.DirectX/Direct2d/IRoundedRectangleGeometry.cs
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// [ID2D1RoundedRectangleGeometry]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1RoundedRectangleGeometry),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public unsafe interface IRoundedRectangleGeometry : IGeometry
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Geometry
- ///
- /// Retrieve the bounds of the geometry, with an optional applied transform.
- ///
- new LtrbRectangleF GetBounds(
- Matrix3x2* worldTransform);
-
- ///
- /// Get the bounds of the corresponding geometry after it has been widened or have
- /// an optional pen style applied.
- ///
- new LtrbRectangleF GetWidenedBounds(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Checks to see whether the corresponding penned and widened geometry contains the
- /// given point.
- ///
- new IntBoolean StrokeContainsPoint(
- PointF point,
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Test whether the given fill of this geometry would contain this point.
- ///
- new IntBoolean FillContainsPoint(
- PointF point,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Compare how one geometry intersects or contains another geometry.
- ///
- new GeometryRelation CompareWithGeometry(
- IGeometry inputGeometry,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance);
-
- ///
- /// Converts a geometry to a simplified geometry that has arcs and quadratic beziers
- /// removed.
- ///
- new void Simplify(
- GeometrySimplificationOption simplificationOption,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Tessellates a geometry into triangles.
- ///
- new void Tessellate(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ITesselationSink tessellationSink);
-
- ///
- /// Performs a combine operation between the two geometries to produce a resulting
- /// geometry.
- ///
- new void CombineWithGeometry(
- IGeometry inputGeometry,
- CombineMode combineMode,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the outline of the geometry. The result is written back into a
- /// simplified geometry sink.
- ///
- new void Outline(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the area of the geometry.
- ///
- new float ComputeArea(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the length of the geometry.
- ///
- new float ComputeLength(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the point and tangent a given distance along the path.
- ///
- new void ComputePointAtLength(
- float length,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- PointF* point,
- PointF* unitTangentVector);
-
- ///
- /// Get the geometry and widen it as well as apply an optional pen style.
- ///
- new void Widen(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
- #endregion
-
- [PreserveSig]
- void GetRoundedRect(
- out RoundedRectangle roundedRect);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/ISimplifiedGeometrySink.cs b/src/WInterop.DirectX/Direct2d/ISimplifiedGeometrySink.cs
deleted file mode 100644
index 64e2057c..00000000
--- a/src/WInterop.DirectX/Direct2d/ISimplifiedGeometrySink.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Describes a geometric path that does not contain quadratic bezier curves or arcs.
- /// [ID2D1SimplifiedGeometrySink]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1SimplifiedGeometrySink),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ISimplifiedGeometrySink
- {
- [PreserveSig]
- void SetFillMode(
- FillMode fillMode);
-
- [PreserveSig]
- void SetSegmentFlags(
- PathSegment vertexFlags);
-
- [PreserveSig]
- void BeginFigure(
- PointF startPoint,
- FigureBegin figureBegin);
-
- [PreserveSig]
- unsafe void AddLines(
- PointF* points,
- uint pointsCount);
-
- [PreserveSig]
- unsafe void AddBeziers(
- BezierSegment* beziers,
- uint beziersCount);
-
- [PreserveSig]
- void EndFigure(
- FigureEnd figureEnd);
-
- [PreserveSig]
- void Close();
- }
-
- public static class SimplifiedGeometrySinkExtensions
- {
- public unsafe static void AddLines(this IGeometrySink sink, ReadOnlySpan points)
- {
- fixed (PointF* p = &MemoryMarshal.GetReference(points))
- {
- sink.AddLines(p, (uint)points.Length);
- }
- }
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/ISolidColorBrush.cs b/src/WInterop.DirectX/Direct2d/ISolidColorBrush.cs
deleted file mode 100644
index 96e153ad..00000000
--- a/src/WInterop.DirectX/Direct2d/ISolidColorBrush.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Paints an area with a solid color. [ID2D1SolidColorBrush]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1SolidColorBrush),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ISolidColorBrush : IBrush
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Brush
- ///
- /// Sets the opacity for when the brush is drawn over the entire fill of the brush.
- ///
- [PreserveSig]
- new void SetOpacity(
- float opacity);
-
- ///
- /// Sets the transform that applies to everything drawn by the brush.
- ///
- [PreserveSig]
- new void SetTransform(
- ref Matrix3x2 transform);
-
- [PreserveSig]
- new float GetOpacity();
-
- [PreserveSig]
- new void GetTransform(
- out Matrix3x2 transform);
- #endregion
-
- [PreserveSig]
- void SetColor(
- in ColorF color);
-
- [PreserveSig]
- void GetColor(
- out ColorF color);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IStrokeStyle.cs b/src/WInterop.DirectX/Direct2d/IStrokeStyle.cs
deleted file mode 100644
index 627f8881..00000000
--- a/src/WInterop.DirectX/Direct2d/IStrokeStyle.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// [ID2D1StrokeStyle]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1StrokeStyle),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IStrokeStyle : IResource
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- [PreserveSig]
- CapStyle GetStartCap();
-
- [PreserveSig]
- CapStyle GetEndCap();
-
- [PreserveSig]
- CapStyle GetDashCap();
-
- [PreserveSig]
- float GetMiterLimit();
-
- [PreserveSig]
- LineJoin GetLineJoin();
-
- [PreserveSig]
- float GetDashOffset();
-
- [PreserveSig]
- DashStyle GetDashStyle();
-
- [PreserveSig]
- uint GetDashesCount();
-
- ///
- /// Returns the dashes from the object into a user allocated array. The user must
- /// call GetDashesCount to retrieve the required size.
- ///
- [PreserveSig]
- unsafe void GetDashes(
- float* dashes,
- uint dashesCount);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/ITesselationSink.cs b/src/WInterop.DirectX/Direct2d/ITesselationSink.cs
index 45bce9ee..6e0db719 100644
--- a/src/WInterop.DirectX/Direct2d/ITesselationSink.cs
+++ b/src/WInterop.DirectX/Direct2d/ITesselationSink.cs
@@ -9,17 +9,34 @@ namespace WInterop.Direct2d
///
/// [ID2D1TessellationSink]
///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1TessellationSink),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITesselationSink
+ [Guid(InterfaceIds.IID_ID2D1TessellationSink)]
+ public readonly unsafe struct TesselationSink : TesselationSink.Interface, IDisposable
{
- [PreserveSig]
- void AddTriangles(
- ref Triangle triangles,
- uint trianglesCount);
+ private readonly ID2D1TessellationSink* _handle;
- [PreserveSig]
- void Close();
+ internal TesselationSink(ID2D1TessellationSink* handle) => _handle = handle;
+
+ public void AddTriangles(ReadOnlySpan triangles)
+ {
+ fixed(void* t = triangles)
+ {
+ _handle->AddTriangles((D2D1_TRIANGLE*)t, (uint)triangles.Length);
+ }
+ }
+
+ public void Close() => _handle->Close();
+
+ public void Dispose()
+ {
+ Close();
+ _handle->Release();
+ }
+
+ internal interface Interface
+ {
+ void AddTriangles(ReadOnlySpan triangles);
+
+ void Close();
+ }
}
}
diff --git a/src/WInterop.DirectX/Direct2d/ITransformedGeometry.cs b/src/WInterop.DirectX/Direct2d/ITransformedGeometry.cs
deleted file mode 100644
index 3d67575a..00000000
--- a/src/WInterop.DirectX/Direct2d/ITransformedGeometry.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.Direct2d
-{
- ///
- /// Represents a geometry that has been transformed. [ID2D1TransformedGeometry]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1TransformedGeometry),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public unsafe interface ITransformedGeometry : IGeometry
- {
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1Geometry
- ///
- /// Retrieve the bounds of the geometry, with an optional applied transform.
- ///
- new LtrbRectangleF GetBounds(
- Matrix3x2* worldTransform);
-
- ///
- /// Get the bounds of the corresponding geometry after it has been widened or have
- /// an optional pen style applied.
- ///
- new LtrbRectangleF GetWidenedBounds(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Checks to see whether the corresponding penned and widened geometry contains the
- /// given point.
- ///
- new IntBoolean StrokeContainsPoint(
- PointF point,
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Test whether the given fill of this geometry would contain this point.
- ///
- new IntBoolean FillContainsPoint(
- PointF point,
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Compare how one geometry intersects or contains another geometry.
- ///
- new GeometryRelation CompareWithGeometry(
- IGeometry inputGeometry,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance);
-
- ///
- /// Converts a geometry to a simplified geometry that has arcs and quadratic beziers
- /// removed.
- ///
- new void Simplify(
- GeometrySimplificationOption simplificationOption,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Tessellates a geometry into triangles.
- ///
- new void Tessellate(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ITesselationSink tessellationSink);
-
- ///
- /// Performs a combine operation between the two geometries to produce a resulting
- /// geometry.
- ///
- new void CombineWithGeometry(
- IGeometry inputGeometry,
- CombineMode combineMode,
- Matrix3x2* inputGeometryTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the outline of the geometry. The result is written back into a
- /// simplified geometry sink.
- ///
- new void Outline(
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
-
- ///
- /// Computes the area of the geometry.
- ///
- new float ComputeArea(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the length of the geometry.
- ///
- new float ComputeLength(
- Matrix3x2* worldTransform,
- float flatteningTolerance);
-
- ///
- /// Computes the point and tangent a given distance along the path.
- ///
- new void ComputePointAtLength(
- float length,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- PointF* point,
- PointF* unitTangentVector);
-
- ///
- /// Get the geometry and widen it as well as apply an optional pen style.
- ///
- new void Widen(
- float strokeWidth,
- IStrokeStyle strokeStyle,
- Matrix3x2* worldTransform,
- float flatteningTolerance,
- ISimplifiedGeometrySink geometrySink);
- #endregion
-
- [PreserveSig]
- void GetSourceGeometry(
- out IGeometry sourceGeometry);
-
- [PreserveSig]
- void GetTransform(
- out Matrix3x2 transform);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/IWindowRenderTarget.cs b/src/WInterop.DirectX/Direct2d/IWindowRenderTarget.cs
index 46d13bf0..bf4bd7a5 100644
--- a/src/WInterop.DirectX/Direct2d/IWindowRenderTarget.cs
+++ b/src/WInterop.DirectX/Direct2d/IWindowRenderTarget.cs
@@ -1,451 +1,10 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-using System;
-using System.Drawing;
-using System.Numerics;
-using System.Runtime.InteropServices;
-using WInterop.DirectWrite;
-using WInterop.Windows.Native;
-
namespace WInterop.Direct2d
{
- ///
- /// Renders drawing instructions to a window. [ID2D1HwndRenderTarget]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_ID2D1HwndRenderTarget),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IWindowRenderTarget : IRenderTarget
{
- #region ID2D1Resource
- [PreserveSig]
- new void GetFactory(
- out IFactory factory);
- #endregion
-
- #region ID2D1RenderTarget
- ///
- /// Create a D2D bitmap by copying from memory, or create uninitialized.
- ///
- new unsafe IBitmap CreateBitmap(
- SizeU size,
- void* srcData,
- uint pitch,
- in BitmapProperties bitmapProperties);
-
- ///
- /// Create a D2D bitmap by copying a WIC bitmap.
- ///
- new unsafe IBitmap CreateBitmapFromWicBitmap(
- object wicBitmapSource, // IWICBitmapSource
- BitmapProperties* bitmapProperties);
-
- ///
- /// Create a D2D bitmap by sharing bits from another resource. The bitmap must be
- /// compatible with the render target for the call to succeed. For example, an
- /// IWICBitmap can be shared with a software target, or a DXGI surface can be shared
- /// with a DXGI render target.
- ///
- new unsafe IBitmap CreateSharedBitmap(
- in Guid riid,
- void* data,
- BitmapProperties* bitmapProperties);
-
- ///
- /// Creates a bitmap brush. The bitmap is scaled, rotated, skewed or tiled to fill
- /// or pen a geometry.
- ///
- new unsafe IBitmapBrush CreateBitmapBrush(
- IBitmap bitmap,
- BitmapBrushProperties* bitmapBrushProperties,
- BrushProperties* brushProperties);
-
- new unsafe ISolidColorBrush CreateSolidColorBrush(
- in ColorF color,
- BrushProperties* brushProperties);
-
- ///
- /// A gradient stop collection represents a set of stops in an ideal unit length.
- /// This is the source resource for a linear gradient and radial gradient brush.
- ///
- /// Specifies which space the color
- /// interpolation occurs in.
- /// Specifies how the gradient will be extended outside of
- /// the unit length.
- new unsafe IGradientStopCollection CreateGradientStopCollection(
- GradientStop* gradientStops,
- uint gradientStopsCount,
- Gamma colorInterpolationGamma,
- ExtendMode extendMode);
-
- new void CreateLinearGradientBrushSTUB();
- //STDMETHOD(CreateLinearGradientBrush)(
- // _In_ CONST D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *linearGradientBrushProperties,
- // _In_opt_ CONST D2D1_BRUSH_PROPERTIES* brushProperties,
- // _In_ ID2D1GradientStopCollection* gradientStopCollection,
- // _COM_Outptr_ ID2D1LinearGradientBrush** linearGradientBrush
- // ) PURE;
-
- new unsafe IRadialGradientBrush CreateRadialGradientBrush(
- in RadialGradientBrushProperties radialGradientBrushProperties,
- BrushProperties* brushProperties,
- IGradientStopCollection gradientStopCollection);
-
- ///
- /// Creates a bitmap render target whose bitmap can be used as a source for
- /// rendering in the API.
- ///
- /// The requested size of the target in DIPs. If the pixel
- /// size is not specified, the DPI is inherited from the parent target. However, the
- /// render target will never contain a fractional number of pixels.
- /// The requested size of the render target in
- /// pixels. If the DIP size is also specified, the DPI is calculated from these two
- /// values. If the desired size is not specified, the DPI is inherited from the
- /// parent render target. If neither value is specified, the compatible render
- /// target will be the same size and have the same DPI as the parent target.
- /// The desired pixel format. The format must be
- /// compatible with the parent render target type. If the format is not specified,
- /// it will be inherited from the parent render target.
- /// Allows the caller to retrieve a GDI compatible render
- /// target.
- /// The returned bitmap render target.
- new unsafe IBitmapRenderTarget CreateCompatibleRenderTarget(
- SizeF* desiredSize,
- SizeU* desiredPixelSize,
- PixelFormat* desiredFormat,
- CompatibleRenderTargetOptions options);
-
- ///
- /// Creates a layer resource that can be used on any target and which will resize
- /// under the covers if necessary.
- ///
- /// The resolution independent minimum size hint for the layer
- /// resource. Specify this to prevent unwanted reallocation of the layer backing
- /// store. The size is in DIPs, but, it is unaffected by the current world
- /// transform. If the size is unspecified, the returned resource is a placeholder
- /// and the backing store will be allocated to be the minimum size that can hold the
- /// content when the layer is pushed.
- new void CreateLayerStub();
- //STDMETHOD(CreateLayer)(
- // _In_opt_ CONST D2D1_SIZE_F *size,
- // _COM_Outptr_ ID2D1Layer **layer
- // ) PURE;
-
- ///
- /// Create a D2D mesh.
- ///
- new void CreateMeshSTUB();
- //STDMETHOD(CreateMesh)(
- // _COM_Outptr_ ID2D1Mesh ** mesh
- // ) PURE;
-
- [PreserveSig]
- new void DrawLine(
- PointF point0,
- PointF point1,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void DrawRectangle(
- in LtrbRectangleF rect,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillRectangle(
- in LtrbRectangleF rect,
- IBrush brush);
-
- [PreserveSig]
- new void DrawRoundedRectangle(
- in RoundedRectangle roundedRect,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillRoundedRectangle(
- in RoundedRectangle roundedRect,
- IBrush brush);
-
- [PreserveSig]
- new void DrawEllipse(
- in Ellipse ellipse,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- [PreserveSig]
- new void FillEllipse(
- in Ellipse ellipse,
- IBrush brush);
-
- [PreserveSig]
- new void DrawGeometry(
- IGeometry geometry,
- IBrush brush,
- float strokeWidth = 1.0f,
- IStrokeStyle strokeStyle = null);
-
- /// An optionally specified opacity brush. Only the alpha
- /// channel of the corresponding brush will be sampled and will be applied to the
- /// entire fill of the geometry. If this brush is specified, the fill brush must be
- /// a bitmap brush with an extend mode of D2D1_EXTEND_MODE_CLAMP.
- [PreserveSig]
- new void FillGeometry(
- IGeometry geometry,
- IBrush brush,
- IBrush opacityBrush = null);
-
- ///
- /// Fill a mesh. Since meshes can only render aliased content, the render target
- /// antialiasing mode must be set to aliased.
- ///
- new void FillMeshSTUB();
- //STDMETHOD_(void, FillMesh)(
- // _In_ ID2D1Mesh * mesh,
- // _In_ ID2D1Brush* brush
- // ) PURE;
-
- ///
- /// Fill using the alpha channel of the supplied opacity mask bitmap. The brush
- /// opacity will be modulated by the mask. The render target antialiasing mode must
- /// be set to aliased.
- ///
- new void FillOpacityMaskSTUB();
- //STDMETHOD_(void, FillOpacityMask)(
- // _In_ ID2D1Bitmap * opacityMask,
- // _In_ ID2D1Brush* brush,
- // D2D1_OPACITY_MASK_CONTENT content,
- // _In_opt_ CONST D2D1_RECT_F* destinationRectangle = NULL,
- // _In_opt_ CONST D2D1_RECT_F *sourceRectangle = NULL
- // ) PURE;
-
- [PreserveSig]
- new unsafe void DrawBitmap(
- IBitmap bitmap,
- LtrbRectangleF* destinationRectangle = null,
- float opacity = 1.0f,
- BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.Linear,
- LtrbRectangleF* sourceRectangle = null);
-
- ///
- /// Draws the text within the given layout rectangle and by default also performs
- /// baseline snapping.
- ///
- [PreserveSig]
- new unsafe void DrawText(
- char* @string,
- uint stringLength,
- ITextFormat textFormat,
- in LtrbRectangleF layoutRect,
- IBrush defaultFillBrush,
- DrawTextOptions options = DrawTextOptions.None,
- MeasuringMode measuringMode = MeasuringMode.Natural);
-
- ///
- /// Draw a text layout object. If the layout is not subsequently changed, this can
- /// be more efficient than DrawText when drawing the same layout repeatedly.
- ///
- ///
- /// The specified text options. If is used, the text
- /// is clipped to the layout bounds. These bounds are derived from the origin and the
- /// layout bounds of the corresponding object.
- ///
- [PreserveSig]
- new void DrawTextLayout(
- PointF origin,
- ITextLayout textLayout,
- IBrush defaultFillBrush,
- DrawTextOptions options = DrawTextOptions.None);
-
- [PreserveSig]
- new void DrawGlyphRun(
- PointF baselineOrigin,
- in GlyphRun glyphRun,
- IBrush foregroundBrush,
- MeasuringMode measuringMode = MeasuringMode.Natural);
-
- [PreserveSig]
- new void SetTransform(
- ref Matrix3x2 transform);
-
- [PreserveSig]
- new void GetTransform(
- out Matrix3x2 transform);
-
- [PreserveSig]
- new void SetAntialiasMode(
- AntialiasMode antialiasMode);
-
- [PreserveSig]
- new AntialiasMode GetAntialiasMode();
-
- [PreserveSig]
- new void SetTextAntialiasMode(
- TextAntialiasMode textAntialiasMode);
-
- [PreserveSig]
- new TextAntialiasMode GetTextAntialiasMode();
-
- [PreserveSig]
- new void SetTextRenderingParams(
- DirectWrite.IRenderingParams textRenderingParams = null);
-
- ///
- /// Retrieve the text render parameters. NOTE: If NULL is specified to
- /// SetTextRenderingParameters, NULL will be returned.
- ///
- [PreserveSig]
- new void GetTextRenderingParams(
- out DirectWrite.IRenderingParams textRenderingParams);
-
- ///
- /// Set a tag to correspond to the succeeding primitives. If an error occurs
- /// rendering a primitive, the tags can be returned from the Flush or EndDraw call.
- ///
- [PreserveSig]
- new void SetTags(
- ulong tag1,
- ulong tag2);
-
- ///
- /// Retrieves the currently set tags. This does not retrieve the tags corresponding
- /// to any primitive that is in error.
- ///
- [PreserveSig]
- new void GetTags(
- out ulong tag1,
- out ulong tag2);
-
- ///
- /// Start a layer of drawing calls. The way in which the layer must be resolved is
- /// specified first as well as the logical resource that stores the layer
- /// parameters. The supplied layer resource might grow if the specified content
- /// cannot fit inside it. The layer will grow monotonically on each axis. If a NULL
- /// ID2D1Layer is provided, then a layer resource will be allocated automatically.
- ///
- new void PushLayerSTUB();
- //STDMETHOD_(void, PushLayer)(
- // _In_ CONST D2D1_LAYER_PARAMETERS *layerParameters,
- //_In_opt_ ID2D1Layer *layer
- //) PURE;
-
- ///
- /// Ends a layer that was defined with particular layer resources.
- ///
- [PreserveSig]
- new void PopLayer();
-
- new void Flush(
- out ulong tag1,
- out ulong tag2);
-
- ///
- /// Gets the current drawing state and saves it into the supplied
- /// IDrawingStatckBlock.
- ///
- [PreserveSig]
- new void SaveDrawingState(
- IDrawingStateBlock drawingStateBlock);
-
- ///
- /// Copies the state stored in the block interface.
- ///
- [PreserveSig]
- new void RestoreDrawingState(
- IDrawingStateBlock drawingStateBlock);
-
- ///
- /// Pushes a clip. The clip can be antialiased. The clip must be axis aligned. If
- /// the current world transform is not axis preserving, then the bounding box of the
- /// transformed clip rect will be used. The clip will remain in effect until a
- /// PopAxisAligned clip call is made.
- ///
- [PreserveSig]
- new void PushAxisAlignedClip(
- in LtrbRectangleF clipRect,
- AntialiasMode antialiasMode);
-
- [PreserveSig]
- new void PopAxisAlignedClip();
-
- [PreserveSig]
- new unsafe void Clear(
- ColorF* clearColor = null);
-
- ///
- /// Start drawing on this render target. Draw calls can only be issued between a
- /// BeginDraw and EndDraw call.
- ///
- [PreserveSig]
- new void BeginDraw();
-
- ///
- /// Ends drawing on the render target, error results can be retrieved at this time,
- /// or when calling flush.
- ///
- new void EndDraw(
- out ulong tag1,
- out ulong tag2);
-
- [PreserveSig]
- new void GetPixelFormat(out PixelFormat pixelFormat);
-
- ///
- /// Sets the DPI on the render target. This results in the render target being
- /// interpreted to a different scale. Neither DPI can be negative. If zero is
- /// specified for both, the system DPI is chosen. If one is zero and the other
- /// unspecified, the DPI is not changed.
- ///
- [PreserveSig]
- new void SetDpi(
- float dpiX,
- float dpiY);
-
- ///
- /// Return the current DPI from the target.
- ///
- [PreserveSig]
- new void GetDpi(
- out float dpiX,
- out float dpiY);
-
- ///
- /// Returns the size of the render target in DIPs.
- ///
- [PreserveSig]
- new void GetSize(out SizeF size);
-
- ///
- /// Returns the size of the render target in pixels.
- ///
- [PreserveSig]
- new SizeU GetPixelSize(out SizeU pixelSize);
-
- ///
- /// Returns the maximum bitmap and render target size that is guaranteed to be
- /// supported by the render target.
- ///
- [PreserveSig]
- new uint GetMaximumBitmapSize();
-
- ///
- /// Returns true if the given properties are supported by this render target. The
- /// DPI is ignored. NOTE: If the render target type is software, then neither
- /// D2D1_FEATURE_LEVEL_9 nor D2D1_FEATURE_LEVEL_10 will be considered to be
- /// supported.
- ///
- [PreserveSig]
- new IntBoolean IsSupported(
- in RenderTargetProperties renderTargetProperties);
- #endregion
-
- [PreserveSig]
WindowState CheckWindowState();
///
@@ -456,10 +15,8 @@ public interface IWindowRenderTarget : IRenderTarget
/// from it when EndDraw is called. In addition an appropriate failure result will
/// be returned from Resize.
///
- void Resize(
- in SizeU pixelSize);
+ void Resize(SizeU pixelSize);
- [PreserveSig]
- HWND GetHwnd();
+ Windows.Native.HWND GetHwnd();
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Image.cs b/src/WInterop.DirectX/Direct2d/Image.cs
new file mode 100644
index 00000000..67486b4b
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/Image.cs
@@ -0,0 +1,25 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Represents a producer of pixels that can fill an arbitrary 2D plane. [ID2D1Image]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1Image)]
+ public unsafe struct Image : Resource.Interface, IDisposable
+ {
+ internal readonly ID2D1Image* _handle;
+
+ internal Image(ID2D1Image* handle) => _handle = handle;
+
+ public unsafe Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public void Dispose() => _handle->Release();
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/LineJoin.cs b/src/WInterop.DirectX/Direct2d/LineJoin.cs
index ff9770de..0d7565c8 100644
--- a/src/WInterop.DirectX/Direct2d/LineJoin.cs
+++ b/src/WInterop.DirectX/Direct2d/LineJoin.cs
@@ -11,21 +11,21 @@ public enum LineJoin : uint
///
/// Miter join. [D2D1_LINE_JOIN_MITER]
///
- Miter = 0,
+ Miter = D2D1_LINE_JOIN.D2D1_LINE_JOIN_MITER,
///
/// Bevel join. [D2D1_LINE_JOIN_BEVEL]
///
- Bevel = 1,
+ Bevel = D2D1_LINE_JOIN.D2D1_LINE_JOIN_BEVEL,
///
/// Round join. [D2D1_LINE_JOIN_ROUND]
///
- Round = 2,
+ Round = D2D1_LINE_JOIN.D2D1_LINE_JOIN_ROUND,
///
/// Miter/Bevel join. [D2D1_LINE_JOIN_MITER_OR_BEVEL]
///
- MiterOrBevel = 3
+ MiterOrBevel = D2D1_LINE_JOIN.D2D1_LINE_JOIN_MITER_OR_BEVEL
}
}
diff --git a/src/WInterop.DirectX/Direct2d/LtrbRectangleF.cs b/src/WInterop.DirectX/Direct2d/LtrbRectangleF.cs
index 3bb2638d..8d65cd3b 100644
--- a/src/WInterop.DirectX/Direct2d/LtrbRectangleF.cs
+++ b/src/WInterop.DirectX/Direct2d/LtrbRectangleF.cs
@@ -9,10 +9,10 @@ namespace WInterop.Direct2d
// https://docs.microsoft.com/en-us/windows/desktop/api/dcommon/ns-dcommon-d2d_rect_f
public readonly struct LtrbRectangleF
{
- public readonly float Left;
- public readonly float Top;
- public readonly float Right;
- public readonly float Bottom;
+ public float Left { get; }
+ public float Top { get; }
+ public float Right { get; }
+ public float Bottom { get; }
public LtrbRectangleF(RectangleF rectangle)
{
@@ -33,13 +33,13 @@ public LtrbRectangleF(SizeF size)
public static implicit operator RectangleF(LtrbRectangleF rect)
=> RectangleF.FromLTRB(rect.Left, rect.Top, rect.Right, rect.Bottom);
- public static implicit operator LtrbRectangleF(RectangleF rectangle)
- => new LtrbRectangleF(rectangle);
+ public unsafe static implicit operator LtrbRectangleF((float Left, float Top, float Right, float Bottom) rectangle)
+ => *(LtrbRectangleF*)&rectangle;
- public static implicit operator LtrbRectangleF(Rectangle rectangle)
- => new LtrbRectangleF(rectangle);
+ public static implicit operator LtrbRectangleF(RectangleF rectangle) => new(rectangle);
- public static implicit operator LtrbRectangleF(SizeF size)
- => new LtrbRectangleF(size);
+ public static implicit operator LtrbRectangleF(Rectangle rectangle) => new(rectangle);
+
+ public static implicit operator LtrbRectangleF(SizeF size) => new(size);
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Native/Imports.cs b/src/WInterop.DirectX/Direct2d/Native/Imports.cs
deleted file mode 100644
index 6cadec9b..00000000
--- a/src/WInterop.DirectX/Direct2d/Native/Imports.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-using WInterop.Errors;
-
-namespace WInterop.Direct2d.Native
-{
- ///
- /// Direct usage of Imports isn't recommended. Use the wrappers that do the heavy lifting for you.
- ///
- public static partial class Imports
- {
- // https://docs.microsoft.com/en-us/windows/desktop/api/d2d1/nf-d2d1-d2d1createfactory
- [DllImport(Libraries.D2Dd1, ExactSpelling = true)]
- public static extern HResult D2D1CreateFactory(
- FactoryType factoryType,
- in Guid riid,
- in DebugLevel pFactoryOptions,
- out IFactory ppIFactory);
- }
-}
diff --git a/src/WInterop.DirectX/Direct2d/PathGeometry.cs b/src/WInterop.DirectX/Direct2d/PathGeometry.cs
new file mode 100644
index 00000000..bfdf6aa8
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/PathGeometry.cs
@@ -0,0 +1,69 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Represents a complex shape that may be composed of arcs, curves, and lines. [ID2D1PathGeometry]
+ ///
+ [Guid(InterfaceIds.IID_ID2D1PathGeometry)]
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly unsafe struct PathGeometry : PathGeometry.Interface, IDisposable
+ {
+ internal readonly ID2D1PathGeometry* _handle;
+
+ internal PathGeometry(ID2D1PathGeometry* handle) => _handle = handle;
+
+ public RectangleF GetBounds() => Geometry.From(this).GetBounds();
+
+ public RectangleF GetBounds(Matrix3x2 worldTransform)
+ => Geometry.From(this).GetBounds(worldTransform);
+
+ public void CombineWithGeometry(Geometry inputGeometry, CombineMode combineMode, SimplifiedGeometrySink geometrySink)
+ => Geometry.From(this).CombineWithGeometry(inputGeometry, combineMode, geometrySink);
+
+ public Factory GetFactory() => Geometry.From(this).GetFactory();
+
+ public uint GetFigureCount()
+ {
+ uint count;
+ _handle->GetFigureCount(&count).ThrowIfFailed();
+ return count;
+ }
+
+ public uint GetSegmentCount()
+ {
+ uint count;
+ _handle->GetSegmentCount(&count).ThrowIfFailed();
+ return count;
+ }
+
+ public GeometrySink Open()
+ {
+ GeometrySink sink;
+ _handle->Open((ID2D1GeometrySink**)&sink).ThrowIfFailed();
+ return sink;
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public static implicit operator Geometry(PathGeometry brush) => new((ID2D1Geometry*)brush._handle);
+
+ internal unsafe interface Interface : Geometry.Interface
+ {
+ ///
+ /// Opens a geometry sink that will be used to create this path geometry.
+ ///
+ GeometrySink Open();
+
+ uint GetSegmentCount();
+
+ uint GetFigureCount();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/PathSegment.cs b/src/WInterop.DirectX/Direct2d/PathSegment.cs
index 92ddc466..c8a1189f 100644
--- a/src/WInterop.DirectX/Direct2d/PathSegment.cs
+++ b/src/WInterop.DirectX/Direct2d/PathSegment.cs
@@ -15,16 +15,16 @@ public enum PathSegment : uint
///
/// [D2D1_PATH_SEGMENT_NONE]
///
- None = 0x00000000,
+ None = D2D1_PATH_SEGMENT.D2D1_PATH_SEGMENT_NONE,
///
/// [D2D1_PATH_SEGMENT_FORCE_UNSTROKED]
///
- ForceUnstroked = 0x00000001,
+ ForceUnstroked = D2D1_PATH_SEGMENT.D2D1_PATH_SEGMENT_FORCE_UNSTROKED,
///
/// [D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN]
///
- ForceRoundLineJoin = 0x00000002
+ ForceRoundLineJoin = D2D1_PATH_SEGMENT.D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN
}
}
diff --git a/src/WInterop.DirectX/Direct2d/PixelFormat.cs b/src/WInterop.DirectX/Direct2d/PixelFormat.cs
index c2bccae1..f61d3564 100644
--- a/src/WInterop.DirectX/Direct2d/PixelFormat.cs
+++ b/src/WInterop.DirectX/Direct2d/PixelFormat.cs
@@ -1,6 +1,8 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System.Runtime.CompilerServices;
+
namespace WInterop.Direct2d
{
///
@@ -11,10 +13,18 @@ public readonly struct PixelFormat
public readonly Dxgi.Format Format;
public readonly AlphaMode AlphaMode;
- public PixelFormat(Dxgi.Format format = Dxgi.Format.DXGI_FORMAT_UNKNOWN, AlphaMode alphaMode = AlphaMode.Unknown)
+ public PixelFormat(Dxgi.Format format = Dxgi.Format.Unknown, AlphaMode alphaMode = AlphaMode.Unknown)
{
Format = format;
AlphaMode = alphaMode;
}
+
+ internal PixelFormat(D2D1_PIXEL_FORMAT format)
+ {
+ Format = (Dxgi.Format)format.format;
+ AlphaMode = (AlphaMode)format.alphaMode;
+ }
+
+ internal D2D1_PIXEL_FORMAT ToD2D() => Unsafe.As(ref Unsafe.AsRef(this));
}
}
diff --git a/src/WInterop.DirectX/Direct2d/RadialGradientBrush.cs b/src/WInterop.DirectX/Direct2d/RadialGradientBrush.cs
new file mode 100644
index 00000000..02896771
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/RadialGradientBrush.cs
@@ -0,0 +1,98 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Paints an area with a radial gradient. [ID2D1RadialGradientBrush]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1RadialGradientBrush)]
+ public readonly unsafe struct RadialGradientBrush : RadialGradientBrush.Interface, IDisposable
+ {
+ private readonly ID2D1RadialGradientBrush* _handle;
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public float Opacity
+ {
+ get => Brush.From(this).Opacity;
+ set => Brush.From(this).Opacity = value;
+ }
+
+ public Matrix3x2 Transform
+ {
+ get => Brush.From(this).Transform;
+ set => Brush.From(this).Transform = value;
+ }
+
+ ///
+ public PointF Center
+ {
+ get => _handle->GetCenter().ToPointF();
+ set => _handle->SetCenter(value.ToD2D());
+ }
+
+ public PointF GradientOriginOffset
+ {
+ get => _handle->GetGradientOriginOffset().ToPointF();
+ set => _handle->SetGradientOriginOffset(value.ToD2D());
+ }
+
+ public float RadiusX
+ {
+ get => _handle->GetRadiusX();
+ set => _handle->SetRadiusX(value);
+ }
+
+ public float RadiusY
+ {
+ get => _handle->GetRadiusY();
+ set => _handle->SetRadiusY(value);
+ }
+
+ public PointF GetCenter() => _handle->GetCenter().ToPointF();
+
+ public PointF GetGradientOriginOffset() => _handle->GetGradientOriginOffset().ToPointF();
+
+ public GradientStopCollection GetGradientStopCollection()
+ {
+ ID2D1GradientStopCollection* collection;
+ _handle->GetGradientStopCollection(&collection);
+ return new(collection);
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public static implicit operator Brush(RadialGradientBrush brush) => new((ID2D1Brush*)brush._handle);
+
+ internal interface Interface : Brush.Interface
+ {
+ ///
+ /// The center of the radial gradient. This will be in local coordinates and
+ /// will not depend on the geometry being filled.
+ ///
+ PointF Center { get; set; }
+
+ ///
+ /// The offset of the origin relative to the radial gradient center.
+ ///
+ PointF GradientOriginOffset { get; set; }
+
+ float RadiusX { get; set; }
+
+ float RadiusY { get; set; }
+
+ PointF GetCenter();
+
+ PointF GetGradientOriginOffset();
+
+ GradientStopCollection GetGradientStopCollection();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/RadialGradientBrushProperties.cs b/src/WInterop.DirectX/Direct2d/RadialGradientBrushProperties.cs
index cf5538d7..50f64ff1 100644
--- a/src/WInterop.DirectX/Direct2d/RadialGradientBrushProperties.cs
+++ b/src/WInterop.DirectX/Direct2d/RadialGradientBrushProperties.cs
@@ -7,7 +7,7 @@ namespace WInterop.Direct2d
{
///
/// Contains the gradient origin offset and the size and position of the gradient
- /// ellipse for an . [D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES]
+ /// ellipse for an . [D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES]
///
public readonly struct RadialGradientBrushProperties
{
@@ -23,5 +23,13 @@ public RadialGradientBrushProperties(PointF center, PointF gradientOriginOffset,
RadiusX = radiusX;
RadiusY = radiusY;
}
+
+ public unsafe RadialGradientBrushProperties((float X, float Y) center, (float X, float Y) gradientOriginOffset, float radiusX, float radiusY)
+ {
+ Center = *(PointF*)¢er;
+ GradientOriginOffset = *(PointF*)&gradientOriginOffset;
+ RadiusX = radiusX;
+ RadiusY = radiusY;
+ }
}
}
diff --git a/src/WInterop.DirectX/Direct2d/RectangleGeometry.cs b/src/WInterop.DirectX/Direct2d/RectangleGeometry.cs
new file mode 100644
index 00000000..4fd6f499
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/RectangleGeometry.cs
@@ -0,0 +1,45 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1RectangleGeometry)]
+ public readonly unsafe struct RectangleGeometry : RectangleGeometry.Interface, IDisposable
+ {
+ internal readonly ID2D1RectangleGeometry* _handle;
+
+ internal RectangleGeometry(ID2D1RectangleGeometry* handle) => _handle = handle;
+
+ public RectangleF GetBounds() => Geometry.From(this).GetBounds();
+
+ public RectangleF GetBounds(Matrix3x2 worldTransform)
+ => Geometry.From(this).GetBounds(worldTransform);
+
+ public void CombineWithGeometry(Geometry inputGeometry, CombineMode combineMode, SimplifiedGeometrySink geometrySink)
+ => Geometry.From(this).CombineWithGeometry(inputGeometry, combineMode, geometrySink);
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public RectangleF GetRect()
+ {
+ D2D_RECT_F rect;
+ _handle->GetRect(&rect);
+ return rect.ToRectangleF();
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public static implicit operator Geometry(RectangleGeometry brush) => new((ID2D1Geometry*)brush._handle);
+
+ internal unsafe interface Interface : Geometry.Interface
+ {
+ RectangleF GetRect();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/RenderTarget.cs b/src/WInterop.DirectX/Direct2d/RenderTarget.cs
new file mode 100644
index 00000000..2350d0e5
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/RenderTarget.cs
@@ -0,0 +1,295 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using WInterop.DirectWrite;
+using WInterop.Errors;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Represents an object that can receive drawing commands. Interfaces that inherit
+ /// from this render the drawing commands they receive in different
+ /// ways. [ID2D1RenderTarget]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1RenderTarget)]
+ internal unsafe class RenderTarget : IRenderTarget, IResource
+ {
+ private readonly ID2D1RenderTarget* _handle;
+
+ ID2D1RenderTarget* IHandle.Handle => _handle;
+
+ public Factory GetFactory() => this.GetFactory();
+
+ internal RenderTarget(ID2D1RenderTarget* handle) => _handle = handle;
+
+ public Matrix3x2 Transform
+ {
+ get
+ {
+ Matrix3x2 transform;
+ _handle->GetTransform((D2D_MATRIX_3X2_F*)&transform);
+ return transform;
+ }
+ set => _handle->SetTransform((D2D_MATRIX_3X2_F*)&value);
+ }
+
+ public AntialiasMode AntialiasMode
+ {
+ get => (AntialiasMode)_handle->GetAntialiasMode();
+ set => _handle->SetAntialiasMode((D2D1_ANTIALIAS_MODE)value);
+ }
+
+ public TextAntialiasMode TextAntialiasMode
+ {
+ get => (TextAntialiasMode)_handle->GetTextAntialiasMode();
+ set => _handle->SetTextAntialiasMode((D2D1_TEXT_ANTIALIAS_MODE)value);
+ }
+
+ public PointF Dpi
+ {
+ get
+ {
+ float x;
+ float y;
+ _handle->GetDpi(&x, &y);
+ return new(x, y);
+ }
+ set => _handle->SetDpi(value.X, value.Y);
+ }
+
+ public void BeginDraw() => _handle->BeginDraw();
+
+ public SolidColorBrush CreateSolidColorBrush(ColorF color)
+ {
+ SolidColorBrush brush;
+ _handle->CreateSolidColorBrush(
+ (DXGI_RGBA*)&color,
+ (ID2D1SolidColorBrush**)&brush).ThrowIfFailed();
+
+ return brush;
+ }
+
+ public BitmapBrush CreateBitmapBrush(
+ Bitmap bitmap,
+ BitmapBrushProperties bitmapBrushProperties,
+ BrushProperties brushProperties)
+ {
+ ID2D1BitmapBrush* brush;
+ _handle->CreateBitmapBrush(
+ bitmap._handle,
+ (D2D1_BITMAP_BRUSH_PROPERTIES*)&bitmapBrushProperties,
+ (D2D1_BRUSH_PROPERTIES*)&brushProperties,
+ &brush).ThrowIfFailed();
+
+ return new(brush);
+ }
+
+ public SolidColorBrush CreateSolidColorBrush(ColorF color, BrushProperties brushProperties)
+ {
+ SolidColorBrush brush;
+ _handle->CreateSolidColorBrush(
+ (DXGI_RGBA*)&color,
+ (D2D1_BRUSH_PROPERTIES*)&brushProperties,
+ (ID2D1SolidColorBrush**)&brush).ThrowIfFailed();
+
+ return brush;
+ }
+
+ public GradientStopCollection CreateGradientStopCollection(
+ ReadOnlySpan gradientStops,
+ Gamma colorInterpolationGamma,
+ ExtendMode extendMode)
+ {
+ fixed (GradientStop* g = gradientStops)
+ {
+ GradientStopCollection collection;
+ _handle->CreateGradientStopCollection(
+ (D2D1_GRADIENT_STOP*)g,
+ (uint)gradientStops.Length,
+ (D2D1_GAMMA)colorInterpolationGamma,
+ (D2D1_EXTEND_MODE)extendMode,
+ (ID2D1GradientStopCollection**)&collection).ThrowIfFailed();
+ return collection;
+ }
+ }
+
+ public RadialGradientBrush CreateRadialGradientBrush(
+ RadialGradientBrushProperties radialGradientBrushProperties,
+ BrushProperties brushProperties,
+ GradientStopCollection gradientStopCollection)
+ {
+ RadialGradientBrush brush;
+ _handle->CreateRadialGradientBrush(
+ (D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES*)&radialGradientBrushProperties,
+ (D2D1_BRUSH_PROPERTIES*)&brushProperties,
+ gradientStopCollection._handle,
+ (ID2D1RadialGradientBrush**)&brush).ThrowIfFailed();
+
+ return brush;
+ }
+
+ public IBitmapRenderTarget CreateCompatibleRenderTarget(
+ SizeF? desiredSize = default,
+ SizeU? desiredPixelSize = default,
+ PixelFormat? desiredFormat = default,
+ CompatibleRenderTargetOptions options = CompatibleRenderTargetOptions.None)
+ {
+ ID2D1BitmapRenderTarget* target;
+ var specifiedSize = desiredSize.GetValueOrDefault();
+ var specifiedPixelSize = desiredPixelSize.GetValueOrDefault();
+ var specifiedFormat = desiredFormat.GetValueOrDefault();
+ _handle->CreateCompatibleRenderTarget(specifiedSize.ToD2D(), specifiedPixelSize.ToD2D(), specifiedFormat.ToD2D(), &target);
+ return new BitmapRenderTarget(target);
+ }
+
+ public void DrawLine(PointF point0, PointF point1, Brush brush, float strokeWidth = 1, StrokeStyle strokeStyle = default)
+ {
+ _handle->DrawLine(
+ point0.ToD2D(),
+ point1.ToD2D(),
+ brush.Handle,
+ strokeWidth,
+ strokeStyle._handle);
+ }
+
+ public void DrawRectangle(LtrbRectangleF rectangle, Brush brush, float strokeWidth = 1, StrokeStyle strokeStyle = default)
+ {
+ _handle->DrawRectangle(
+ (D2D_RECT_F*)&rectangle,
+ brush.Handle,
+ strokeWidth,
+ strokeStyle._handle);
+ }
+
+ public void FillRectangle(LtrbRectangleF rectangle, Brush brush)
+ {
+ _handle->FillRectangle(
+ (D2D_RECT_F*)&rectangle,
+ brush.Handle);
+ }
+
+ public void DrawRoundedRectangle(
+ RoundedRectangle roundedRectangle,
+ Brush brush,
+ float strokeWidth = 1,
+ StrokeStyle strokeStyle = default)
+ {
+ _handle->DrawRoundedRectangle(
+ (D2D1_ROUNDED_RECT*)&roundedRectangle,
+ brush.Handle,
+ strokeWidth,
+ strokeStyle._handle);
+ }
+
+ public void FillRoundedRectangle(RoundedRectangle roundedRectangle, Brush brush)
+ {
+ _handle->FillRoundedRectangle(
+ (D2D1_ROUNDED_RECT*)&roundedRectangle,
+ brush.Handle);
+ }
+
+ public void DrawEllipse(Ellipse ellipse, Brush brush, float strokeWidth = 1, StrokeStyle strokeStyle = default)
+ {
+ _handle->DrawEllipse(
+ (D2D1_ELLIPSE*)&ellipse,
+ brush.Handle,
+ strokeWidth,
+ strokeStyle._handle);
+ }
+
+ public void FillEllipse(Ellipse ellipse, Brush brush)
+ {
+ _handle->FillEllipse(
+ (D2D1_ELLIPSE*)&ellipse,
+ brush.Handle);
+ }
+
+ public void DrawGeometry(Geometry geometry, Brush brush, float strokeWidth = 1, StrokeStyle strokeStyle = default)
+ {
+ _handle->DrawGeometry(
+ geometry._handle,
+ brush.Handle,
+ strokeWidth,
+ strokeStyle._handle);
+ }
+
+ public void FillGeometry(Geometry geometry, Brush brush, Brush opacityBrush = default)
+ {
+ _handle->FillGeometry(
+ geometry._handle,
+ brush.Handle,
+ opacityBrush.Handle);
+ }
+
+ public Tags Tags
+ {
+ get
+ {
+ Tags tags;
+ _handle->GetTags(&tags.One, &tags.Two);
+ return tags;
+ }
+ set => _handle->SetTags(value.One, value.Two);
+ }
+
+ public void PopLayer() => _handle->PopLayer();
+
+ public Tags Flush()
+ {
+ Tags tags;
+ _handle->Flush(&tags.One, &tags.Two);
+ return tags;
+ }
+
+ public void PushAxisAlignedClip(LtrbRectangleF clipRect, AntialiasMode antialiasMode)
+ {
+ _handle->PushAxisAlignedClip((D2D_RECT_F*)&clipRect, (D2D1_ANTIALIAS_MODE)antialiasMode);
+ }
+
+ public void PopAxisAlignedClip() => _handle->PopAxisAlignedClip();
+
+ public void Clear() => _handle->Clear();
+
+ public void Clear(ColorF clearColor) => _handle->Clear((DXGI_RGBA*)&clearColor);
+
+ public Tags EndDraw(out bool recreateTarget)
+ {
+ Tags tags;
+ HResult result = _handle->EndDraw(&tags.One, &tags.Two).ToHResult();
+ recreateTarget = result == HResult.D2DERR_RECREATE_TARGET;
+ result.ThrowIfFailed();
+ return tags;
+ }
+
+ public PixelFormat PixelFormat => new(_handle->GetPixelFormat());
+
+ public SizeF Size => _handle->GetSize().ToSizeF();
+
+ public SizeU PixelSize => new(_handle->GetPixelSize());
+
+ public uint MaximumBitmapSize => _handle->GetMaximumBitmapSize();
+
+ public bool IsSupported(RenderTargetProperties renderTargetProperties)
+ => _handle->IsSupported((D2D1_RENDER_TARGET_PROPERTIES*)&renderTargetProperties);
+
+ public void Dispose() => _handle->Release();
+
+ public void DrawTextLayout(
+ PointF origin,
+ TextLayout textLayout,
+ Brush defaultFillBrush,
+ DrawTextOptions options = DrawTextOptions.None)
+ {
+ _handle->DrawTextLayout(
+ origin.ToD2D(),
+ textLayout.Handle,
+ defaultFillBrush.Handle,
+ (D2D1_DRAW_TEXT_OPTIONS)options);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/RenderTargetExtensions.cs b/src/WInterop.DirectX/Direct2d/RenderTargetExtensions.cs
new file mode 100644
index 00000000..9adf5946
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/RenderTargetExtensions.cs
@@ -0,0 +1,59 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Drawing;
+
+namespace WInterop.Direct2d
+{
+ public static class RenderTargetExtensions
+ {
+ public static SolidColorBrush CreateSolidColorBrush(
+ this IRenderTarget renderTarget,
+ float r,
+ float g,
+ float b,
+ float a = 1.0f)
+ => renderTarget.CreateSolidColorBrush(new(r, g, b, a));
+
+ public static IBitmapRenderTarget CreateCompatibleRenderTarget(
+ this IRenderTarget renderTarget,
+ (float X, float Y) desiredSize)
+ => renderTarget.CreateCompatibleRenderTarget(new(desiredSize.X, desiredSize.Y));
+
+ public static BitmapBrush CreateBitmapBrush(
+ this IRenderTarget renderTarget,
+ Bitmap bitmap,
+ BitmapBrushProperties bitmapBrushProperties)
+ => renderTarget.CreateBitmapBrush(bitmap, bitmapBrushProperties, BrushProperties.Default);
+
+ public static RadialGradientBrush CreateRadialGradientBrush(
+ this IRenderTarget renderTarget,
+ RadialGradientBrushProperties radialGradientBrushProperties,
+ GradientStopCollection gradientStopCollection)
+ => renderTarget.CreateRadialGradientBrush(radialGradientBrushProperties, BrushProperties.Default, gradientStopCollection);
+
+ public static Tags EndDraw(
+ this IRenderTarget renderTarget)
+ => renderTarget.EndDraw(out _);
+
+ public unsafe static void DrawLine(
+ this IRenderTarget renderTarget,
+ (float X, float Y) point0,
+ (float X, float Y) point1,
+ Brush brush,
+ float strokeWidth = 1.0f,
+ StrokeStyle strokeStyle = default)
+ => renderTarget.DrawLine(
+ *(PointF*)&point0,
+ *(PointF*)&point1,
+ brush,
+ strokeWidth,
+ strokeStyle);
+
+ //public static void FillRectangle(
+ // this IRenderTarget renderTarget,
+ // (float Left, float Top, float Right, float Bottom) rectangle,
+ // Brush brush)
+ // => renderTarget.FillRectangle(LtrbRectangleF.)
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/RenderTargetProperties.cs b/src/WInterop.DirectX/Direct2d/RenderTargetProperties.cs
index 7ff41fb4..88fded4b 100644
--- a/src/WInterop.DirectX/Direct2d/RenderTargetProperties.cs
+++ b/src/WInterop.DirectX/Direct2d/RenderTargetProperties.cs
@@ -1,6 +1,8 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System.Runtime.CompilerServices;
+
namespace WInterop.Direct2d
{
///
@@ -16,5 +18,11 @@ public readonly struct RenderTargetProperties
public readonly float DpiY;
public readonly RenderTargetUsage Usage;
public readonly FeatureLevel MinLevel;
+
+ public static implicit operator RenderTargetProperties(in D2D1_RENDER_TARGET_PROPERTIES properties)
+ => Unsafe.As(ref Unsafe.AsRef(properties));
+
+ public static implicit operator D2D1_RENDER_TARGET_PROPERTIES(in RenderTargetProperties properties)
+ => Unsafe.As(ref Unsafe.AsRef(properties));
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Resource.cs b/src/WInterop.DirectX/Direct2d/Resource.cs
new file mode 100644
index 00000000..60a7ed37
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/Resource.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ public interface IResource
+ {
+ Factory GetFactory();
+ }
+
+ internal interface IResource : IHandle where T : unmanaged
+ {
+ }
+
+ internal unsafe static class ResourceExtensions
+ {
+ public static Factory GetFactory(this T resource) where T : IResource where H : unmanaged
+ {
+ ID2D1Factory* factory;
+ ((ID2D1Resource*)resource.Handle)->GetFactory(&factory);
+ return new(factory);
+ }
+ }
+
+ [Guid(InterfaceIds.IID_ID2D1Resource)]
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly unsafe struct Resource : Resource.Interface
+ {
+ private readonly ID2D1Resource* _resource;
+
+ public Factory GetFactory()
+ {
+ ID2D1Factory* factory;
+ _resource->GetFactory(&factory);
+ return new(factory);
+ }
+
+ internal static Factory GetFactory(ID2D1Resource* resource)
+ {
+ ID2D1Factory* factory;
+ resource->GetFactory(&factory);
+ return new(factory);
+ }
+
+ internal static ref Brush From(in TFrom from)
+ where TFrom : unmanaged, Interface
+ => ref Unsafe.AsRef(Unsafe.AsPointer(ref Unsafe.AsRef(from)));
+
+ public void Dispose() => _resource->Release();
+
+ ///
+ /// [ID2D1Resource]
+ ///
+ internal interface Interface : IDisposable
+ {
+ Factory GetFactory();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/RoundedRectangle.cs b/src/WInterop.DirectX/Direct2d/RoundedRectangle.cs
index 4777374c..df36e246 100644
--- a/src/WInterop.DirectX/Direct2d/RoundedRectangle.cs
+++ b/src/WInterop.DirectX/Direct2d/RoundedRectangle.cs
@@ -2,25 +2,27 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Drawing;
+using System.Runtime.InteropServices;
namespace WInterop.Direct2d
{
///
/// [D2D1_ROUNDED_RECT]
///
+ [StructLayout(LayoutKind.Sequential)]
public readonly struct RoundedRectangle
{
- private readonly LtrbRectangleF rect;
+ private readonly LtrbRectangleF _rect;
public readonly float RadiusX;
public readonly float RadiusY;
public RoundedRectangle(RectangleF rectangle, float radiusX, float radiusY)
{
- rect = new LtrbRectangleF(rectangle);
+ _rect = new LtrbRectangleF(rectangle);
RadiusX = radiusX;
RadiusY = radiusY;
}
- public RectangleF Rectangle => rect;
+ public RectangleF Rectangle => _rect;
}
}
diff --git a/src/WInterop.DirectX/Direct2d/RoundedRectangleGeometry.cs b/src/WInterop.DirectX/Direct2d/RoundedRectangleGeometry.cs
new file mode 100644
index 00000000..fed8ed8a
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/RoundedRectangleGeometry.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// [ID2D1RoundedRectangleGeometry]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1RoundedRectangleGeometry)]
+ public unsafe struct RoundedRectangleGeometry : RoundedRectangleGeometry.Interface
+ {
+ private readonly ID2D1RoundedRectangleGeometry* _handle;
+
+ internal RoundedRectangleGeometry(ID2D1RoundedRectangleGeometry* handle) => _handle = handle;
+
+ public RectangleF GetBounds() => Geometry.From(this).GetBounds();
+
+ public RectangleF GetBounds(Matrix3x2 worldTransform)
+ => Geometry.From(this).GetBounds(worldTransform);
+
+ public void CombineWithGeometry(Geometry inputGeometry, CombineMode combineMode, SimplifiedGeometrySink geometrySink)
+ => Geometry.From(this).CombineWithGeometry(inputGeometry, combineMode, geometrySink);
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public RoundedRectangle GetRoundedRect(RoundedRectangle roundedRect)
+ {
+ RoundedRectangle rect;
+ _handle->GetRoundedRect((D2D1_ROUNDED_RECT*) &rect);
+ return rect;
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public static implicit operator Geometry(RoundedRectangleGeometry geometry) => new((ID2D1Geometry*)geometry._handle);
+
+ internal interface Interface : Geometry.Interface
+ {
+ RoundedRectangle GetRoundedRect(RoundedRectangle roundedRect);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/SimplifiedGeometrySink.cs b/src/WInterop.DirectX/Direct2d/SimplifiedGeometrySink.cs
new file mode 100644
index 00000000..c628966a
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/SimplifiedGeometrySink.cs
@@ -0,0 +1,82 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Describes a geometric path that does not contain quadratic bezier curves or arcs.
+ /// [ID2D1SimplifiedGeometrySink]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1SimplifiedGeometrySink)]
+ public unsafe struct SimplifiedGeometrySink : SimplifiedGeometrySink.Interface, IDisposable
+ {
+ internal ID2D1SimplifiedGeometrySink* Handle { get; }
+
+ internal SimplifiedGeometrySink(ID2D1SimplifiedGeometrySink* handle) => Handle = handle;
+
+ public void AddBeziers(ReadOnlySpan beziers)
+ {
+ fixed(BezierSegment* b = beziers)
+ {
+ Handle->AddBeziers((D2D1_BEZIER_SEGMENT*)b, (uint)beziers.Length);
+ }
+ }
+
+ public void AddLines(ReadOnlySpan points)
+ {
+ fixed(PointF* p = points)
+ {
+ Handle->AddLines((D2D_POINT_2F*)p, (uint)points.Length);
+ }
+ }
+
+ public void BeginFigure(PointF startPoint, FigureBegin figureBegin)
+ => Handle->BeginFigure(startPoint.ToD2D(), (D2D1_FIGURE_BEGIN)figureBegin);
+
+ public void BeginFigure((float X, float Y) startPoint, FigureBegin figureBegin)
+ => Handle->BeginFigure(new D2D_POINT_2F(startPoint.X, startPoint.Y), (D2D1_FIGURE_BEGIN)figureBegin);
+
+ public void Close() => Handle->Close().ThrowIfFailed();
+
+ public void EndFigure(FigureEnd figureEnd) => Handle->EndFigure((D2D1_FIGURE_END)figureEnd);
+
+ public void SetFillMode(FillMode fillMode) => Handle->SetFillMode((D2D1_FILL_MODE)fillMode);
+
+ public void SetSegmentFlags(PathSegment vertexFlags) => Handle->SetSegmentFlags((D2D1_PATH_SEGMENT)vertexFlags);
+
+ internal static ref SimplifiedGeometrySink From(in TFrom from)
+ where TFrom : unmanaged, Interface
+ => ref Unsafe.AsRef(Unsafe.AsPointer(ref Unsafe.AsRef(from)));
+
+ public void Dispose()
+ {
+ Handle->Close();
+ Handle->Release();
+ }
+
+ internal interface Interface : IDisposable
+ {
+ void SetFillMode(FillMode fillMode);
+
+ void SetSegmentFlags(PathSegment vertexFlags);
+
+ void BeginFigure(
+ PointF startPoint,
+ FigureBegin figureBegin);
+
+ void AddLines(ReadOnlySpan points);
+
+ void AddBeziers(ReadOnlySpan beziers);
+
+ void EndFigure(FigureEnd figureEnd);
+
+ void Close();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/SizeU.cs b/src/WInterop.DirectX/Direct2d/SizeU.cs
index 9a3cb91f..4657cf30 100644
--- a/src/WInterop.DirectX/Direct2d/SizeU.cs
+++ b/src/WInterop.DirectX/Direct2d/SizeU.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Drawing;
+using System.Runtime.CompilerServices;
namespace WInterop.Direct2d
{
@@ -19,7 +20,15 @@ public SizeU(uint width, uint height)
Height = height;
}
- public static implicit operator Size(SizeU size) => new Size((int)size.Width, (int)size.Height);
- public static implicit operator SizeU(Size size) => new SizeU((uint)size.Width, (uint)size.Height);
+ internal SizeU(D2D_SIZE_U size)
+ {
+ Width = size.width;
+ Height = size.height;
+ }
+
+ public static implicit operator Size(SizeU size) => checked(new((int)size.Width, (int)size.Height));
+ public static implicit operator SizeU(Size size) => checked(new((uint)size.Width, (uint)size.Height));
+
+ internal D2D_SIZE_U ToD2D() => Unsafe.As(ref Unsafe.AsRef(this));
}
}
diff --git a/src/WInterop.DirectX/Direct2d/SolidColorBrush.cs b/src/WInterop.DirectX/Direct2d/SolidColorBrush.cs
new file mode 100644
index 00000000..a756a3ed
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/SolidColorBrush.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Paints an area with a solid color. [ID2D1SolidColorBrush]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1SolidColorBrush)]
+ public readonly unsafe struct SolidColorBrush : SolidColorBrush.Interface, IDisposable
+ {
+ private readonly ID2D1SolidColorBrush* _handle;
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public float Opacity
+ {
+ get => Brush.From(this).Opacity;
+ set => Brush.From(this).Opacity = value;
+ }
+
+ public Matrix3x2 Transform
+ {
+ get => Brush.From(this).Transform;
+ set => Brush.From(this).Transform = value;
+ }
+
+ public ColorF Color
+ {
+ get => _handle->GetColor();
+ set => _handle->SetColor((DXGI_RGBA*)&value);
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public static implicit operator Brush(SolidColorBrush brush) => new((ID2D1Brush*)brush._handle);
+
+ internal interface Interface : Brush.Interface
+ {
+ ColorF Color { get; set; }
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/StrokeStyle.cs b/src/WInterop.DirectX/Direct2d/StrokeStyle.cs
new file mode 100644
index 00000000..dd1853c7
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/StrokeStyle.cs
@@ -0,0 +1,70 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ [StructLayout(LayoutKind.Sequential)]
+ [Guid(InterfaceIds.IID_ID2D1StrokeStyle)]
+ public readonly unsafe struct StrokeStyle : StrokeStyle.Interface, IDisposable
+ {
+ internal readonly ID2D1StrokeStyle* _handle;
+
+ internal StrokeStyle(ID2D1StrokeStyle* handle) => _handle = handle;
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public CapStyle StartCap => (CapStyle)_handle->GetStartCap();
+
+ public CapStyle EndCap => (CapStyle)_handle->GetEndCap();
+
+ public CapStyle DashCap => (CapStyle)_handle->GetDashCap();
+
+ public float MiterLimit => _handle->GetMiterLimit();
+
+ public LineJoin LineJoin => (LineJoin)_handle->GetLineJoin();
+
+ public float DashOffset => _handle->GetDashOffset();
+
+ public DashStyle DashStyle => (DashStyle)_handle->GetDashStyle();
+
+ public uint DashesCount => _handle->GetDashesCount();
+
+ public void GetDashes(Span dashes)
+ {
+ fixed (float* f = dashes)
+ {
+ _handle->GetDashes(f, (uint)dashes.Length);
+ }
+ }
+
+ public void Dispose() => _handle->Release();
+
+ internal interface Interface : Resource.Interface
+ {
+ CapStyle StartCap { get; }
+
+ CapStyle EndCap { get; }
+
+ CapStyle DashCap { get; }
+
+ float MiterLimit { get; }
+
+ LineJoin LineJoin { get; }
+
+ float DashOffset { get; }
+
+ DashStyle DashStyle { get; }
+
+ uint DashesCount { get; }
+
+ ///
+ /// Returns the dashes from the object into a user allocated array.
+ /// Call to retrieve the required size.
+ ///
+ void GetDashes(Span dashes);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/SweepDirection.cs b/src/WInterop.DirectX/Direct2d/SweepDirection.cs
index 5c44c8b9..cb65f5f6 100644
--- a/src/WInterop.DirectX/Direct2d/SweepDirection.cs
+++ b/src/WInterop.DirectX/Direct2d/SweepDirection.cs
@@ -11,11 +11,11 @@ public enum SweepDirection : uint
///
/// [D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE]
///
- CounterClockwise = 0,
+ CounterClockwise = D2D1_SWEEP_DIRECTION.D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
///
/// [D2D1_SWEEP_DIRECTION_CLOCKWISE]
///
- Clockwise = 1
+ Clockwise = D2D1_SWEEP_DIRECTION.D2D1_SWEEP_DIRECTION_CLOCKWISE
}
}
diff --git a/src/WInterop.DirectX/Direct2d/Tags.cs b/src/WInterop.DirectX/Direct2d/Tags.cs
new file mode 100644
index 00000000..9746d0d7
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/Tags.cs
@@ -0,0 +1,11 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace WInterop.Direct2d
+{
+ public struct Tags
+ {
+ public ulong One;
+ public ulong Two;
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/TransformedGeometry.cs b/src/WInterop.DirectX/Direct2d/TransformedGeometry.cs
new file mode 100644
index 00000000..65cf3207
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/TransformedGeometry.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Represents a geometry that has been transformed. [ID2D1TransformedGeometry]
+ ///
+ [Guid(InterfaceIds.IID_ID2D1TransformedGeometry)]
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly unsafe struct TransformedGeometry : TransformedGeometry.Interface, IDisposable
+ {
+ internal readonly ID2D1TransformedGeometry* _handle;
+
+ internal TransformedGeometry(ID2D1TransformedGeometry* handle) => _handle = handle;
+
+ public RectangleF GetBounds() => Geometry.From(this).GetBounds();
+
+ public RectangleF GetBounds(Matrix3x2 worldTransform)
+ => Geometry.From(this).GetBounds(worldTransform);
+
+ public void CombineWithGeometry(Geometry inputGeometry, CombineMode combineMode, SimplifiedGeometrySink geometrySink)
+ => Geometry.From(this).CombineWithGeometry(inputGeometry, combineMode, geometrySink);
+
+ public Factory GetFactory() => Resource.From(this).GetFactory();
+
+ public Geometry SourceGeometry
+ {
+ get
+ {
+ Geometry geometry;
+ _handle->GetSourceGeometry((ID2D1Geometry**)&geometry);
+ return geometry;
+ }
+ }
+
+ public Matrix3x2 Transform
+ {
+ get
+ {
+ Matrix3x2 transform;
+ _handle->GetTransform((D2D_MATRIX_3X2_F*)&transform);
+ return transform;
+ }
+ }
+
+ public static implicit operator Geometry(TransformedGeometry geometry) => new((ID2D1Geometry*)geometry._handle);
+
+ public void Dispose() => _handle->Release();
+
+ internal interface Interface : Geometry.Interface
+ {
+ Geometry SourceGeometry { get; }
+
+ Matrix3x2 Transform { get; }
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/WindowRenderTarget.cs b/src/WInterop.DirectX/Direct2d/WindowRenderTarget.cs
new file mode 100644
index 00000000..9587ce5d
--- /dev/null
+++ b/src/WInterop.DirectX/Direct2d/WindowRenderTarget.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Runtime.InteropServices;
+
+namespace WInterop.Direct2d
+{
+ ///
+ /// Renders drawing instructions to a window. [ID2D1HwndRenderTarget]
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe class WindowRenderTarget : RenderTarget, IWindowRenderTarget
+ {
+ private readonly ID2D1HwndRenderTarget* _handle;
+
+ internal WindowRenderTarget(ID2D1HwndRenderTarget* handle)
+ : base ((ID2D1RenderTarget*)handle)
+ => _handle = handle;
+
+ public WindowState CheckWindowState() => (WindowState)_handle->CheckWindowState();
+
+ public void Resize(SizeU pixelSize) => _handle->Resize((D2D_SIZE_U*)&pixelSize).ThrowIfFailed();
+
+ public Windows.Native.HWND GetHwnd() => new(_handle->GetHwnd());
+ }
+}
diff --git a/src/WInterop.DirectX/Direct2d/WindowRenderTargetProperties.cs b/src/WInterop.DirectX/Direct2d/WindowRenderTargetProperties.cs
index 885ffcb1..5640a5ab 100644
--- a/src/WInterop.DirectX/Direct2d/WindowRenderTargetProperties.cs
+++ b/src/WInterop.DirectX/Direct2d/WindowRenderTargetProperties.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Drawing;
+using System.Runtime.InteropServices;
using WInterop.Windows;
using WInterop.Windows.Native;
@@ -11,6 +12,7 @@ namespace WInterop.Direct2d
/// Contains the HWND, pixel size, and presentation options for an ID2D1HwndRenderTarget.
/// [D2D1_HWND_RENDER_TARGET_PROPERTIES]
///
+ [StructLayout(LayoutKind.Sequential)]
public readonly struct WindowRenderTargetProperties
{
private readonly HWND _hwnd;
diff --git a/src/WInterop.DirectX/DirectWrite/DirectWrite.cs b/src/WInterop.DirectX/DirectWrite/DirectWrite.cs
index 30873e41..9d27a1fc 100644
--- a/src/WInterop.DirectX/DirectWrite/DirectWrite.cs
+++ b/src/WInterop.DirectX/DirectWrite/DirectWrite.cs
@@ -9,10 +9,10 @@ namespace WInterop.DirectWrite
{
public static class DirectWrite
{
- public static IFactory CreateFactory(FactoryType factoryType = FactoryType.Shared)
+ public static WriteFactory CreateFactory(FactoryType factoryType = FactoryType.Shared)
{
Imports.DWriteCreateFactory(
- factoryType, new Guid(InterfaceIds.IID_IDWriteFactory), out IFactory factory)
+ factoryType, new Guid(InterfaceIds.IID_IDWriteFactory), out WriteFactory factory)
.ThrowIfFailed();
return factory;
diff --git a/src/WInterop.DirectX/DirectWrite/FlowDirection.cs b/src/WInterop.DirectX/DirectWrite/FlowDirection.cs
index 0c9b3e41..b6643ac7 100644
--- a/src/WInterop.DirectX/DirectWrite/FlowDirection.cs
+++ b/src/WInterop.DirectX/DirectWrite/FlowDirection.cs
@@ -11,21 +11,21 @@ public enum FlowDirection : uint
///
/// Text lines are placed from top to bottom.
///
- TopToBottom = 0,
+ TopToBottom = DWRITE_FLOW_DIRECTION.DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM,
///
/// Text lines are placed from bottom to top.
///
- BottomToTop = 1,
+ BottomToTop = DWRITE_FLOW_DIRECTION.DWRITE_FLOW_DIRECTION_BOTTOM_TO_TOP,
///
/// Text lines are placed from left to right.
///
- LeftToRight = 2,
+ LeftToRight = DWRITE_FLOW_DIRECTION.DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT,
///
/// Text lines are placed from right to left.
///
- RightToLeft = 3,
+ RightToLeft = DWRITE_FLOW_DIRECTION.DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT,
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/Font.cs b/src/WInterop.DirectX/DirectWrite/Font.cs
new file mode 100644
index 00000000..e72540ab
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/Font.cs
@@ -0,0 +1,151 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.InteropServices;
+using WInterop.Direct2d;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The interface represents a physical font in a font collection.
+ /// [IDWriteFont]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteFont)]
+ public readonly unsafe struct Font : Font.Interface, IDisposable
+ {
+ private readonly IDWriteFont* _handle;
+
+ internal Font(IDWriteFont* handle) => _handle = handle;
+
+ public FontWeight Weight => (FontWeight)_handle->GetWeight();
+
+ public FontStretch Stretch => (FontStretch)_handle->GetStretch();
+
+ public FontStyle Style => (FontStyle)_handle->GetStyle();
+
+ public bool IsSymbolFont => _handle->IsSymbolFont();
+
+ public FontSimulations Simulations => (FontSimulations)_handle->GetSimulations();
+
+ public FontMetrics Metrics
+ {
+ get
+ {
+ FontMetrics* metrics;
+ _handle->GetMetrics((DWRITE_FONT_METRICS*)&metrics);
+ return Metrics;
+ }
+ }
+
+ public FontFace CreateFontFace()
+ {
+ IDWriteFontFace* fontFace;
+ _handle->CreateFontFace(&fontFace).ThrowIfFailed();
+ return new(fontFace);
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public LocalizedStrings GetFaceNames()
+ {
+ IDWriteLocalizedStrings* strings;
+ _handle->GetFaceNames(&strings).ThrowIfFailed();
+ return new(strings);
+ }
+
+ public FontFamily GetFontFamily()
+ {
+ IDWriteFontFamily* family;
+ _handle->GetFontFamily(&family).ThrowIfFailed();
+ return new(family);
+ }
+
+ public bool GetInformationalStrings(InformationalStringId informationalStringID, out LocalizedStrings informationalStrings)
+ {
+ IDWriteLocalizedStrings* strings;
+ TerraFX.Interop.Windows.BOOL exists;
+ _handle->GetInformationalStrings((DWRITE_INFORMATIONAL_STRING_ID)informationalStringID, &strings, &exists).ThrowIfFailed();
+ informationalStrings = new(strings);
+ return exists;
+ }
+
+ public bool HasCharacter(uint unicodeValue)
+ {
+ TerraFX.Interop.Windows.BOOL exists;
+ _handle->HasCharacter(unicodeValue, &exists).ThrowIfFailed();
+ return exists;
+ }
+
+ internal interface Interface
+ {
+ ///
+ /// Gets the font family to which the specified font belongs.
+ ///
+ FontFamily GetFontFamily();
+
+ ///
+ /// Gets the weight of the specified font.
+ ///
+ FontWeight Weight { get; }
+
+ ///
+ /// Gets the stretch (aka. width) of the specified font.
+ ///
+ FontStretch Stretch { get; }
+
+ ///
+ /// Gets the style (aka. slope) of the specified font.
+ ///
+ FontStyle Style { get; }
+
+ ///
+ /// Returns TRUE if the font is a symbol font or FALSE if not.
+ ///
+ bool IsSymbolFont { get; }
+
+ ///
+ /// Gets a localized strings collection containing the face names for the font (e.g., Regular or Bold), indexed by locale name.
+ ///
+ ///
+ /// A pointer to the newly created localized strings object.
+ ///
+ LocalizedStrings GetFaceNames();
+
+ ///
+ /// Gets a localized strings collection containing the specified informational strings, indexed by locale name.
+ ///
+ /// Identifies the string to get.
+ /// Receives a pointer to the newly created localized strings object.
+ bool GetInformationalStrings(
+ InformationalStringId informationalStringID,
+ out LocalizedStrings informationalStrings);
+
+ ///
+ /// Gets a value that indicates what simulation are applied to the specified font.
+ ///
+ FontSimulations Simulations { get; }
+
+ ///
+ /// Gets the metrics for the font.
+ ///
+ /// Receives the font metrics.
+ FontMetrics Metrics { get; }
+
+ ///
+ /// Determines whether the font supports the specified character.
+ ///
+ /// Unicode (UCS-4) character value.
+ /// Receives the value TRUE if the font supports the specified character or FALSE if not.
+ bool HasCharacter(uint unicodeValue);
+
+ ///
+ /// Creates a font face object for the font.
+ ///
+ ///
+ /// S pointer to the newly created font face object.
+ ///
+ FontFace CreateFontFace();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/FontCollection.cs b/src/WInterop.DirectX/DirectWrite/FontCollection.cs
new file mode 100644
index 00000000..e23c92d7
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/FontCollection.cs
@@ -0,0 +1,79 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The IDWriteFontCollection encapsulates a collection of font families. [IDWriteFontCollection]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteFontCollection)]
+ public readonly unsafe struct FontCollection : FontCollection.Interface, IDisposable
+ {
+ internal IDWriteFontCollection* Handle { get; }
+
+ internal FontCollection(IDWriteFontCollection* handle) => Handle = handle;
+
+ public uint FontFamilyCount => Handle->GetFontFamilyCount();
+
+ public void Dispose() => Handle->Release();
+
+ public bool FindFamilyName(string familyName, out uint index)
+ {
+ TerraFX.Interop.Windows.BOOL exists;
+ fixed (void* n = familyName)
+ fixed (uint* i = &index)
+ {
+ Handle->FindFamilyName((ushort*)n, i, &exists).ThrowIfFailed();
+ }
+
+ return exists;
+ }
+
+ public FontFamily GetFontFamily(uint index)
+ {
+ IDWriteFontFamily* family;
+ Handle->GetFontFamily(index, &family).ThrowIfFailed();
+ return new(family);
+ }
+
+ public Font GetFontFromFontFace(FontFace fontFace)
+ {
+ IDWriteFont* font;
+ Handle->GetFontFromFontFace(fontFace._handle, &font).ThrowIfFailed();
+ return new(font);
+ }
+
+ internal interface Interface
+ {
+ ///
+ /// Gets the number of font families in the collection.
+ ///
+ uint FontFamilyCount { get; }
+
+ ///
+ /// Creates a font family object given a zero-based font family index.
+ ///
+ /// Zero-based index of the font family.
+ FontFamily GetFontFamily(uint index);
+
+ ///
+ /// Finds the font family with the specified family name.
+ ///
+ /// Name of the font family. The name is not case-sensitive but must otherwise exactly match a family name in the collection.
+ /// Receives the zero-based index of the matching font family if the family name was found or UINT_MAX otherwise.
+ bool FindFamilyName(
+ string familyName,
+ out uint index);
+
+ ///
+ /// Gets the font object that corresponds to the same physical font as the specified font face object. The specified physical font must belong
+ /// to the font collection.
+ ///
+ /// Font face object that specifies the physical font.
+ Font GetFontFromFontFace(FontFace fontFace);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/FontFace.cs b/src/WInterop.DirectX/DirectWrite/FontFace.cs
new file mode 100644
index 00000000..0c6001c6
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/FontFace.cs
@@ -0,0 +1,358 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using WInterop.Direct2d;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// This interface exposes various font data such as metrics, names, and glyph outlines.
+ /// It contains font face type, appropriate file references and face identification data.
+ /// [IDWriteFontFace]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteFontFace)]
+ public unsafe readonly struct FontFace : FontFace.Interface, IDisposable
+ {
+ internal readonly IDWriteFontFace* _handle;
+
+ internal FontFace(IDWriteFontFace* handle) => _handle = handle;
+
+ public FontFaceType Type => (FontFaceType)_handle->GetType();
+
+ public uint Index => _handle->GetIndex();
+
+ public FontSimulations Simulations => (FontSimulations)_handle->GetSimulations();
+
+ public FontMetrics Metrics
+ {
+ get
+ {
+ FontMetrics metrics;
+ _handle->GetMetrics((DWRITE_FONT_METRICS*)&metrics);
+ return metrics;
+ }
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public void GetGdiCompatibleGlyphMetrics(
+ float emSize,
+ float pixelsPerDip,
+ Matrix3x2 transform,
+ bool useGdiNatural,
+ ReadOnlySpan glyphIndices,
+ Span glyphMetrics,
+ bool isSideways)
+ {
+ if (glyphMetrics.Length != glyphIndices.Length)
+ throw new ArgumentException($"{nameof(glyphIndices)} and {nameof(glyphMetrics)} must have matching lengths");
+
+ fixed (ushort* i = glyphIndices)
+ fixed (GlyphMetrics* m = glyphMetrics)
+ {
+ _handle->GetGdiCompatibleGlyphMetrics(
+ emSize,
+ pixelsPerDip,
+ (DWRITE_MATRIX*)&transform,
+ useGdiNatural,
+ i,
+ (uint)glyphIndices.Length,
+ (DWRITE_GLYPH_METRICS*)m,
+ isSideways).ThrowIfFailed();
+ }
+ }
+
+ public FontMetrics GetGdiCompatibleMetrics(float emSize, float pixelsPerDip, Matrix3x2 transform)
+ {
+ FontMetrics metrics;
+ _handle->GetGdiCompatibleMetrics(emSize,
+ pixelsPerDip,
+ (DWRITE_MATRIX*)&transform,
+ (DWRITE_FONT_METRICS*)&metrics).ThrowIfFailed();
+ return metrics;
+ }
+
+ public ushort GlyphCount => _handle->GetGlyphCount();
+
+ public void GetGlyphRunOutline(
+ float emSize,
+ ReadOnlySpan glyphIndices,
+ ReadOnlySpan glyphAdvances,
+ ReadOnlySpan glyphOffsets,
+ bool isSideways,
+ bool isRightToLeft,
+ SimplifiedGeometrySink geometrySink)
+ {
+ fixed (ushort* gi = glyphIndices)
+ fixed (float* ga = glyphAdvances)
+ fixed (void* go = glyphOffsets)
+ {
+ _handle->GetGlyphRunOutline(
+ emSize,
+ gi,
+ ga,
+ (DWRITE_GLYPH_OFFSET*)go,
+ (uint)glyphIndices.Length,
+ isSideways,
+ isRightToLeft,
+ geometrySink.Handle).ThrowIfFailed();
+ }
+ }
+
+ public RenderingMode GetRecommendedRenderingMode(
+ float emSize,
+ float pixelsPerDip,
+ MeasuringMode measuringMode,
+ RenderingParams renderingParams)
+ {
+ RenderingMode renderingMode;
+ _handle->GetRecommendedRenderingMode(
+ emSize,
+ pixelsPerDip,
+ (DWRITE_MEASURING_MODE)measuringMode,
+ renderingParams.Handle,
+ (DWRITE_RENDERING_MODE*)&renderingMode).ThrowIfFailed();
+
+ return renderingMode;
+ }
+
+ public bool IsSymbolFont() => _handle->IsSymbolFont();
+
+ internal interface Interface
+ {
+ ///
+ /// Obtains the file format type of a font face.
+ ///
+ FontFaceType Type { get; }
+
+/*
+ ///
+ /// Obtains the font files representing a font face.
+ ///
+ /// The number of files representing the font face.
+ /// User provided array that stores pointers to font files representing the font face.
+ /// This parameter can be NULL if the user is only interested in the number of files representing the font face.
+ /// This API increments reference count of the font file pointers returned according to COM conventions, and the client
+ /// should release them when finished.
+ ///
+ /// Standard HRESULT error code.
+ ///
+ //STDMETHOD(GetFiles)(
+ // _Inout_ UINT32* numberOfFiles,
+ // _Out_writes_opt_(*numberOfFiles) IDWriteFontFile** fontFiles
+ //) PURE;
+*/
+
+ ///
+ /// Obtains the zero-based index of the font face in its font file or files. If the font files contain a single face,
+ /// the return value is zero.
+ ///
+ uint Index { get; }
+
+ ///
+ /// Obtains the algorithmic style simulation flags of a font face.
+ ///
+ FontSimulations Simulations { get; }
+
+ ///
+ /// Determines whether the font is a symbol font.
+ ///
+ bool IsSymbolFont();
+
+ ///
+ /// Obtains design units and common metrics for the font face.
+ /// These metrics are applicable to all the glyphs within a fontface and are used by applications for layout calculations.
+ ///
+ FontMetrics Metrics { get; }
+
+ ///
+ /// Obtains the number of glyphs in the font face.
+ ///
+ ushort GlyphCount { get; }
+
+/*
+ ///// An array of glyph indices to compute the metrics for.
+ ///// The number of elements in the glyphIndices array.
+ ///// Array of DWRITE_GLYPH_METRICS structures filled by this function.
+ ///// The metrics returned by this function are in font design units.
+ ///// Indicates whether the font is being used in a sideways run.
+ ///// This can affect the glyph metrics if the font has oblique simulation
+ ///// because sideways oblique simulation differs from non-sideways oblique simulation.
+ ///
+ /// Obtains ideal glyph metrics in font design units. Design glyphs metrics are used for glyph positioning.
+ ///
+ ///
+ /// Standard HRESULT error code. If any of the input glyph indices are outside of the valid glyph index range
+ /// for the current font face, E_INVALIDARG will be returned.
+ ///
+ // void GetDesignGlyphMetricsSTUB();
+ //STDMETHOD(GetDesignGlyphMetrics)(
+ // _In_reads_(glyphCount) UINT16 const* glyphIndices,
+ // UINT32 glyphCount,
+ //_Out_writes_(glyphCount) DWRITE_GLYPH_METRICS* glyphMetrics,
+ //BOOL isSideways = FALSE
+ //) PURE;
+
+ ///
+ /// Returns the nominal mapping of UTF-32 Unicode code points to glyph indices as defined by the font 'cmap'
+ /// table. Note that this mapping is primarily provided for line layout engines built on top of the physical
+ /// font API. Because of OpenType glyph substitution and line layout character substitution, the nominal
+ /// conversion does not always correspond to how a Unicode string will map to glyph indices when rendering
+ /// using a particular font face. Also, note that Unicode Variation Selectors provide for alternate mappings
+ /// for character to glyph. This call will always return the default variant.
+ ///
+ /// An array of UTF-32 code points to obtain nominal glyph indices from.
+ /// The number of elements in the codePoints array.
+ /// Array of nominal glyph indices filled by this function.
+ ///
+ /// Standard HRESULT error code.
+ ///
+ //unsafe void GetGlyphIndices(
+ // uint* codePoints,
+ // uint codePointCount,
+ // ushort* glyphIndices);
+
+ ///
+ /// Finds the specified OpenType font table if it exists and returns a pointer to it.
+ /// The function accesses the underlying font data via the IDWriteFontFileStream interface
+ /// implemented by the font file loader.
+ ///
+ /// Four character tag of table to find.
+ /// Use the DWRITE_MAKE_OPENTYPE_TAG() macro to create it.
+ /// Unlike GDI, it does not support the special TTCF and null tags to access the whole font.
+ ///
+ /// Pointer to base of table in memory.
+ /// The pointer is only valid so long as the FontFace used to get the font table still exists
+ /// (not any other FontFace, even if it actually refers to the same physical font).
+ ///
+ /// Byte size of table.
+ ///
+ /// Opaque context which must be freed by calling ReleaseFontTable.
+ /// The context actually comes from the lower level IDWriteFontFileStream,
+ /// which may be implemented by the application or DWrite itself.
+ /// It is possible for a NULL tableContext to be returned, especially if
+ /// the implementation directly memory maps the whole file.
+ /// Nevertheless, always release it later, and do not use it as a test for function success.
+ /// The same table can be queried multiple times,
+ /// but each returned context can be different, so release each separately.
+ ///
+ /// True if table exists.
+ ///
+ /// Standard HRESULT error code.
+ /// If a table can not be found, the function will not return an error, but the size will be 0, table NULL, and exists = FALSE.
+ /// The context does not need to be freed if the table was not found.
+ ///
+ ///
+ /// The context for the same tag may be different for each call,
+ /// so each one must be held and released separately.
+ ///
+ //unsafe IntBoolean TryGetFontTable(
+ // uint openTypeTableTag,
+ // void** tableData,
+ // out uint tableSize,
+ // out IntPtr tableContext,
+ // out IntBoolean exists);
+
+ ///
+ /// Releases the table obtained earlier from TryGetFontTable.
+ ///
+ /// Opaque context from TryGetFontTable.
+ //void ReleaseFontTable(IntPtr tableContext);
+
+ */
+
+ ///
+ /// Computes the outline of a run of glyphs by calling back to the outline sink interface.
+ ///
+ /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
+ /// Array of glyph indices.
+ /// Optional array of glyph advances in DIPs.
+ /// Optional array of glyph offsets.
+ /// If true, specifies that glyphs are rotated 90 degrees to the left and vertical metrics are used.
+ /// A client can render a vertical run by specifying isSideways = true and rotating the resulting geometry 90 degrees to the
+ /// right using a transform.
+ /// If true, specifies that the advance direction is right to left. By default, the advance direction
+ /// is left to right.
+ /// Interface the function calls back to draw each element of the geometry.
+ unsafe void GetGlyphRunOutline(
+ float emSize,
+ ReadOnlySpan glyphIndices,
+ ReadOnlySpan glyphAdvances,
+ ReadOnlySpan glyphOffsets,
+ bool isSideways,
+ bool isRightToLeft,
+ SimplifiedGeometrySink geometrySink);
+
+ ///
+ /// Determines the recommended rendering mode for the font given the specified size and rendering parameters.
+ ///
+ /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
+ /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this
+ /// value is 1.0f. If the DPI is 120, this value is 120.0f/96.
+ /// Specifies measuring mode that will be used for glyphs in the font.
+ /// Renderer implementations may choose different rendering modes for given measuring modes, but
+ /// best results are seen when the corresponding modes match:
+ /// for
+ /// for
+ /// for
+ ///
+ /// Rendering parameters object. This parameter is necessary in case the rendering parameters
+ /// object overrides the rendering mode.
+ ///
+ /// The recommended rendering mode to use.
+ ///
+ RenderingMode GetRecommendedRenderingMode(
+ float emSize,
+ float pixelsPerDip,
+ MeasuringMode measuringMode,
+ RenderingParams renderingParams);
+
+ ///
+ /// Obtains design units and common metrics for the font face.
+ /// These metrics are applicable to all the glyphs within a fontface and are used by applications for layout calculations.
+ ///
+ /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
+ /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this
+ /// value is 1.0f. If the DPI is 120, this value is 120.0f/96.
+ /// Optional transform applied to the glyphs and their positions. This transform is applied after the
+ /// scaling specified by the font size and pixelsPerDip.
+ unsafe FontMetrics GetGdiCompatibleMetrics(
+ float emSize,
+ float pixelsPerDip,
+ Matrix3x2 transform);
+
+ ///
+ /// Obtains glyph metrics in font design units with the return values compatible with what GDI would produce.
+ /// Glyphs metrics are used for positioning of individual glyphs.
+ ///
+ /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
+ /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this
+ /// value is 1.0f. If the DPI is 120, this value is 120.0f/96.
+ /// Optional transform applied to the glyphs and their positions. This transform is applied after the
+ /// scaling specified by the font size and pixelsPerDip.
+ ///
+ /// When set to FALSE, the metrics are the same as the metrics of GDI aliased text.
+ /// When set to TRUE, the metrics are the same as the metrics of text measured by GDI using a font
+ /// created with CLEARTYPE_NATURAL_QUALITY.
+ ///
+ /// An array of glyph indices to compute the metrics for.
+ /// The number of elements in the glyphIndices array.
+ /// Array of DWRITE_GLYPH_METRICS structures filled by this function.
+ /// The metrics returned by this function are in font design units.
+ /// Indicates whether the font is being used in a sideways run.
+ /// This can affect the glyph metrics if the font has oblique simulation
+ /// because sideways oblique simulation differs from non-sideways oblique simulation.
+ unsafe void GetGdiCompatibleGlyphMetrics(
+ float emSize,
+ float pixelsPerDip,
+ Matrix3x2 transform,
+ bool useGdiNatural,
+ ReadOnlySpan glyphIndices,
+ Span glyphMetrics,
+ bool isSideways);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/FontFaceType.cs b/src/WInterop.DirectX/DirectWrite/FontFaceType.cs
index 075f96a7..a17c4756 100644
--- a/src/WInterop.DirectX/DirectWrite/FontFaceType.cs
+++ b/src/WInterop.DirectX/DirectWrite/FontFaceType.cs
@@ -15,37 +15,37 @@ public enum FontFaceType : uint
///
/// OpenType font face with CFF outlines.
///
- Cff,
+ Cff = DWRITE_FONT_FACE_TYPE.DWRITE_FONT_FACE_TYPE_CFF,
///
/// OpenType font face with TrueType outlines.
///
- TrueType,
+ TrueType = DWRITE_FONT_FACE_TYPE.DWRITE_FONT_FACE_TYPE_TRUETYPE,
///
/// OpenType font face that is a part of a TrueType or CFF collection.
///
- OpenTypeCollection,
+ OpenTypeCollection = DWRITE_FONT_FACE_TYPE.DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION,
///
/// A Type 1 font face.
///
- Type1,
+ Type1 = DWRITE_FONT_FACE_TYPE.DWRITE_FONT_FACE_TYPE_TYPE1,
///
/// A vector .FON format font face.
///
- Vector,
+ Vector = DWRITE_FONT_FACE_TYPE.DWRITE_FONT_FACE_TYPE_VECTOR,
///
/// A bitmap .FON format font face.
///
- Bitmap,
+ Bitmap = DWRITE_FONT_FACE_TYPE.DWRITE_FONT_FACE_TYPE_BITMAP,
///
/// Font face type is not recognized by the DirectWrite font system.
///
- Unknown,
+ Unknown = DWRITE_FONT_FACE_TYPE.DWRITE_FONT_FACE_TYPE_UNKNOWN,
///
/// The font data includes only the CFF table from an OpenType CFF font.
@@ -53,6 +53,6 @@ public enum FontFaceType : uint
/// font file loaders) and the resulting font face object supports only the
/// minimum functionality necessary to render glyphs.
///
- RawCff
+ RawCff = DWRITE_FONT_FACE_TYPE.DWRITE_FONT_FACE_TYPE_RAW_CFF
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/FontFamily.cs b/src/WInterop.DirectX/DirectWrite/FontFamily.cs
new file mode 100644
index 00000000..14432e49
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/FontFamily.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.InteropServices;
+using WInterop.Direct2d;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The IDWriteFontFamily interface represents a set of fonts that share the same design but are differentiated
+ /// by weight, stretch, and style. [IDWriteFontFamily]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteFontFamily)]
+ public readonly unsafe struct FontFamily : FontFamily.Interface, IDisposable
+ {
+ private readonly IDWriteFontFamily* _handle;
+
+ internal FontFamily(IDWriteFontFamily* handle) => _handle = handle;
+
+ public uint FontCount => throw new NotImplementedException();
+
+ public void Dispose() => _handle->Release();
+
+ public LocalizedStrings GetFamilyNames()
+ {
+ IDWriteLocalizedStrings* names;
+ _handle->GetFamilyNames(&names).ThrowIfFailed();
+ return new(names);
+ }
+
+ public Font GetFont(uint index) => FontList.From(this).GetFont(index);
+
+ public FontCollection GetFontCollection() => FontList.From(this).GetFontCollection();
+
+ public Font GetFirstMatchingFont(FontWeight weight, FontStretch stretch, FontStyle style)
+ {
+ IDWriteFont* font;
+ _handle->GetFirstMatchingFont(
+ (DWRITE_FONT_WEIGHT)weight,
+ (DWRITE_FONT_STRETCH)stretch,
+ (DWRITE_FONT_STYLE)style,
+ &font).ThrowIfFailed();
+
+ return new(font);
+ }
+
+ public FontList GetMatchingFonts(FontWeight weight, FontStretch stretch, FontStyle style)
+ {
+ IDWriteFontList* fontList;
+ _handle->GetMatchingFonts(
+ (DWRITE_FONT_WEIGHT)weight,
+ (DWRITE_FONT_STRETCH)stretch,
+ (DWRITE_FONT_STYLE)style,
+ &fontList).ThrowIfFailed();
+
+ return new(fontList);
+ }
+
+ internal interface Interface : FontList.Interface
+ {
+ ///
+ /// Creates a localized strings object that contains the family names for the font family, indexed by locale name.
+ ///
+ LocalizedStrings GetFamilyNames();
+
+ ///
+ /// Gets the font that best matches the specified properties.
+ ///
+ /// Requested font weight.
+ /// Requested font stretch.
+ /// Requested font style.
+ Font GetFirstMatchingFont(
+ FontWeight weight,
+ FontStretch stretch,
+ FontStyle style);
+
+ ///
+ /// Gets a list of fonts in the font family ranked in order of how well they match the specified properties.
+ ///
+ /// Requested font weight.
+ /// Requested font stretch.
+ /// Requested font style.
+ FontList GetMatchingFonts(
+ FontWeight weight,
+ FontStretch stretch,
+ FontStyle style);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/FontFeatureTag.cs b/src/WInterop.DirectX/DirectWrite/FontFeatureTag.cs
index 8eb68b08..f857cd51 100644
--- a/src/WInterop.DirectX/DirectWrite/FontFeatureTag.cs
+++ b/src/WInterop.DirectX/DirectWrite/FontFeatureTag.cs
@@ -8,86 +8,86 @@ namespace WInterop.DirectWrite
///
public enum FontFeatureTag : uint
{
- AlternativeFractions = ((byte)'a') | ((byte)'f' << 8) | ((byte)'r' << 16) | ((byte)'c' << 24),
- PetiteCapitalsFromCapitals = ((byte)'c') | ((byte)'2' << 8) | ((byte)'p' << 16) | ((byte)'c' << 24),
- SmallCapitalsFromCapitals = ((byte)'c') | ((byte)'2' << 8) | ((byte)'s' << 16) | ((byte)'c' << 24),
- ContextualAlternates = ((byte)'c') | ((byte)'a' << 8) | ((byte)'l' << 16) | ((byte)'t' << 24),
- CaseSensitiveForms = ((byte)'c') | ((byte)'a' << 8) | ((byte)'s' << 16) | ((byte)'e' << 24),
- GlyphCompositionDecomposition = ((byte)'c') | ((byte)'c' << 8) | ((byte)'m' << 16) | ((byte)'p' << 24),
- ContextualLigatures = ((byte)'c') | ((byte)'l' << 8) | ((byte)'i' << 16) | ((byte)'g' << 24),
- CapitalSpacing = ((byte)'c') | ((byte)'p' << 8) | ((byte)'s' << 16) | ((byte)'p' << 24),
- ContextualSwash = ((byte)'c') | ((byte)'s' << 8) | ((byte)'w' << 16) | ((byte)'h' << 24),
- CursivePositioning = ((byte)'c') | ((byte)'u' << 8) | ((byte)'r' << 16) | ((byte)'s' << 24),
- Default = ((byte)'d') | ((byte)'f' << 8) | ((byte)'l' << 16) | ((byte)'t' << 24),
- DiscretionaryLigatures = ((byte)'d') | ((byte)'l' << 8) | ((byte)'i' << 16) | ((byte)'g' << 24),
- ExpertForms = ((byte)'e') | ((byte)'x' << 8) | ((byte)'p' << 16) | ((byte)'t' << 24),
- Fractions = ((byte)'f') | ((byte)'r' << 8) | ((byte)'a' << 16) | ((byte)'c' << 24),
- FullWidth = ((byte)'f') | ((byte)'w' << 8) | ((byte)'i' << 16) | ((byte)'d' << 24),
- HalfForms = ((byte)'h') | ((byte)'a' << 8) | ((byte)'l' << 16) | ((byte)'f' << 24),
- HalantForms = ((byte)'h') | ((byte)'a' << 8) | ((byte)'l' << 16) | ((byte)'n' << 24),
- AlternateHalfWidth = ((byte)'h') | ((byte)'a' << 8) | ((byte)'l' << 16) | ((byte)'t' << 24),
- HistoricalForms = ((byte)'h') | ((byte)'i' << 8) | ((byte)'s' << 16) | ((byte)'t' << 24),
- HorizontalKanaAlternates = ((byte)'h') | ((byte)'k' << 8) | ((byte)'n' << 16) | ((byte)'a' << 24),
- HistoricalLigatures = ((byte)'h') | ((byte)'l' << 8) | ((byte)'i' << 16) | ((byte)'g' << 24),
- HalfWidth = ((byte)'h') | ((byte)'w' << 8) | ((byte)'i' << 16) | ((byte)'d' << 24),
- HojoKanjiForms = ((byte)'h') | ((byte)'o' << 8) | ((byte)'j' << 16) | ((byte)'o' << 24),
- Jis04Forms = ((byte)'j') | ((byte)'p' << 8) | ((byte)'0' << 16) | ((byte)'4' << 24),
- Jis78Forms = ((byte)'j') | ((byte)'p' << 8) | ((byte)'7' << 16) | ((byte)'8' << 24),
- Jis83Forms = ((byte)'j') | ((byte)'p' << 8) | ((byte)'8' << 16) | ((byte)'3' << 24),
- Jis90Forms = ((byte)'j') | ((byte)'p' << 8) | ((byte)'9' << 16) | ((byte)'0' << 24),
- Kerning = ((byte)'k') | ((byte)'e' << 8) | ((byte)'r' << 16) | ((byte)'n' << 24),
- StandardLigatures = ((byte)'l') | ((byte)'i' << 8) | ((byte)'g' << 16) | ((byte)'a' << 24),
- LiningFigures = ((byte)'l') | ((byte)'n' << 8) | ((byte)'u' << 16) | ((byte)'m' << 24),
- LocalizedForms = ((byte)'l') | ((byte)'o' << 8) | ((byte)'c' << 16) | ((byte)'l' << 24),
- MarkPositioning = ((byte)'m') | ((byte)'a' << 8) | ((byte)'r' << 16) | ((byte)'k' << 24),
- MathematicalGreek = ((byte)'m') | ((byte)'g' << 8) | ((byte)'r' << 16) | ((byte)'k' << 24),
- MarkToMarkPositioning = ((byte)'m') | ((byte)'k' << 8) | ((byte)'m' << 16) | ((byte)'k' << 24),
- AlternateAnnotationForms = ((byte)'n') | ((byte)'a' << 8) | ((byte)'l' << 16) | ((byte)'t' << 24),
- NlcKanjiForms = ((byte)'n') | ((byte)'l' << 8) | ((byte)'c' << 16) | ((byte)'k' << 24),
- OldStyleFigures = ((byte)'o') | ((byte)'n' << 8) | ((byte)'u' << 16) | ((byte)'m' << 24),
- Ordinals = ((byte)'o') | ((byte)'r' << 8) | ((byte)'d' << 16) | ((byte)'n' << 24),
- ProportionalAlternateWidth = ((byte)'p') | ((byte)'a' << 8) | ((byte)'l' << 16) | ((byte)'t' << 24),
- PetiteCapitals = ((byte)'p') | ((byte)'c' << 8) | ((byte)'a' << 16) | ((byte)'p' << 24),
- ProportionalFigures = ((byte)'p') | ((byte)'n' << 8) | ((byte)'u' << 16) | ((byte)'m' << 24),
- ProportionalWidths = ((byte)'p') | ((byte)'w' << 8) | ((byte)'i' << 16) | ((byte)'d' << 24),
- QuarterWidths = ((byte)'q') | ((byte)'w' << 8) | ((byte)'i' << 16) | ((byte)'d' << 24),
- RequiredLigatures = ((byte)'r') | ((byte)'l' << 8) | ((byte)'i' << 16) | ((byte)'g' << 24),
- RubyNotationForms = ((byte)'r') | ((byte)'u' << 8) | ((byte)'b' << 16) | ((byte)'y' << 24),
- StylisticAlternates = ((byte)'s') | ((byte)'a' << 8) | ((byte)'l' << 16) | ((byte)'t' << 24),
- ScientificInferiors = ((byte)'s') | ((byte)'i' << 8) | ((byte)'n' << 16) | ((byte)'f' << 24),
- SmallCapitals = ((byte)'s') | ((byte)'m' << 8) | ((byte)'c' << 16) | ((byte)'p' << 24),
- SimplifiedForms = ((byte)'s') | ((byte)'m' << 8) | ((byte)'p' << 16) | ((byte)'l' << 24),
- StylisticSet1 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'1' << 24),
- StylisticSet2 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'2' << 24),
- StylisticSet3 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'3' << 24),
- StylisticSet4 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'4' << 24),
- StylisticSet5 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'5' << 24),
- StylisticSet6 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'6' << 24),
- StylisticSet7 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'7' << 24),
- StylisticSet8 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'8' << 24),
- StylisticSet9 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'0' << 16) | ((byte)'9' << 24),
- StylisticSet10 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'0' << 24),
- StylisticSet11 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'1' << 24),
- StylisticSet12 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'2' << 24),
- StylisticSet13 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'3' << 24),
- StylisticSet14 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'4' << 24),
- StylisticSet15 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'5' << 24),
- StylisticSet16 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'6' << 24),
- StylisticSet17 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'7' << 24),
- StylisticSet18 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'8' << 24),
- StylisticSet19 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'1' << 16) | ((byte)'9' << 24),
- StylisticSet20 = ((byte)'s') | ((byte)'s' << 8) | ((byte)'2' << 16) | ((byte)'0' << 24),
- Subscript = ((byte)'s') | ((byte)'u' << 8) | ((byte)'b' << 16) | ((byte)'s' << 24),
- Superscript = ((byte)'s') | ((byte)'u' << 8) | ((byte)'p' << 16) | ((byte)'s' << 24),
- Swash = ((byte)'s') | ((byte)'w' << 8) | ((byte)'s' << 16) | ((byte)'h' << 24),
- Titling = ((byte)'t') | ((byte)'i' << 8) | ((byte)'t' << 16) | ((byte)'l' << 24),
- TraditionalNameForms = ((byte)'t') | ((byte)'n' << 8) | ((byte)'a' << 16) | ((byte)'m' << 24),
- TabularFigures = ((byte)'t') | ((byte)'n' << 8) | ((byte)'u' << 16) | ((byte)'m' << 24),
- TraditionalForms = ((byte)'t') | ((byte)'r' << 8) | ((byte)'a' << 16) | ((byte)'d' << 24),
- ThirdWidths = ((byte)'t') | ((byte)'w' << 8) | ((byte)'i' << 16) | ((byte)'d' << 24),
- Unicase = ((byte)'u') | ((byte)'n' << 8) | ((byte)'i' << 16) | ((byte)'c' << 24),
- VerticalWriting = ((byte)'v') | ((byte)'e' << 8) | ((byte)'r' << 16) | ((byte)'t' << 24),
- VerticalAlternatesAndRotation = ((byte)'v') | ((byte)'r' << 8) | ((byte)'t' << 16) | ((byte)'2' << 24),
- SlashedZero = ((byte)'z') | ((byte)'e' << 8) | ((byte)'r' << 16) | ((byte)'o' << 24),
+ AlternativeFractions = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_ALTERNATIVE_FRACTIONS,
+ PetiteCapitalsFromCapitals = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_PETITE_CAPITALS_FROM_CAPITALS,
+ SmallCapitalsFromCapitals = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_SMALL_CAPITALS_FROM_CAPITALS,
+ ContextualAlternates = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_ALTERNATES,
+ CaseSensitiveForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_CASE_SENSITIVE_FORMS,
+ GlyphCompositionDecomposition = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_GLYPH_COMPOSITION_DECOMPOSITION,
+ ContextualLigatures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_LIGATURES,
+ CapitalSpacing = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_CAPITAL_SPACING,
+ ContextualSwash = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_SWASH,
+ CursivePositioning = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_CURSIVE_POSITIONING,
+ Default = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_DEFAULT,
+ DiscretionaryLigatures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_DISCRETIONARY_LIGATURES,
+ ExpertForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_EXPERT_FORMS,
+ Fractions = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_FRACTIONS,
+ FullWidth = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_FULL_WIDTH,
+ HalfForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_HALF_FORMS,
+ HalantForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_HALANT_FORMS,
+ AlternateHalfWidth = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_ALTERNATE_HALF_WIDTH,
+ HistoricalForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_HISTORICAL_FORMS,
+ HorizontalKanaAlternates = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_HORIZONTAL_KANA_ALTERNATES,
+ HistoricalLigatures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_HISTORICAL_LIGATURES,
+ HalfWidth = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_HALF_WIDTH,
+ HojoKanjiForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_HOJO_KANJI_FORMS,
+ Jis04Forms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_JIS04_FORMS,
+ Jis78Forms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_JIS78_FORMS,
+ Jis83Forms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_JIS83_FORMS,
+ Jis90Forms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_JIS90_FORMS,
+ Kerning = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_KERNING,
+ StandardLigatures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STANDARD_LIGATURES,
+ LiningFigures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_LINING_FIGURES,
+ LocalizedForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_LOCALIZED_FORMS,
+ MarkPositioning = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_MARK_POSITIONING,
+ MathematicalGreek = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_MATHEMATICAL_GREEK,
+ MarkToMarkPositioning = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING,
+ AlternateAnnotationForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_ALTERNATE_ANNOTATION_FORMS,
+ NlcKanjiForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_NLC_KANJI_FORMS,
+ OldStyleFigures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_OLD_STYLE_FIGURES,
+ Ordinals = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_ORDINALS,
+ ProportionalAlternateWidth = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_PROPORTIONAL_ALTERNATE_WIDTH,
+ PetiteCapitals = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_PETITE_CAPITALS,
+ ProportionalFigures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_PROPORTIONAL_FIGURES,
+ ProportionalWidths = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_PROPORTIONAL_WIDTHS,
+ QuarterWidths = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_QUARTER_WIDTHS,
+ RequiredLigatures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_REQUIRED_LIGATURES,
+ RubyNotationForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_RUBY_NOTATION_FORMS,
+ StylisticAlternates = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_ALTERNATES,
+ ScientificInferiors = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_SCIENTIFIC_INFERIORS,
+ SmallCapitals = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_SMALL_CAPITALS,
+ SimplifiedForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_SIMPLIFIED_FORMS,
+ StylisticSet1 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_1,
+ StylisticSet2 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_2,
+ StylisticSet3 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_3,
+ StylisticSet4 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_4,
+ StylisticSet5 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_5,
+ StylisticSet6 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_6,
+ StylisticSet7 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_7,
+ StylisticSet8 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_8,
+ StylisticSet9 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_9,
+ StylisticSet10 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_10,
+ StylisticSet11 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_11,
+ StylisticSet12 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_12,
+ StylisticSet13 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_13,
+ StylisticSet14 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_14,
+ StylisticSet15 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_15,
+ StylisticSet16 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_16,
+ StylisticSet17 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_17,
+ StylisticSet18 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_18,
+ StylisticSet19 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_19,
+ StylisticSet20 = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_20,
+ Subscript = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_SUBSCRIPT,
+ Superscript = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_SUPERSCRIPT,
+ Swash = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_SWASH,
+ Titling = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_TITLING,
+ TraditionalNameForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_TRADITIONAL_NAME_FORMS,
+ TabularFigures = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_TABULAR_FIGURES,
+ TraditionalForms = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_TRADITIONAL_FORMS,
+ ThirdWidths = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_THIRD_WIDTHS,
+ Unicase = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_UNICASE,
+ VerticalWriting = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING,
+ VerticalAlternatesAndRotation = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_VERTICAL_ALTERNATES_AND_ROTATION,
+ SlashedZero = DWRITE_FONT_FEATURE_TAG.DWRITE_FONT_FEATURE_TAG_SLASHED_ZERO,
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/FontList.cs b/src/WInterop.DirectX/DirectWrite/FontList.cs
new file mode 100644
index 00000000..5cdb6f16
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/FontList.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using WInterop.Direct2d;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The interface represents an ordered set of fonts that are part of an .
+ /// [IDWriteFontList]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteFontList)]
+ public readonly unsafe struct FontList : FontList.Interface, IDisposable
+ {
+ private readonly IDWriteFontList* _handle;
+
+ internal FontList(IDWriteFontList* handle) => _handle = handle;
+
+ public uint FontCount => _handle->GetFontCount();
+
+ internal static ref FontList From(in TFrom from)
+ where TFrom : unmanaged, Interface
+ => ref Unsafe.AsRef(Unsafe.AsPointer(ref Unsafe.AsRef(from)));
+
+ public void Dispose() => _handle->Release();
+
+ public Font GetFont(uint index)
+ {
+ IDWriteFont* font;
+ _handle->GetFont(index, &font).ThrowIfFailed();
+ return new(font);
+ }
+
+ public FontCollection GetFontCollection()
+ {
+ IDWriteFontCollection* collection;
+ _handle->GetFontCollection(&collection).ThrowIfFailed();
+ return new(collection);
+ }
+
+ internal interface Interface
+ {
+ ///
+ /// Gets the font collection that contains the fonts.
+ ///
+ FontCollection GetFontCollection();
+
+ ///
+ /// Gets the number of fonts in the font list.
+ ///
+ uint FontCount { get; }
+
+ ///
+ /// Gets a font given its zero-based index.
+ ///
+ /// Zero-based index of the font in the font list.
+ Font GetFont(uint index);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/FontSimulations.cs b/src/WInterop.DirectX/DirectWrite/FontSimulations.cs
index 76490e50..797db7ab 100644
--- a/src/WInterop.DirectX/DirectWrite/FontSimulations.cs
+++ b/src/WInterop.DirectX/DirectWrite/FontSimulations.cs
@@ -16,16 +16,16 @@ public enum FontSimulations : uint
///
/// No simulations are performed.
///
- None = 0x0000,
+ None = DWRITE_FONT_SIMULATIONS.DWRITE_FONT_SIMULATIONS_NONE,
///
/// Algorithmic emboldening is performed.
///
- Bold = 0x0001,
+ Bold = DWRITE_FONT_SIMULATIONS.DWRITE_FONT_SIMULATIONS_BOLD,
///
/// Algorithmic italicization is performed.
///
- Oblique = 0x0002
+ Oblique = DWRITE_FONT_SIMULATIONS.DWRITE_FONT_SIMULATIONS_OBLIQUE
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/GlyphRun.cs b/src/WInterop.DirectX/DirectWrite/GlyphRun.cs
index b0e24f15..5d423642 100644
--- a/src/WInterop.DirectX/DirectWrite/GlyphRun.cs
+++ b/src/WInterop.DirectX/DirectWrite/GlyphRun.cs
@@ -17,9 +17,7 @@ public readonly unsafe struct GlyphRun
///
/// The physical font face to draw with. (IFontFace)
///
- private readonly IntPtr _fontFace;
-
- public IFontFace FontFace => (IFontFace)Marshal.GetObjectForIUnknown(_fontFace);
+ public readonly FontFace FontFace;
///
/// Logical size of the font in DIPs, not points (equals 1/96 inch).
@@ -31,20 +29,26 @@ public readonly unsafe struct GlyphRun
///
public readonly uint GlyphCount;
+ private readonly ushort* _glyphIndices;
+
///
/// The indices to render.
///
- public readonly ushort* GlyphIndices;
+ public ReadOnlySpan GlyphIndices => new(_glyphIndices, (int)GlyphCount);
+
+ private readonly float* _glyphAdvances;
///
/// Glyph advance widths.
///
- public readonly float* GlyphAdvances;
+ public ReadOnlySpan GlyphAdvances => new(_glyphAdvances, (int)GlyphCount);
+
+ private readonly GlyphOffset* _glyphOffsets;
///
/// Glyph offsets.
///
- public readonly GlyphOffset* GlyphOffsets;
+ public ReadOnlySpan GlyphOffsets => new(_glyphOffsets, (int)GlyphCount);
///
/// If true, specifies that glyphs are rotated 90 degrees to the left and
diff --git a/src/WInterop.DirectX/DirectWrite/HitTestMetrics.cs b/src/WInterop.DirectX/DirectWrite/HitTestMetrics.cs
index c596963c..58ec1c01 100644
--- a/src/WInterop.DirectX/DirectWrite/HitTestMetrics.cs
+++ b/src/WInterop.DirectX/DirectWrite/HitTestMetrics.cs
@@ -43,14 +43,18 @@ public readonly struct HitTestMetrics
///
public readonly uint BidiLevel;
+ private readonly TerraFX.Interop.Windows.BOOL _isText;
+
///
/// Geometry encloses text?
///
- public readonly IntBoolean IsText;
+ public bool IsText => _isText;
+
+ private readonly TerraFX.Interop.Windows.BOOL _isTrimmed;
///
/// Range is trimmed.
///
- public readonly IntBoolean IsTrimmed;
+ public bool IsTrimmed => _isTrimmed;
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/IFactory.cs b/src/WInterop.DirectX/DirectWrite/IFactory.cs
deleted file mode 100644
index 3e8be9c6..00000000
--- a/src/WInterop.DirectX/DirectWrite/IFactory.cs
+++ /dev/null
@@ -1,386 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Globalization;
-using System.Numerics;
-using System.Runtime.InteropServices;
-using WInterop.Windows.Native;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The root factory interface for all DWrite objects. [IDWriteFactory]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteFactory),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IFactory
- {
- ///
- /// Gets a font collection representing the set of installed fonts.
- ///
- /// Receives a pointer to the system font collection object, or NULL in case of failure.
- /// If this parameter is nonzero, the function performs an immediate check for changes to the set of
- /// installed fonts. If this parameter is FALSE, the function will still detect changes if the font cache service is running, but
- /// there may be some latency. For example, an application might specify TRUE if it has itself just installed a font and wants to
- /// be sure the font collection contains that font.
- void GetSystemFontCollection(
- out IFontCollection fontCollection,
- IntBoolean checkForUpdates);
-
- ///
- /// Creates a font collection using a custom font collection loader.
- ///
- /// Application-defined font collection loader, which must have been previously
- /// registered using RegisterFontCollectionLoader.
- /// Key used by the loader to identify a collection of font files.
- /// Size in bytes of the collection key.
- /// Receives a pointer to the system font collection object, or NULL in case of failure.
- void CreateCustomFontCollectionSTUB();
- //STDMETHOD(CreateCustomFontCollection)(
- // _In_ IDWriteFontCollectionLoader* collectionLoader,
- // _In_reads_bytes_(collectionKeySize) void const* collectionKey,
- // UINT32 collectionKeySize,
- // _COM_Outptr_ IDWriteFontCollection** fontCollection
- // ) PURE;
-
- ///
- /// Registers a custom font collection loader with the factory object.
- ///
- /// Application-defined font collection loader.
- void RegisterFontCollectionLoaderSTUB();
- //STDMETHOD(RegisterFontCollectionLoader)(
- // _In_ IDWriteFontCollectionLoader* fontCollectionLoader
- // ) PURE;
-
- ///
- /// Unregisters a custom font collection loader that was previously registered using RegisterFontCollectionLoader.
- ///
- /// Application-defined font collection loader.
- ///
- /// Standard HRESULT error code.
- ///
- void UnregisterFontCollectionLoaderSTUB();
- //STDMETHOD(UnregisterFontCollectionLoader)(
- // _In_ IDWriteFontCollectionLoader* fontCollectionLoader
- // ) PURE;
-
- ///
- /// CreateFontFileReference creates a font file reference object from a local font file.
- ///
- /// Absolute file path. Subsequent operations on the constructed object may fail
- /// if the user provided filePath doesn't correspond to a valid file on the disk.
- /// Last modified time of the input file path. If the parameter is omitted,
- /// the function will access the font file to obtain its last write time, so the clients are encouraged to specify this value
- /// to avoid extra disk access. Subsequent operations on the constructed object may fail
- /// if the user provided lastWriteTime doesn't match the file on the disk.
- /// Contains newly created font file reference object, or NULL in case of failure.
- void CreateFontFileReferenceSTUB();
- //STDMETHOD(CreateFontFileReference)(
- // _In_z_ WCHAR const* filePath,
- // _In_opt_ FILETIME const* lastWriteTime,
- // _COM_Outptr_ IDWriteFontFile** fontFile
- // ) PURE;
-
- ///
- /// CreateCustomFontFileReference creates a reference to an application specific font file resource.
- /// This function enables an application or a document to use a font without having to install it on the system.
- /// The fontFileReferenceKey has to be unique only in the scope of the fontFileLoader used in this call.
- ///
- /// Font file reference key that uniquely identifies the font file resource
- /// during the lifetime of fontFileLoader.
- /// Size of font file reference key in bytes.
- /// Font file loader that will be used by the font system to load data from the file identified by
- /// fontFileReferenceKey.
- /// Contains the newly created font file object, or NULL in case of failure.
- ///
- /// Standard HRESULT error code.
- ///
- ///
- /// This function is provided for cases when an application or a document needs to use a font
- /// without having to install it on the system. fontFileReferenceKey has to be unique only in the scope
- /// of the fontFileLoader used in this call.
- ///
- void CreateCustomFontFileReferenceSTUB();
- //STDMETHOD(CreateCustomFontFileReference)(
- // _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey,
- // UINT32 fontFileReferenceKeySize,
- // _In_ IDWriteFontFileLoader* fontFileLoader,
- // _COM_Outptr_ IDWriteFontFile** fontFile
- // ) PURE;
-
- ///
- /// Creates a font face object.
- ///
- /// The file format of the font face.
- /// The number of font files required to represent the font face.
- /// Font files representing the font face. Since IDWriteFontFace maintains its own references
- /// to the input font file objects, it's OK to release them after this call.
- /// The zero based index of a font face in cases when the font files contain a collection of font faces.
- /// If the font files contain a single face, this value should be zero.
- /// Font face simulation flags for algorithmic emboldening and italicization.
- /// Contains the newly created font face object, or NULL in case of failure.
- void CreateFontFaceSTUB();
- //IFontFace CreateFontFace(
- // FontFaceType fontFaceType,
- // uint numberOfFiles,
- // _In_reads_(numberOfFiles) IDWriteFontFile* const* fontFiles,
- // uint faceIndex,
- // DWRITE_FONT_SIMULATIONS fontFaceSimulationFlags);
-
- ///
- /// Creates a rendering parameters object with default settings for the primary monitor.
- ///
- IRenderingParams CreateRenderingParams();
-
- ///
- /// Creates a rendering parameters object with default settings for the specified monitor.
- ///
- /// The monitor to read the default values from.
- IRenderingParams CreateMonitorRenderingParams(HMONITOR monitor);
-
- ///
- /// Creates a rendering parameters object with the specified properties.
- ///
- /// The gamma value used for gamma correction, which must be greater than zero and cannot exceed 256.
- /// The amount of contrast enhancement, zero or greater.
- /// The degree of ClearType level, from 0.0f (no ClearType) to 1.0f (full ClearType).
- /// The geometry of a device pixel.
- /// Method of rendering glyphs. In most cases, this should be DWRITE_RENDERING_MODE_DEFAULT to automatically use an appropriate mode.
- IRenderingParams CreateCustomRenderingParams(
- float gamma,
- float enhancedContrast,
- float clearTypeLevel,
- PixelGeometry pixelGeometry,
- RenderingMode renderingMode);
-
- ///
- /// Registers a font file loader with DirectWrite.
- ///
- /// Pointer to the implementation of the IDWriteFontFileLoader for a particular file resource type.
- ///
- /// This function registers a font file loader with DirectWrite.
- /// Font file loader interface handles loading font file resources of a particular type from a key.
- /// The font file loader interface is recommended to be implemented by a singleton object.
- /// A given instance can only be registered once.
- /// Succeeding attempts will return an error that it has already been registered.
- /// IMPORTANT: font file loader implementations must not register themselves with DirectWrite
- /// inside their constructors and must not unregister themselves in their destructors, because
- /// registration and unregistration operations increment and decrement the object reference count respectively.
- /// Instead, registration and unregistration of font file loaders with DirectWrite should be performed
- /// outside of the font file loader implementation as a separate step.
- ///
- void RegisterFontFileLoaderSTUB();
- //STDMETHOD(RegisterFontFileLoader)(
- // _In_ IDWriteFontFileLoader* fontFileLoader
- // ) PURE;
-
- ///
- /// Unregisters a font file loader that was previously registered with the DirectWrite font system using RegisterFontFileLoader.
- ///
- /// Pointer to the file loader that was previously registered with the DirectWrite font system using RegisterFontFileLoader.
- ///
- /// This function will succeed if the user loader is requested to be removed.
- /// It will fail if the pointer to the file loader identifies a standard DirectWrite loader,
- /// or a loader that is never registered or has already been unregistered.
- ///
- ///
- /// This function unregisters font file loader callbacks with the DirectWrite font system.
- /// The font file loader interface is recommended to be implemented by a singleton object.
- /// IMPORTANT: font file loader implementations must not register themselves with DirectWrite
- /// inside their constructors and must not unregister themselves in their destructors, because
- /// registration and unregistration operations increment and decrement the object reference count respectively.
- /// Instead, registration and unregistration of font file loaders with DirectWrite should be performed
- /// outside of the font file loader implementation as a separate step.
- ///
- void UnregisterFontFileLoaderSTUB();
- //STDMETHOD(UnregisterFontFileLoader)(
- // _In_ IDWriteFontFileLoader* fontFileLoader
- // ) PURE;
-
- ///
- /// Create a text format object used for text layout.
- ///
- /// Name of the font family
- /// Font collection. 'null' indicates the system font collection.
- /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
- /// Locale name
- ITextFormat CreateTextFormat(
- [MarshalAs(UnmanagedType.LPWStr)]
- string fontFamilyName,
- IFontCollection fontCollection,
- FontWeight fontWeight,
- FontStyle fontStyle,
- FontStretch fontStretch,
- float fontSize,
- [MarshalAs(UnmanagedType.LPWStr)]
- string localeName);
-
- ///
- /// Create a typography object used in conjunction with text format for text layout.
- ///
- ITypography CreateTypography();
-
- ///
- /// Create an object used for interoperability with GDI.
- ///
- /// Receives the GDI interop object if successful, or NULL in case of failure.
- ///
- /// Standard HRESULT error code.
- ///
- void GetGdiInteropSTUB();
- //STDMETHOD(GetGdiInterop)(
- // _COM_Outptr_ IDWriteGdiInterop** gdiInterop
- // ) PURE;
-
- ///
- /// CreateTextLayout takes a string, format, and associated constraints
- /// and produces an object representing the fully analyzed
- /// and formatted result.
- ///
- /// The string to layout.
- /// The length of the string.
- /// The format to apply to the string.
- /// Width of the layout box.
- /// Height of the layout box.
- /// The resultant object.
- unsafe ITextLayout CreateTextLayout(
- char* @string,
- uint stringLength,
- ITextFormat textFormat,
- float maxWidth,
- float maxHeight);
-
- ///
- /// CreateGdiCompatibleTextLayout takes a string, format, and associated constraints
- /// and produces and object representing the result formatted for a particular display resolution
- /// and measuring mode. The resulting text layout should only be used for the intended resolution,
- /// and for cases where text scalability is desired, CreateTextLayout should be used instead.
- ///
- /// The string to layout.
- /// The length of the string.
- /// The format to apply to the string.
- /// Width of the layout box.
- /// Height of the layout box.
- /// Number of physical pixels per DIP. For example, if rendering onto a 96 DPI device then pixelsPerDip
- /// is 1. If rendering onto a 120 DPI device then pixelsPerDip is 120/96.
- /// Optional transform applied to the glyphs and their positions. This transform is applied after the
- /// scaling specified the font size and pixelsPerDip.
- ///
- /// When set to FALSE, instructs the text layout to use the same metrics as GDI aliased text.
- /// When set to TRUE, instructs the text layout to use the same metrics as text measured by GDI using a font
- /// created with CLEARTYPE_NATURAL_QUALITY.
- ///
- /// The resultant object.
- ///
- /// Standard HRESULT error code.
- ///
- unsafe ITextLayout CreateGdiCompatibleTextLayout(
- [MarshalAs(UnmanagedType.LPWStr)]
- string @string,
- uint stringLength,
- ITextFormat textFormat,
- float layoutWidth,
- float layoutHeight,
- float pixelsPerDip,
- Matrix3x2* transform,
- IntBoolean useGdiNatural);
-
- ///
- /// The application may call this function to create an inline object for trimming, using an ellipsis as the
- /// omission sign. The ellipsis will be created using the current settings of the format, including base font,
- /// style, and any effects. Alternate omission signs can be created by the application by implementing
- /// IDWriteInlineObject.
- ///
- /// Text format used as a template for the omission sign.
- /// Created omission sign.
- IInlineObject CreateEllipsisTrimmingSign(ITextFormat textFormat);
-
- ///// The resultant object.
- ///
- /// Return an interface to perform text analysis with.
- ///
- void CreateTextAnalyzerSTUB();
- //STDMETHOD(CreateTextAnalyzer)(
- // _COM_Outptr_ IDWriteTextAnalyzer** textAnalyzer
- // ) PURE;
-
-
- ///// Method of number substitution to use.
- ///// Which locale to obtain the digits from.
- ///// Ignore the user's settings and use the locale defaults
- ///// Receives a pointer to the newly created object.
- ///
- /// Creates a number substitution object using a locale name,
- /// substitution method, and whether to ignore user overrides (uses NLS
- /// defaults for the given culture instead).
- ///
- void CreateNumberSubstitutionSTUB();
- //STDMETHOD(CreateNumberSubstitution)(
- // _In_ DWRITE_NUMBER_SUBSTITUTION_METHOD substitutionMethod,
- // _In_z_ WCHAR const* localeName,
- // _In_ BOOL ignoreUserOverride,
- // _COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution
- // ) PURE;
-
- ///
- /// Creates a glyph run analysis object, which encapsulates information
- /// used to render a glyph run.
- ///
- /// Structure specifying the properties of the glyph run.
- /// Number of physical pixels per DIP. For example, if rendering onto a 96 DPI bitmap then pixelsPerDip
- /// is 1. If rendering onto a 120 DPI bitmap then pixelsPerDip is 120/96.
- /// Optional transform applied to the glyphs and their positions. This transform is applied after the
- /// scaling specified by the emSize and pixelsPerDip.
- /// Specifies the rendering mode, which must be one of the raster rendering modes (i.e., not default
- /// and not outline).
- /// Specifies the method to measure glyphs.
- /// Horizontal position of the baseline origin, in DIPs.
- /// Vertical position of the baseline origin, in DIPs.
- /// Receives a pointer to the newly created object.
- void CreateGlyphRunAnalysisSTUB();
- //STDMETHOD(CreateGlyphRunAnalysis)(
- // _In_ DWRITE_GLYPH_RUN const* glyphRun,
- // FLOAT pixelsPerDip,
- // _In_opt_ DWRITE_MATRIX const* transform,
- // DWRITE_RENDERING_MODE renderingMode,
- // DWRITE_MEASURING_MODE measuringMode,
- // FLOAT baselineOriginX,
- // FLOAT baselineOriginY,
- // _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis
- // ) PURE;
-
- }
-
- public static class FactoryExtensions
- {
- public unsafe static ITextLayout CreateTextLayout(this IFactory factory, ReadOnlySpan text, ITextFormat textFormat, SizeF maxSize)
- {
- fixed (char* c = &MemoryMarshal.GetReference(text))
- {
- return factory.CreateTextLayout(c, (uint)text.Length, textFormat, maxSize.Width, maxSize.Height);
- }
- }
-
- public unsafe static ITextFormat CreateTextFormat(
- this IFactory factory,
- string fontFamilyName,
- FontWeight fontWeight = FontWeight.Normal,
- FontStyle fontStyle = FontStyle.Normal,
- FontStretch fontStretch = FontStretch.Normal,
- float fontSize = 12.0f,
- string localeName = null)
- {
- return factory.CreateTextFormat(
- fontFamilyName,
- fontCollection: null,
- fontWeight,
- fontStyle,
- fontStretch,
- fontSize,
- localeName ?? CultureInfo.CurrentCulture.Name);
- }
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/IFont.cs b/src/WInterop.DirectX/DirectWrite/IFont.cs
deleted file mode 100644
index e934cc1c..00000000
--- a/src/WInterop.DirectX/DirectWrite/IFont.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The interface represents a physical font in a font collection.
- /// [IDWriteFont]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteFont),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IFont
- {
- ///
- /// Gets the font family to which the specified font belongs.
- ///
- IFontFamily GetFontFamily();
-
- ///
- /// Gets the weight of the specified font.
- ///
- [PreserveSig]
- FontWeight GetWeight();
-
- ///
- /// Gets the stretch (aka. width) of the specified font.
- ///
- [PreserveSig]
- FontStretch GetStretch();
-
- ///
- /// Gets the style (aka. slope) of the specified font.
- ///
- [PreserveSig]
- FontStyle GetStyle();
-
- ///
- /// Returns TRUE if the font is a symbol font or FALSE if not.
- ///
- [PreserveSig]
- IntBoolean IsSymbolFont();
-
- ///
- /// Gets a localized strings collection containing the face names for the font (e.g., Regular or Bold), indexed by locale name.
- ///
- ///
- /// A pointer to the newly created localized strings object.
- ///
- ILocalizedStrings GetFaceNames();
-
- ///
- /// Gets a localized strings collection containing the specified informational strings, indexed by locale name.
- ///
- /// Identifies the string to get.
- /// Receives a pointer to the newly created localized strings object.
- /// Receives the value TRUE if the font contains the specified string ID or FALSE if not.
- ///
- /// Standard HRESULT error code. If the font does not contain the specified string, the return value is S_OK but
- /// informationalStrings receives a NULL pointer and exists receives the value FALSE.
- ///
- IntBoolean GetInformationalStrings(
- InformationalStringId informationalStringID,
- out ILocalizedStrings informationalStrings);
-
- ///
- /// Gets a value that indicates what simulation are applied to the specified font.
- ///
- [PreserveSig]
- FontSimulations GetSimulations();
-
- ///
- /// Gets the metrics for the font.
- ///
- /// Receives the font metrics.
- [PreserveSig]
- void GetMetrics(out FontMetrics fontMetrics);
-
- ///
- /// Determines whether the font supports the specified character.
- ///
- /// Unicode (UCS-4) character value.
- /// Receives the value TRUE if the font supports the specified character or FALSE if not.
- IntBoolean HasCharacter(uint unicodeValue);
-
- ///
- /// Creates a font face object for the font.
- ///
- ///
- /// S pointer to the newly created font face object.
- ///
- IFontFace CreateFontFace();
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/IFontCollection.cs b/src/WInterop.DirectX/DirectWrite/IFontCollection.cs
deleted file mode 100644
index 39f93bc2..00000000
--- a/src/WInterop.DirectX/DirectWrite/IFontCollection.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The IDWriteFontCollection encapsulates a collection of font families. [IDWriteFontCollection]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteFontCollection),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IFontCollection
- {
- ///
- /// Gets the number of font families in the collection.
- ///
- [PreserveSig]
- uint GetFontFamilyCount();
-
- ///
- /// Creates a font family object given a zero-based font family index.
- ///
- /// Zero-based index of the font family.
- IFontFamily GetFontFamily(uint index);
-
- ///
- /// Finds the font family with the specified family name.
- ///
- /// Name of the font family. The name is not case-sensitive but must otherwise exactly match a family name in the collection.
- /// Receives the zero-based index of the matching font family if the family name was found or UINT_MAX otherwise.
- IntBoolean FindFamilyName(
- [MarshalAs(UnmanagedType.LPWStr)]
- string familyName,
- out uint index);
-
- ///
- /// Gets the font object that corresponds to the same physical font as the specified font face object. The specified physical font must belong
- /// to the font collection.
- ///
- /// Font face object that specifies the physical font.
- IFont GetFontFromFontFace(IFontFace fontFace);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/IFontFace.cs b/src/WInterop.DirectX/DirectWrite/IFontFace.cs
deleted file mode 100644
index 0a38ebba..00000000
--- a/src/WInterop.DirectX/DirectWrite/IFontFace.cs
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Numerics;
-using System.Runtime.InteropServices;
-using WInterop.Direct2d;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// This interface exposes various font data such as metrics, names, and glyph outlines.
- /// It contains font face type, appropriate file references and face identification data.
- /// [IDWriteFontFace]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteFontFace),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IFontFace
- {
- ///
- /// Obtains the file format type of a font face.
- ///
- [PreserveSig]
- FontFaceType GetType();
-
- ///
- /// Obtains the font files representing a font face.
- ///
- /// The number of files representing the font face.
- /// User provided array that stores pointers to font files representing the font face.
- /// This parameter can be NULL if the user is only interested in the number of files representing the font face.
- /// This API increments reference count of the font file pointers returned according to COM conventions, and the client
- /// should release them when finished.
- ///
- /// Standard HRESULT error code.
- ///
- void GetFilesSTUB();
- //STDMETHOD(GetFiles)(
- // _Inout_ UINT32* numberOfFiles,
- // _Out_writes_opt_(*numberOfFiles) IDWriteFontFile** fontFiles
- //) PURE;
-
- ///
- /// Obtains the zero-based index of the font face in its font file or files. If the font files contain a single face,
- /// the return value is zero.
- ///
- [PreserveSig]
- uint GetIndex();
-
- ///
- /// Obtains the algorithmic style simulation flags of a font face.
- ///
- [PreserveSig]
- FontSimulations GetSimulations();
-
- ///
- /// Determines whether the font is a symbol font.
- ///
- [PreserveSig]
- IntBoolean IsSymbolFont();
-
- ///
- /// Obtains design units and common metrics for the font face.
- /// These metrics are applicable to all the glyphs within a fontface and are used by applications for layout calculations.
- ///
- /// Points to a DWRITE_FONT_METRICS structure to fill in.
- /// The metrics returned by this function are in font design units.
- [PreserveSig]
- void GetMetrics(out FontMetrics fontFaceMetrics);
-
- ///
- /// Obtains the number of glyphs in the font face.
- ///
- [PreserveSig]
- ushort GetGlyphCount();
-
- ///// An array of glyph indices to compute the metrics for.
- ///// The number of elements in the glyphIndices array.
- ///// Array of DWRITE_GLYPH_METRICS structures filled by this function.
- ///// The metrics returned by this function are in font design units.
- ///// Indicates whether the font is being used in a sideways run.
- ///// This can affect the glyph metrics if the font has oblique simulation
- ///// because sideways oblique simulation differs from non-sideways oblique simulation.
- ///
- /// Obtains ideal glyph metrics in font design units. Design glyphs metrics are used for glyph positioning.
- ///
- ///
- /// Standard HRESULT error code. If any of the input glyph indices are outside of the valid glyph index range
- /// for the current font face, E_INVALIDARG will be returned.
- ///
- void GetDesignGlyphMetricsSTUB();
- //STDMETHOD(GetDesignGlyphMetrics)(
- // _In_reads_(glyphCount) UINT16 const* glyphIndices,
- // UINT32 glyphCount,
- //_Out_writes_(glyphCount) DWRITE_GLYPH_METRICS* glyphMetrics,
- //BOOL isSideways = FALSE
- //) PURE;
-
- ///
- /// Returns the nominal mapping of UTF-32 Unicode code points to glyph indices as defined by the font 'cmap'
- /// table. Note that this mapping is primarily provided for line layout engines built on top of the physical
- /// font API. Because of OpenType glyph substitution and line layout character substitution, the nominal
- /// conversion does not always correspond to how a Unicode string will map to glyph indices when rendering
- /// using a particular font face. Also, note that Unicode Variation Selectors provide for alternate mappings
- /// for character to glyph. This call will always return the default variant.
- ///
- /// An array of UTF-32 code points to obtain nominal glyph indices from.
- /// The number of elements in the codePoints array.
- /// Array of nominal glyph indices filled by this function.
- ///
- /// Standard HRESULT error code.
- ///
- unsafe void GetGlyphIndices(
- uint* codePoints,
- uint codePointCount,
- ushort* glyphIndices);
-
- ///
- /// Finds the specified OpenType font table if it exists and returns a pointer to it.
- /// The function accesses the underlying font data via the IDWriteFontFileStream interface
- /// implemented by the font file loader.
- ///
- /// Four character tag of table to find.
- /// Use the DWRITE_MAKE_OPENTYPE_TAG() macro to create it.
- /// Unlike GDI, it does not support the special TTCF and null tags to access the whole font.
- ///
- /// Pointer to base of table in memory.
- /// The pointer is only valid so long as the FontFace used to get the font table still exists
- /// (not any other FontFace, even if it actually refers to the same physical font).
- ///
- /// Byte size of table.
- ///
- /// Opaque context which must be freed by calling ReleaseFontTable.
- /// The context actually comes from the lower level IDWriteFontFileStream,
- /// which may be implemented by the application or DWrite itself.
- /// It is possible for a NULL tableContext to be returned, especially if
- /// the implementation directly memory maps the whole file.
- /// Nevertheless, always release it later, and do not use it as a test for function success.
- /// The same table can be queried multiple times,
- /// but each returned context can be different, so release each separately.
- ///
- /// True if table exists.
- ///
- /// Standard HRESULT error code.
- /// If a table can not be found, the function will not return an error, but the size will be 0, table NULL, and exists = FALSE.
- /// The context does not need to be freed if the table was not found.
- ///
- ///
- /// The context for the same tag may be different for each call,
- /// so each one must be held and released separately.
- ///
- unsafe IntBoolean TryGetFontTable(
- uint openTypeTableTag,
- void** tableData,
- out uint tableSize,
- out IntPtr tableContext,
- out IntBoolean exists);
-
- ///
- /// Releases the table obtained earlier from TryGetFontTable.
- ///
- /// Opaque context from TryGetFontTable.
- [PreserveSig]
- void ReleaseFontTable(IntPtr tableContext);
-
- ///
- /// Computes the outline of a run of glyphs by calling back to the outline sink interface.
- ///
- /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
- /// Array of glyph indices.
- /// Optional array of glyph advances in DIPs.
- /// Optional array of glyph offsets.
- /// Number of glyphs.
- /// If true, specifies that glyphs are rotated 90 degrees to the left and vertical metrics are used.
- /// A client can render a vertical run by specifying isSideways = true and rotating the resulting geometry 90 degrees to the
- /// right using a transform.
- /// If true, specifies that the advance direction is right to left. By default, the advance direction
- /// is left to right.
- /// Interface the function calls back to draw each element of the geometry.
- unsafe void GetGlyphRunOutline(
- float emSize,
- ushort* glyphIndices,
- float* glyphAdvances,
- GlyphOffset* glyphOffsets,
- uint glyphCount,
- IntBoolean isSideways,
- IntBoolean isRightToLeft,
- IGeometrySink geometrySink);
-
- ///
- /// Determines the recommended rendering mode for the font given the specified size and rendering parameters.
- ///
- /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
- /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this
- /// value is 1.0f. If the DPI is 120, this value is 120.0f/96.
- /// Specifies measuring mode that will be used for glyphs in the font.
- /// Renderer implementations may choose different rendering modes for given measuring modes, but
- /// best results are seen when the corresponding modes match:
- /// for
- /// for
- /// for
- ///
- /// Rendering parameters object. This parameter is necessary in case the rendering parameters
- /// object overrides the rendering mode.
- ///
- /// The recommended rendering mode to use.
- ///
- RenderingMode GetRecommendedRenderingMode(
- float emSize,
- float pixelsPerDip,
- MeasuringMode measuringMode,
- IRenderingParams renderingParams);
-
- ///
- /// Obtains design units and common metrics for the font face.
- /// These metrics are applicable to all the glyphs within a fontface and are used by applications for layout calculations.
- ///
- /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
- /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this
- /// value is 1.0f. If the DPI is 120, this value is 120.0f/96.
- /// Optional transform applied to the glyphs and their positions. This transform is applied after the
- /// scaling specified by the font size and pixelsPerDip.
- unsafe FontMetrics GetGdiCompatibleMetrics(
- float emSize,
- float pixelsPerDip,
- Matrix3x2* transform);
-
- ///
- /// Obtains glyph metrics in font design units with the return values compatible with what GDI would produce.
- /// Glyphs metrics are used for positioning of individual glyphs.
- ///
- /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
- /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this
- /// value is 1.0f. If the DPI is 120, this value is 120.0f/96.
- /// Optional transform applied to the glyphs and their positions. This transform is applied after the
- /// scaling specified by the font size and pixelsPerDip.
- ///
- /// When set to FALSE, the metrics are the same as the metrics of GDI aliased text.
- /// When set to TRUE, the metrics are the same as the metrics of text measured by GDI using a font
- /// created with CLEARTYPE_NATURAL_QUALITY.
- ///
- /// An array of glyph indices to compute the metrics for.
- /// The number of elements in the glyphIndices array.
- /// Array of DWRITE_GLYPH_METRICS structures filled by this function.
- /// The metrics returned by this function are in font design units.
- /// Indicates whether the font is being used in a sideways run.
- /// This can affect the glyph metrics if the font has oblique simulation
- /// because sideways oblique simulation differs from non-sideways oblique simulation.
- unsafe void GetGdiCompatibleGlyphMetrics(
- float emSize,
- float pixelsPerDip,
- Matrix3x2* transform,
- IntBoolean useGdiNatural,
- in ushort glyphIndices,
- uint glyphCount,
- out GlyphMetrics glyphMetrics,
- IntBoolean isSideways);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/IFontFamily.cs b/src/WInterop.DirectX/DirectWrite/IFontFamily.cs
deleted file mode 100644
index 244b87cc..00000000
--- a/src/WInterop.DirectX/DirectWrite/IFontFamily.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The IDWriteFontFamily interface represents a set of fonts that share the same design but are differentiated
- /// by weight, stretch, and style. [IDWriteFontFamily]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteFontFamily),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IFontFamily : IFontList
- {
- #region IDWriteFontList
- ///
- /// Gets the font collection that contains the fonts.
- ///
- new IFontCollection GetFontCollection();
-
- ///
- /// Gets the number of fonts in the font list.
- ///
- [PreserveSig]
- new uint GetFontCount();
-
- ///
- /// Gets a font given its zero-based index.
- ///
- /// Zero-based index of the font in the font list.
- new IFont GetFont(uint index);
- #endregion
-
- ///
- /// Creates a localized strings object that contains the family names for the font family, indexed by locale name.
- ///
- ILocalizedStrings GetFamilyNames();
-
- ///
- /// Gets the font that best matches the specified properties.
- ///
- /// Requested font weight.
- /// Requested font stretch.
- /// Requested font style.
- IFont GetFirstMatchingFont(
- FontWeight weight,
- FontStretch stretch,
- FontStyle style);
-
- ///
- /// Gets a list of fonts in the font family ranked in order of how well they match the specified properties.
- ///
- /// Requested font weight.
- /// Requested font stretch.
- /// Requested font style.
- IFontList GetMatchingFonts(
- FontWeight weight,
- FontStretch stretch,
- FontStyle style);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/IFontList.cs b/src/WInterop.DirectX/DirectWrite/IFontList.cs
deleted file mode 100644
index 7876fe9d..00000000
--- a/src/WInterop.DirectX/DirectWrite/IFontList.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The interface represents an ordered set of fonts that are part of an .
- /// [IDWriteFontList]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteFontList),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IFontList
- {
- ///
- /// Gets the font collection that contains the fonts.
- ///
- IFontCollection GetFontCollection();
-
- ///
- /// Gets the number of fonts in the font list.
- ///
- [PreserveSig]
- uint GetFontCount();
-
- ///
- /// Gets a font given its zero-based index.
- ///
- /// Zero-based index of the font in the font list.
- IFont GetFont(uint index);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/IInlineObject.cs b/src/WInterop.DirectX/DirectWrite/IInlineObject.cs
deleted file mode 100644
index 31995a2f..00000000
--- a/src/WInterop.DirectX/DirectWrite/IInlineObject.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteInlineObject),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IInlineObject
- {
- ///
- /// The application implemented rendering callback (IDWriteTextRenderer::DrawInlineObject)
- /// can use this to draw the inline object without needing to cast or query the object
- /// type. The text layout does not call this method directly.
- ///
- /// The context passed to IDWriteTextLayout::Draw.
- /// The renderer passed to IDWriteTextLayout::Draw as the object's containing parent.
- /// X-coordinate at the top-left corner of the inline object.
- /// Y-coordinate at the top-left corner of the inline object.
- /// The object should be drawn on its side.
- /// The object is in an right-to-left context and should be drawn flipped.
- /// The drawing effect set in IDWriteTextLayout::SetDrawingEffect.
- void Draw(
- IntPtr clientDrawingContext,
- [MarshalAs(UnmanagedType.IUnknown)]
- object renderer, // TODO: IDWriteTextRenderer
- float originX,
- float originY,
- IntBoolean isSideways,
- IntBoolean isRightToLeft,
- [MarshalAs(UnmanagedType.IUnknown)]
- object clientDrawingEffect);
-
- ///
- /// TextLayout calls this callback function to get the measurement of the inline object.
- ///
- InlineObjectMetrics GetMetrics();
-
- ///
- /// TextLayout calls this callback function to get the visible extents (in DIPs) of the inline object.
- /// In the case of a simple bitmap, with no padding and no overhang, all the overhangs will simply be zeroes.
- ///
- /// Overshoot of visible extents (in DIPs) outside the object.
- ///
- /// The overhangs should be returned relative to the reported size of the object (DWRITE_INLINE_OBJECT_METRICS
- /// ::width/height), and should not be baseline adjusted. If you have an image that is actually 100x100 DIPs,
- /// but you want it slightly inset (perhaps it has a glow) by 20 DIPs on each side, you would return a
- /// width/height of 60x60 and four overhangs of 20 DIPs.
- ///
- OverhangMetrics GetOverhangMetrics();
-
- ///
- /// Layout uses this to determine the line breaking behavior of the inline object amidst the text.
- ///
- ///
- /// Line-breaking condition between the object and the content immediately preceding it.
- ///
- ///
- /// Line-breaking condition between the object and the content immediately following it.
- ///
- void GetBreakConditions(
- out BreakCondition breakConditionBefore,
- out BreakCondition breakConditionAfter);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/ILocalizedStrings.cs b/src/WInterop.DirectX/DirectWrite/ILocalizedStrings.cs
deleted file mode 100644
index d23c4893..00000000
--- a/src/WInterop.DirectX/DirectWrite/ILocalizedStrings.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// Represents a collection of strings indexed by locale name. [IDWriteLocalizedStrings]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteLocalizedStrings),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ILocalizedStrings
- {
- ///
- /// Gets the number of language/string pairs.
- ///
- [PreserveSig]
- uint GetCount();
-
- ///
- /// Gets the index of the item with the specified locale name.
- ///
- /// Locale name to look for.
- /// Receives the zero-based index of the locale name/string pair.
- /// TRUE if the locale name exists or FALSE if not.
- IntBoolean FindLocaleName(
- [MarshalAs(UnmanagedType.LPWStr)]
- string localeName,
- out uint index);
-
- ///
- /// Gets the length in characters (not including the null terminator) of the locale name with the specified index.
- ///
- /// Zero-based index of the locale name.
- /// Receives the length in characters, not including the null terminator.
- uint GetLocaleNameLength(uint index);
-
- ///
- /// Copies the locale name with the specified index to the specified array.
- ///
- /// Zero-based index of the locale name.
- /// Character array that receives the locale name.
- /// Size of the array in characters. The size must include space for the terminating
- /// null character.
- unsafe void GetLocaleName(
- uint index,
- char* localeName,
- uint size);
-
- ///
- /// Gets the length in characters (not including the null terminator) of the string with the specified index.
- ///
- /// Zero-based index of the string.
- ///
- /// The length in characters, not including the null terminator.
- ///
- uint GetStringLength(uint index);
-
- ///
- /// Copies the string with the specified index to the specified array.
- ///
- /// Zero-based index of the string.
- /// Character array that receives the string.
- /// Size of the array in characters. The size must include space for the terminating
- /// null character.
- ///
- /// Standard HRESULT error code.
- ///
- unsafe void GetString(
- uint index,
- char* stringBuffer,
- uint size);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/IPixelSnapping.cs b/src/WInterop.DirectX/DirectWrite/IPixelSnapping.cs
deleted file mode 100644
index 2f81be6a..00000000
--- a/src/WInterop.DirectX/DirectWrite/IPixelSnapping.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The interface defines the pixel snapping properties of a text renderer.
- /// [IDWritePixelSnapping]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWritePixelSnapping),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IPixelSnapping
- {
- ///
- /// Determines whether pixel snapping is disabled. The recommended default is FALSE,
- /// unless doing animation that requires subpixel vertical placement.
- ///
- /// The context passed to IDWriteTextLayout::Draw.
- IntBoolean IsPixelSnappingDisabled(IntPtr clientDrawingContext);
-
- ///
- /// Gets the current transform that maps abstract coordinates to DIPs,
- /// which may disable pixel snapping upon any rotation or shear.
- ///
- /// The context passed to IDWriteTextLayout::Draw.
- Matrix3x2 GetCurrentTransform(IntPtr clientDrawingContext);
-
- ///
- /// Gets the number of physical pixels per DIP. A DIP (device-independent pixel) is 1/96 inch,
- /// so the pixelsPerDip value is the number of logical pixels per inch divided by 96 (yielding
- /// a value of 1 for 96 DPI and 1.25 for 120).
- ///
- /// The context passed to IDWriteTextLayout::Draw.
- /// Receives the number of physical pixels per DIP.
- float GetPixelsPerDip(IntPtr clientDrawingContext);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/IRenderingParams.cs b/src/WInterop.DirectX/DirectWrite/IRenderingParams.cs
deleted file mode 100644
index 51f41ff5..00000000
--- a/src/WInterop.DirectX/DirectWrite/IRenderingParams.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The interface that represents text rendering settings for glyph rasterization and filtering.
- /// [IDWriteRenderingParams]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteRenderingParams),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IRenderingParams
- {
- ///
- /// Gets the gamma value used for gamma correction. Valid values must be
- /// greater than zero and cannot exceed 256.
- ///
- [PreserveSig]
- float GetGamma();
-
- ///
- /// Gets the amount of contrast enhancement. Valid values are greater than
- /// or equal to zero.
- ///
- [PreserveSig]
- float GetEnhancedContrast();
-
- ///
- /// Gets the ClearType level. Valid values range from 0.0f (no ClearType)
- /// to 1.0f (full ClearType).
- ///
- [PreserveSig]
- float GetClearTypeLevel();
-
- ///
- /// Gets the pixel geometry.
- ///
- [PreserveSig]
- PixelGeometry GetPixelGeometry();
-
- ///
- /// Gets the rendering mode.
- ///
- [PreserveSig]
- RenderingMode GetRenderingMode();
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/ITextFormat.cs b/src/WInterop.DirectX/DirectWrite/ITextFormat.cs
deleted file mode 100644
index a9c05449..00000000
--- a/src/WInterop.DirectX/DirectWrite/ITextFormat.cs
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The format of text used for text layout. [IDWriteTextFormat]
- ///
- ///
- /// This object may not be thread-safe and it may carry the state of text format change.
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteTextFormat),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITextFormat
- {
- ///
- /// Set alignment option of text relative to layout box's leading and trailing edge.
- ///
- /// Text alignment option
- ///
- /// Standard HRESULT error code.
- ///
- void SetTextAlignment(TextAlignment textAlignment);
-
- ///
- /// Set alignment option of paragraph relative to layout box's top and bottom edge.
- ///
- /// Paragraph alignment option
- void SetParagraphAlignment(ParagraphAlignment paragraphAlignment);
-
- ///
- /// Set word wrapping option.
- ///
- /// Word wrapping option
- void SetWordWrapping(WordWrapping wordWrapping);
-
- ///
- /// Set paragraph reading direction.
- ///
- /// Text reading direction
- ///
- /// The flow direction must be perpendicular to the reading direction. Setting both to a vertical direction
- /// or both to horizontal yields DWRITE_E_FLOWDIRECTIONCONFLICTS when calling GetMetrics or Draw.
- ///
- void SetReadingDirection(ReadingDirection readingDirection);
-
- ///
- /// Set paragraph flow direction.
- ///
- /// Paragraph flow direction
- ///
- /// The flow direction must be perpendicular to the reading direction. Setting both to a vertical direction
- /// or both to horizontal yields DWRITE_E_FLOWDIRECTIONCONFLICTS when calling GetMetrics or Draw.
- ///
- void SetFlowDirection(FlowDirection flowDirection);
-
- ///
- /// Set incremental tab stop position.
- ///
- /// The incremental tab stop value
- void SetIncrementalTabStop(float incrementalTabStop);
-
- ///
- /// Set trimming options for any trailing text exceeding the layout width or for any far text exceeding the
- /// layout height.
- ///
- /// Text trimming options.
- ///
- /// Application-defined omission sign. This parameter may be NULL if no trimming sign is desired.
- ///
- ///
- /// Any inline object can be used for the trimming sign, but CreateEllipsisTrimmingSign provides a typical
- /// ellipsis symbol. Trimming is also useful vertically for hiding partial lines.
- ///
- void SetTrimming(
- in Trimming trimmingOptions,
- IInlineObject trimmingSign);
-
- ///
- /// Set line spacing.
- ///
- /// How to determine line height.
- /// The line height, or rather distance between one baseline to another.
- /// Distance from top of line to baseline. A reasonable ratio to lineSpacing is 80%.
- ///
- /// For the default method, spacing depends solely on the content. For uniform spacing, the given line height
- /// will override the content.
- ///
- void SetLineSpacing(
- LineSpacingMethod lineSpacingMethod,
- float lineSpacing,
- float baseline);
-
- ///
- /// Get alignment option of text relative to layout box's leading and trailing edge.
- ///
- [PreserveSig]
- TextAlignment GetTextAlignment();
-
- ///
- /// Get alignment option of paragraph relative to layout box's top and bottom edge.
- ///
- [PreserveSig]
- ParagraphAlignment GetParagraphAlignment();
-
- ///
- /// Get word wrapping option.
- ///
- [PreserveSig]
- WordWrapping GetWordWrapping();
-
- ///
- /// Get paragraph reading direction.
- ///
- [PreserveSig]
- ReadingDirection GetReadingDirection();
-
- ///
- /// Get paragraph flow direction.
- ///
- [PreserveSig]
- FlowDirection GetFlowDirection();
-
- ///
- /// Get incremental tab stop position.
- ///
- [PreserveSig]
- float GetIncrementalTabStop();
-
- ///
- /// Get trimming options for text overflowing the layout width.
- ///
- /// Text trimming options.
- IInlineObject GetTrimming(out Trimming trimmingOptions);
-
- ///
- /// Get line spacing.
- ///
- /// How line height is determined.
- /// The line height, or rather distance between one baseline to another.
- /// Distance from top of line to baseline.
- void GetLineSpacing(
- out LineSpacingMethod lineSpacingMethod,
- out float lineSpacing,
- out float baseline);
-
- ///
- /// Get the font collection.
- ///
- IFontCollection GetFontCollection();
-
- ///
- /// Get the length of the font family name, in characters, not including the terminating NULL character.
- ///
- [PreserveSig]
- uint GetFontFamilyNameLength();
-
- ///
- /// Get a copy of the font family name.
- ///
- /// Character array that receives the current font family name
- /// Size of the character array in character count including the terminated NULL character.
- unsafe void GetFontFamilyName(
- char* fontFamilyName,
- uint nameSize);
-
- ///
- /// Get the font weight.
- ///
- [PreserveSig]
- FontWeight GetFontWeight();
-
- ///
- /// Get the font style.
- ///
- [PreserveSig]
- FontStyle GetFontStyle();
-
- ///
- /// Get the font stretch.
- ///
- [PreserveSig]
- FontStretch GetFontStretch();
-
- ///
- /// Get the font em height.
- ///
- [PreserveSig]
- float GetFontSize();
-
- ///
- /// Get the length of the locale name, in characters, not including the terminating NULL character.
- ///
- [PreserveSig]
- uint GetLocaleNameLength();
-
- ///
- /// Get a copy of the locale name.
- ///
- /// Character array that receives the current locale name
- /// Size of the character array in character count including the terminated NULL character.
- unsafe void GetLocaleName(
- char* localeName,
- uint nameSize);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/ITextLayout.cs b/src/WInterop.DirectX/DirectWrite/ITextLayout.cs
deleted file mode 100644
index 67eaf80d..00000000
--- a/src/WInterop.DirectX/DirectWrite/ITextLayout.cs
+++ /dev/null
@@ -1,710 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Drawing;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The IDWriteTextLayout interface represents a block of text after it has
- /// been fully analyzed and formatted. [IDWriteTextLayout]
- ///
- /// All coordinates are in device independent pixels (DIPs).
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteTextLayout),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITextLayout : ITextFormat
- {
- #region IID_IDWriteTextFormat
- ///
- /// Set alignment option of text relative to layout box's leading and trailing edge.
- ///
- /// Text alignment option
- ///
- /// Standard HRESULT error code.
- ///
- new void SetTextAlignment(TextAlignment textAlignment);
-
- ///
- /// Set alignment option of paragraph relative to layout box's top and bottom edge.
- ///
- /// Paragraph alignment option
- new void SetParagraphAlignment(ParagraphAlignment paragraphAlignment);
-
- ///
- /// Set word wrapping option.
- ///
- /// Word wrapping option
- new void SetWordWrapping(WordWrapping wordWrapping);
-
- ///
- /// Set paragraph reading direction.
- ///
- /// Text reading direction
- ///
- /// The flow direction must be perpendicular to the reading direction. Setting both to a vertical direction
- /// or both to horizontal yields DWRITE_E_FLOWDIRECTIONCONFLICTS when calling GetMetrics or Draw.
- ///
- new void SetReadingDirection(ReadingDirection readingDirection);
-
- ///
- /// Set paragraph flow direction.
- ///
- /// Paragraph flow direction
- ///
- /// The flow direction must be perpendicular to the reading direction. Setting both to a vertical direction
- /// or both to horizontal yields DWRITE_E_FLOWDIRECTIONCONFLICTS when calling GetMetrics or Draw.
- ///
- new void SetFlowDirection(FlowDirection flowDirection);
-
- ///
- /// Set incremental tab stop position.
- ///
- /// The incremental tab stop value
- new void SetIncrementalTabStop(float incrementalTabStop);
-
- ///
- /// Set trimming options for any trailing text exceeding the layout width or for any far text exceeding the
- /// layout height.
- ///
- /// Text trimming options.
- ///
- /// Application-defined omission sign. This parameter may be NULL if no trimming sign is desired.
- ///
- ///
- /// Any inline object can be used for the trimming sign, but CreateEllipsisTrimmingSign provides a typical
- /// ellipsis symbol. Trimming is also useful vertically for hiding
- /// partial lines.
- ///
- new void SetTrimming(
- in Trimming trimmingOptions,
- IInlineObject trimmingSign);
-
- ///
- /// Set line spacing.
- ///
- /// How to determine line height.
- /// The line height, or rather distance between one baseline to another.
- /// Distance from top of line to baseline. A reasonable ratio to lineSpacing is 80%.
- ///
- /// For the default method, spacing depends solely on the content.
- /// For uniform spacing, the given line height will override the content.
- ///
- new void SetLineSpacing(
- LineSpacingMethod lineSpacingMethod,
- float lineSpacing,
- float baseline);
-
- ///
- /// Get alignment option of text relative to layout box's leading and trailing edge.
- ///
- [PreserveSig]
- new TextAlignment GetTextAlignment();
-
- ///
- /// Get alignment option of paragraph relative to layout box's top and bottom edge.
- ///
- [PreserveSig]
- new ParagraphAlignment GetParagraphAlignment();
-
- ///
- /// Get word wrapping option.
- ///
- [PreserveSig]
- new WordWrapping GetWordWrapping();
-
- ///
- /// Get paragraph reading direction.
- ///
- [PreserveSig]
- new ReadingDirection GetReadingDirection();
-
- ///
- /// Get paragraph flow direction.
- ///
- [PreserveSig]
- new FlowDirection GetFlowDirection();
-
- ///
- /// Get incremental tab stop position.
- ///
- [PreserveSig]
- new float GetIncrementalTabStop();
-
- ///
- /// Get trimming options for text overflowing the layout width.
- ///
- /// Text trimming options.
- new IInlineObject GetTrimming(out Trimming trimmingOptions);
-
- ///
- /// Get line spacing.
- ///
- /// How line height is determined.
- /// The line height, or rather distance between one baseline to another.
- /// Distance from top of line to baseline.
- new void GetLineSpacing(
- out LineSpacingMethod lineSpacingMethod,
- out float lineSpacing,
- out float baseline);
-
- ///
- /// Get the font collection.
- ///
- new IFontCollection GetFontCollection();
-
- ///
- /// Get the length of the font family name, in characters, not including the terminating NULL character.
- ///
- [PreserveSig]
- new uint GetFontFamilyNameLength();
-
- ///
- /// Get a copy of the font family name.
- ///
- /// Character array that receives the current font family name
- /// Size of the character array in character count including the terminated NULL character.
- new unsafe void GetFontFamilyName(
- char* fontFamilyName,
- uint nameSize);
-
- ///
- /// Get the font weight.
- ///
- [PreserveSig]
- new FontWeight GetFontWeight();
-
- ///
- /// Get the font style.
- ///
- [PreserveSig]
- new FontStyle GetFontStyle();
-
- ///
- /// Get the font stretch.
- ///
- [PreserveSig]
- new FontStretch GetFontStretch();
-
- ///
- /// Get the font em height.
- ///
- [PreserveSig]
- new float GetFontSize();
-
- ///
- /// Get the length of the locale name, in characters, not including the terminating NULL character.
- ///
- [PreserveSig]
- new uint GetLocaleNameLength();
-
- ///
- /// Get a copy of the locale name.
- ///
- /// Character array that receives the current locale name
- /// Size of the character array in character count including the terminated NULL character.
- new unsafe void GetLocaleName(
- char* localeName,
- uint nameSize);
- #endregion
-
- ///
- /// Set layout maximum width
- ///
- /// Layout maximum width
- void SetMaxWidth(float maxWidth);
-
- ///
- /// Set layout maximum height
- ///
- /// Layout maximum height
- void SetMaxHeight(float maxHeight);
-
- ///
- /// Set the font collection.
- ///
- /// The font collection to set
- /// Text range to which this change applies.
- void SetFontCollection(
- IFontCollection fontCollection,
- TextRange textRange);
-
- ///
- /// Set null-terminated font family name.
- ///
- /// Font family name
- /// Text range to which this change applies.
- void SetFontFamilyName(
- [MarshalAs(UnmanagedType.LPWStr)]
- string fontFamilyName,
- TextRange textRange);
-
- ///
- /// Set font weight.
- ///
- /// Font weight
- /// Text range to which this change applies.
- void SetFontWeight(
- FontWeight fontWeight,
- TextRange textRange);
-
- ///
- /// Set font style.
- ///
- /// Font style
- /// Text range to which this change applies.
- void SetFontStyle(
- FontStyle fontStyle,
- TextRange textRange);
-
- ///
- /// Set font stretch.
- ///
- /// font stretch
- /// Text range to which this change applies.
- void SetFontStretch(
- FontStretch fontStretch,
- TextRange textRange);
-
- ///
- /// Set font em height.
- ///
- /// Font em height
- /// Text range to which this change applies.
- void SetFontSize(
- float fontSize,
- TextRange textRange);
-
- ///
- /// Set underline.
- ///
- /// The Boolean flag indicates whether underline takes place
- /// Text range to which this change applies.
- void SetUnderline(
- IntBoolean hasUnderline,
- TextRange textRange);
-
- ///
- /// Set strikethrough.
- ///
- /// The Boolean flag indicates whether strikethrough takes place
- /// Text range to which this change applies.
- void SetStrikethrough(
- IntBoolean hasStrikethrough,
- TextRange textRange);
-
- ///
- /// Set application-defined drawing effect.
- ///
- /// Pointer to an application-defined drawing effect.
- /// Text range to which this change applies.
- ///
- /// This drawing effect is associated with the specified range and will be passed back
- /// to the application via the callback when the range is drawn at drawing time.
- ///
- void SetDrawingEffect(
- [MarshalAs(UnmanagedType.IUnknown)]
- object drawingEffect,
- TextRange textRange);
-
- ///
- /// Set inline object.
- ///
- /// Pointer to an application-implemented inline object.
- /// Text range to which this change applies.
- ///
- /// This inline object applies to the specified range and will be passed back
- /// to the application via the DrawInlineObject callback when the range is drawn.
- /// Any text in that range will be suppressed.
- ///
- void SetInlineObject(
- IInlineObject inlineObject,
- TextRange textRange);
-
- ///
- /// Set font typography features.
- ///
- /// Pointer to font typography setting.
- /// Text range to which this change applies.
- void SetTypography(
- ITypography typography,
- TextRange textRange);
-
- ///
- /// Set locale name.
- ///
- /// Locale name
- /// Text range to which this change applies.
- void SetLocaleName(
- [MarshalAs(UnmanagedType.LPWStr)]
- string localeName,
- TextRange textRange);
-
- ///
- /// Get layout maximum width
- ///
- [PreserveSig]
- float GetMaxWidth();
-
- ///
- /// Get layout maximum height
- ///
- [PreserveSig]
- float GetMaxHeight();
-
- ///
- /// Get the font collection where the current position is at.
- ///
- /// The current text position.
- /// The current font collection
- /// Text range to which this change applies.
- unsafe void GetFontCollection(
- uint currentPosition,
- out IFontCollection fontCollection,
- TextRange* textRange);
-
- ///
- /// Get the length of the font family name where the current position is at.
- ///
- /// The current text position.
- /// Size of the character array in character count not including the terminated NULL character.
- /// The position range of the current format.
- unsafe void GetFontFamilyNameLength(
- uint currentPosition,
- out uint nameLength,
- TextRange* textRange);
-
- ///
- /// Copy the font family name where the current position is at.
- ///
- /// The current text position.
- /// Character array that receives the current font family name
- /// Size of the character array in character count including the terminated NULL character.
- /// The position range of the current format.
- unsafe void GetFontFamilyName(
- uint currentPosition,
- char* fontFamilyName,
- uint nameSize,
- TextRange* textRange);
-
- ///
- /// Get the font weight where the current position is at.
- ///
- /// The current text position.
- /// The current font weight
- /// The position range of the current format.
- unsafe void GetFontWeight(
- uint currentPosition,
- out FontWeight fontWeight,
- TextRange* textRange);
-
- ///
- /// Get the font style where the current position is at.
- ///
- /// The current text position.
- /// The current font style
- /// The position range of the current format.
- ///
- /// Standard HRESULT error code.
- ///
- unsafe void GetFontStyle(
- uint currentPosition,
- out FontStyle fontStyle,
- TextRange* textRange);
-
- ///
- /// Get the font stretch where the current position is at.
- ///
- /// The current text position.
- /// The current font stretch
- /// The position range of the current format.
- unsafe void GetFontStretch(
- uint currentPosition,
- out FontStretch fontStretch,
- TextRange* textRange);
-
- ///
- /// Get the font em height where the current position is at.
- ///
- /// The current text position.
- /// The current font em height
- /// The position range of the current format.
- unsafe void GetFontSize(
- uint currentPosition,
- out float fontSize,
- TextRange* textRange);
-
- ///
- /// Get the underline presence where the current position is at.
- ///
- /// The current text position.
- /// The Boolean flag indicates whether text is underlined.
- /// The position range of the current format.
-
- unsafe void GetUnderline(
- uint currentPosition,
- out IntBoolean hasUnderline,
- TextRange* textRange);
-
- ///
- /// Get the strikethrough presence where the current position is at.
- ///
- /// The current text position.
- /// The Boolean flag indicates whether text has strikethrough.
- /// The position range of the current format.
- unsafe void GetStrikethrough(
- uint currentPosition,
- out IntBoolean hasStrikethrough,
- TextRange* textRange);
-
- ///
- /// Get the application-defined drawing effect where the current position is at.
- ///
- /// The current text position.
- /// The current application-defined drawing effect.
- /// The position range of the current format.
- unsafe void GetDrawingEffect(
- uint currentPosition,
- [MarshalAs(UnmanagedType.IUnknown)]
- out object drawingEffect,
- TextRange* textRange);
-
- ///
- /// Get the inline object at the given position.
- ///
- /// The given text position.
- /// The inline object.
- /// The position range of the current format.
- unsafe void GetInlineObject(
- uint currentPosition,
- out IInlineObject inlineObject,
- TextRange* textRange);
-
- ///
- /// Get the typography setting where the current position is at.
- ///
- /// The current text position.
- /// The current typography setting.
- /// The position range of the current format.
- unsafe void GetTypography(
- uint currentPosition,
- out ITypography typography,
- TextRange* textRange);
-
- ///
- /// Get the length of the locale name where the current position is at.
- ///
- /// The current text position.
- /// Size of the character array in character count not including the terminated NULL character.
- /// The position range of the current format.
- unsafe void GetLocaleNameLength(
- uint currentPosition,
- out uint nameLength,
- TextRange* textRange);
-
- ///
- /// Get the locale name where the current position is at.
- ///
- /// The current text position.
- /// Character array that receives the current locale name
- /// Size of the character array in character count including the terminated NULL character.
- /// The position range of the current format.
- unsafe void GetLocaleName(
- uint currentPosition,
- char* localeName,
- uint nameSize,
- TextRange* textRange);
-
- ///
- /// Initiate drawing of the text.
- ///
- /// An application defined value
- /// included in rendering callbacks.
- /// The set of application-defined callbacks that do
- /// the actual rendering.
- /// X-coordinate of the layout's left side.
- /// Y-coordinate of the layout's top side.
- void Draw(
- IntPtr clientDrawingContext,
- ITextRenderer renderer,
- float originX,
- float originY);
-
- ///
- /// GetLineMetrics returns properties of each line.
- ///
- /// The array to fill with line information.
- /// The maximum size of the lineMetrics array.
- /// The actual size of the lineMetrics
- /// array that is needed.
- ///
- /// If maxLineCount is not large enough E_NOT_SUFFICIENT_BUFFER,
- /// which is equivalent to HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER),
- /// is returned and *actualLineCount is set to the number of lines
- /// needed.
- ///
- unsafe void GetLineMetrics(
- LineMetrics* lineMetrics,
- uint maxLineCount,
- out uint actualLineCount);
-
- ///
- /// GetMetrics retrieves overall metrics for the formatted string.
- ///
- ///
- /// Drawing effects like underline and strikethrough do not contribute to the text size, which is essentially
- /// the sum of advance widths and line heights. Additionally, visible swashes and other graphic adornments
- /// may extend outside the returned width and height.
- ///
- TextMetrics GetMetrics();
-
- ///
- /// GetOverhangMetrics returns the overhangs (in DIPs) of the layout and all objects contained in it,
- /// including text glyphs and inline objects.
- ///
- /// Overshoots of visible extents (in DIPs) outside the layout.
- ///
- /// Any underline and strikethrough do not contribute to the black box determination, since these are
- /// actually drawn by the renderer, which is allowed to draw them in any variety of styles.
- ///
- OverhangMetrics GetOverhangMetrics();
-
- ///
- /// Retrieve logical properties and measurement of each cluster.
- ///
- /// The array to fill with cluster information.
- /// The maximum size of the clusterMetrics array.
- /// The actual size of the clusterMetrics array that is needed.
- ///
- /// If maxClusterCount is not large enough E_NOT_SUFFICIENT_BUFFER,
- /// which is equivalent to HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER),
- /// is returned and *actualClusterCount is set to the number of clusters
- /// needed.
- ///
- unsafe void GetClusterMetrics(
- ClusterMetrics* clusterMetrics,
- uint maxClusterCount,
- out uint actualClusterCount);
-
- ///
- /// Determines the minimum possible width the layout can be set to without emergency breaking between
- /// the characters of whole words.
- ///
- float DetermineMinWidth();
-
- ///
- /// Given a coordinate (in DIPs) relative to the top-left of the layout box, this returns the corresponding
- /// hit-test metrics of the text string where the hit-test has occurred. This is useful for mapping mouse
- /// clicks to caret positions. When the given coordinate is outside the text string, the function sets the
- /// output value *isInside to false but returns the nearest character position.
- ///
- /// X coordinate to hit-test, relative to the top-left location of the layout box.
- /// Y coordinate to hit-test, relative to the top-left location of the layout box.
- ///
- /// Output flag indicating whether the hit-test location is at the leading or the trailing side of the
- /// character. When is set to false, this value is set according to the output
- /// *position value to represent the edge closest to the hit-test location.
- ///
- ///
- /// Output flag indicating whether the hit-test location is inside the text string. When false, the position
- /// nearest the text's edge is returned.
- ///
- /// Output geometry fully enclosing the hit-test location. When the output value
- /// is set to false, this structure represents the geometry enclosing the edge closest to the hit-test
- /// location.
- ///
- HitTestMetrics HitTestPoint(
- float pointX,
- float pointY,
- out IntBoolean isTrailingHit,
- out IntBoolean isInside);
-
- ///
- /// Given a text position and whether the caret is on the leading or trailing
- /// edge of that position, this returns the corresponding coordinate (in DIPs)
- /// relative to the top-left of the layout box. This is most useful for drawing
- /// the caret's current position, but it could also be used to anchor an IME to the
- /// typed text or attach a floating menu near the point of interest. It may also be
- /// used to programmatically obtain the geometry of a particular text position
- /// for UI automation.
- ///
- /// Text position to get the coordinate of.
- /// Flag indicating whether the location is of the leading or the trailing side of the specified text position.
- /// Output caret X, relative to the top-left of the layout box.
- /// Output caret Y, relative to the top-left of the layout box.
- /// Output geometry fully enclosing the specified text position.
- ///
- /// When drawing a caret at the returned X,Y, it should be centered on X
- /// and drawn from the Y coordinate down. The height will be the size of the
- /// hit-tested text (which can vary in size within a line).
- /// Reading direction also affects which side of the character the caret is drawn.
- /// However, the returned X coordinate will be correct for either case.
- /// You can get a text length back that is larger than a single character.
- /// This happens for complex scripts when multiple characters form a single cluster,
- /// when diacritics join their base character, or when you test a surrogate pair.
- ///
- HitTestMetrics HitTestTextPosition(
- uint textPosition,
- IntBoolean isTrailingHit,
- out float pointX,
- out float pointY);
-
- ///
- /// The application calls this function to get a set of hit-test metrics
- /// corresponding to a range of text positions. The main usage for this
- /// is to draw highlighted selection of the text string.
- ///
- /// The function returns E_NOT_SUFFICIENT_BUFFER, which is equivalent to
- /// HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), when the buffer size of
- /// hitTestMetrics is too small to hold all the regions calculated by the
- /// function. In such situation, the function sets the output value
- /// *actualHitTestMetricsCount to the number of geometries calculated.
- /// The application is responsible to allocate a new buffer of greater
- /// size and call the function again.
- ///
- /// A good value to use as an initial value for maxHitTestMetricsCount may
- /// be calculated from the following equation:
- /// maxHitTestMetricsCount = lineCount * maxBidiReorderingDepth
- ///
- /// where lineCount is obtained from the value of the output argument
- /// *actualLineCount from the function IDWriteTextLayout::GetLineMetrics,
- /// and the maxBidiReorderingDepth value from the DWRITE_TEXT_METRICS
- /// structure of the output argument *textMetrics from the function
- /// .
- ///
- /// First text position of the specified range.
- /// Number of positions of the specified range.
- /// Offset of the X origin (left of the layout box) which is added to each of the hit-test metrics returned.
- /// Offset of the Y origin (top of the layout box) which is added to each of the hit-test metrics returned.
- /// Pointer to a buffer of the output geometry fully enclosing the specified position range.
- /// Maximum number of distinct metrics it could hold in its buffer memory.
- /// Actual number of metrics returned or needed.
- ///
- /// There are no gaps in the returned metrics. While there could be visual gaps,
- /// depending on bidi ordering, each range is contiguous and reports all the text,
- /// including any hidden characters and trimmed text.
- /// The height of each returned range will be the same within each line, regardless
- /// of how the font sizes vary.
- ///
- unsafe void HitTestTextRange(
- uint textPosition,
- uint textLength,
- float originX,
- float originY,
- HitTestMetrics* hitTestMetrics,
- uint maxHitTestMetricsCount,
- out uint actualHitTestMetricsCount);
- }
-
- public static class TextLayoutExtensions
- {
- public static void SetMaxSize(this ITextLayout textLayout, SizeF maxSize)
- {
- textLayout.SetMaxHeight(maxSize.Height);
- textLayout.SetMaxWidth(maxSize.Width);
- }
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/ITextRenderer.cs b/src/WInterop.DirectX/DirectWrite/ITextRenderer.cs
deleted file mode 100644
index 1538d0a3..00000000
--- a/src/WInterop.DirectX/DirectWrite/ITextRenderer.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// The interface represents a set of application-defined
- /// callbacks that perform rendering of text, inline objects, and decorations
- /// such as underlines. [IDWriteTextRenderer]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteTextRenderer),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITextRenderer : IPixelSnapping
- {
- #region IDWritePixelSnapping
- ///
- /// Determines whether pixel snapping is disabled. The recommended default is FALSE,
- /// unless doing animation that requires subpixel vertical placement.
- ///
- /// The context passed to IDWriteTextLayout::Draw.
- new IntBoolean IsPixelSnappingDisabled(IntPtr clientDrawingContext);
-
- ///
- /// Gets the current transform that maps abstract coordinates to DIPs,
- /// which may disable pixel snapping upon any rotation or shear.
- ///
- /// The context passed to IDWriteTextLayout::Draw.
- new Matrix3x2 GetCurrentTransform(IntPtr clientDrawingContext);
-
- ///
- /// Gets the number of physical pixels per DIP. A DIP (device-independent pixel) is 1/96 inch,
- /// so the pixelsPerDip value is the number of logical pixels per inch divided by 96 (yielding
- /// a value of 1 for 96 DPI and 1.25 for 120).
- ///
- /// The context passed to IDWriteTextLayout::Draw.
- /// Receives the number of physical pixels per DIP.
- new float GetPixelsPerDip(IntPtr clientDrawingContext);
- #endregion
-
- ///
- /// IDWriteTextLayout::Draw calls this function to instruct the client to
- /// render a run of glyphs.
- ///
- /// The context passed to
- /// IDWriteTextLayout::Draw.
- /// X-coordinate of the baseline.
- /// Y-coordinate of the baseline.
- /// Specifies measuring mode for glyphs in the run.
- /// Renderer implementations may choose different rendering modes for given measuring modes,
- /// but best results are seen when the rendering mode matches the corresponding measuring mode:
- /// DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL for DWRITE_MEASURING_MODE_NATURAL
- /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC for DWRITE_MEASURING_MODE_GDI_CLASSIC
- /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL for DWRITE_MEASURING_MODE_GDI_NATURAL
- ///
- /// The glyph run to draw.
- /// Properties of the characters associated with this run.
- /// The drawing effect set in
- void DrawGlyphRun(
- IntPtr clientDrawingContext,
- float baselineOriginX,
- float baselineOriginY,
- MeasuringMode measuringMode,
- in GlyphRun glyphRun,
- in GlyphRunDescription glyphRunDescription,
- [MarshalAs(UnmanagedType.IUnknown)]
- object clientDrawingEffect);
-
- ///
- /// IDWriteTextLayout::Draw calls this function to instruct the client to draw
- /// an underline.
- ///
- /// The context passed to
- /// IDWriteTextLayout::Draw.
- /// X-coordinate of the baseline.
- /// Y-coordinate of the baseline.
- /// Underline logical information.
- /// The drawing effect set in
- /// IDWriteTextLayout::SetDrawingEffect.
- ///
- /// A single underline can be broken into multiple calls, depending on
- /// how the formatting changes attributes. If font sizes/styles change
- /// within an underline, the thickness and offset will be averaged
- /// weighted according to characters.
- /// To get the correct top coordinate of the underline rect, add underline::offset
- /// to the baseline's Y. Otherwise the underline will be immediately under the text.
- /// The x coordinate will always be passed as the left side, regardless
- /// of text directionality. This simplifies drawing and reduces the
- /// problem of round-off that could potentially cause gaps or a double
- /// stamped alpha blend. To avoid alpha overlap, round the end points
- /// to the nearest device pixel.
- ///
- void DrawUnderline(
- IntPtr clientDrawingContext,
- float baselineOriginX,
- float baselineOriginY,
- in Underline underline,
- [MarshalAs(UnmanagedType.IUnknown)]
- object clientDrawingEffect);
-
- ///
- /// IDWriteTextLayout::Draw calls this function to instruct the client to draw
- /// a strikethrough.
- ///
- /// The context passed to
- /// IDWriteTextLayout::Draw.
- /// X-coordinate of the baseline.
- /// Y-coordinate of the baseline.
- /// Strikethrough logical information.
- /// The drawing effect set in
- /// IDWriteTextLayout::SetDrawingEffect.
- ///
- /// A single strikethrough can be broken into multiple calls, depending on
- /// how the formatting changes attributes. Strikethrough is not averaged
- /// across font sizes/styles changes.
- /// To get the correct top coordinate of the strikethrough rect,
- /// add strikethrough::offset to the baseline's Y.
- /// Like underlines, the x coordinate will always be passed as the left side,
- /// regardless of text directionality.
- ///
- void DrawStrikethrough(
- IntPtr clientDrawingContext,
- float baselineOriginX,
- float baselineOriginY,
- in Strikethrough strikethrough,
- [MarshalAs(UnmanagedType.IUnknown)]
- object clientDrawingEffect);
-
- ///
- /// IDWriteTextLayout::Draw calls this application callback when it needs to
- /// draw an inline object.
- ///
- /// The context passed to IDWriteTextLayout::Draw.
- /// X-coordinate at the top-left corner of the inline object.
- /// Y-coordinate at the top-left corner of the inline object.
- /// The object set using IDWriteTextLayout::SetInlineObject.
- /// The object should be drawn on its side.
- /// The object is in an right-to-left context and should be drawn flipped.
- /// The drawing effect set in
- /// IDWriteTextLayout::SetDrawingEffect.
- ///
- /// The right-to-left flag is a hint for those cases where it would look
- /// strange for the image to be shown normally (like an arrow pointing to
- /// right to indicate a submenu).
- ///
- void DrawInlineObject(
- IntPtr clientDrawingContext,
- float originX,
- float originY,
- IInlineObject inlineObject,
- IntBoolean isSideways,
- IntBoolean isRightToLeft,
- [MarshalAs(UnmanagedType.IUnknown)]
- object clientDrawingEffect);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/ITypography.cs b/src/WInterop.DirectX/DirectWrite/ITypography.cs
deleted file mode 100644
index b36e23fa..00000000
--- a/src/WInterop.DirectX/DirectWrite/ITypography.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) Jeremy W. Kuhne. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace WInterop.DirectWrite
-{
- ///
- /// Font typography setting. [IDWriteTypography]
- ///
- [ComImport,
- Guid(InterfaceIds.IID_IDWriteTypography),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface ITypography
- {
- ///
- /// Add font feature.
- ///
- /// The font feature to add.
- void AddFontFeature(FontFeature fontFeature);
-
- ///
- /// Get the number of font features.
- ///
- [PreserveSig]
- uint GetFontFeatureCount();
-
- ///
- /// Get the font feature at the specified index.
- ///
- /// The zero-based index of the font feature to get.
- /// The font feature.
- void GetFontFeature(
- uint fontFeatureIndex,
- out FontFeature fontFeature);
- }
-}
diff --git a/src/WInterop.DirectX/DirectWrite/InformationalStringId.cs b/src/WInterop.DirectX/DirectWrite/InformationalStringId.cs
index b49c1c22..372e9778 100644
--- a/src/WInterop.DirectX/DirectWrite/InformationalStringId.cs
+++ b/src/WInterop.DirectX/DirectWrite/InformationalStringId.cs
@@ -11,116 +11,116 @@ public enum InformationalStringId : uint
///
/// Unspecified name ID.
///
- None,
+ None = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_NONE,
///
/// Copyright notice provided by the font.
///
- CopyrightNotice,
+ CopyrightNotice = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE,
///
/// String containing a version number.
///
- VersionStrings,
+ VersionStrings = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS,
///
/// Trademark information provided by the font.
///
- Trademark,
+ Trademark = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_TRADEMARK,
///
/// Name of the font manufacturer.
///
- Manufacturer,
+ Manufacturer = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_MANUFACTURER,
///
/// Name of the font designer.
///
- Designer,
+ Designer = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_DESIGNER,
///
/// URL of font designer (with protocol, e.g., http://, ftp://).
///
- DesignerUrl,
+ DesignerUrl = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_DESIGNER_URL,
///
/// Description of the font. Can contain revision information, usage recommendations, history, features, etc.
///
- Description,
+ Description = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_DESCRIPTION,
///
/// URL of font vendor (with protocol, e.g., http://, ftp://). If a unique serial number is embedded in the URL, it can be used to register the font.
///
- VendorUrl,
+ VendorUrl = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_FONT_VENDOR_URL,
///
/// Description of how the font may be legally used, or different example scenarios for licensed use. This field should be written in plain language, not legalese.
///
- LicenseDescription,
+ LicenseDescription = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_LICENSE_DESCRIPTION,
///
/// URL where additional licensing information can be found.
///
- LicenseInfoUrl,
+ LicenseInfoUrl = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_LICENSE_INFO_URL,
///
/// GDI-compatible family name. Because GDI allows a maximum of four fonts per family, fonts in the same family may have different GDI-compatible family names
/// (e.g., "Arial", "Arial Narrow", "Arial Black").
///
- Win32FamilyNames,
+ Win32FamilyNames = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES,
///
/// GDI-compatible subfamily name.
///
- Win32SubfamilyName,
+ Win32SubfamilyNames = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES,
///
/// Typographic family name preferred by the designer. This enables font designers to group more than four fonts in a single family without losing compatibility with
/// GDI. This name is typically only present if it differs from the GDI-compatible family name.
///
- TypographicFamilyNames,
+ TypographicFamilyNames = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_FAMILY_NAMES,
///
/// Typographic subfamily name preferred by the designer. This name is typically only present if it differs from the GDI-compatible subfamily name.
///
- TypographicSubfamilyNames,
+ TypographicSubfamilyNames = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_SUBFAMILY_NAMES,
///
/// Sample text. This can be the font name or any other text that the designer thinks is the best example to display the font in.
///
- SampleText,
+ SampleText = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT,
///
/// The full name of the font, e.g. "Arial Bold", from name id 4 in the name table.
///
- FullName,
+ FullName = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_FULL_NAME,
///
/// The postscript name of the font, e.g. "GillSans-Bold" from name id 6 in the name table.
///
- PostscriptName,
+ PostscriptName = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,
///
/// The postscript CID findfont name, from name id 20 in the name table.
///
- PostscriptCidName,
+ PostscriptCidName = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME,
///
/// Family name for the weight-stretch-style model.
///
- WeightStretchStyleFamilyName,
+ WeightStretchStyleFamilyName = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME,
///
/// Script/language tag to identify the scripts or languages that the font was
/// primarily designed to support. See DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
/// for a longer description.
///
- DesignScriptLanguageTag,
+ DesignScriptLanguageTag = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG,
///
/// Script/language tag to identify the scripts or languages that the font declares
/// it is able to support.
///
- SupportedScriptLanguageTag
+ SupportedScriptLanguageTag = DWRITE_INFORMATIONAL_STRING_ID.DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/InlineObject.cs b/src/WInterop.DirectX/DirectWrite/InlineObject.cs
new file mode 100644
index 00000000..f0cd2a75
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/InlineObject.cs
@@ -0,0 +1,115 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using TerraFX.Interop.Windows;
+using WInterop.Direct2d;
+
+namespace WInterop.DirectWrite
+{
+ [Guid(InterfaceIds.IID_IDWriteInlineObject)]
+ public readonly unsafe struct InlineObject : InlineObject.Interface, IDisposable
+ {
+ internal IDWriteInlineObject* Handle { get; }
+
+ internal InlineObject(IDWriteInlineObject* handle) => Handle = handle;
+
+ public void Dispose() => Handle->Release();
+
+ public void Draw(
+ IntPtr clientDrawingContext,
+ TextRenderer renderer,
+ PointF origin,
+ bool isSideways,
+ bool isRightToLeft,
+ IntPtr clientDrawingEffect)
+ {
+ Handle->Draw(
+ (void*)clientDrawingContext,
+ renderer.Handle,
+ origin.X,
+ origin.Y,
+ isSideways,
+ isRightToLeft,
+ (IUnknown*)(void*)clientDrawingEffect).ThrowIfFailed();
+ }
+
+ public void GetBreakConditions(out BreakCondition breakConditionBefore, out BreakCondition breakConditionAfter)
+ {
+ BreakCondition before;
+ BreakCondition after;
+ Handle->GetBreakConditions((DWRITE_BREAK_CONDITION*)&before, (DWRITE_BREAK_CONDITION*)&after);
+ breakConditionBefore = before;
+ breakConditionAfter = after;
+ }
+
+ public InlineObjectMetrics GetMetrics()
+ {
+ InlineObjectMetrics metrics;
+ Handle->GetMetrics((DWRITE_INLINE_OBJECT_METRICS*)&metrics);
+ return metrics;
+ }
+
+ public OverhangMetrics GetOverhangMetrics()
+ {
+ OverhangMetrics metrics;
+ Handle->GetOverhangMetrics((DWRITE_OVERHANG_METRICS*)&metrics);
+ return metrics;
+ }
+
+ internal interface Interface
+ {
+ ///
+ /// The application implemented rendering callback (IDWriteTextRenderer::DrawInlineObject)
+ /// can use this to draw the inline object without needing to cast or query the object
+ /// type. The text layout does not call this method directly.
+ ///
+ /// The context passed to IDWriteTextLayout::Draw.
+ /// The renderer passed to IDWriteTextLayout::Draw as the object's containing parent.
+ /// Top-left corner of the inline object.
+ /// The object should be drawn on its side.
+ /// The object is in an right-to-left context and should be drawn flipped.
+ /// The drawing effect set in IDWriteTextLayout::SetDrawingEffect.
+ void Draw(
+ IntPtr clientDrawingContext,
+ TextRenderer renderer,
+ PointF origin,
+ bool isSideways,
+ bool isRightToLeft,
+ IntPtr clientDrawingEffect);
+
+ ///
+ /// TextLayout calls this callback function to get the measurement of the inline object.
+ ///
+ InlineObjectMetrics GetMetrics();
+
+ ///
+ /// TextLayout calls this callback function to get the visible extents (in DIPs) of the inline object.
+ /// In the case of a simple bitmap, with no padding and no overhang, all the overhangs will simply be zeroes.
+ ///
+ /// Overshoot of visible extents (in DIPs) outside the object.
+ ///
+ /// The overhangs should be returned relative to the reported size of the object (DWRITE_INLINE_OBJECT_METRICS
+ /// ::width/height), and should not be baseline adjusted. If you have an image that is actually 100x100 DIPs,
+ /// but you want it slightly inset (perhaps it has a glow) by 20 DIPs on each side, you would return a
+ /// width/height of 60x60 and four overhangs of 20 DIPs.
+ ///
+ OverhangMetrics GetOverhangMetrics();
+
+ ///
+ /// Layout uses this to determine the line breaking behavior of the inline object amidst the text.
+ ///
+ ///
+ /// Line-breaking condition between the object and the content immediately preceding it.
+ ///
+ ///
+ /// Line-breaking condition between the object and the content immediately following it.
+ ///
+ void GetBreakConditions(
+ out BreakCondition breakConditionBefore,
+ out BreakCondition breakConditionAfter);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/LineSpacingMethod.cs b/src/WInterop.DirectX/DirectWrite/LineSpacingMethod.cs
index 25733b10..e5a9e366 100644
--- a/src/WInterop.DirectX/DirectWrite/LineSpacingMethod.cs
+++ b/src/WInterop.DirectX/DirectWrite/LineSpacingMethod.cs
@@ -11,17 +11,17 @@ public enum LineSpacingMethod : uint
///
/// Line spacing depends solely on the content, growing to accommodate the size of fonts and inline objects.
///
- Default,
+ Default = DWRITE_LINE_SPACING_METHOD.DWRITE_LINE_SPACING_METHOD_DEFAULT,
///
/// Lines are explicitly set to uniform spacing, regardless of contained font sizes.
/// This can be useful to avoid the uneven appearance that can occur from font fallback.
///
- Uniform,
+ Uniform = DWRITE_LINE_SPACING_METHOD.DWRITE_LINE_SPACING_METHOD_UNIFORM,
///
/// Line spacing and baseline distances are proportional to the computed values based on the content, the size of the fonts and inline objects.
///
- Proportional
+ Proportional = DWRITE_LINE_SPACING_METHOD.DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/LocalizedStrings.cs b/src/WInterop.DirectX/DirectWrite/LocalizedStrings.cs
new file mode 100644
index 00000000..db09d325
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/LocalizedStrings.cs
@@ -0,0 +1,100 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.InteropServices;
+using WInterop.Direct2d;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// Represents a collection of strings indexed by locale name. [IDWriteLocalizedStrings]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteLocalizedStrings)]
+ public unsafe readonly struct LocalizedStrings : LocalizedStrings.Interface, IDisposable
+ {
+ private readonly IDWriteLocalizedStrings* _handle;
+
+ internal LocalizedStrings(IDWriteLocalizedStrings* handle) => _handle = handle;
+
+ public uint Count => throw new NotImplementedException();
+
+ public void Dispose()
+ {
+ if (_handle is not null)
+ {
+ _handle->Release();
+ }
+ }
+
+ public bool FindLocaleName(string localeName, out uint index)
+ {
+ TerraFX.Interop.Windows.BOOL exists;
+ fixed (void* l = localeName)
+ fixed (uint* i = &index)
+ {
+ _handle->FindLocaleName((ushort*)l, i, &exists).ThrowIfFailed();
+ }
+
+ return exists;
+ }
+
+ public string GetLocaleName(uint index)
+ {
+ uint length;
+ _handle->GetLocaleNameLength(index, &length).ThrowIfFailed();
+ Span name = stackalloc char[(int)length + 1];
+ fixed (void* n = name)
+ {
+ _handle->GetLocaleName(index, (ushort*)n, length + 1);
+ }
+
+ return name[..(int)length].ToString();
+ }
+
+ public string GetString(uint index)
+ {
+ uint length;
+ _handle->GetStringLength(index, &length).ThrowIfFailed();
+ Span name = stackalloc char[(int)length + 1];
+ fixed (void* n = name)
+ {
+ _handle->GetString(index, (ushort*)n, length + 1);
+ }
+
+ return name[..(int)length].ToString();
+ }
+
+ internal interface Interface
+ {
+ ///
+ /// Gets the number of language/string pairs.
+ ///
+ uint Count { get; }
+
+ ///
+ /// Gets the index of the item with the specified locale name.
+ ///
+ /// Locale name to look for.
+ /// Receives the zero-based index of the locale name/string pair.
+ /// if the locale name exists or if not.
+ bool FindLocaleName(
+ string localeName,
+ out uint index);
+
+ ///
+ /// Gets the locale name with the specified index.
+ ///
+ /// Zero-based index of the locale name.
+ string GetLocaleName(
+ uint index);
+
+ ///
+ /// Gets the string with the specified index.
+ ///
+ /// Zero-based index of the string.
+ string GetString(
+ uint index);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/ManagedTextRenderer.cs b/src/WInterop.DirectX/DirectWrite/ManagedTextRenderer.cs
new file mode 100644
index 00000000..f551ca9c
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/ManagedTextRenderer.cs
@@ -0,0 +1,246 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using TerraFX.Interop.Windows;
+using WInterop.Com.Native;
+
+namespace WInterop.DirectWrite
+{
+ public unsafe abstract class ManagedTextRenderer : IDisposable
+ {
+ private readonly IDWriteTextRenderer* _ccw;
+ private bool _disposedValue;
+
+ public ManagedTextRenderer()
+ {
+ _ccw = CCW.CreateInstance(this);
+ }
+
+ public virtual bool IsPixelSnappingDisabled(IntPtr clientDrawingContext) => false;
+
+ public virtual Matrix3x2 GetCurrentTransform(IntPtr clientDrawingContext) => Matrix3x2.Identity;
+
+ public virtual float GetPixelsPerDip(IntPtr clientDrawingContext) => 1.0f;
+
+
+ public virtual void DrawGlyphRun(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ MeasuringMode measuringMode,
+ GlyphRun glyphRun,
+ GlyphRunDescription glyphRunDescription,
+ IntPtr clientDrawingEffect)
+ {
+ }
+
+ public virtual void DrawUnderline(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ Underline underline,
+ IntPtr clientDrawingEffect)
+ {
+ }
+
+ public virtual void DrawStrikethrough(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ Strikethrough strikethrough,
+ IntPtr clientDrawingEffect)
+ {
+ }
+
+ public virtual void DrawInlineObject(
+ IntPtr clientDrawingContext,
+ PointF origin,
+ InlineObject inlineObject,
+ bool isSideways,
+ bool isRightToLeft,
+ IntPtr clientDrawingEffect)
+ {
+ }
+
+ public static implicit operator TextRenderer(ManagedTextRenderer renderer) => new(renderer._ccw);
+
+ private unsafe static class CCW
+ {
+ private static readonly IDWriteTextRenderer.Vtbl* s_vtable = AllocateVTable();
+
+ private static IDWriteTextRenderer.Vtbl* AllocateVTable()
+ {
+ // Allocate and create a singular VTable for this type projection.
+ var vtable = (IDWriteTextRenderer.Vtbl*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(CCW), sizeof(IDWriteTextRenderer.Vtbl));
+
+ // IUnknown
+ vtable->QueryInterface = &QueryInterface;
+ vtable->AddRef = &AddRef;
+ vtable->Release = &Release;
+ vtable->GetPixelsPerDip = &GetPixelsPerDip;
+ vtable->GetCurrentTransform = &GetCurrentTransform;
+ vtable->IsPixelSnappingDisabled = &IsPixelSnappingDisabled;
+ vtable->DrawGlyphRun = &DrawGlyphRun;
+ vtable->DrawInlineObject = &DrawInlineObject;
+ vtable->DrawStrikethrough = &DrawStrikethrough;
+ vtable->DrawUnderline = &DrawUnderline;
+ return vtable;
+ }
+
+ public static IDWriteTextRenderer* CreateInstance(ManagedTextRenderer renderer)
+ => (IDWriteTextRenderer*)Lifetime.Allocate(renderer, s_vtable);
+
+ [UnmanagedCallersOnly]
+ private static int QueryInterface(void* @this, Guid* iid, void* ppObject)
+ {
+ if (*iid == Com.Native.IUnknown.IID_IUnknown
+ || *iid == typeof(PixelSnapping).GUID
+ || *iid == typeof(TextRenderer).GUID)
+ {
+ ppObject = @this;
+ }
+ else
+ {
+ ppObject = null;
+ return (int)Errors.HResult.E_NOINTERFACE;
+ }
+
+ Lifetime.AddRef(@this);
+ return (int)Errors.HResult.S_OK;
+ }
+
+ [UnmanagedCallersOnly]
+ private static uint AddRef(void* @this) => Lifetime.AddRef(@this);
+
+ [UnmanagedCallersOnly]
+ private static uint Release(void* @this) => Lifetime.Release(@this);
+
+ [UnmanagedCallersOnly]
+ private static int IsPixelSnappingDisabled(void* @this, void* clientDrawingContext, TerraFX.Interop.Windows.BOOL* isDisabled)
+ {
+ *isDisabled = Lifetime.GetObject(@this)
+ .IsPixelSnappingDisabled((IntPtr)clientDrawingContext);
+ return (int)Errors.HResult.S_OK;
+ }
+
+ [UnmanagedCallersOnly]
+ private static int GetCurrentTransform(void* @this, void* clientDrawingContext, DWRITE_MATRIX* transform)
+ {
+ Matrix3x2 matrix = Lifetime.GetObject(@this)
+ .GetCurrentTransform((IntPtr)clientDrawingContext);
+ *transform = *(DWRITE_MATRIX*)&matrix;
+ return (int)Errors.HResult.S_OK;
+ }
+
+ [UnmanagedCallersOnly]
+ private static unsafe int GetPixelsPerDip(void* @this, void* clientDrawingContext, float* pixelsPerDip)
+ {
+ *pixelsPerDip = Lifetime.GetObject(@this)
+ .GetPixelsPerDip((IntPtr)clientDrawingContext);
+ return (int)Errors.HResult.S_OK;
+ }
+
+ [UnmanagedCallersOnly]
+ private static unsafe int DrawGlyphRun(
+ void* @this,
+ void* clientDrawingContext,
+ float baselineOriginX,
+ float baselineOriginY,
+ DWRITE_MEASURING_MODE measuringMode,
+ DWRITE_GLYPH_RUN* glyphRun,
+ DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,
+ TerraFX.Interop.Windows.IUnknown* clientDrawingEffect)
+ {
+ Lifetime.GetObject(@this).DrawGlyphRun(
+ (IntPtr)clientDrawingContext,
+ new(baselineOriginX, baselineOriginY),
+ (MeasuringMode)measuringMode,
+ *(GlyphRun*)glyphRun,
+ *(GlyphRunDescription*)glyphRunDescription,
+ (IntPtr)clientDrawingEffect);
+
+ return (int)Errors.HResult.S_OK;
+ }
+
+ [UnmanagedCallersOnly]
+ private static unsafe int DrawUnderline(
+ void* @this,
+ void* clientDrawingContext,
+ float baselineOriginX,
+ float baselineOriginY,
+ DWRITE_UNDERLINE* underline,
+ TerraFX.Interop.Windows.IUnknown* clientDrawingEffect)
+ {
+ Lifetime.GetObject(@this).DrawUnderline(
+ (IntPtr)clientDrawingContext,
+ new(baselineOriginX, baselineOriginY),
+ *(Underline*)underline,
+ (IntPtr)clientDrawingEffect);
+
+ return (int)Errors.HResult.S_OK;
+ }
+
+ [UnmanagedCallersOnly]
+ private static unsafe int DrawStrikethrough(
+ void* @this,
+ void* clientDrawingContext,
+ float baselineOriginX,
+ float baselineOriginY,
+ DWRITE_STRIKETHROUGH* strikethrough,
+ TerraFX.Interop.Windows.IUnknown* clientDrawingEffect)
+ {
+ Lifetime.GetObject(@this).DrawStrikethrough(
+ (IntPtr)clientDrawingContext,
+ new(baselineOriginX, baselineOriginY),
+ *(Strikethrough*)strikethrough,
+ (IntPtr)clientDrawingEffect);
+
+ return (int)Errors.HResult.S_OK;
+ }
+
+ [UnmanagedCallersOnly]
+ private static unsafe int DrawInlineObject(
+ void* @this,
+ void* clientDrawingContext,
+ float originX,
+ float originY,
+ IDWriteInlineObject* inlineObject,
+ TerraFX.Interop.Windows.BOOL isSideways,
+ TerraFX.Interop.Windows.BOOL isRightToLeft,
+ TerraFX.Interop.Windows.IUnknown* clientDrawingEffect)
+ {
+ Lifetime.GetObject(@this).DrawInlineObject(
+ (IntPtr)clientDrawingContext,
+ new(originX, originY),
+ new(inlineObject),
+ isSideways,
+ isRightToLeft,
+ (IntPtr)clientDrawingEffect);
+
+ return (int)Errors.HResult.S_OK;
+ }
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ _ccw->Release();
+ _disposedValue = true;
+ }
+ }
+
+ ~ManagedTextRenderer()
+ {
+ Dispose(disposing: false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/Native/Imports.cs b/src/WInterop.DirectX/DirectWrite/Native/Imports.cs
index a43d5f16..e5081f7c 100644
--- a/src/WInterop.DirectX/DirectWrite/Native/Imports.cs
+++ b/src/WInterop.DirectX/DirectWrite/Native/Imports.cs
@@ -17,6 +17,6 @@ public static partial class Imports
public static extern HResult DWriteCreateFactory(
FactoryType factoryType,
in Guid riid,
- out IFactory ppIFactory);
+ out WriteFactory ppIFactory);
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/ParagraphAlignment.cs b/src/WInterop.DirectX/DirectWrite/ParagraphAlignment.cs
index 4e5fe197..62780a95 100644
--- a/src/WInterop.DirectX/DirectWrite/ParagraphAlignment.cs
+++ b/src/WInterop.DirectX/DirectWrite/ParagraphAlignment.cs
@@ -12,16 +12,16 @@ public enum ParagraphAlignment : uint
///
/// The first line of paragraph is aligned to the flow's beginning edge of the layout box.
///
- Near,
+ Near = DWRITE_PARAGRAPH_ALIGNMENT.DWRITE_PARAGRAPH_ALIGNMENT_NEAR,
///
/// The last line of paragraph is aligned to the flow's ending edge of the layout box.
///
- Far,
+ Far = DWRITE_PARAGRAPH_ALIGNMENT.DWRITE_PARAGRAPH_ALIGNMENT_FAR,
///
/// The center of the paragraph is aligned to the center of the flow of the layout box.
///
- Center
+ Center = DWRITE_PARAGRAPH_ALIGNMENT.DWRITE_PARAGRAPH_ALIGNMENT_CENTER
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/PixelGeometry.cs b/src/WInterop.DirectX/DirectWrite/PixelGeometry.cs
index b4c33760..77bd161e 100644
--- a/src/WInterop.DirectX/DirectWrite/PixelGeometry.cs
+++ b/src/WInterop.DirectX/DirectWrite/PixelGeometry.cs
@@ -14,19 +14,19 @@ public enum PixelGeometry
/// The red, green, and blue color components of each pixel are assumed to occupy the same point.
/// [DWRITE_PIXEL_GEOMETRY_FLAT]
///
- Flat,
+ Flat = DWRITE_PIXEL_GEOMETRY.DWRITE_PIXEL_GEOMETRY_FLAT,
///
/// Each pixel comprises three vertical stripes, with red on the left, green in the center, and
/// blue on the right. This is the most common pixel geometry for LCD monitors.
/// [DWRITE_PIXEL_GEOMETRY_RGB]
///
- Rgb,
+ Rgb = DWRITE_PIXEL_GEOMETRY.DWRITE_PIXEL_GEOMETRY_RGB,
///
/// Each pixel comprises three vertical stripes, with blue on the left, green in the center, and
/// red on the right. [DWRITE_PIXEL_GEOMETRY_BGR]
///
- Bgr
+ Bgr = DWRITE_PIXEL_GEOMETRY.DWRITE_PIXEL_GEOMETRY_BGR
};
}
diff --git a/src/WInterop.DirectX/DirectWrite/PixelSnapping.cs b/src/WInterop.DirectX/DirectWrite/PixelSnapping.cs
new file mode 100644
index 00000000..dd83cc18
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/PixelSnapping.cs
@@ -0,0 +1,74 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The interface defines the pixel snapping properties of a text renderer.
+ /// [IDWritePixelSnapping]
+ ///
+ [Guid(InterfaceIds.IID_IDWritePixelSnapping)]
+ public unsafe readonly struct PixelSnapping : PixelSnapping.Interface, IDisposable
+ {
+ private readonly IDWritePixelSnapping* _handle;
+
+ internal PixelSnapping(IDWritePixelSnapping* handle) => _handle = handle;
+
+ public Matrix3x2 GetCurrentTransform(IntPtr clientDrawingContext)
+ {
+ Matrix3x2 matrix;
+ _handle->GetCurrentTransform((void*)clientDrawingContext, (DWRITE_MATRIX*)&matrix).ThrowIfFailed();
+ return matrix;
+ }
+
+ public float GetPixelsPerDip(IntPtr clientDrawingContext)
+ {
+ float pixels;
+ _handle->GetPixelsPerDip((void*)clientDrawingContext, &pixels).ThrowIfFailed();
+ return pixels;
+ }
+
+ public bool IsPixelSnappingDisabled(IntPtr clientDrawingContext)
+ {
+ TerraFX.Interop.Windows.BOOL result;
+ _handle->IsPixelSnappingDisabled((void*)clientDrawingContext, &result).ThrowIfFailed();
+ return result;
+ }
+
+ internal static ref PixelSnapping From(in TFrom from)
+ where TFrom : unmanaged, Interface
+ => ref Unsafe.AsRef(Unsafe.AsPointer(ref Unsafe.AsRef(from)));
+
+ public void Dispose() => _handle->Release();
+
+ internal interface Interface
+ {
+ ///
+ /// Determines whether pixel snapping is disabled. The recommended default is FALSE,
+ /// unless doing animation that requires subpixel vertical placement.
+ ///
+ /// The context passed to IDWriteTextLayout::Draw.
+ bool IsPixelSnappingDisabled(IntPtr clientDrawingContext);
+
+ ///
+ /// Gets the current transform that maps abstract coordinates to DIPs,
+ /// which may disable pixel snapping upon any rotation or shear.
+ ///
+ /// The context passed to IDWriteTextLayout::Draw.
+ Matrix3x2 GetCurrentTransform(IntPtr clientDrawingContext);
+
+ ///
+ /// Gets the number of physical pixels per DIP. A DIP (device-independent pixel) is 1/96 inch,
+ /// so the pixelsPerDip value is the number of logical pixels per inch divided by 96 (yielding
+ /// a value of 1 for 96 DPI and 1.25 for 120).
+ ///
+ /// The context passed to IDWriteTextLayout::Draw.
+ float GetPixelsPerDip(IntPtr clientDrawingContext);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/RenderingMode.cs b/src/WInterop.DirectX/DirectWrite/RenderingMode.cs
index 98627f8e..f45b9a54 100644
--- a/src/WInterop.DirectX/DirectWrite/RenderingMode.cs
+++ b/src/WInterop.DirectX/DirectWrite/RenderingMode.cs
@@ -12,13 +12,13 @@ public enum RenderingMode
/// Specifies that the rendering mode is determined automatically based on the font and size.
/// [DWRITE_RENDERING_MODE_DEFAULT]
///
- Default,
+ Default = DWRITE_RENDERING_MODE.DWRITE_RENDERING_MODE_DEFAULT,
///
/// Specifies that no antialiasing is performed. Each pixel is either set to the foreground
/// color of the text or retains the color of the background. [DWRITE_RENDERING_MODE_ALIASED]
///
- Aliased,
+ Aliased = DWRITE_RENDERING_MODE.DWRITE_RENDERING_MODE_ALIASED,
///
/// Specifies that antialiasing is performed in the horizontal direction and the appearance
@@ -26,7 +26,7 @@ public enum RenderingMode
/// to get glyph advances. The antialiasing may be either ClearType or grayscale depending on
/// the text antialiasing mode. [DWRITE_RENDERING_MODE_GDI_CLASSIC]
///
- GdiClassic,
+ GdiClassic = DWRITE_RENDERING_MODE.DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
///
/// Specifies that antialiasing is performed in the horizontal direction and the appearance
@@ -35,7 +35,7 @@ public enum RenderingMode
/// DWRITE_MEASURING_MODE_GDI_NATURAL to get glyph advances. The antialiasing may be either
/// ClearType or grayscale depending on the text antialiasing mode. [DWRITE_RENDERING_MODE_GDI_NATURAL]
///
- GdiNatural,
+ GdiNatural = DWRITE_RENDERING_MODE.DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL,
///
/// Specifies that antialiasing is performed in the horizontal direction. This rendering
@@ -43,7 +43,7 @@ public enum RenderingMode
/// for natural (i.e., resolution-independent) layout. The antialiasing may be either
/// ClearType or grayscale depending on the text antialiasing mode. [DWRITE_RENDERING_MODE_NATURAL]
///
- Natural,
+ Natural = DWRITE_RENDERING_MODE.DWRITE_RENDERING_MODE_NATURAL,
///
/// Similar to natural mode except that antialiasing is performed in both the horizontal
@@ -51,12 +51,12 @@ public enum RenderingMode
/// diagonal lines look smoother. The antialiasing may be either ClearType or grayscale
/// depending on the text antialiasing mode. [DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC]
///
- NaturalSymmetric,
+ NaturalSymmetric = DWRITE_RENDERING_MODE.DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
///
/// Specifies that rendering should bypass the rasterizer and use the outlines directly.
/// This is typically used at very large sizes. [DWRITE_RENDERING_MODE_OUTLINE]
///
- Outline,
+ Outline = DWRITE_RENDERING_MODE.DWRITE_RENDERING_MODE_OUTLINE,
};
}
diff --git a/src/WInterop.DirectX/DirectWrite/RenderingParams.cs b/src/WInterop.DirectX/DirectWrite/RenderingParams.cs
new file mode 100644
index 00000000..2ea388fe
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/RenderingParams.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The interface that represents text rendering settings for glyph rasterization and filtering.
+ /// [IDWriteRenderingParams]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteRenderingParams)]
+ public unsafe readonly struct RenderingParams : RenderingParams.Interface, IDisposable
+ {
+ internal IDWriteRenderingParams* Handle { get; }
+
+ internal RenderingParams(IDWriteRenderingParams* handle) => Handle = handle;
+
+ public float Gamma => Handle->GetGamma();
+
+ public float EnhancedContrast => Handle->GetEnhancedContrast();
+
+ public float ClearTypeLevel => Handle->GetClearTypeLevel();
+
+ public PixelGeometry PixelGeometry => (PixelGeometry)Handle->GetPixelGeometry();
+
+ public RenderingMode RenderingMode => (RenderingMode)Handle->GetRenderingMode();
+
+ public void Dispose() => Handle->Release();
+
+ internal interface Interface
+ {
+ ///
+ /// Gets the gamma value used for gamma correction. Valid values must be
+ /// greater than zero and cannot exceed 256.
+ ///
+ float Gamma { get; }
+
+ ///
+ /// Gets the amount of contrast enhancement. Valid values are greater than
+ /// or equal to zero.
+ ///
+ float EnhancedContrast { get; }
+
+ ///
+ /// Gets the ClearType level. Valid values range from 0.0f (no ClearType)
+ /// to 1.0f (full ClearType).
+ ///
+ float ClearTypeLevel { get; }
+
+ ///
+ /// Gets the pixel geometry.
+ ///
+ PixelGeometry PixelGeometry { get; }
+
+ ///
+ /// Gets the rendering mode.
+ ///
+ RenderingMode RenderingMode { get; }
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/TextAlignment.cs b/src/WInterop.DirectX/DirectWrite/TextAlignment.cs
index 1bfd54cf..477ce5d6 100644
--- a/src/WInterop.DirectX/DirectWrite/TextAlignment.cs
+++ b/src/WInterop.DirectX/DirectWrite/TextAlignment.cs
@@ -12,21 +12,21 @@ public enum TextAlignment : uint
///
/// The leading edge of the paragraph text is aligned to the layout box's leading edge.
///
- Leading,
+ Leading = DWRITE_TEXT_ALIGNMENT.DWRITE_TEXT_ALIGNMENT_LEADING,
///
/// The trailing edge of the paragraph text is aligned to the layout box's trailing edge.
///
- Trailing,
+ Trailing = DWRITE_TEXT_ALIGNMENT.DWRITE_TEXT_ALIGNMENT_TRAILING,
///
/// The center of the paragraph text is aligned to the center of the layout box.
///
- Center,
+ Center = DWRITE_TEXT_ALIGNMENT.DWRITE_TEXT_ALIGNMENT_CENTER,
///
/// Align text to the leading side, and also justify text to fill the lines.
///
- Justified
+ Justified = DWRITE_TEXT_ALIGNMENT.DWRITE_TEXT_ALIGNMENT_JUSTIFIED
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/TextFormat.cs b/src/WInterop.DirectX/DirectWrite/TextFormat.cs
new file mode 100644
index 00000000..f5cd0502
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/TextFormat.cs
@@ -0,0 +1,238 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The format of text used for text layout. [IDWriteTextFormat]
+ ///
+ ///
+ /// This object may not be thread-safe and it may carry the state of text format change.
+ ///
+ [Guid(InterfaceIds.IID_IDWriteTextFormat)]
+ public readonly unsafe struct TextFormat : TextFormat.Interface, IDisposable
+ {
+ internal IDWriteTextFormat* Handle { get; }
+
+ internal TextFormat(IDWriteTextFormat* handle) => Handle = handle;
+
+ internal static ref TextFormat From(in TFrom from)
+ where TFrom : unmanaged, Interface
+ => ref Unsafe.AsRef(Unsafe.AsPointer(ref Unsafe.AsRef(from)));
+
+ public TextAlignment TextAlignment
+ {
+ get => (TextAlignment)Handle->GetTextAlignment();
+ set => Handle->SetTextAlignment((DWRITE_TEXT_ALIGNMENT)value).ThrowIfFailed();
+ }
+
+ public ParagraphAlignment ParagraphAlignment
+ {
+ get => (ParagraphAlignment)Handle->GetParagraphAlignment();
+ set => Handle->SetParagraphAlignment((DWRITE_PARAGRAPH_ALIGNMENT)value).ThrowIfFailed();
+ }
+
+ public WordWrapping WordWrapping
+ {
+ get => (WordWrapping)Handle->GetWordWrapping();
+ set => Handle->SetWordWrapping((DWRITE_WORD_WRAPPING)value).ThrowIfFailed();
+ }
+
+ public ReadingDirection ReadingDirection
+ {
+ get => (ReadingDirection)Handle->GetReadingDirection();
+ set => Handle->SetReadingDirection((DWRITE_READING_DIRECTION)value).ThrowIfFailed();
+ }
+
+ public FlowDirection FlowDirection
+ {
+ get => (FlowDirection)Handle->GetFlowDirection();
+ set => Handle->SetFlowDirection((DWRITE_FLOW_DIRECTION)value).ThrowIfFailed();
+ }
+
+ public float IncrementalTabStop
+ {
+ get => Handle->GetIncrementalTabStop();
+ set => Handle->SetIncrementalTabStop(value).ThrowIfFailed();
+ }
+
+ public Trimming Trimming
+ {
+ get
+ {
+ Trimming trimming;
+ Handle->GetTrimming((DWRITE_TRIMMING*)&trimming, null).ThrowIfFailed();
+ return trimming;
+ }
+ set => Handle->SetTrimming((DWRITE_TRIMMING*)&value, null).ThrowIfFailed();
+ }
+
+ public FontWeight FontWeight => (FontWeight)Handle->GetFontWeight();
+
+ public FontStyle FontStyle => (FontStyle)Handle->GetFontStyle();
+
+ public FontStretch FontStretch => (FontStretch)Handle->GetFontStretch();
+
+ public float FontSize => Handle->GetFontSize();
+
+ public void Dispose() => Handle->Release();
+
+ public FontCollection GetFontCollection()
+ {
+ IDWriteFontCollection* collection;
+ Handle->GetFontCollection(&collection).ThrowIfFailed();
+ return new(collection);
+ }
+
+ public string GetFontFamilyName()
+ {
+ uint length = Handle->GetFontFamilyNameLength();
+ Span name = stackalloc char[(int)length + 1];
+ fixed (void* n = name)
+ {
+ Handle->GetFontFamilyName((ushort*)n, length + 1).ThrowIfFailed();
+ }
+ return name[..(int)length].ToString();
+ }
+
+ public void GetLineSpacing(out LineSpacingMethod lineSpacingMethod, out float lineSpacing, out float baseline)
+ {
+ fixed (void* lsm = &lineSpacingMethod)
+ fixed (float* ls = &lineSpacing)
+ fixed (float* bl = &baseline)
+ {
+ Handle->GetLineSpacing((DWRITE_LINE_SPACING_METHOD*)lsm, ls, bl).ThrowIfFailed();
+ }
+ }
+
+ public string GetLocaleName()
+ {
+ uint length = Handle->GetLocaleNameLength();
+ Span name = stackalloc char[(int)length + 1];
+ fixed (void* n = name)
+ {
+ Handle->GetLocaleName((ushort*)n, length + 1).ThrowIfFailed();
+ }
+ return name[..(int)length].ToString();
+ }
+
+ public void SetLineSpacing(LineSpacingMethod lineSpacingMethod, float lineSpacing, float baseline)
+ => Handle->SetLineSpacing((DWRITE_LINE_SPACING_METHOD)lineSpacingMethod, lineSpacing, baseline).ThrowIfFailed();
+
+ ///
+ /// https://docs.microsoft.com/windows/win32/api/dwrite/nn-dwrite-idwritetextformat
+ ///
+ internal interface Interface
+ {
+ ///
+ /// Gets/sets alignment option of text relative to layout box's leading and trailing edge.
+ ///
+ TextAlignment TextAlignment { get; set; }
+
+ ///
+ /// Gets/sets alignment option of paragraphs relative to layout box's top and bottom edge.
+ ///
+ ParagraphAlignment ParagraphAlignment { get; set; }
+
+ ///
+ /// Gets/sets the style of word wrapping.
+ ///
+ WordWrapping WordWrapping { get; set; }
+
+ ///
+ /// Gets/sets paragraph reading direction.
+ ///
+ ///
+ /// must be perpendicular to .
+ ///
+ ReadingDirection ReadingDirection { get; set; }
+
+ ///
+ /// Gets/sets paragraph flow direction.
+ ///
+ /// Paragraph flow direction
+ ///
+ /// must be perpendicular to .
+ ///
+ FlowDirection FlowDirection { get; set; }
+
+ ///
+ /// Gets/sets incremental tab stop position.
+ ///
+ float IncrementalTabStop { get; set; }
+
+ ///
+ /// Set trimming options for any trailing text exceeding the layout width or for any far text exceeding the
+ /// layout height.
+ ///
+ Trimming Trimming { get; set; }
+
+ // (Trimming options, InlineObject sign) TrimmingWithSign { get; set; }
+
+ ///
+ /// Set line spacing.
+ ///
+ /// How to determine line height.
+ /// The line height, or rather distance between one baseline to another.
+ /// Distance from top of line to baseline. A reasonable ratio to lineSpacing is 80%.
+ ///
+ /// For the default method, spacing depends solely on the content. For uniform spacing, the given line height
+ /// will override the content.
+ ///
+ void SetLineSpacing(
+ LineSpacingMethod lineSpacingMethod,
+ float lineSpacing,
+ float baseline);
+
+ ///
+ /// Get line spacing.
+ ///
+ /// How line height is determined.
+ /// The line height, or rather distance between one baseline to another.
+ /// Distance from top of line to baseline.
+ void GetLineSpacing(
+ out LineSpacingMethod lineSpacingMethod,
+ out float lineSpacing,
+ out float baseline);
+
+ ///
+ /// Get the font collection.
+ ///
+ FontCollection GetFontCollection();
+
+ ///
+ /// Get a copy of the font family name.
+ ///
+ string GetFontFamilyName();
+
+ ///
+ /// Get the font weight.
+ ///
+ FontWeight FontWeight { get; }
+
+ ///
+ /// Get the font style.
+ ///
+ FontStyle FontStyle { get; }
+
+ ///
+ /// Get the font stretch.
+ ///
+ FontStretch FontStretch { get; }
+
+ ///
+ /// Get the font em height.
+ ///
+ float FontSize { get; }
+
+ ///
+ /// Get the locale name.
+ ///
+ string GetLocaleName();
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/TextLayout.cs b/src/WInterop.DirectX/DirectWrite/TextLayout.cs
new file mode 100644
index 00000000..3885829b
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/TextLayout.cs
@@ -0,0 +1,718 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using TerraFX.Interop.Windows;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The IDWriteTextLayout interface represents a block of text after it has
+ /// been fully analyzed and formatted. [IDWriteTextLayout]
+ ///
+ /// All coordinates are in device independent pixels (DIPs).
+ ///
+ [Guid(InterfaceIds.IID_IDWriteTextLayout)]
+ public readonly unsafe struct TextLayout : TextLayout.Interface, IDisposable
+ {
+ internal readonly IDWriteTextLayout* Handle { get; }
+
+ internal TextLayout(IDWriteTextLayout* handle) => Handle = handle;
+
+ public float MaxWidth
+ {
+ get => Handle->GetMaxWidth();
+ set => Handle->SetMaxWidth(value).ThrowIfFailed();
+ }
+
+ public float MaxHeight
+ {
+ get => Handle->GetMaxHeight();
+ set => Handle->SetMaxHeight(value).ThrowIfFailed();
+ }
+
+ public TextAlignment TextAlignment
+ {
+ get => TextFormat.From(this).TextAlignment;
+ set => TextFormat.From(this).TextAlignment = value;
+ }
+
+ public ParagraphAlignment ParagraphAlignment
+ {
+ get => TextFormat.From(this).ParagraphAlignment;
+ set => TextFormat.From(this).ParagraphAlignment = value;
+ }
+
+ public WordWrapping WordWrapping
+ {
+ get => TextFormat.From(this).WordWrapping;
+ set => TextFormat.From(this).WordWrapping = value;
+ }
+
+ public ReadingDirection ReadingDirection
+ {
+ get => TextFormat.From(this).ReadingDirection;
+ set => TextFormat.From(this).ReadingDirection = value;
+ }
+
+ public FlowDirection FlowDirection
+ {
+ get => TextFormat.From(this).FlowDirection;
+ set => TextFormat.From(this).FlowDirection = value;
+ }
+
+ public float IncrementalTabStop
+ {
+ get => TextFormat.From(this).IncrementalTabStop;
+ set => TextFormat.From(this).IncrementalTabStop = value;
+ }
+
+ public Trimming Trimming
+ {
+ get => TextFormat.From(this).Trimming;
+ set => TextFormat.From(this).Trimming = value;
+ }
+
+ public FontWeight FontWeight => TextFormat.From(this).FontWeight;
+
+ public FontStyle FontStyle => TextFormat.From(this).FontStyle;
+
+ public FontStretch FontStretch => TextFormat.From(this).FontStretch;
+
+ public float FontSize => TextFormat.From(this).FontSize;
+
+ public float DetermineMinWidth()
+ {
+ float minWidth;
+ Handle->DetermineMinWidth(&minWidth).ThrowIfFailed();
+ return minWidth;
+ }
+
+ public void Dispose() => Handle->Release();
+
+ public void Draw(IntPtr clientDrawingContext, TextRenderer renderer, PointF origin)
+ {
+ Handle->Draw(
+ (void*)clientDrawingContext,
+ renderer.Handle,
+ origin.X,
+ origin.Y).ThrowIfFailed();
+ }
+
+ public ClusterMetrics[] GetClusterMetrics()
+ {
+ uint count;
+ var result = Handle->GetClusterMetrics(null, 0, &count);
+
+ if (count == 0)
+ {
+ return Array.Empty();
+ }
+
+ ClusterMetrics[] metrics = new ClusterMetrics[(int)count];
+ fixed (void* m = metrics)
+ {
+ Handle->GetClusterMetrics((DWRITE_CLUSTER_METRICS*)m, count, &count).ThrowIfFailed();
+ }
+ return metrics;
+ }
+
+ public IntPtr GetDrawingEffect(uint currentPosition)
+ {
+ IUnknown* effect;
+ Handle->GetDrawingEffect(currentPosition, &effect).ThrowIfFailed();
+ return (IntPtr)effect;
+ }
+
+ public FontCollection GetFontCollection(uint currentPosition)
+ {
+ IDWriteFontCollection* collection;
+ Handle->GetFontCollection(currentPosition, &collection).ThrowIfFailed();
+ return new(collection);
+ }
+
+ public FontCollection GetFontCollection() => TextFormat.From(this).GetFontCollection();
+
+ public string GetFontFamilyName(uint currentPosition)
+ {
+ uint length;
+ Handle->GetFontFamilyNameLength(currentPosition, &length).ThrowIfFailed();
+ Span name = stackalloc char[(int)length + 1];
+ fixed (void* n = name)
+ {
+ Handle->GetFontFamilyName(currentPosition, (ushort*)n, length + 1).ThrowIfFailed();
+ }
+ return name[..(int)length].ToString();
+ }
+
+ public string GetFontFamilyName() => TextFormat.From(this).GetFontFamilyName();
+
+ public float GetFontSize(uint currentPosition)
+ {
+ float size;
+ Handle->GetFontSize(currentPosition, &size).ThrowIfFailed();
+ return size;
+ }
+
+ public FontStretch GetFontStretch(uint currentPosition)
+ {
+ FontStretch stretch;
+ Handle->GetFontStretch(currentPosition, (DWRITE_FONT_STRETCH*)&stretch).ThrowIfFailed();
+ return stretch;
+ }
+
+ public FontStyle GetFontStyle(uint currentPosition)
+ {
+ FontStyle style;
+ Handle->GetFontStyle(currentPosition, (DWRITE_FONT_STYLE*)&style).ThrowIfFailed();
+ return style;
+ }
+
+ public FontWeight GetFontWeight(uint currentPosition)
+ {
+ FontWeight weight;
+ Handle->GetFontWeight(currentPosition, (DWRITE_FONT_WEIGHT*)&weight).ThrowIfFailed();
+ return weight;
+ }
+
+ public InlineObject GetInlineObject(uint currentPosition)
+ {
+ IDWriteInlineObject* inlineObject;
+ Handle->GetInlineObject(currentPosition, &inlineObject).ThrowIfFailed();
+ return new(inlineObject);
+ }
+
+ public LineMetrics[] GetLineMetrics()
+ {
+ uint count;
+ var result = Handle->GetLineMetrics(null, 0, &count);
+ if (count == 0)
+ {
+ return Array.Empty();
+ }
+
+ LineMetrics[] metrics = new LineMetrics[count];
+ fixed (void* m = metrics)
+ {
+ Handle->GetLineMetrics((DWRITE_LINE_METRICS*)m, count, &count).ThrowIfFailed();
+ }
+
+ return metrics;
+ }
+
+ public void GetLineSpacing(out LineSpacingMethod lineSpacingMethod, out float lineSpacing, out float baseline)
+ => TextFormat.From(this).GetLineSpacing(out lineSpacingMethod, out lineSpacing, out baseline);
+
+ public string GetLocaleName(uint currentPosition)
+ {
+ uint length;
+ Handle->GetLocaleNameLength(currentPosition, &length).ThrowIfFailed();
+ Span name = stackalloc char[(int)length + 1];
+ fixed (void* n = name)
+ {
+ Handle->GetLocaleName(currentPosition, (ushort*)n, length + 1).ThrowIfFailed();
+ }
+ return name[..(int)length].ToString();
+ }
+
+ public string GetLocaleName() => TextFormat.From(this).GetLocaleName();
+
+ public TextMetrics GetMetrics()
+ {
+ TextMetrics metrics;
+ Handle->GetMetrics((DWRITE_TEXT_METRICS*)&metrics).ThrowIfFailed();
+ return metrics;
+ }
+
+ public OverhangMetrics GetOverhangMetrics()
+ {
+ OverhangMetrics metrics;
+ Handle->GetOverhangMetrics((DWRITE_OVERHANG_METRICS*)&metrics).ThrowIfFailed();
+ return metrics;
+ }
+
+ public bool GetStrikethrough(uint currentPosition)
+ {
+ TerraFX.Interop.Windows.BOOL strikeThrough;
+ Handle->GetStrikethrough(currentPosition, &strikeThrough).ThrowIfFailed();
+ return strikeThrough;
+ }
+
+ public Typography GetTypography(uint currentPosition)
+ {
+ IDWriteTypography* typography;
+ Handle->GetTypography(currentPosition, &typography).ThrowIfFailed();
+ return new(typography);
+ }
+
+ public bool GetUnderline(uint currentPosition)
+ {
+ TerraFX.Interop.Windows.BOOL underline;
+ Handle->GetUnderline(currentPosition, &underline).ThrowIfFailed();
+ return underline;
+ }
+
+ public void HitTestPoint(PointF point, out bool isTrailingHit, out bool isInside, out HitTestMetrics hitTestMetrics)
+ {
+ TerraFX.Interop.Windows.BOOL ith;
+ TerraFX.Interop.Windows.BOOL ii;
+ fixed (void* htm = &hitTestMetrics)
+ {
+ Handle->HitTestPoint(point.X, point.Y, &ith, &ii, (DWRITE_HIT_TEST_METRICS*)htm).ThrowIfFailed();
+ }
+
+ isTrailingHit = ith;
+ isInside = ii;
+ }
+
+ public void HitTestTextPosition(uint textPosition, bool isTrailingHit, out PointF point, out HitTestMetrics hitTestMetrics)
+ {
+ float x;
+ float y;
+ fixed (void* htm = &hitTestMetrics)
+ {
+ Handle->HitTestTextPosition(textPosition, isTrailingHit, &x, &y, (DWRITE_HIT_TEST_METRICS*)htm).ThrowIfFailed();
+ }
+
+ point = new(x, y);
+ }
+
+ public void SetDrawingEffect(IntPtr drawingEffect, TextRange textRange)
+ => Handle->SetDrawingEffect((IUnknown*)(void*)drawingEffect, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetFontCollection(FontCollection fontCollection, TextRange textRange)
+ => Handle->SetFontCollection(fontCollection.Handle, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetFontFamilyName(string fontFamilyName, TextRange textRange)
+ {
+ fixed (void* n = fontFamilyName)
+ {
+ Handle->SetFontFamilyName((ushort*)n, textRange.ToD2D()).ThrowIfFailed(); ;
+ }
+ }
+
+ public void SetFontSize(float fontSize, TextRange textRange)
+ => Handle->SetFontSize(fontSize, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetFontStretch(FontStretch fontStretch, TextRange textRange)
+ => Handle->SetFontStretch((DWRITE_FONT_STRETCH)fontStretch, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetFontStyle(FontStyle fontStyle, TextRange textRange)
+ => Handle->SetFontStyle((DWRITE_FONT_STYLE)fontStyle, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetFontWeight(FontWeight fontWeight, TextRange textRange)
+ => Handle->SetFontWeight((DWRITE_FONT_WEIGHT)fontWeight, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetInlineObject(InlineObject inlineObject, TextRange textRange)
+ => Handle->SetInlineObject(inlineObject.Handle, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetLineSpacing(LineSpacingMethod lineSpacingMethod, float lineSpacing, float baseline)
+ => Handle->SetLineSpacing((DWRITE_LINE_SPACING_METHOD)lineSpacingMethod, lineSpacing, baseline).ThrowIfFailed();
+
+ public void SetLocaleName(string localeName, TextRange textRange)
+ {
+ fixed (void* n = localeName)
+ {
+ Handle->SetLocaleName((ushort*)n, textRange.ToD2D()).ThrowIfFailed();
+ }
+ }
+
+ public void SetStrikethrough(bool hasStrikethrough, TextRange textRange)
+ => Handle->SetStrikethrough(hasStrikethrough, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetTypography(Typography typography, TextRange textRange)
+ => Handle->SetTypography(typography.Handle, textRange.ToD2D()).ThrowIfFailed();
+
+ public void SetUnderline(bool hasUnderline, TextRange textRange)
+ => Handle->SetUnderline(hasUnderline, textRange.ToD2D()).ThrowIfFailed();
+
+ ///
+ /// https://docs.microsoft.com/windows/win32/api/dwrite/nn-dwrite-idwritetextlayout
+ ///
+ internal interface Interface : TextFormat.Interface
+ {
+ ///
+ /// Get/set layout maximum width.
+ ///
+ float MaxWidth { get; set; }
+
+ ///
+ /// Get/set layout maximum height
+ ///
+ float MaxHeight { get; set; }
+
+ ///
+ /// Set the font collection.
+ ///
+ /// The font collection to set
+ /// Text range to which this change applies.
+ void SetFontCollection(
+ FontCollection fontCollection,
+ TextRange textRange);
+
+ ///
+ /// Set null-terminated font family name.
+ ///
+ /// Font family name
+ /// Text range to which this change applies.
+ void SetFontFamilyName(
+ string fontFamilyName,
+ TextRange textRange);
+
+ ///
+ /// Set font weight.
+ ///
+ /// Font weight
+ /// Text range to which this change applies.
+ void SetFontWeight(
+ FontWeight fontWeight,
+ TextRange textRange);
+
+ ///
+ /// Set font style.
+ ///
+ /// Font style
+ /// Text range to which this change applies.
+ void SetFontStyle(
+ FontStyle fontStyle,
+ TextRange textRange);
+
+ ///
+ /// Set font stretch.
+ ///
+ /// font stretch
+ /// Text range to which this change applies.
+ void SetFontStretch(
+ FontStretch fontStretch,
+ TextRange textRange);
+
+ ///
+ /// Set font em height.
+ ///
+ /// Font em height
+ /// Text range to which this change applies.
+ void SetFontSize(
+ float fontSize,
+ TextRange textRange);
+
+ ///
+ /// Set underline.
+ ///
+ /// The Boolean flag indicates whether underline takes place
+ /// Text range to which this change applies.
+ void SetUnderline(
+ bool hasUnderline,
+ TextRange textRange);
+
+ ///
+ /// Set strikethrough.
+ ///
+ /// The Boolean flag indicates whether strikethrough takes place
+ /// Text range to which this change applies.
+ void SetStrikethrough(
+ bool hasStrikethrough,
+ TextRange textRange);
+
+ ///
+ /// Set application-defined drawing effect.
+ ///
+ /// Pointer to an application-defined drawing effect.
+ /// Text range to which this change applies.
+ ///
+ /// This drawing effect is associated with the specified range and will be passed back
+ /// to the application via the callback when the range is drawn at drawing time.
+ ///
+ void SetDrawingEffect(
+ IntPtr drawingEffect,
+ TextRange textRange);
+
+ ///
+ /// Set inline object.
+ ///
+ /// Pointer to an application-implemented inline object.
+ /// Text range to which this change applies.
+ ///
+ /// This inline object applies to the specified range and will be passed back
+ /// to the application via the DrawInlineObject callback when the range is drawn.
+ /// Any text in that range will be suppressed.
+ ///
+ void SetInlineObject(
+ InlineObject inlineObject,
+ TextRange textRange);
+
+ ///
+ /// Set font typography features.
+ ///
+ /// Pointer to font typography setting.
+ /// Text range to which this change applies.
+ void SetTypography(
+ Typography typography,
+ TextRange textRange);
+
+ ///
+ /// Set locale name.
+ ///
+ /// Locale name
+ /// Text range to which this change applies.
+ void SetLocaleName(
+ string localeName,
+ TextRange textRange);
+
+ // TODO: Add overloads that out the TextRange for getters. Presumption is
+ // there is extra overhead in calculating the TextRange.
+
+ ///
+ /// Get the font collection where the current position is at.
+ ///
+ /// The current text position.
+ FontCollection GetFontCollection(uint currentPosition);
+
+ ///
+ /// Copy the font family name where the current position is at.
+ ///
+ /// The current text position.
+ string GetFontFamilyName(uint currentPosition);
+
+ ///
+ /// Get the font weight where the current position is at.
+ ///
+ /// The current text position.
+ FontWeight GetFontWeight(uint currentPosition);
+
+ ///
+ /// Get the font style where the current position is at.
+ ///
+ /// The current text position.
+ FontStyle GetFontStyle(uint currentPosition);
+
+ ///
+ /// Get the font stretch where the current position is at.
+ ///
+ /// The current text position.
+ FontStretch GetFontStretch(uint currentPosition);
+
+ ///
+ /// Get the font em height where the current position is at.
+ ///
+ /// The current text position.
+ float GetFontSize(uint currentPosition);
+
+ ///
+ /// Get the underline presence where the current position is at.
+ ///
+ /// The current text position.
+ bool GetUnderline(uint currentPosition);
+
+ ///
+ /// Get the strikethrough presence where the current position is at.
+ ///
+ /// The current text position.
+ bool GetStrikethrough(uint currentPosition);
+
+ ///
+ /// Get the application-defined drawing effect where the current position is at.
+ ///
+ /// The current text position.
+ IntPtr GetDrawingEffect(uint currentPosition);
+
+ ///
+ /// Get the inline object at the given position.
+ ///
+ /// The given text position.
+ InlineObject GetInlineObject(uint currentPosition);
+
+ ///
+ /// Get the typography setting where the current position is at.
+ ///
+ /// The current text position.
+ Typography GetTypography(uint currentPosition);
+
+ ///
+ /// Get the locale name where the current position is at.
+ ///
+ /// The current text position.
+ string GetLocaleName(uint currentPosition);
+
+ ///
+ /// Initiate drawing of the text.
+ ///
+ /// An application defined value
+ /// included in rendering callbacks.
+ /// The set of application-defined callbacks that do
+ /// the actual rendering.
+ /// The layout's top-left side.
+ void Draw(
+ IntPtr clientDrawingContext,
+ TextRenderer renderer,
+ PointF origin);
+
+ ///
+ /// GetLineMetrics returns properties of each line.
+ ///
+ /// The array to fill with line information.
+ /// The maximum size of the lineMetrics array.
+ /// The actual size of the lineMetrics
+ /// array that is needed.
+ ///
+ /// If maxLineCount is not large enough E_NOT_SUFFICIENT_BUFFER,
+ /// which is equivalent to HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER),
+ /// is returned and *actualLineCount is set to the number of lines
+ /// needed.
+ ///
+ LineMetrics[] GetLineMetrics();
+
+ ///
+ /// GetMetrics retrieves overall metrics for the formatted string.
+ ///
+ ///
+ /// Drawing effects like underline and strikethrough do not contribute to the text size, which is essentially
+ /// the sum of advance widths and line heights. Additionally, visible swashes and other graphic adornments
+ /// may extend outside the returned width and height.
+ ///
+ TextMetrics GetMetrics();
+
+ ///
+ /// GetOverhangMetrics returns the overhangs (in DIPs) of the layout and all objects contained in it,
+ /// including text glyphs and inline objects.
+ ///
+ /// Overshoots of visible extents (in DIPs) outside the layout.
+ ///
+ /// Any underline and strikethrough do not contribute to the black box determination, since these are
+ /// actually drawn by the renderer, which is allowed to draw them in any variety of styles.
+ ///
+ OverhangMetrics GetOverhangMetrics();
+
+ ///
+ /// Retrieve logical properties and measurement of each cluster.
+ ///
+ /// The array to fill with cluster information.
+ /// The maximum size of the clusterMetrics array.
+ /// The actual size of the clusterMetrics array that is needed.
+ ///
+ /// If maxClusterCount is not large enough E_NOT_SUFFICIENT_BUFFER,
+ /// which is equivalent to HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER),
+ /// is returned and *actualClusterCount is set to the number of clusters
+ /// needed.
+ ///
+ ClusterMetrics[] GetClusterMetrics();
+
+ ///
+ /// Determines the minimum possible width the layout can be set to without emergency breaking between
+ /// the characters of whole words.
+ ///
+ float DetermineMinWidth();
+
+ ///
+ /// Given a coordinate (in DIPs) relative to the top-left of the layout box, this returns the corresponding
+ /// hit-test metrics of the text string where the hit-test has occurred. This is useful for mapping mouse
+ /// clicks to caret positions. When the given coordinate is outside the text string, the function sets the
+ /// output value *isInside to false but returns the nearest character position.
+ ///
+ /// Point to hit-test, relative to the top-left location of the layout box.
+ ///
+ /// Output flag indicating whether the hit-test location is at the leading or the trailing side of the
+ /// character. When is set to false, this value is set according to the output
+ /// *position value to represent the edge closest to the hit-test location.
+ ///
+ ///
+ /// Output flag indicating whether the hit-test location is inside the text string. When false, the position
+ /// nearest the text's edge is returned.
+ ///
+ /// Output geometry fully enclosing the hit-test location. When the output value
+ /// is set to false, this structure represents the geometry enclosing the edge closest to the hit-test
+ /// location.
+ ///
+ void HitTestPoint(
+ PointF point,
+ out bool isTrailingHit,
+ out bool isInside,
+ out HitTestMetrics hitTestMetrics);
+
+ ///
+ /// Given a text position and whether the caret is on the leading or trailing
+ /// edge of that position, this returns the corresponding coordinate (in DIPs)
+ /// relative to the top-left of the layout box. This is most useful for drawing
+ /// the caret's current position, but it could also be used to anchor an IME to the
+ /// typed text or attach a floating menu near the point of interest. It may also be
+ /// used to programmatically obtain the geometry of a particular text position
+ /// for UI automation.
+ ///
+ /// Text position to get the coordinate of.
+ /// Flag indicating whether the location is of the leading or the trailing side of the specified text position.
+ /// Output caret point, relative to the top-left of the layout box.
+ /// Output geometry fully enclosing the specified text position.
+ ///
+ /// When drawing a caret at the returned X,Y, it should be centered on X
+ /// and drawn from the Y coordinate down. The height will be the size of the
+ /// hit-tested text (which can vary in size within a line).
+ /// Reading direction also affects which side of the character the caret is drawn.
+ /// However, the returned X coordinate will be correct for either case.
+ /// You can get a text length back that is larger than a single character.
+ /// This happens for complex scripts when multiple characters form a single cluster,
+ /// when diacritics join their base character, or when you test a surrogate pair.
+ ///
+ void HitTestTextPosition(
+ uint textPosition,
+ bool isTrailingHit,
+ out PointF point,
+ out HitTestMetrics hitTestMetrics);
+
+/*
+ ///
+ /// The application calls this function to get a set of hit-test metrics
+ /// corresponding to a range of text positions. The main usage for this
+ /// is to draw highlighted selection of the text string.
+ ///
+ /// The function returns E_NOT_SUFFICIENT_BUFFER, which is equivalent to
+ /// HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), when the buffer size of
+ /// hitTestMetrics is too small to hold all the regions calculated by the
+ /// function. In such situation, the function sets the output value
+ /// *actualHitTestMetricsCount to the number of geometries calculated.
+ /// The application is responsible to allocate a new buffer of greater
+ /// size and call the function again.
+ ///
+ /// A good value to use as an initial value for maxHitTestMetricsCount may
+ /// be calculated from the following equation:
+ /// maxHitTestMetricsCount = lineCount * maxBidiReorderingDepth
+ ///
+ /// where lineCount is obtained from the value of the output argument
+ /// *actualLineCount from the function IDWriteTextLayout::GetLineMetrics,
+ /// and the maxBidiReorderingDepth value from the DWRITE_TEXT_METRICS
+ /// structure of the output argument *textMetrics from the function
+ /// .
+ ///
+ /// First text position of the specified range.
+ /// Number of positions of the specified range.
+ /// Offset of the origin (left-top of the layout box) which is added to each of the hit-test metrics returned.
+ /// Pointer to a buffer of the output geometry fully enclosing the specified position range.
+ /// Maximum number of distinct metrics it could hold in its buffer memory.
+ /// Actual number of metrics returned or needed.
+ ///
+ /// There are no gaps in the returned metrics. While there could be visual gaps,
+ /// depending on bidi ordering, each range is contiguous and reports all the text,
+ /// including any hidden characters and trimmed text.
+ /// The height of each returned range will be the same within each line, regardless
+ /// of how the font sizes vary.
+ ///
+ unsafe void HitTestTextRange(
+ uint textPosition,
+ uint textLength,
+ PointF origin,
+ out HitTestMetrics hitTestMetrics,
+ uint maxHitTestMetricsCount,
+ out uint actualHitTestMetricsCount);
+ */
+ }
+ }
+
+ public static class TextLayoutExtensions
+ {
+ public static void SetMaxSize(this TextLayout textLayout, SizeF maxSize)
+ {
+ textLayout.MaxHeight = maxSize.Height;
+ textLayout.MaxWidth = maxSize.Width;
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/TextRange.cs b/src/WInterop.DirectX/DirectWrite/TextRange.cs
index 8e544bc7..f93a63b0 100644
--- a/src/WInterop.DirectX/DirectWrite/TextRange.cs
+++ b/src/WInterop.DirectX/DirectWrite/TextRange.cs
@@ -1,6 +1,8 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System.Runtime.CompilerServices;
+
namespace WInterop.DirectWrite
{
///
@@ -26,6 +28,12 @@ public TextRange(uint startPosition, uint length)
}
public static implicit operator TextRange((int StartPosition, int Length) tuple)
- => new TextRange((uint)tuple.StartPosition, (uint)tuple.Length);
+ => new((uint)tuple.StartPosition, (uint)tuple.Length);
+
+ internal unsafe DWRITE_TEXT_RANGE ToD2D()
+ {
+ fixed(void* p = &this)
+ return *(DWRITE_TEXT_RANGE*)p;
+ }
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/TextRenderer.cs b/src/WInterop.DirectX/DirectWrite/TextRenderer.cs
new file mode 100644
index 00000000..8c8b93e1
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/TextRenderer.cs
@@ -0,0 +1,207 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using TerraFX.Interop.Windows;
+
+namespace WInterop.DirectWrite
+{
+
+ ///
+ /// The interface represents a set of application-defined
+ /// callbacks that perform rendering of text, inline objects, and decorations
+ /// such as underlines. [IDWriteTextRenderer]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteTextRenderer)]
+ public unsafe readonly struct TextRenderer : TextRenderer.Interface, IDisposable
+ {
+ internal IDWriteTextRenderer* Handle { get; }
+
+ internal TextRenderer(IDWriteTextRenderer* handle) => Handle = handle;
+
+ public void DrawGlyphRun(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ MeasuringMode measuringMode,
+ GlyphRun glyphRun,
+ GlyphRunDescription glyphRunDescription,
+ IntPtr clientDrawingEffect)
+ {
+ Handle->DrawGlyphRun(
+ (void*)clientDrawingContext,
+ baselineOrigin.X,
+ baselineOrigin.Y,
+ (DWRITE_MEASURING_MODE)measuringMode,
+ (DWRITE_GLYPH_RUN*)&glyphRun,
+ (DWRITE_GLYPH_RUN_DESCRIPTION*)&glyphRunDescription,
+ (IUnknown*)(void*)clientDrawingEffect).ThrowIfFailed();
+ }
+
+ public void DrawInlineObject(
+ IntPtr clientDrawingContext,
+ PointF origin,
+ InlineObject inlineObject,
+ bool isSideways,
+ bool isRightToLeft,
+ IntPtr clientDrawingEffect)
+ {
+ Handle->DrawInlineObject(
+ (void*)clientDrawingContext,
+ origin.X,
+ origin.Y,
+ inlineObject.Handle,
+ isSideways,
+ isRightToLeft,
+ (IUnknown*)(void*)clientDrawingEffect).ThrowIfFailed();
+ }
+
+ public void DrawStrikethrough(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ Strikethrough strikethrough,
+ IntPtr clientDrawingEffect)
+ {
+ Handle->DrawStrikethrough(
+ (void*)clientDrawingContext,
+ baselineOrigin.X,
+ baselineOrigin.Y,
+ (DWRITE_STRIKETHROUGH*)&strikethrough,
+ (IUnknown*)(void*)clientDrawingEffect).ThrowIfFailed();
+ }
+
+ public void DrawUnderline(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ Underline underline,
+ IntPtr clientDrawingEffect)
+ {
+ Handle->DrawUnderline(
+ (void*)clientDrawingContext,
+ baselineOrigin.X,
+ baselineOrigin.Y,
+ (DWRITE_UNDERLINE*)&underline,
+ (IUnknown*)(void*)clientDrawingEffect).ThrowIfFailed();
+ }
+
+ public Matrix3x2 GetCurrentTransform(IntPtr clientDrawingContext)
+ => PixelSnapping.From(this).GetCurrentTransform(clientDrawingContext);
+
+ public float GetPixelsPerDip(IntPtr clientDrawingContext)
+ => PixelSnapping.From(this).GetPixelsPerDip(clientDrawingContext);
+
+ public bool IsPixelSnappingDisabled(IntPtr clientDrawingContext)
+ => PixelSnapping.From(this).IsPixelSnappingDisabled(clientDrawingContext);
+
+ public void Dispose() => Handle->Release();
+
+ internal interface Interface : PixelSnapping.Interface
+ {
+ ///
+ /// IDWriteTextLayout::Draw calls this function to instruct the client to
+ /// render a run of glyphs.
+ ///
+ /// The context passed to
+ /// IDWriteTextLayout::Draw.
+ /// Origin of the baseline.
+ /// Specifies measuring mode for glyphs in the run.
+ /// Renderer implementations may choose different rendering modes for given measuring modes,
+ /// but best results are seen when the rendering mode matches the corresponding measuring mode:
+ /// DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL for DWRITE_MEASURING_MODE_NATURAL
+ /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC for DWRITE_MEASURING_MODE_GDI_CLASSIC
+ /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL for DWRITE_MEASURING_MODE_GDI_NATURAL
+ ///
+ /// The glyph run to draw.
+ /// Properties of the characters associated with this run.
+ /// The drawing effect set in SetDrawingEffect.
+ void DrawGlyphRun(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ MeasuringMode measuringMode,
+ GlyphRun glyphRun,
+ GlyphRunDescription glyphRunDescription,
+ IntPtr clientDrawingEffect);
+
+ ///
+ /// IDWriteTextLayout::Draw calls this function to instruct the client to draw
+ /// an underline.
+ ///
+ /// The context passed to
+ /// IDWriteTextLayout::Draw.
+ /// Origin of the baseline.
+ /// Underline logical information.
+ /// The drawing effect set in
+ /// IDWriteTextLayout::SetDrawingEffect.
+ ///
+ /// A single underline can be broken into multiple calls, depending on
+ /// how the formatting changes attributes. If font sizes/styles change
+ /// within an underline, the thickness and offset will be averaged
+ /// weighted according to characters.
+ /// To get the correct top coordinate of the underline rect, add underline::offset
+ /// to the baseline's Y. Otherwise the underline will be immediately under the text.
+ /// The x coordinate will always be passed as the left side, regardless
+ /// of text directionality. This simplifies drawing and reduces the
+ /// problem of round-off that could potentially cause gaps or a double
+ /// stamped alpha blend. To avoid alpha overlap, round the end points
+ /// to the nearest device pixel.
+ ///
+ void DrawUnderline(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ Underline underline,
+ IntPtr clientDrawingEffect);
+
+ ///
+ /// IDWriteTextLayout::Draw calls this function to instruct the client to draw
+ /// a strikethrough.
+ ///
+ /// The context passed to
+ /// IDWriteTextLayout::Draw.
+ /// X-coordinate of the baseline.
+ /// Y-coordinate of the baseline.
+ /// Strikethrough logical information.
+ /// The drawing effect set in
+ /// IDWriteTextLayout::SetDrawingEffect.
+ ///
+ /// A single strikethrough can be broken into multiple calls, depending on
+ /// how the formatting changes attributes. Strikethrough is not averaged
+ /// across font sizes/styles changes.
+ /// To get the correct top coordinate of the strikethrough rect,
+ /// add strikethrough::offset to the baseline's Y.
+ /// Like underlines, the x coordinate will always be passed as the left side,
+ /// regardless of text directionality.
+ ///
+ void DrawStrikethrough(
+ IntPtr clientDrawingContext,
+ PointF baselineOrigin,
+ Strikethrough strikethrough,
+ IntPtr clientDrawingEffect);
+
+ ///
+ /// IDWriteTextLayout::Draw calls this application callback when it needs to
+ /// draw an inline object.
+ ///
+ /// The context passed to IDWriteTextLayout::Draw.
+ /// The top-left corner of the inline object.
+ /// The object set using IDWriteTextLayout::SetInlineObject.
+ /// The object should be drawn on its side.
+ /// The object is in an right-to-left context and should be drawn flipped.
+ /// The drawing effect set in
+ /// IDWriteTextLayout::SetDrawingEffect.
+ ///
+ /// The right-to-left flag is a hint for those cases where it would look
+ /// strange for the image to be shown normally (like an arrow pointing to
+ /// right to indicate a submenu).
+ ///
+ void DrawInlineObject(
+ IntPtr clientDrawingContext,
+ PointF origin,
+ InlineObject inlineObject,
+ bool isSideways,
+ bool isRightToLeft,
+ IntPtr clientDrawingEffect);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/TrimmingGranularity.cs b/src/WInterop.DirectX/DirectWrite/TrimmingGranularity.cs
index 8ded52ec..d390875c 100644
--- a/src/WInterop.DirectX/DirectWrite/TrimmingGranularity.cs
+++ b/src/WInterop.DirectX/DirectWrite/TrimmingGranularity.cs
@@ -11,16 +11,16 @@ public enum TrimmingGranularity : uint
///
/// No trimming occurs. Text flows beyond the layout width.
///
- None,
+ None = DWRITE_TRIMMING_GRANULARITY.DWRITE_TRIMMING_GRANULARITY_NONE,
///
/// Trimming occurs at character cluster boundary.
///
- Character,
+ Character = DWRITE_TRIMMING_GRANULARITY.DWRITE_TRIMMING_GRANULARITY_CHARACTER,
///
/// Trimming occurs at word boundary.
///
- Word
+ Word = DWRITE_TRIMMING_GRANULARITY.DWRITE_TRIMMING_GRANULARITY_WORD
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/Typography.cs b/src/WInterop.DirectX/DirectWrite/Typography.cs
new file mode 100644
index 00000000..24bd705f
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/Typography.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// Font typography setting. [IDWriteTypography]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteTypography)]
+ public readonly unsafe struct Typography : Typography.Interface, IDisposable
+ {
+ internal IDWriteTypography* Handle { get; }
+
+ internal Typography(IDWriteTypography* handle) => Handle = handle;
+
+ public void AddFontFeature(FontFeature fontFeature)
+ {
+ Handle->AddFontFeature(Unsafe.As(ref fontFeature)).ThrowIfFailed();
+ }
+
+ public void Dispose() => Handle->Release();
+
+ public void GetFontFeature(uint fontFeatureIndex, out FontFeature fontFeature)
+ {
+ fixed (void* f = &fontFeature)
+ {
+ Handle->GetFontFeature(fontFeatureIndex, (DWRITE_FONT_FEATURE*)f);
+ }
+ }
+
+ public uint FontFeatureCount => Handle->GetFontFeatureCount();
+
+ internal interface Interface
+ {
+ ///
+ /// Add font feature.
+ ///
+ /// The font feature to add.
+ void AddFontFeature(FontFeature fontFeature);
+
+ ///
+ /// Get the number of font features.
+ ///
+ uint FontFeatureCount { get; }
+
+ ///
+ /// Get the font feature at the specified index.
+ ///
+ /// The zero-based index of the font feature to get.
+ /// The font feature.
+ void GetFontFeature(
+ uint fontFeatureIndex,
+ out FontFeature fontFeature);
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectWrite/WordWrapping.cs b/src/WInterop.DirectX/DirectWrite/WordWrapping.cs
index 89dc950d..f4f78ef8 100644
--- a/src/WInterop.DirectX/DirectWrite/WordWrapping.cs
+++ b/src/WInterop.DirectX/DirectWrite/WordWrapping.cs
@@ -11,29 +11,29 @@ public enum WordWrapping : uint
///
/// Words are broken across lines to avoid text overflowing the layout box.
///
- Wrap = 0,
+ Wrap = DWRITE_WORD_WRAPPING.DWRITE_WORD_WRAPPING_WRAP,
///
/// Words are kept within the same line even when it overflows the layout box.
/// This option is often used with scrolling to reveal overflow text.
///
- NoWrap = 1,
+ NoWrap = DWRITE_WORD_WRAPPING.DWRITE_WORD_WRAPPING_NO_WRAP,
///
/// Words are broken across lines to avoid text overflowing the layout box.
/// Emergency wrapping occurs if the word is larger than the maximum width.
///
- EmergencyBreak = 2,
+ EmergencyBreak = DWRITE_WORD_WRAPPING.DWRITE_WORD_WRAPPING_EMERGENCY_BREAK,
///
/// Only wrap whole words, never breaking words (emergency wrapping) when the
/// layout width is too small for even a single word.
///
- WholeWord = 3,
+ WholeWord = DWRITE_WORD_WRAPPING.DWRITE_WORD_WRAPPING_WHOLE_WORD,
///
/// Wrap between any valid characters clusters.
///
- Character = 4,
+ Character = DWRITE_WORD_WRAPPING.DWRITE_WORD_WRAPPING_CHARACTER,
}
}
diff --git a/src/WInterop.DirectX/DirectWrite/WriteFactory.cs b/src/WInterop.DirectX/DirectWrite/WriteFactory.cs
new file mode 100644
index 00000000..99ba0494
--- /dev/null
+++ b/src/WInterop.DirectX/DirectWrite/WriteFactory.cs
@@ -0,0 +1,484 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Drawing;
+using System.Globalization;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using WInterop.Windows.Native;
+
+namespace WInterop.DirectWrite
+{
+ ///
+ /// The root factory interface for all DWrite objects. [IDWriteFactory]
+ ///
+ [Guid(InterfaceIds.IID_IDWriteFactory)]
+ public readonly unsafe struct WriteFactory : WriteFactory.Interface, IDisposable
+ {
+ private readonly IDWriteFactory* _handle;
+
+ internal WriteFactory(IDWriteFactory* handle) => _handle = handle;
+
+ public RenderingParams CreateCustomRenderingParams(
+ float gamma,
+ float enhancedContrast,
+ float clearTypeLevel,
+ PixelGeometry pixelGeometry,
+ RenderingMode renderingMode)
+ {
+ IDWriteRenderingParams* rendering;
+
+ _handle->CreateCustomRenderingParams(
+ gamma,
+ enhancedContrast,
+ clearTypeLevel,
+ (DWRITE_PIXEL_GEOMETRY)pixelGeometry,
+ (DWRITE_RENDERING_MODE)renderingMode,
+ &rendering).ThrowIfFailed();
+
+ return new(rendering);
+ }
+
+ public InlineObject CreateEllipsisTrimmingSign(TextFormat textFormat)
+ {
+ IDWriteInlineObject* inlineObject;
+ _handle->CreateEllipsisTrimmingSign(textFormat.Handle, &inlineObject).ThrowIfFailed();
+ return new(inlineObject);
+ }
+
+ public TextLayout CreateGdiCompatibleTextLayout(
+ ReadOnlySpan @string,
+ uint stringLength,
+ TextFormat textFormat,
+ float layoutWidth,
+ float layoutHeight,
+ float pixelsPerDip,
+ Matrix3x2 transform,
+ bool useGdiNatural)
+ {
+ IDWriteTextLayout* layout;
+ fixed (void* s = @string)
+ {
+ _handle->CreateGdiCompatibleTextLayout(
+ (ushort*)s,
+ (uint)@string.Length,
+ textFormat.Handle,
+ layoutWidth,
+ layoutHeight,
+ pixelsPerDip,
+ (DWRITE_MATRIX*)&transform,
+ useGdiNatural,
+ &layout).ThrowIfFailed();
+ }
+
+ return new(layout);
+ }
+
+ public RenderingParams CreateMonitorRenderingParams(HMONITOR monitor)
+ {
+ IDWriteRenderingParams* rendering;
+ _handle->CreateMonitorRenderingParams((TerraFX.Interop.Windows.HMONITOR)monitor.Value, &rendering).ThrowIfFailed();
+ return new(rendering);
+ }
+
+ public RenderingParams CreateRenderingParams()
+ {
+ IDWriteRenderingParams* rendering;
+ _handle->CreateRenderingParams(&rendering).ThrowIfFailed();
+ return new(rendering);
+ }
+
+ public TextFormat CreateTextFormat(
+ string fontFamilyName,
+ FontCollection fontCollection = default,
+ FontWeight fontWeight = FontWeight.Normal,
+ FontStyle fontStyle = FontStyle.Normal,
+ FontStretch fontStretch = FontStretch.Normal,
+ float fontSize = 12,
+ string localeName = null)
+ {
+ IDWriteTextFormat* format;
+ localeName ??= CultureInfo.CurrentCulture.Name;
+
+ fixed (void* n = fontFamilyName)
+ fixed (void* l = localeName)
+ {
+ _handle->CreateTextFormat(
+ (ushort*)n,
+ fontCollection.Handle,
+ (DWRITE_FONT_WEIGHT)fontWeight,
+ (DWRITE_FONT_STYLE)fontStyle,
+ (DWRITE_FONT_STRETCH)fontStretch,
+ fontSize,
+ (ushort*)l,
+ &format).ThrowIfFailed();
+ }
+
+ return new(format);
+ }
+
+ public TextLayout CreateTextLayout(ReadOnlySpan @string, TextFormat textFormat, SizeF maxSize)
+ {
+ IDWriteTextLayout* layout;
+
+ fixed (void* s = @string)
+ {
+ _handle->CreateTextLayout(
+ (ushort*)s,
+ (uint)@string.Length,
+ textFormat.Handle,
+ maxSize.Width,
+ maxSize.Height,
+ &layout).ThrowIfFailed();
+ }
+
+ return new(layout);
+ }
+
+ public Typography CreateTypography()
+ {
+ IDWriteTypography* typography;
+ _handle->CreateTypography(&typography).ThrowIfFailed();
+ return new(typography);
+ }
+
+ public void Dispose() => _handle->Release();
+
+ public FontCollection GetSystemFontCollection(bool checkForUpdates)
+ {
+ IDWriteFontCollection* collection;
+ _handle->GetSystemFontCollection(&collection, checkForUpdates).ThrowIfFailed();
+ return new(collection);
+ }
+
+ internal interface Interface
+ {
+ ///
+ /// Gets a font collection representing the set of installed fonts.
+ ///
+ ///
+ /// If this parameter is true, the function performs an immediate check for changes to the set of installed fonts.
+ /// If this parameter is false, the function will still detect changes if the font cache service is running, but
+ /// there may be some latency. For example, an application might specify true if it has itself just installed a font
+ /// and wants to be sure the font collection contains that font.
+ ///
+ FontCollection GetSystemFontCollection(bool checkForUpdates);
+
+ /*
+ ///
+ /// Creates a font collection using a custom font collection loader.
+ ///
+ /// Application-defined font collection loader, which must have been previously
+ /// registered using RegisterFontCollectionLoader.
+ /// Key used by the loader to identify a collection of font files.
+ /// Size in bytes of the collection key.
+ /// Receives a pointer to the system font collection object, or NULL in case of failure.
+ //void CreateCustomFontCollectionSTUB();
+ //STDMETHOD(CreateCustomFontCollection)(
+ // _In_ IDWriteFontCollectionLoader* collectionLoader,
+ // _In_reads_bytes_(collectionKeySize) void const* collectionKey,
+ // UINT32 collectionKeySize,
+ // _COM_Outptr_ IDWriteFontCollection** fontCollection
+ // ) PURE;
+
+ ///
+ /// Registers a custom font collection loader with the factory object.
+ ///
+ /// Application-defined font collection loader.
+ void RegisterFontCollectionLoaderSTUB();
+ //STDMETHOD(RegisterFontCollectionLoader)(
+ // _In_ IDWriteFontCollectionLoader* fontCollectionLoader
+ // ) PURE;
+
+ ///
+ /// Unregisters a custom font collection loader that was previously registered using RegisterFontCollectionLoader.
+ ///
+ /// Application-defined font collection loader.
+ ///
+ /// Standard HRESULT error code.
+ ///
+ void UnregisterFontCollectionLoaderSTUB();
+ //STDMETHOD(UnregisterFontCollectionLoader)(
+ // _In_ IDWriteFontCollectionLoader* fontCollectionLoader
+ // ) PURE;
+
+ ///
+ /// CreateFontFileReference creates a font file reference object from a local font file.
+ ///
+ /// Absolute file path. Subsequent operations on the constructed object may fail
+ /// if the user provided filePath doesn't correspond to a valid file on the disk.
+ /// Last modified time of the input file path. If the parameter is omitted,
+ /// the function will access the font file to obtain its last write time, so the clients are encouraged to specify this value
+ /// to avoid extra disk access. Subsequent operations on the constructed object may fail
+ /// if the user provided lastWriteTime doesn't match the file on the disk.
+ /// Contains newly created font file reference object, or NULL in case of failure.
+ void CreateFontFileReferenceSTUB();
+ //STDMETHOD(CreateFontFileReference)(
+ // _In_z_ WCHAR const* filePath,
+ // _In_opt_ FILETIME const* lastWriteTime,
+ // _COM_Outptr_ IDWriteFontFile** fontFile
+ // ) PURE;
+
+ ///
+ /// CreateCustomFontFileReference creates a reference to an application specific font file resource.
+ /// This function enables an application or a document to use a font without having to install it on the system.
+ /// The fontFileReferenceKey has to be unique only in the scope of the fontFileLoader used in this call.
+ ///
+ /// Font file reference key that uniquely identifies the font file resource
+ /// during the lifetime of fontFileLoader.
+ /// Size of font file reference key in bytes.
+ /// Font file loader that will be used by the font system to load data from the file identified by
+ /// fontFileReferenceKey.
+ /// Contains the newly created font file object, or NULL in case of failure.
+ ///
+ /// Standard HRESULT error code.
+ ///
+ ///
+ /// This function is provided for cases when an application or a document needs to use a font
+ /// without having to install it on the system. fontFileReferenceKey has to be unique only in the scope
+ /// of the fontFileLoader used in this call.
+ ///
+ void CreateCustomFontFileReferenceSTUB();
+ //STDMETHOD(CreateCustomFontFileReference)(
+ // _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey,
+ // UINT32 fontFileReferenceKeySize,
+ // _In_ IDWriteFontFileLoader* fontFileLoader,
+ // _COM_Outptr_ IDWriteFontFile** fontFile
+ // ) PURE;
+
+ ///
+ /// Creates a font face object.
+ ///
+ /// The file format of the font face.
+ /// The number of font files required to represent the font face.
+ /// Font files representing the font face. Since IDWriteFontFace maintains its own references
+ /// to the input font file objects, it's OK to release them after this call.
+ /// The zero based index of a font face in cases when the font files contain a collection of font faces.
+ /// If the font files contain a single face, this value should be zero.
+ /// Font face simulation flags for algorithmic emboldening and italicization.
+ /// Contains the newly created font face object, or NULL in case of failure.
+ void CreateFontFaceSTUB();
+ //IFontFace CreateFontFace(
+ // FontFaceType fontFaceType,
+ // uint numberOfFiles,
+ // _In_reads_(numberOfFiles) IDWriteFontFile* const* fontFiles,
+ // uint faceIndex,
+ // DWRITE_FONT_SIMULATIONS fontFaceSimulationFlags);
+ */
+
+ ///
+ /// Creates a rendering parameters object with default settings for the primary monitor.
+ ///
+ RenderingParams CreateRenderingParams();
+
+ ///
+ /// Creates a rendering parameters object with default settings for the specified monitor.
+ ///
+ /// The monitor to read the default values from.
+ RenderingParams CreateMonitorRenderingParams(HMONITOR monitor);
+
+ ///
+ /// Creates a rendering parameters object with the specified properties.
+ ///
+ /// The gamma value used for gamma correction, which must be greater than zero and cannot exceed 256.
+ /// The amount of contrast enhancement, zero or greater.
+ /// The degree of ClearType level, from 0.0f (no ClearType) to 1.0f (full ClearType).
+ /// The geometry of a device pixel.
+ /// Method of rendering glyphs. In most cases, this should be DWRITE_RENDERING_MODE_DEFAULT to automatically use an appropriate mode.
+ RenderingParams CreateCustomRenderingParams(
+ float gamma,
+ float enhancedContrast,
+ float clearTypeLevel,
+ PixelGeometry pixelGeometry,
+ RenderingMode renderingMode);
+
+/*
+ ///
+ /// Registers a font file loader with DirectWrite.
+ ///
+ /// Pointer to the implementation of the IDWriteFontFileLoader for a particular file resource type.
+ ///
+ /// This function registers a font file loader with DirectWrite.
+ /// Font file loader interface handles loading font file resources of a particular type from a key.
+ /// The font file loader interface is recommended to be implemented by a singleton object.
+ /// A given instance can only be registered once.
+ /// Succeeding attempts will return an error that it has already been registered.
+ /// IMPORTANT: font file loader implementations must not register themselves with DirectWrite
+ /// inside their constructors and must not unregister themselves in their destructors, because
+ /// registration and unregistration operations increment and decrement the object reference count respectively.
+ /// Instead, registration and unregistration of font file loaders with DirectWrite should be performed
+ /// outside of the font file loader implementation as a separate step.
+ ///
+ void RegisterFontFileLoaderSTUB();
+ //STDMETHOD(RegisterFontFileLoader)(
+ // _In_ IDWriteFontFileLoader* fontFileLoader
+ // ) PURE;
+
+ ///
+ /// Unregisters a font file loader that was previously registered with the DirectWrite font system using RegisterFontFileLoader.
+ ///
+ /// Pointer to the file loader that was previously registered with the DirectWrite font system using RegisterFontFileLoader.
+ ///
+ /// This function will succeed if the user loader is requested to be removed.
+ /// It will fail if the pointer to the file loader identifies a standard DirectWrite loader,
+ /// or a loader that is never registered or has already been unregistered.
+ ///
+ ///
+ /// This function unregisters font file loader callbacks with the DirectWrite font system.
+ /// The font file loader interface is recommended to be implemented by a singleton object.
+ /// IMPORTANT: font file loader implementations must not register themselves with DirectWrite
+ /// inside their constructors and must not unregister themselves in their destructors, because
+ /// registration and unregistration operations increment and decrement the object reference count respectively.
+ /// Instead, registration and unregistration of font file loaders with DirectWrite should be performed
+ /// outside of the font file loader implementation as a separate step.
+ ///
+ void UnregisterFontFileLoaderSTUB();
+ //STDMETHOD(UnregisterFontFileLoader)(
+ // _In_ IDWriteFontFileLoader* fontFileLoader
+ // ) PURE;
+*/
+
+ ///
+ /// Create a text format object used for text layout.
+ ///
+ /// Name of the font family
+ /// Font collection. 'null' indicates the system font collection.
+ /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch.
+ /// Locale name
+ TextFormat CreateTextFormat(
+ string fontFamilyName,
+ FontCollection fontCollection = default,
+ FontWeight fontWeight = FontWeight.Normal,
+ FontStyle fontStyle = FontStyle.Normal,
+ FontStretch fontStretch = FontStretch.Normal,
+ float fontSize = 12.0f,
+ string localeName = null);
+
+ ///
+ /// Create a typography object used in conjunction with text format for text layout.
+ ///
+ Typography CreateTypography();
+
+/*
+ ///
+ /// Create an object used for interoperability with GDI.
+ ///
+ /// Receives the GDI interop object if successful, or NULL in case of failure.
+ void GetGdiInteropSTUB();
+ //STDMETHOD(GetGdiInterop)(
+ // _COM_Outptr_ IDWriteGdiInterop** gdiInterop
+ // ) PURE;
+*/
+
+ ///
+ /// CreateTextLayout takes a string, format, and associated constraints
+ /// and produces an object representing the fully analyzed
+ /// and formatted result.
+ ///
+ /// The string to layout.
+ /// The format to apply to the string.
+ /// Size of the layout box.
+ TextLayout CreateTextLayout(
+ ReadOnlySpan @string,
+ TextFormat textFormat,
+ SizeF maxSize);
+
+ ///
+ /// CreateGdiCompatibleTextLayout takes a string, format, and associated constraints
+ /// and produces and object representing the result formatted for a particular display resolution
+ /// and measuring mode. The resulting text layout should only be used for the intended resolution,
+ /// and for cases where text scalability is desired, CreateTextLayout should be used instead.
+ ///
+ /// The string to layout.
+ /// The length of the string.
+ /// The format to apply to the string.
+ /// Width of the layout box.
+ /// Height of the layout box.
+ /// Number of physical pixels per DIP. For example, if rendering onto a 96 DPI device then pixelsPerDip
+ /// is 1. If rendering onto a 120 DPI device then pixelsPerDip is 120/96.
+ /// Optional transform applied to the glyphs and their positions. This transform is applied after the
+ /// scaling specified the font size and pixelsPerDip.
+ ///
+ /// When set to FALSE, instructs the text layout to use the same metrics as GDI aliased text.
+ /// When set to TRUE, instructs the text layout to use the same metrics as text measured by GDI using a font
+ /// created with CLEARTYPE_NATURAL_QUALITY.
+ ///
+ TextLayout CreateGdiCompatibleTextLayout(
+ ReadOnlySpan @string,
+ uint stringLength,
+ TextFormat textFormat,
+ float layoutWidth,
+ float layoutHeight,
+ float pixelsPerDip,
+ Matrix3x2 transform,
+ bool useGdiNatural);
+
+ ///
+ /// The application may call this function to create an inline object for trimming, using an ellipsis as the
+ /// omission sign. The ellipsis will be created using the current settings of the format, including base font,
+ /// style, and any effects. Alternate omission signs can be created by the application by implementing
+ /// IDWriteInlineObject.
+ ///
+ /// Text format used as a template for the omission sign.
+ /// Created omission sign.
+ InlineObject CreateEllipsisTrimmingSign(TextFormat textFormat);
+
+/*
+ ///// The resultant object.
+ ///
+ /// Return an interface to perform text analysis with.
+ ///
+ void CreateTextAnalyzerSTUB();
+ //STDMETHOD(CreateTextAnalyzer)(
+ // _COM_Outptr_ IDWriteTextAnalyzer** textAnalyzer
+ // ) PURE;
+
+
+ ///// Method of number substitution to use.
+ ///// Which locale to obtain the digits from.
+ ///// Ignore the user's settings and use the locale defaults
+ ///// Receives a pointer to the newly created object.
+ ///
+ /// Creates a number substitution object using a locale name,
+ /// substitution method, and whether to ignore user overrides (uses NLS
+ /// defaults for the given culture instead).
+ ///
+ void CreateNumberSubstitutionSTUB();
+ //STDMETHOD(CreateNumberSubstitution)(
+ // _In_ DWRITE_NUMBER_SUBSTITUTION_METHOD substitutionMethod,
+ // _In_z_ WCHAR const* localeName,
+ // _In_ BOOL ignoreUserOverride,
+ // _COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution
+ // ) PURE;
+
+ ///
+ /// Creates a glyph run analysis object, which encapsulates information
+ /// used to render a glyph run.
+ ///
+ /// Structure specifying the properties of the glyph run.
+ /// Number of physical pixels per DIP. For example, if rendering onto a 96 DPI bitmap then pixelsPerDip
+ /// is 1. If rendering onto a 120 DPI bitmap then pixelsPerDip is 120/96.
+ /// Optional transform applied to the glyphs and their positions. This transform is applied after the
+ /// scaling specified by the emSize and pixelsPerDip.
+ /// Specifies the rendering mode, which must be one of the raster rendering modes (i.e., not default
+ /// and not outline).
+ /// Specifies the method to measure glyphs.
+ /// Horizontal position of the baseline origin, in DIPs.
+ /// Vertical position of the baseline origin, in DIPs.
+ /// Receives a pointer to the newly created object.
+ void CreateGlyphRunAnalysisSTUB();
+ //STDMETHOD(CreateGlyphRunAnalysis)(
+ // _In_ DWRITE_GLYPH_RUN const* glyphRun,
+ // FLOAT pixelsPerDip,
+ // _In_opt_ DWRITE_MATRIX const* transform,
+ // DWRITE_RENDERING_MODE renderingMode,
+ // DWRITE_MEASURING_MODE measuringMode,
+ // FLOAT baselineOriginX,
+ // FLOAT baselineOriginY,
+ // _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis
+ // ) PURE;
+*/
+ }
+ }
+}
diff --git a/src/WInterop.DirectX/DirectX/DirectXWindowClass.cs b/src/WInterop.DirectX/DirectX/DirectXWindowClass.cs
index c264d51f..576d3917 100644
--- a/src/WInterop.DirectX/DirectX/DirectXWindowClass.cs
+++ b/src/WInterop.DirectX/DirectX/DirectXWindowClass.cs
@@ -2,8 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using WInterop.Direct2d;
-using WInterop.DirectWrite;
-using WInterop.Errors;
using WInterop.Gdi;
using WInterop.Modules;
using WInterop.Windows;
@@ -13,7 +11,6 @@ namespace WInterop.DirectX
public class DirectXWindowClass : WindowClass
{
private bool _resourcesValid;
- private IWindowRenderTarget _renderTarget;
public unsafe DirectXWindowClass(
string className = default,
@@ -30,16 +27,16 @@ public unsafe DirectXWindowClass(
{
}
- protected IRenderTarget RenderTarget => _renderTarget;
+ protected IWindowRenderTarget RenderTarget { get; private set; }
- protected static Direct2d.IFactory Direct2dFactory { get; } = Direct2d.Direct2d.CreateFactory();
- protected static DirectWrite.IFactory DirectWriteFactory { get; } = DirectWrite.DirectWrite.CreateFactory();
+ protected static Factory Direct2dFactory { get; } = Direct2d.Direct2d.CreateFactory();
+ protected static DirectWrite.WriteFactory DirectWriteFactory { get; } = DirectWrite.DirectWrite.CreateFactory();
private void CreateResourcesInternal(WindowHandle window)
{
if (!_resourcesValid)
{
- _renderTarget = Direct2dFactory.CreateWindowRenderTarget(
+ RenderTarget = Direct2dFactory.CreateWindowRenderTarget(
default, new WindowRenderTargetProperties(window, window.GetClientRectangle().Size));
CreateResources();
_resourcesValid = true;
@@ -50,14 +47,14 @@ private void CreateResourcesInternal(WindowHandle window, in Message.Size size)
{
if (!_resourcesValid)
{
- _renderTarget = Direct2dFactory.CreateWindowRenderTarget(
+ RenderTarget = Direct2dFactory.CreateWindowRenderTarget(
default, new WindowRenderTargetProperties(window, size.NewSize));
CreateResources();
_resourcesValid = true;
}
else
{
- _renderTarget.Resize(size.NewSize);
+ RenderTarget.Resize(size.NewSize);
}
}
@@ -87,19 +84,16 @@ protected sealed override LResult WindowProcedure(WindowHandle window, MessageTy
break;
case MessageType.Paint:
CreateResourcesInternal(window);
- _renderTarget.BeginDraw();
+ RenderTarget.BeginDraw();
OnPaint(window);
- HResult result = _renderTarget.EndDraw();
+ RenderTarget.EndDraw(out bool recreateTarget);
window.Validate();
- if (result == HResult.D2DERR_RECREATE_TARGET)
+ if (recreateTarget)
{
_resourcesValid = false;
}
- else
- {
- result.ThrowIfFailed();
- }
+
break;
}
@@ -114,9 +108,7 @@ protected virtual LResult Direct2dWindowProcedure(WindowHandle window, MessageTy
switch (message)
{
case MessageType.Size:
- return 0;
case MessageType.DisplayChange:
- return 0;
case MessageType.Paint:
return 0;
}
diff --git a/src/WInterop.DirectX/Dxgi/Format.cs b/src/WInterop.DirectX/Dxgi/Format.cs
index eb278b78..09dd9ff5 100644
--- a/src/WInterop.DirectX/Dxgi/Format.cs
+++ b/src/WInterop.DirectX/Dxgi/Format.cs
@@ -8,11 +8,11 @@ namespace WInterop.Dxgi
///
public enum Format : uint
{
- DXGI_FORMAT_UNKNOWN = 0,
- DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
- DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
- DXGI_FORMAT_R32G32B32A32_UINT = 3,
- DXGI_FORMAT_R32G32B32A32_SINT = 4,
+ Unknown = DXGI_FORMAT.DXGI_FORMAT_UNKNOWN,
+ TypelessR32G32B32A32 = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ FloatR32G32B32A32 = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT,
+ UIntR32G32B32A32 = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_UINT,
+ SIntR32G32B32A32 = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_SINT,
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
DXGI_FORMAT_R32G32B32_FLOAT = 6,
DXGI_FORMAT_R32G32B32_UINT = 7,
diff --git a/src/WInterop.DirectX/GlobalUsings.cs b/src/WInterop.DirectX/GlobalUsings.cs
new file mode 100644
index 00000000..d360b7b7
--- /dev/null
+++ b/src/WInterop.DirectX/GlobalUsings.cs
@@ -0,0 +1 @@
+global using TerraFX.Interop.DirectX;
diff --git a/src/WInterop.DirectX/IHandle.cs b/src/WInterop.DirectX/IHandle.cs
new file mode 100644
index 00000000..aada67c3
--- /dev/null
+++ b/src/WInterop.DirectX/IHandle.cs
@@ -0,0 +1,12 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#nullable enable
+
+namespace WInterop
+{
+ internal interface IHandle where T : unmanaged
+ {
+ unsafe T* Handle { get; }
+ }
+}
diff --git a/src/WInterop.DirectX/InteropExtensions.cs b/src/WInterop.DirectX/InteropExtensions.cs
new file mode 100644
index 00000000..4852ddfb
--- /dev/null
+++ b/src/WInterop.DirectX/InteropExtensions.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Jeremy W. Kuhne. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#nullable enable
+
+using System;
+using System.Drawing;
+using System.Runtime.CompilerServices;
+using TerraFX.Interop.Windows;
+using WInterop.Errors;
+
+namespace WInterop
+{
+ internal static class InteropExtensions
+ {
+ internal static RectangleF ToRectangleF(this in D2D_RECT_F rect)
+ => RectangleF.FromLTRB(rect.left, rect.top, rect.right, rect.bottom);
+
+ internal static D2D_RECT_F ToD2D(this in RectangleF rect)
+ => new(rect.Left, rect.Top, rect.Right, rect.Bottom);
+
+ internal static D2D_RECT_U ToD2D(this in Rectangle rect)
+ => checked(new((uint)rect.Left, (uint)rect.Top, (uint)rect.Right, (uint)rect.Bottom));
+
+ internal static PointF ToPointF(this in D2D_POINT_2F point)
+ => Unsafe.As(ref Unsafe.AsRef(point));
+
+ internal static D2D_POINT_2F ToD2D(this in PointF point)
+ => Unsafe.As(ref Unsafe.AsRef(point));
+
+ internal static SizeF ToSizeF(this in D2D_SIZE_F size)
+ => Unsafe.As(ref Unsafe.AsRef(size));
+
+ internal static D2D_SIZE_F ToD2D(this in SizeF size)
+ => Unsafe.As(ref Unsafe.AsRef(size));
+
+ internal static HResult ToHResult(this in HRESULT result)
+ => (HResult)(int)result;
+
+ internal static void ThrowIfFailed(this in HRESULT result, string? detail = null)
+ => result.ToHResult().ThrowIfFailed(detail);
+ }
+}
diff --git a/src/WInterop.DirectX/WInterop.Direct2d.csproj b/src/WInterop.DirectX/WInterop.Direct2d.csproj
index cca54b6d..3346fb51 100644
--- a/src/WInterop.DirectX/WInterop.Direct2d.csproj
+++ b/src/WInterop.DirectX/WInterop.Direct2d.csproj
@@ -6,7 +6,11 @@
False
True
WInterop
+ true
+
+
+