smourier / DirectN

Direct interop Code for .NET Framework, .NET Core and .NET 5+ : DXGI, WIC, DirectX 9 to 12, Direct2D, Direct Write, Direct Composition, Media Foundation, WASAPI, CodecAPI, GDI, Spatial Audio, DVD, Windows Media Player, UWP DXInterop, WinUI3, etc.
MIT License
311 stars 28 forks source link

GetMatchingFonts - FontSet #19

Closed miquik closed 2 years ago

miquik commented 2 years ago

Hi, I don't know if it is a bug or if I'm missing something; I can't get IDWriteFontSet.GetMatchingFonts to work I always get Access Violation exception. This is my sample code:

HRESULT hr = DWriteFunctions.DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, typeof(IDWriteFactory7).GUID, out object factory);
if (factory == null)    
   return;           
IDWriteFactory7 dwritef = (IDWriteFactory7)factory;
hr = dwritef.GetSystemFontSet(out IDWriteFontSet fontSet);
hr = fontSet.GetMatchingFonts("Arial",      <-- calling this method generate exception
            DWRITE_FONT_WEIGHT.DWRITE_FONT_WEIGHT_REGULAR,
            DWRITE_FONT_STRETCH.DWRITE_FONT_STRETCH_NORMAL,
            DWRITE_FONT_STYLE.DWRITE_FONT_STYLE_NORMAL,
            out IDWriteFontSet filteredSet);

I tried different IDWriteFactory interfaces (IDWriteFactory3 to IDWriteFactory7) and different IDWriteFontSet interfaces, but I always get same exception

Any idea? I'm doing something wrong? Thanks

smourier commented 2 years ago

Hi,

Hmmm... there are two GetMatchingFonts methods to IDWriteFontSet. That may be the issue described here: https://stackoverflow.com/questions/61542063/inversion-of-generated-vtable-functions-order-for-functions-with-the-same-name

Can you test change this:

    public partial interface IDWriteFontSet
    {
        ...
        [PreserveSig]
        HRESULT GetMatchingFonts(/* _In_reads_(propertyCount) */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] DWRITE_FONT_PROPERTY[] properties, int propertyCount, /* _COM_Outptr_ */ out IDWriteFontSet filteredSet);

        [PreserveSig]
        HRESULT GetMatchingFonts(/* _In_z_ */ [MarshalAs(UnmanagedType.LPWStr)] string familyName, DWRITE_FONT_WEIGHT fontWeight, DWRITE_FONT_STRETCH fontStretch, DWRITE_FONT_STYLE fontStyle, /* _COM_Outptr_ */ out IDWriteFontSet filteredSet);
    }

into this:

 public partial interface IDWriteFontSet
    {
        ...
        [PreserveSig]
        HRESULT GetMatchingFonts(/* _In_z_ */ [MarshalAs(UnmanagedType.LPWStr)] string familyName, DWRITE_FONT_WEIGHT fontWeight, DWRITE_FONT_STRETCH fontStretch, DWRITE_FONT_STYLE fontStyle, /* _COM_Outptr_ */ out IDWriteFontSet filteredSet);

        [PreserveSig]
        HRESULT GetMatchingFonts(/* _In_reads_(propertyCount) */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] DWRITE_FONT_PROPERTY[] properties, int propertyCount, /* _COM_Outptr_ */ out IDWriteFontSet filteredSet);
    }

and see it it works any better?

miquik commented 2 years ago

Yes, that seems to be the problem. I made a quick test and at least I didn’t get any exception. Later I will try deeper but I think this solve my problem. I’m not sure but probably also GetPropertyValues in same interface have same problems

smourier commented 2 years ago

Certainly, all methods with the same name should be declared in reverse order with respect to the native C/C++ header order.

I need to work on this. I think this is not the only interface like that (not even speaking of derivates IDWriteFontSet2, etc.)