Streamline Font Creation and Usage.

Generally, when using GDI+ objects such as brushes, pens and fonts, the technique is to create the object, use it and then explicitly dispose of it in the Paint handler. This usually ensures that memory usage us kept to a minimum and valuable resources are not kept hanging around for too long.

For text intensive applications however, this may not be the case because the process of creating a font is a computationally expensive one and creating and destroying many fonts in a single paint cycle can cause serious bottlenecks in the drawing process. One answer to this problem is to pre-create your fonts and keep them around for the life of the application but this method also falls down when fonts are chosen by the user at runtime, a choice that you cannot really predict. The best way to overcome this problem is to create the font whenever you need it but keep it around, just in case you need it again. To do this, you can associate the description of the font with the font object and store it in a Hashtable.

The hashtable associates an object with a key and enables very fast searching for a specific object through that key. Creating the string description of the font is simply a matter of concatenating the font family name, size and style in some text form and then associating that with the actual font instance provides a way to find a font if it's been used before. Of course, if it hasn't been used before the font is created and stored in the hashtable with it's key.

When the object owning the hashtable is disposed of then the hashtable can be cleared and all the font objects in it disposed of in turn. For text intensive applications this trick can speed up the draw process considerably.

The following code shows how this technique works. Instead of creating a new font, use GetFont and if one has already been created with the same specification, it will be used instead.

C#

    Hashtable Fonts=new Hashtable();

 

    protected virtual Font GetFont(string family, float size, FontStyle style)

    {

      string s=family+size.ToString()+((int)style).ToString();

      if(Fonts.Contains(s))

        return (Font)Fonts[s];

      Font f=new Font(family,size,style);

      Fonts.Add(s,f);

      return f;

    }

 

 

    protected override void Dispose(bool disposing)

    {

      foreach(Font f in Fonts.Values)

        f.Dispose();

      Fonts.Clear();

 

      base.Dispose (disposing);

    }

VB

   Dim Fonts As Hashtable = New Hashtable()

 

    Protected Overridable Function GetFont(ByVal family As String, ByVal size As single, ByVal style As FontStyle) As Font

      Dim s As String = family & size.ToString() & CInt(style).ToString()

      If Fonts.Contains(s) Then

        Return CType(Fonts(s), Font)

      End If

      Dim f As Font = New Font(family,size,style)

      Fonts.Add(s,f)

      Return f

    End Function

 

 

    Protected Overrides  Sub Dispose(ByVal disposing As Boolean)

      Dim f As Font

      For Each f In Fonts.Values

        f.Dispose()

      Next

      Fonts.Clear()

      MyBase.Dispose (disposing)

    End Sub

Return to Windows Forms Tips and Tricks

Copyright Robert W. Powell 2004. All rights reserved