Closed snnz closed 2 years ago
Hi,
Thanks for reporting that.
Yes, absolutely. The type should be this:
[StructLayout(LayoutKind.Sequential)]
public partial struct DWRITE_GLYPH_RUN_DESCRIPTION
{
/// <summary>
/// The locale name associated with this run.
/// </summary>
public IntPtr localeName;
/// <summary>
/// The text associated with the glyphs.
/// </summary>
public IntPtr @string;
/// <summary>
/// The number of characters (UTF16 code-units). Note that this may be different than the number of glyphs.
/// </summary>
public uint stringLength;
/// <summary>
/// An array of indices to the glyph indices array, of the first glyphs of all the glyph clusters of the glyphs to render.
/// </summary>
public IntPtr clusterMap;
/// <summary>
/// Corresponding text position in the original string this glyph run came from.
/// </summary>
public uint textPosition;
}
99% of the code is generated automatically. It's possible that there are other places like this.
I will have a look at it when I find some time.
Fields localeName and @string are declared as char in DWRITE_GLYPH_RUN_DESCRIPTION, but there should be string instead, or just IntPtr without marshalling. Type char is incompatible with MarshalAs(UnmanagedType.LPWStr) attribute, and when DWrite is trying to call the DrawGlyphRun method in a C# implementation of the IDWriteTextRenderer interface (that takes DWRITE_GLYPH_RUN_DESCRIPTION as an argument), the marshaler quietly returns 0, while actual managed member is not called. DWrite is pretty happy with the result and reports success too. It took me a while to figure out what had been going wrong...