Search code examples
c#fontsc++-clitruetype

Check if FontFamily is TrueType


Is it possible to determine whether a certain font family is a TrueType-font using C#, C++/CLI or by P/Invoking the WinAPI?

In the end I would like to have some result like this

bool result1 = CheckIfIsTrueType(new FontFamily("Consolas")); //returns true
bool result2 = CheckIfIsTrueType(new FontFamily("Arial")); // returns true
bool result3 = CheckIfIsTrueType(new FontFamily("PseudoSaudi")); // returns false
bool result4 = CheckIfIsTrueType(new FontFamily("Ubuntu")); // returns true
bool result5 = CheckIfIsTrueType(new FontFamily("Purista")); // returns false

Of course the results are dependant of the target Operating System and its fonts...


Solution

  • It has the overhead of handling an exception, but the FontFamily constructor throws an ArgumentException if the supplied font is not TrueType:

    public bool CheckIfIsTrueType(string font)
    {
        try
        {
            var ff = new FontFamily(font)
        }
        catch(ArgumentException ae)
        {
            // this is also thrown if a font is not found
            if(ae.Message.Contains("TrueType"))
                return false;        
    
            throw;
        }
        return true;
    }
    

    Digging into the FontFamily constructor, it calls the external GDIPlus function GdipCreateFontFamilyFromName:

    [DllImport("Gdiplus", SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Unicode)] // 3 = Unicode
    internal static extern int GdipCreateFontFamilyFromName(string name, HandleRef fontCollection, out IntPtr FontFamily);
    

    which return a code of 16 if the font is not a true type font. So you can bypass the overhead of an exception:

    public bool CheckIfIsTrueType(string name)
    {
        IntPtr fontfamily = IntPtr.Zero;
        IntPtr nativeFontCollection = IntPtr.Zero ;
    
        int status = GdipCreateFontFamilyFromName(name, new HandleRef(null, nativeFontCollection), out fontfamily);
    
        if(status != 0)
            if(status == 16)  // not true type font)
                return false;
            else
                throw new ArgumentException("GDI Error occurred creating Font");
    
        return true;
    }
    

    Obviously you might want to use an enum of constants for the codes, which can be found here, and throw a better exception