DirectWrite bindings support and preparation for Direct2D1.

This commit is contained in:
Amer Koleci
2022-09-19 10:35:31 +02:00
parent 475f91c721
commit 6237581041
13 changed files with 31070 additions and 21 deletions

View File

@@ -24,7 +24,7 @@ public static class Program
"Graphics.Direct3D.Dxc.json", "Graphics.Direct3D.Dxc.json",
"Graphics.Direct2D.Common.json", "Graphics.Direct2D.Common.json",
"Graphics.Imaging.json", "Graphics.Imaging.json",
//"Graphics.DirectWrite.json", "Graphics.DirectWrite.json",
//"Graphics.Direct2D.json", //"Graphics.Direct2D.json",
//"Graphics.Imaging.D2D.json", //"Graphics.Imaging.D2D.json",
@@ -85,6 +85,9 @@ public static class Program
{ "Graphics.Gdi.HBITMAP", "IntPtr" }, { "Graphics.Gdi.HBITMAP", "IntPtr" },
{ "Graphics.Gdi.HPALETTE", "IntPtr" }, { "Graphics.Gdi.HPALETTE", "IntPtr" },
{ "UI.WindowsAndMessaging.HICON", "IntPtr" }, { "UI.WindowsAndMessaging.HICON", "IntPtr" },
{ "Globalization.FONTSIGNATURE", "Win32.Graphics.Gdi.FontSignature" },
{ "Graphics.Gdi.LOGFONTA", "Win32.Graphics.Gdi.LogFontA" },
{ "Graphics.Gdi.LOGFONTW", "Win32.Graphics.Gdi.LogFontW" },
{ "Graphics.Direct3D.D3DVECTOR", "Vector3" }, { "Graphics.Direct3D.D3DVECTOR", "Vector3" },
{ "Graphics.Direct3D.D3DMATRIX", "Matrix4x4" }, { "Graphics.Direct3D.D3DMATRIX", "Matrix4x4" },
@@ -893,7 +896,7 @@ public static class Program
} }
// Generate docs // Generate docs
//DocGenerator.Generate(new[] { "WIC" }, Path.Combine(outputPath, "Imaging.xml")); //DocGenerator.Generate(new[] { "D2D1" }, Path.Combine(outputPath, "Direct2D.xml"));
//DocGenerator.Generate(new[] { "DWRITE" }, Path.Combine(outputPath, "DirectWrite.xml")); //DocGenerator.Generate(new[] { "DWRITE" }, Path.Combine(outputPath, "DirectWrite.xml"));
//DocGenerator.Generate(new[] { "D3D" }, Path.Combine(outputPath, "Direct3D.xml")); //DocGenerator.Generate(new[] { "D3D" }, Path.Combine(outputPath, "Direct3D.xml"));
//DocGenerator.Generate(new[] { "DXGI" }, Path.Combine(outputPath, "Dxgi.xml")); //DocGenerator.Generate(new[] { "DXGI" }, Path.Combine(outputPath, "Dxgi.xml"));

View File

@@ -31,7 +31,7 @@ public readonly struct VariantFullType : IEquatable<VariantFullType>
} }
public bool Equals(VariantFullType other) => vt == other.vt; public bool Equals(VariantFullType other) => vt == other.vt;
public override bool Equals(object obj) => obj is VariantFullType other && Equals(other); public override bool Equals(object? obj) => obj is VariantFullType other && Equals(other);
public override int GetHashCode() => vt.GetHashCode(); public override int GetHashCode() => vt.GetHashCode();
public static bool operator ==(VariantFullType left, VariantFullType right) => left.Equals(right); public static bool operator ==(VariantFullType left, VariantFullType right) => left.Equals(right);
public static bool operator !=(VariantFullType left, VariantFullType right) => !left.Equals(right); public static bool operator !=(VariantFullType left, VariantFullType right) => !left.Equals(right);

View File

@@ -232,7 +232,9 @@ public unsafe struct ComPtr<T> : IDisposable
return ptr_; return ptr_;
} }
/// <summary>Gets the address of the current <see cref="ComPtr{T}"/> instance as a raw <typeparamref name="T"/> double pointer. This method is only valid when the current <see cref="ComPtr{T}"/> instance is on the stack or pinned. /// <summary>
/// Gets the address of the current <see cref="ComPtr{T}"/> instance as a raw <typeparamref name="T"/> double pointer.
/// This method is only valid when the current <see cref="ComPtr{T}"/> instance is on the stack or pinned.
/// </summary> /// </summary>
/// <returns>The raw pointer to the current <see cref="ComPtr{T}"/> instance.</returns> /// <returns>The raw pointer to the current <see cref="ComPtr{T}"/> instance.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -252,6 +254,17 @@ public unsafe struct ComPtr<T> : IDisposable
return (void**)Unsafe.AsPointer(ref Unsafe.AsRef(in this)); return (void**)Unsafe.AsPointer(ref Unsafe.AsRef(in this));
} }
/// <summary>
/// Gets the address of the current <see cref="ComPtr{T}"/> instance as a raw <see cref="IUnknown"/> double pointer.
/// This method is only valid when the current <see cref="ComPtr{T}"/> instance is on the stack or pinned.
/// </summary>
/// <returns>The raw pointer to the current <see cref="ComPtr{T}"/> instance.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly IUnknown** GetIUnknownAddressOf()
{
return (IUnknown**)Unsafe.AsPointer(ref Unsafe.AsRef(in this));
}
/// <summary>Gets the address of the current <see cref="ComPtr{T}"/> instance as a raw <typeparamref name="T"/> double pointer.</summary> /// <summary>Gets the address of the current <see cref="ComPtr{T}"/> instance as a raw <typeparamref name="T"/> double pointer.</summary>
/// <returns>The raw pointer to the current <see cref="ComPtr{T}"/> instance.</returns> /// <returns>The raw pointer to the current <see cref="ComPtr{T}"/> instance.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,12 +8,12 @@ namespace Win32.Graphics.Direct2D.Common;
public partial struct PixelFormat public partial struct PixelFormat
{ {
/// <summary> /// <summary>
/// An unkown <see cref="PixelFormat"/> with <see cref="Format"/> to <see cref="Format.Unknown"/> and <see cref="DCommon.AlphaMode"/> to <see cref="AlphaMode.Unknown"/>. /// An unkown <see cref="PixelFormat"/> with <see cref="Format"/> to <see cref="Format.Unknown"/> and <see cref="AlphaMode"/> to <see cref="AlphaMode.Unknown"/>.
/// </summary> /// </summary>
public static readonly PixelFormat Unknown = new(Format.Unknown, AlphaMode.Unknown); public static readonly PixelFormat Unknown = new(Format.Unknown, AlphaMode.Unknown);
/// <summary> /// <summary>
/// A Premultiplied <see cref="PixelFormat"/> with <see cref="Format"/> to <see cref="Format.Unknown"/> and <see cref="DCommon.AlphaMode"/> to <see cref="AlphaMode.Premultiplied"/>. /// A Premultiplied <see cref="PixelFormat"/> with <see cref="Format"/> to <see cref="Format.Unknown"/> and <see cref="AlphaMode"/> to <see cref="AlphaMode.Premultiplied"/>.
/// </summary> /// </summary>
public static readonly PixelFormat Premultiplied = new(Format.Unknown, AlphaMode.Premultiplied); public static readonly PixelFormat Premultiplied = new(Format.Unknown, AlphaMode.Premultiplied);

View File

@@ -0,0 +1,100 @@
// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
using System.Runtime.InteropServices.ComTypes;
using Win32.Graphics.Imaging;
namespace Win32.Graphics.DirectWrite;
/// <summary>
/// A <see langword="class"/> with extensions for the <see cref="IDWriteFactory"/> type.
/// </summary>
public static unsafe class IDWriteFactoryExtensions
{
public static ComPtr<IDWriteTextFormat> CreateTextFormat(
this ref IDWriteFactory factory,
ReadOnlySpan<char> fontFamilyName,
float fontSize,
FontWeight fontWeight = FontWeight.Normal,
FontStyle fontStyle = FontStyle.Normal,
FontStretch fontStretch = FontStretch.Normal)
{
using ComPtr<IDWriteTextFormat> textFormat = default;
fixed (char* fontFamilyNamePtr = fontFamilyName)
{
factory.CreateTextFormat(
(ushort*)fontFamilyNamePtr,
null,
fontWeight,
fontStyle,
fontStretch,
fontSize,
null,
textFormat.GetAddressOf()).ThrowIfFailed();
return textFormat.Move();
}
}
public static ComPtr<IDWriteTextFormat> CreateTextFormat(
this ref IDWriteFactory factory,
ReadOnlySpan<char> fontFamilyName,
float fontSize,
ReadOnlySpan<char> localeName,
FontWeight fontWeight = FontWeight.Normal,
FontStyle fontStyle = FontStyle.Normal,
FontStretch fontStretch = FontStretch.Normal)
{
using ComPtr<IDWriteTextFormat> textFormat = default;
fixed (char* fontFamilyNamePtr = fontFamilyName)
{
fixed (char* localeNamePtr = localeName)
{
factory.CreateTextFormat(
(ushort*)fontFamilyNamePtr,
null,
fontWeight,
fontStyle,
fontStretch,
fontSize,
(ushort*)localeNamePtr,
textFormat.GetAddressOf()).ThrowIfFailed();
}
return textFormat.Move();
}
}
public static ComPtr<IDWriteTextFormat> CreateTextFormat(
this ref IDWriteFactory factory,
ReadOnlySpan<char> fontFamilyName,
IDWriteFontCollection* fontCollection,
float fontSize,
ReadOnlySpan<char> localeName,
FontWeight fontWeight = FontWeight.Normal,
FontStyle fontStyle = FontStyle.Normal,
FontStretch fontStretch = FontStretch.Normal)
{
using ComPtr<IDWriteTextFormat> textFormat = default;
fixed (char* fontFamilyNamePtr = fontFamilyName)
{
fixed (char* localeNamePtr = localeName)
{
factory.CreateTextFormat(
(ushort*)fontFamilyNamePtr,
fontCollection,
fontWeight,
fontStyle,
fontStretch,
fontSize,
(ushort*)localeNamePtr,
textFormat.GetAddressOf()).ThrowIfFailed();
}
return textFormat.Move();
}
}
}

View File

@@ -0,0 +1,12 @@
// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
namespace Win32.Graphics.Gdi;
/// <unmanaged>FONTSIGNATURE</unmanaged>
public partial struct FontSignature
{
public unsafe fixed uint fsUsb[4];
public unsafe fixed uint fsCsb[2];
}

View File

@@ -0,0 +1,69 @@
// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
namespace Win32.Graphics.Gdi;
/// <unmanaged>LOGFONTA</unmanaged>
public partial struct LogFontA
{
/// <summary>
/// The height, in logical units, of the font's character cell or character.
/// The character height value (also known as the em height) is the character cell height value minus the internal-leading value.
/// </summary>
public int Height;
/// <summary>
/// The average width, in logical units, of characters in the font.
/// </summary>
public int Width;
/// <summary>
/// The angle, in tenths of degrees, between the escapement vector and the x-axis of the device.
/// The escapement vector is parallel to the base line of a row of text.
/// </summary>
public int Escapement;
/// <summary>
/// The angle, in tenths of degrees, between each character's base line and the x-axis of the device.
/// </summary>
public int Orientation;
/// <summary>
/// The weight of the font in the range 0 through 1000.
/// For example, 400 is normal and 700 is bold. If this value is zero, a default weight is used.
/// </summary>
public int Weight;
/// <summary>
/// An italic font if set to TRUE.
/// </summary>
public byte Italic;
/// <summary>
/// An underlined font if set to TRUE.
/// </summary>
public byte Underline;
/// <summary>
/// A strikeout font if set to TRUE.
/// </summary>
public byte StrikeOut;
/// <summary>
/// The character set.
/// </summary>
public byte CharSet;
/// <summary>
/// The output precision. The output precision defines how closely the output must match the requested font's height, width, character orientation, escapement, pitch, and font type.
/// </summary>
public byte OutPrecision;
public byte ClipPrecision;
public byte Quality;
public byte PitchAndFamily;
public unsafe fixed sbyte FaceName[32];
}

View File

@@ -0,0 +1,69 @@
// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
namespace Win32.Graphics.Gdi;
/// <unmanaged>LOGFONTW</unmanaged>
public partial struct LogFontW
{
/// <summary>
/// The height, in logical units, of the font's character cell or character.
/// The character height value (also known as the em height) is the character cell height value minus the internal-leading value.
/// </summary>
public int Height;
/// <summary>
/// The average width, in logical units, of characters in the font.
/// </summary>
public int Width;
/// <summary>
/// The angle, in tenths of degrees, between the escapement vector and the x-axis of the device.
/// The escapement vector is parallel to the base line of a row of text.
/// </summary>
public int Escapement;
/// <summary>
/// The angle, in tenths of degrees, between each character's base line and the x-axis of the device.
/// </summary>
public int Orientation;
/// <summary>
/// The weight of the font in the range 0 through 1000.
/// For example, 400 is normal and 700 is bold. If this value is zero, a default weight is used.
/// </summary>
public int Weight;
/// <summary>
/// An italic font if set to TRUE.
/// </summary>
public byte Italic;
/// <summary>
/// An underlined font if set to TRUE.
/// </summary>
public byte Underline;
/// <summary>
/// A strikeout font if set to TRUE.
/// </summary>
public byte StrikeOut;
/// <summary>
/// The character set.
/// </summary>
public byte CharSet;
/// <summary>
/// The output precision. The output precision defines how closely the output must match the requested font's height, width, character orientation, escapement, pitch, and font type.
/// </summary>
public byte OutPrecision;
public byte ClipPrecision;
public byte Quality;
public byte PitchAndFamily;
public unsafe fixed ushort FaceName[32];
}

View File

@@ -15,15 +15,9 @@ public static unsafe class UnsafeUtilities
where TFrom : unmanaged where TFrom : unmanaged
where TTo : unmanaged where TTo : unmanaged
{ {
//Assert(AssertionsEnabled && (SizeOf<TFrom>() == SizeOf<TTo>()));
return CreateReadOnlySpan(in AsReadOnly<TFrom, TTo>(in span.GetReference()), span.Length); return CreateReadOnlySpan(in AsReadOnly<TFrom, TTo>(in span.GetReference()), span.Length);
} }
/// <inheritdoc cref="Unsafe.AsPointer{T}(ref T)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* AsPointer<T>(ref T source)
where T : unmanaged => (T*)Unsafe.AsPointer(ref source);
/// <inheritdoc cref="Unsafe.As{TFrom, TTo}(ref TFrom)" /> /// <inheritdoc cref="Unsafe.As{TFrom, TTo}(ref TFrom)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref readonly TTo AsReadOnly<TFrom, TTo>(in TFrom source) public static ref readonly TTo AsReadOnly<TFrom, TTo>(in TFrom source)
@@ -40,19 +34,11 @@ public static unsafe class UnsafeUtilities
/// <inheritdoc cref="MemoryMarshal.CreateReadOnlySpan{T}(ref T, int)" /> /// <inheritdoc cref="MemoryMarshal.CreateReadOnlySpan{T}(ref T, int)" />
public static ReadOnlySpan<T> CreateReadOnlySpan<T>(in T reference, int length) => MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in reference), length); public static ReadOnlySpan<T> CreateReadOnlySpan<T>(in T reference, int length) => MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in reference), length);
/// <summary>Returns a pointer to the element of the span at index zero.</summary>
/// <typeparam name="T">The type of items in <paramref name="span" />.</typeparam>
/// <param name="span">The span from which the pointer is retrieved.</param>
/// <returns>A pointer to the item at index zero of <paramref name="span" />.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* GetPointer<T>(this Span<T> span)
where T : unmanaged => AsPointer(ref MemoryMarshal.GetReference(span));
/// <summary>Returns a pointer to the element of the span at index zero.</summary> /// <summary>Returns a pointer to the element of the span at index zero.</summary>
/// <typeparam name="T">The type of items in <paramref name="span" />.</typeparam> /// <typeparam name="T">The type of items in <paramref name="span" />.</typeparam>
/// <param name="span">The span from which the pointer is retrieved.</param> /// <param name="span">The span from which the pointer is retrieved.</param>
/// <returns>A pointer to the item at index zero of <paramref name="span" />.</returns> /// <returns>A pointer to the item at index zero of <paramref name="span" />.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* GetPointer<T>(this ReadOnlySpan<T> span) public static T* GetPointer<T>(this ReadOnlySpan<T> span)
where T : unmanaged => AsPointer(ref Unsafe.AsRef(in span.GetReference())); where T : unmanaged => (T*)Unsafe.AsPointer(ref Unsafe.AsRef(in span.GetReference()));
} }

View File

@@ -14,6 +14,10 @@
<Using Include="System.Runtime.InteropServices" /> <Using Include="System.Runtime.InteropServices" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<Compile Remove="UnscopedRefAttribute.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="System.Memory" Version="4.5.4" /> <PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" /> <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />

View File

@@ -14,8 +14,10 @@ using static Win32.Graphics.Direct3D.Dxc.Apis;
using static Win32.Graphics.Direct3D11.Apis; using static Win32.Graphics.Direct3D11.Apis;
using static Win32.Graphics.Dxgi.Apis; using static Win32.Graphics.Dxgi.Apis;
using static Win32.Graphics.Imaging.Apis; using static Win32.Graphics.Imaging.Apis;
using static Win32.Graphics.DirectWrite.Apis;
using InfoQueueFilter = Win32.Graphics.Direct3D11.InfoQueueFilter; using InfoQueueFilter = Win32.Graphics.Direct3D11.InfoQueueFilter;
using MessageId = Win32.Graphics.Direct3D11.MessageId; using MessageId = Win32.Graphics.Direct3D11.MessageId;
using Win32.Graphics.DirectWrite;
namespace ClearScreen; namespace ClearScreen;
@@ -72,10 +74,28 @@ public static unsafe class Program
//wicBitmapFrameDecode.Get()->CopyPixels(rowPitch, pixels); //wicBitmapFrameDecode.Get()->CopyPixels(rowPitch, pixels);
} }
private static void TestD2D1AndDWrite()
{
using ComPtr<IDWriteFactory> dwriteFactory = default;
DWriteCreateFactory(FactoryType.Shared, __uuidof<IDWriteFactory>(), dwriteFactory.GetIUnknownAddressOf()).ThrowIfFailed();
using ComPtr<IDWriteTextFormat> textFormat =
dwriteFactory.Get()->CreateTextFormat(
"Gabriola".AsSpan(), // Font family name.
72.0f,
fontWeight: FontWeight.Regular,
localeName: "en-us".AsSpan()
);
textFormat.Get()->SetTextAlignment(TextAlignment.Center).ThrowIfFailed();
textFormat.Get()->SetParagraphAlignment(ParagraphAlignment.Center).ThrowIfFailed();
}
public static void Main() public static void Main()
{ {
TestDxc(); TestDxc();
TestWic(); TestWic();
TestD2D1AndDWrite();
using ComPtr<IDXGIFactory2> factory = default; using ComPtr<IDXGIFactory2> factory = default;
uint factoryFlags = 0; uint factoryFlags = 0;