If you need to use the TTF version of a font for PDF export and do not want to have it installed on the box (maybe the business uses the OTF version for everything else), you can programmatically add the TTF font to your process memory (application scope only) and remove the conflicting OTF fonts. It will only work for Export. The View and Print commands do not use fonts installed in process memory.
1. Add TTF files to your project as resources (Add Resource --> Add Existing File)
2. Add methods and classes below to check for required font names and install/remove fonts before exporting the Crystal Report object to PDF
Dim RequiredFontNames As New List(Of String)
Dim RequiredFontFileNames As New List(Of String)
Dim ConflictingFontFileNames As New List(Of String)
RequiredFontNames.Add("Gotham-Book")
RequiredFontNames.Add("Gotham-Medium")
RequiredFontFileNames.Add("GOTHMBOK.TTF")
RequiredFontFileNames.Add("GOTHMLIG.TTF")
RequiredFontFileNames.Add("GOTHMLIT.TTF")
RequiredFontFileNames.Add("GOTHMMED.TTF")
RequiredFontFileNames.Add("GOTHMMIT.TTF")
RequiredFontFileNames.Add("GOTHMZIT.TTF")
ConflictingFontFileNames.Add("Gotham-Book.otf")
ConflictingFontFileNames.Add("Gotham-BookItalic.otf")
ConflictingFontFileNames.Add("Gotham-Light.otf")
ConflictingFontFileNames.Add("Gotham-LightItalic.otf")
ConflictingFontFileNames.Add("Gotham-Medium.otf")
ConflictingFontFileNames.Add("Gotham-MediumItalic.otf")
Private Function CheckForRequiredFonts(Optional ByVal manageFonts As Boolean = False) As Boolean
Dim hasRequiredFonts As Boolean = True
If manageFonts Then
FontUtil.RemoveFontFiles(ConflictingFontFileNames)
End If
For Each item As String In RequiredFontNames
If FontUtil.FontExists(item) = False Then
mReasonForFailure = String.Format("The font '{0}' is not installed on your system.", item)
hasRequiredFonts = False
Exit For
End If
Next
If Not hasRequiredFonts And manageFonts Then
Try
FontUtil.InstallFontFiles(RequiredFontFileNames)
hasRequiredFonts = True
mReasonForFailure = ""
Catch ex As Exception
mReasonForFailure &= vbCrLf & "Required font files failed to install."
End Try
End If
Return hasRequiredFonts
End Function
Imports System.Drawing.Text
Imports System.Drawing
Imports System.Runtime.InteropServices
Public Class FontUtil
<DllImport("gdi32.dll")>
Private Shared Function RemoveFontResource(lpFileName As String) As Boolean
End Function
<DllImport("gdi32.dll")>
Private Shared Function AddFontMemResourceEx(pbFont As IntPtr, cbFont As UInteger, pdv As IntPtr, <[In]> ByRef pcFonts As UInteger) As IntPtr
End Function
Public Shared Function FontExists(fontName As String) As Boolean
Dim ifc As New InstalledFontCollection()
For Each item As FontFamily In ifc.Families
If item.Name = fontName Then
Return True
End If
Next
Return False
End Function
Public Sub AddFontResource(ByVal resourceName As String)
Dim fontStream As IO.Stream = Me.GetType().Assembly.GetManifestResourceStream(resourceName)
Dim data As System.IntPtr = Marshal.AllocCoTaskMem(CInt(fontStream.Length))
Dim fontData As [Byte]() = New [Byte](fontStream.Length - 1) {}
fontStream.Read(fontData, 0, CInt(fontStream.Length))
Marshal.Copy(fontData, 0, data, CInt(fontStream.Length))
Dim cFonts As UInteger = 0
AddFontMemResourceEx(data, CUInt(fontData.Length), IntPtr.Zero, cFonts)
fontStream.Close()
Marshal.FreeCoTaskMem(data)
End Sub
Public Shared Sub InstallFontFiles(ByVal fontFileNameList As List(Of String))
Dim assemblyName As String = "MyAssembly.ReportLib."
Dim myFontUtil As New FontUtil
For Each fileName In fontFileNameList
myFontUtil.AddFontResource(assemblyName & fileName)
Next
End Sub
Public Shared Sub RemoveFontFiles(ByVal fontFileNameList As List(Of String))
For Each fileName In fontFileNameList
Dim isDeleted As Boolean = RemoveFontResource(fileName)
Next
End Sub
End Class