Interesting facts about fonts in .NET

Andrey Akinshin

Today we will talk about a wonderful Font class. Sometimes when I work with the fonts I get some questions which are not that obvious as I would like them to be.
 
Let’s check some of them.
 
Q: How to identify a monospaced font?
 
A: It’s not such a simple question as it may seem. You can find the following advice in the Google search results: describe LOGFONT class in your project and use ToLogFont method to convert the font to a corresponding object. After that (as legend has it) the first bit in the IfPitchAndFamily field should identify if the font is monospaced. So, this is shit! Nowadays the field is always equal to zero. Sometimes and somewhere this option worked, but in doesn’t now. In real life you have to use not very pretty, but very efficient solution as:
 

// graphics — preliminary created instance of the Graphics class
public static bool IsMonospace(Font font)
{
    return Math.Abs(graphics.MeasureString("iii", font).Width -
                    graphics.MeasureString("WWW", font).Width) < 1e-3;
}

 
Q: How to define the size of a string when using this font?
 
A: We will need Graphics which will be used to draw and namely its MeasureString method. Pass the drawn text and used font to it and it gets the string size.
 

Q: What if I need to get size of a definite part of a string?
 
A: You can do it with the Graphics.MeasureCharacterRanges method. But at first (and there is a good sample in MSDN), it is necessary to set target intervals of the characters with the StringFormat.SetMeasurableCharacterRanges method. This method has an amazing limitation, you can’t pass more than 32 intervals to it.
 
Q: This method gets too big boundaries. They include not only the characters but also some space near to it. What to do?
 
A: Actually the regions that you get contain the symbols in the way they are listed in the initial font – together with a little space next to it. There is no neat way to get exact boundaries. You will have to create a picture with the target characters and review it pixel-by-pixel (just don’t use Bitmap.GetPixel it’s too time consuming, there are quicker methods) and find extreme characters of the string.
 
Q: I created a font by using its string name, got no exceptions. Is there such font in the system?
 
A: Not always. Font class constructor tries to get the most closely matching font (to its consideration) for this name. It’s better to check if the correct font was created:
 

var font = new Font(fontName, 12);
var isExist = font.Name == fontName;

 
And it would also be good to check if the font family you use is able to support your FontStyle:
 

var fontFamily = new FontFamily(fontName);
isExist &= fontFamily.IsStyleAvailable(fontStyle);
August 9th, 2013

Leave a Comment