MILO
MILO

Reputation: 295

What are the benefits to using PrivateFontCollection's AddMemoryFont() over AddFontFile()

After much trial and error I have finally got my application to work with custom fonts on machines other than the development machine, however, I'm not sure which of the two methods I have gotten to work is the preferred way of doing things.

Either embedding the font as a resource and using Assembly.GetManifestResourceStream() to push the font files data into unmanaged memory and adding it to a PrivateFontCollection using AddMemoryFont() like this:

(All error handling and superfluous code removed)

Imports System.Runtime.InteropServices
Imports System.Drawing.Text

Public Class FormExample

    Private ReadOnly pfc As New PrivateFontCollection
    Private f As Font
    Private ReadOnly Bytes() As Byte = GetFontData(Reflection.Assembly.GetExecutingAssembly, "MyFont.ttf")
    Private ReadOnly fontPtr As IntPtr = Marshal.AllocCoTaskMem(Me.Bytes.Length)

    Private Sub FormExample_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Marshal.Copy(Me.Bytes, 0, Me.fontPtr, Me.Bytes.Length)
        Me.pfc.AddMemoryFont(Me.fontPtr, Me.Bytes.Length)
        Me.f = New Font(Me.pfc.Families(0), 14, FontStyle.Regular)
        'Iterate through forms controls and set font where valid
        SetFormsCustomFont(Me, Me.f)
    End Sub

    Private Sub FormExample_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
        Marshal.FreeCoTaskMem(Me.fontPtr)
        Me.pfc.Dispose()
    End Sub

    Private Function GetFontData(Asm As Assembly, Name As String) As Byte()
        Using Stream As Stream = Asm.GetManifestResourceStream(Name)
            Dim Buffer() As Byte = New Byte(CInt(Stream.Length - 1)) {}
            Stream.Read(Buffer, 0, CInt(Stream.Length))
            Return Buffer
        End Using
    End Function

End Class

Or by simply including the font with the application rather than embedding it as a resource and using PrivateFontCollection.AddFontFile():

Public Class FormExample2

    Private ReadOnly pfc As New PrivateFontCollection
    Private f As Font

    Private Sub FormExample2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim fontFile As String = ".\Path\To\MyFont.ttf"
        Me.pfc.AddFontFile(fontFile)
        Me.f = New Font(Me.pfc.Families(0), 14)
        'Iterate through forms controls and set font where valid
        SetFormsCustomFont(Me, Me.f)
    End Sub

    Private Sub FormExample2_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
        Me.pfc.Dispose()
    End Sub

End Class

In both methods the font collections need to be kept around for the life of the form, and I have to repeat the code and have font objects for each form in the application so that I don't trample over the unmanaged memory.

Other than the fact that the second method gives users access to your font file, is there any other benefit to doing it the first way?

OR, is there another preferred way of doing this that I am unaware of?

Upvotes: 0

Views: 536

Answers (0)

Related Questions