PDF: Working with fonts of PDF document
In This Topic
Fonts are used for drawing text on PDF page. The font may be a standard one (a list of standard fonts defines the PDF specification and can be obtained using
PdfStandardFontType enumeration) and a non-standard one. Also a font can be stored separately from PDF document or be embedded into PDF document.
PdfFont class represents a font of PDF document and contains information about that font.
A list of fonts of PDF document can be obtained using
PdfDocument.GetFonts method. A list of fonts of PDF page can be obtained using
PdfPage.GetFonts method.
Here is C#/VB.NET code that demonstrates how to obtain information about all fonts of PDF document:
/// <summary>
/// Gets and prints information about fonts of PDF document.
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
public static void PrintPdfFontsInfo(string pdfFilename)
{
// open pdf document
using (Vintasoft.Imaging.Pdf.PdfDocument document =
new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// get collection of font of PDF document
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont[] fonts = document.GetFonts();
// print font count
System.Console.WriteLine("Font count: {0}", fonts.Length);
System.Console.WriteLine();
// for each font
foreach (Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont font in fonts)
// print name and type of font
System.Console.WriteLine("\tName: {0,-30} Type:{1}", font.FontName, font.FontType);
}
}
/* This code example produces the following output:
Font count: 10
Name: XIMJKA+TTE11BB980t00 Type:TrueType
Name: ANAPBW+TTE1198D80t00 Type:TrueType
Name: MyriadPro-Regular Type:Type1
Name: IXDUSS+MyriadPro-Bold Type:Type1
Name: GZINQW+MyriadPro-Black Type:Type1
Name: SMICCY+MyriadPro-Regular Type:Type1
Name: IXDUSS+MinionPro-SemiboldIt Type:Type1
Name: IXDUSS+MinionPro-It Type:Type1
Name: IXDUSS+MinionPro-Bold Type:Type1
Name: YDDMIM+MinionPro-Regular Type:Type1
*/
''' <summary>
''' Gets and prints information about fonts of PDF document.
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
Public Shared Sub PrintPdfFontsInfo(pdfFilename As String)
' open pdf document
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' get collection of font of PDF document
Dim fonts As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont() = document.GetFonts()
' print font count
System.Console.WriteLine("Font count: {0}", fonts.Length)
System.Console.WriteLine()
' for each font
For Each font As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont In fonts
' print name and type of font
System.Console.WriteLine(vbTab & "Name: {0,-30} Type:{1}", font.FontName, font.FontType)
Next
End Using
End Sub
' This code example produces the following output:
' Font count: 10
'
' Name: XIMJKA+TTE11BB980t00 Type:TrueType
' Name: ANAPBW+TTE1198D80t00 Type:TrueType
' Name: MyriadPro-Regular Type:Type1
' Name: IXDUSS+MyriadPro-Bold Type:Type1
' Name: GZINQW+MyriadPro-Black Type:Type1
' Name: SMICCY+MyriadPro-Regular Type:Type1
' Name: IXDUSS+MinionPro-SemiboldIt Type:Type1
' Name: IXDUSS+MinionPro-It Type:Type1
' Name: IXDUSS+MinionPro-Bold Type:Type1
' Name: YDDMIM+MinionPro-Regular Type:Type1
'
Create new PDF font
PdfFontManager class is intended for creating fonts of PDF document and allows to:
Here is C#/VB.NET code that demonstrates how to create a PDF font based on standard Times-Roman font:
/// <summary>
/// Creates font of PDF document based on "Times-Roman".
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
public static void CreateStandartFont(string pdfFilename)
{
// open PDF document
using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// create font based on "Times-Roman" font
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont timesRomanFont = document.FontManager.GetStandardFont(
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfStandardFontType.TimesRoman);
//...
}
}
''' <summary>
''' Creates font of PDF document based on "Times-Roman".
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
Public Shared Sub CreateStandartFont(pdfFilename As String)
' open PDF document
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' create font based on "Times-Roman" font
'...
Dim timesRomanFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = document.FontManager.GetStandardFont(Vintasoft.Imaging.Pdf.Tree.Fonts.PdfStandardFontType.TimesRoman)
End Using
End Sub
Here is C#/VB.NET code that demonstrates how to create a simple PDF font based on TrueType font:
/// <summary>
/// Create font of PDF document based on TrueType font.
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
/// <param name="trueTypeFontFilename">The filename of TrueType font.</param>
public static void CreateSimpleFont(string pdfFilename, string trueTypeFontFilename)
{
// open PDF document
using (Vintasoft.Imaging.Pdf.PdfDocument document =
new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// create font of PDF document based on TrueType font
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont newFont =
document.FontManager.CreateSimpleFontFromTrueTypeFont(trueTypeFontFilename);
//...
}
}
''' <summary>
''' Create font of PDF document based on TrueType font.
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
''' <param name="trueTypeFontFilename">The filename of TrueType font.</param>
Public Shared Sub CreateSimpleFont(pdfFilename As String, trueTypeFontFilename As String)
' open PDF document
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' create font of PDF document based on TrueType font
'...
Dim newFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = document.FontManager.CreateSimpleFontFromTrueTypeFont(trueTypeFontFilename)
End Using
End Sub
Here is C#/VB.NET code that demonstrates how to create a PDF CID font based on TrueType font:
/// <summary>
/// Creates CID font of PDF document based on TrueType font.
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
/// <param name="trueTypeFontFilename">The filename of TrueType font.</param>
public static void CreateCIDFont(string pdfFilename, string trueTypeFontFilename)
{
// open PDF document
using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// create CID font of PDF document based on TrueType font
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont newFont =
document.FontManager.CreateCIDFontFromTrueTypeFont(trueTypeFontFilename);
//...
}
}
''' <summary>
''' Creates CID font of PDF document based on TrueType font.
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
''' <param name="trueTypeFontFilename">The filename of TrueType font.</param>
Public Shared Sub CreateCIDFont(pdfFilename As String, trueTypeFontFilename As String)
' open PDF document
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' create CID font of PDF document based on TrueType font
'...
Dim newFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = document.FontManager.CreateCIDFontFromTrueTypeFont(trueTypeFontFilename)
End Using
End Sub
Here is C#/VB.NET code that demonstrates how to create a PDF font based on subset of symbols of an existing PDF font:
/// <summary>
/// Creates CID font, which is based on the specified TrueType font,
/// creates a PDF font, which is a minimal subset necessary for drawing specified text, and
/// creates a PDF document with the specified text and font.
/// </summary>
/// <param name="pdfFilename">The name of file, where PDF document must be saved.</param>
/// <param name="trueTypeFontFilename">The filename of TrueType font.</param>
/// <param name="text">The text to draw on PDF page.</param>
public static void CreatePdfFontSubset(string pdfFilename, string trueTypeFontFilename, string text)
{
// list of unique necessary characters to render specified text
System.Collections.Generic.List<char> usedChars =
new System.Collections.Generic.List<char>();
for (int i = 0; i < text.Length; i++)
{
if (!usedChars.Contains(text[i]))
usedChars.Add(text[i]);
}
// create new PDF document
using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument())
{
// create initial PDF font
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont sourceFont =
document.FontManager.CreateCIDFontFromTrueTypeFont(trueTypeFontFilename);
// get symbols of the font
Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol[] fontSymbols =
Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol.GetFontSymbols(sourceFont);
// list of PDF font symbols, which are necessary for rendering the specified text
System.Collections.Generic.List<Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol> necessarySymbols =
new System.Collections.Generic.List<Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol>();
for (int i = 0; i < fontSymbols.Length; i++)
{
// get next PDF font symbol
Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol fontSymbol = fontSymbols[i];
// determine if symbol is used in text
for (int j = 0; j < usedChars.Count; j++)
{
if (fontSymbol.Symbol == usedChars[j])
{
necessarySymbols.Add(fontSymbol);
break;
}
}
if (necessarySymbols.Count == usedChars.Count)
{
// optimization: we have all necessary symbols and can go on
break;
}
}
// determine symbol code size in bytes
int symbolCodeSizeInBytes = sourceFont.FontType == Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFontType.Type0 ? 2 : 1;
Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol[] newSymbols = null;
// create font subset
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont pdfFontSubset = document.FontManager.CreateFontSubset(
sourceFont,
necessarySymbols.ToArray(),
symbolCodeSizeInBytes,
true,
out newSymbols);
// add PDF page
Vintasoft.Imaging.Pdf.Tree.PdfPage page = document.Pages.Add(
Vintasoft.Imaging.PaperSizeKind.A4);
// open PDF graphics
using (Vintasoft.Imaging.Pdf.Drawing.PdfGraphics graphics = page.GetGraphics())
{
Vintasoft.Imaging.Pdf.Drawing.PdfBrush brush =
new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black);
System.Drawing.PointF location = new System.Drawing.PointF(30, page.Size.Height - 150);
// draw text using created font
graphics.DrawString(text, pdfFontSubset, 18f, brush, location);
}
// pack PDF document to the specified location
document.Pack(pdfFilename);
}
}
''' <summary>
''' Creates CID font, which is based on the specified TrueType font,
''' creates a PDF font, which is a minimal subset necessary for drawing specified text, and
''' creates a PDF document with the specified text and font.
''' </summary>
''' <param name="pdfFilename">The name of file, where PDF document must be saved.</param>
''' <param name="trueTypeFontFilename">The filename of TrueType font.</param>
''' <param name="text">The text to draw on PDF page.</param>
Public Shared Sub CreatePdfFontSubset(pdfFilename As String, trueTypeFontFilename As String, text As String)
' list of unique necessary characters to render specified text
Dim usedChars As New System.Collections.Generic.List(Of Char)()
For i As Integer = 0 To text.Length - 1
If Not usedChars.Contains(text(i)) Then
usedChars.Add(text(i))
End If
Next
' create new PDF document
Using document As New Vintasoft.Imaging.Pdf.PdfDocument()
' create initial PDF font
Dim sourceFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = document.FontManager.CreateCIDFontFromTrueTypeFont(trueTypeFontFilename)
' get symbols of the font
Dim fontSymbols As Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol() = Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol.GetFontSymbols(sourceFont)
' list of PDF font symbols, which are necessary for rendering the specified text
Dim necessarySymbols As New System.Collections.Generic.List(Of Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol)()
For i As Integer = 0 To fontSymbols.Length - 1
' get next PDF font symbol
Dim fontSymbol As Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol = fontSymbols(i)
' determine if symbol is used in text
For j As Integer = 0 To usedChars.Count - 1
If fontSymbol.Symbol = usedChars(j) Then
necessarySymbols.Add(fontSymbol)
Exit For
End If
Next
If necessarySymbols.Count = usedChars.Count Then
' optimization: we have all necessary symbols and can go on
Exit For
End If
Next
' determine symbol code size in bytes
Dim symbolCodeSizeInBytes As Integer = If(sourceFont.FontType = Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFontType.Type0, 2, 1)
Dim newSymbols As Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol() = Nothing
' create font subset
Dim pdfFontSubset As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = document.FontManager.CreateFontSubset(sourceFont, necessarySymbols.ToArray(), symbolCodeSizeInBytes, True, newSymbols)
' add PDF page
Dim page As Vintasoft.Imaging.Pdf.Tree.PdfPage = document.Pages.Add(Vintasoft.Imaging.PaperSizeKind.A4)
' open PDF graphics
Using graphics As Vintasoft.Imaging.Pdf.Drawing.PdfGraphics = page.GetGraphics()
Dim brush As New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black)
Dim location As New System.Drawing.PointF(30, page.Size.Height - 150)
' draw text using created font
graphics.DrawString(text, pdfFontSubset, 18F, brush, location)
End Using
' pack PDF document to the specified location
document.Pack(pdfFilename)
End Using
End Sub
Add a new font to PDF document
To add a new font into PDF document it is necessary to:
- Create a font
- Draw text using the font on PDF page
Here is C#/VB.NET code that demonstrates how to add a text in English, Russian and Chinese languages onto a PDF page:
/// <summary>
/// Creates page of PDF document with English, Russian and Chinese text.
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
public static void CreatePdfPageWithEnRuCh(string pdfFilename)
{
// open PDF document
using (Vintasoft.Imaging.Pdf.PdfDocument document =
new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// create empty PDF page
Vintasoft.Imaging.Pdf.Tree.PdfPage page = new Vintasoft.Imaging.Pdf.Tree.PdfPage(
document, Vintasoft.Imaging.PaperSizeKind.A4);
// add page to PDF document
document.Pages.Add(page);
// text size
float fontSize = 24f;
// text brush
Vintasoft.Imaging.Pdf.Drawing.PdfBrush brush =
new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black);
// get names of font
System.Collections.Generic.List<string> fontNames = new System.Collections.Generic.List<string>(Vintasoft.Imaging.Fonts.FontProgramsControllerBase.Default.GetAvailableFontNames());
// create fornt for English text
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont englishFont = null;
// if "Microsoft Himalaya" font exists
if (fontNames.IndexOf("Microsoft Himalaya") >= 0)
{
using (Vintasoft.Imaging.Fonts.FontProgramSearchResult programSearchResult =
Vintasoft.Imaging.Fonts.FontProgramsControllerBase.Default.GetTrueTypeFontProgram(new Vintasoft.Imaging.Fonts.FontInfo("Microsoft Himalaya")))
// create PDF font based on "Microsoft Himalaya" font
englishFont = document.FontManager.CreateSimpleFontFromTrueTypeFont(programSearchResult.FontProgramStream);
}
// if "Microsoft Himalaya" font does NOT exist
else
{
throw new System.Exception("'Microsoft Himalaya' font is not found in the system.");
}
// create font for Russian text
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont russianFont = null;
// if "Times New Roman" font exists
if (fontNames.IndexOf("Times New Roman") >= 0)
{
// create PDF font based on "Times New Roman" font
using (Vintasoft.Imaging.Fonts.FontProgramSearchResult programSearchResult =
Vintasoft.Imaging.Fonts.FontProgramsControllerBase.Default.GetTrueTypeFontProgram(new Vintasoft.Imaging.Fonts.FontInfo("Times New Roman")))
russianFont = document.FontManager.CreateCIDFontFromTrueTypeFont(programSearchResult.FontProgramStream);
}
// if "Times New Roman" font does NOT exist
else
{
throw new System.Exception("'Times New Roman' font is not found in the system.");
}
// create font for Chinese text
Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont chineseFont = null;
// if "SimHei" font exists
if (fontNames.IndexOf("SimHei") >= 0)
{
// create PDF font based on "SimHei" font
using (Vintasoft.Imaging.Fonts.FontProgramSearchResult programSearchResult =
Vintasoft.Imaging.Fonts.FontProgramsControllerBase.Default.GetTrueTypeFontProgram(new Vintasoft.Imaging.Fonts.FontInfo("SimHei")))
chineseFont = document.FontManager.CreateCIDFontFromTrueTypeFont(programSearchResult.FontProgramStream);
}
// if "SimHei" font does NOT exist
else
{
throw new System.Exception("'SimHei' font is not found in the system.");
}
// get PDF graphics of page
using (Vintasoft.Imaging.Pdf.Drawing.PdfGraphics graphics = page.GetGraphics())
{
// location of English text
System.Drawing.PointF location = new System.Drawing.PointF(50, page.Size.Height - 50);
// draw English text
graphics.DrawString("Hello", englishFont, fontSize, brush, location);
// location of Russian text
location.Y -= 50;
// draw Russian text
graphics.DrawString("Привет", russianFont, fontSize, brush, location);
// location of Chinese text
location.Y -= 50;
// draw Chinese text
graphics.DrawString("您好", chineseFont, fontSize, brush, location);
}
// save changes to a file
document.SaveChanges();
}
}
''' <summary>
''' Creates page of PDF document with English, Russian and Chinese text.
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
Public Shared Sub CreatePdfPageWithEnRuCh(pdfFilename As String)
' open PDF document
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' create empty PDF page
Dim page As New Vintasoft.Imaging.Pdf.Tree.PdfPage(document, Vintasoft.Imaging.PaperSizeKind.A4)
' add page to PDF document
document.Pages.Add(page)
' text size
Dim fontSize As Single = 24F
' text brush
Dim brush As New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black)
' get names of font
Dim fontNames As New System.Collections.Generic.List(Of String)(Vintasoft.Imaging.Fonts.FontProgramsControllerBase.[Default].GetAvailableFontNames())
' create fornt for English text
Dim englishFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = Nothing
' if "Microsoft Himalaya" font exists
If fontNames.IndexOf("Microsoft Himalaya") >= 0 Then
Using programSearchResult As Vintasoft.Imaging.Fonts.FontProgramSearchResult = Vintasoft.Imaging.Fonts.FontProgramsControllerBase.[Default].GetTrueTypeFontProgram(New Vintasoft.Imaging.Fonts.FontInfo("Microsoft Himalaya"))
' create PDF font based on "Microsoft Himalaya" font
englishFont = document.FontManager.CreateSimpleFontFromTrueTypeFont(programSearchResult.FontProgramStream)
End Using
Else
' if "Microsoft Himalaya" font does NOT exist
Throw New System.Exception("'Microsoft Himalaya' font is not found in the system.")
End If
' create font for Russian text
Dim russianFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = Nothing
' if "Times New Roman" font exists
If fontNames.IndexOf("Times New Roman") >= 0 Then
' create PDF font based on "Times New Roman" font
Using programSearchResult As Vintasoft.Imaging.Fonts.FontProgramSearchResult = Vintasoft.Imaging.Fonts.FontProgramsControllerBase.[Default].GetTrueTypeFontProgram(New Vintasoft.Imaging.Fonts.FontInfo("Times New Roman"))
russianFont = document.FontManager.CreateCIDFontFromTrueTypeFont(programSearchResult.FontProgramStream)
End Using
Else
' if "Times New Roman" font does NOT exist
Throw New System.Exception("'Times New Roman' font is not found in the system.")
End If
' create font for Chinese text
Dim chineseFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = Nothing
' if "SimHei" font exists
If fontNames.IndexOf("SimHei") >= 0 Then
' create PDF font based on "SimHei" font
Using programSearchResult As Vintasoft.Imaging.Fonts.FontProgramSearchResult = Vintasoft.Imaging.Fonts.FontProgramsControllerBase.[Default].GetTrueTypeFontProgram(New Vintasoft.Imaging.Fonts.FontInfo("SimHei"))
chineseFont = document.FontManager.CreateCIDFontFromTrueTypeFont(programSearchResult.FontProgramStream)
End Using
Else
' if "SimHei" font does NOT exist
Throw New System.Exception("'SimHei' font is not found in the system.")
End If
' get PDF graphics of page
Using graphics As Vintasoft.Imaging.Pdf.Drawing.PdfGraphics = page.GetGraphics()
' location of English text
Dim location As New System.Drawing.PointF(50, page.Size.Height - 50)
' draw English text
graphics.DrawString("Hello", englishFont, fontSize, brush, location)
' location of Russian text
location.Y -= 50
' draw Russian text
graphics.DrawString("Привет", russianFont, fontSize, brush, location)
' location of Chinese text
location.Y -= 50
' draw Chinese text
graphics.DrawString("您好", chineseFont, fontSize, brush, location)
End Using
' save changes to a file
document.SaveChanges()
End Using
End Sub
Work with external fonts of PDF document
A font is external if it is stored separately from PDF document. The external font is defined using PostScript name of font.
The SDK can load an external font only if it is a TrueType, OpenType font or a collection of TrueType fonts. By default, the SDK searches for the font by its name in directory "$ASSEMBLY_DIRECTORY$\Fonts\". If the font is not found, the SDK will search font in "Fonts" directory of operating system. If font is not found again, default font (Arial) will be used instead of not found font.
The
FontProgramsControllerBase class is a base class for controllers of external fonts of the PDF document. The controller of external fonts of the PDF document defines the algorithm, which searches external fonts of PDF document, and allows to override the algorithm. The
PdfDocument.FontProgramsController property returns a controller of external fonts of the PDF document. By default the property returns an instance of
FileFontProgramsControllerWithFallbackFont class. The
FileFontProgramsController class allows to specify another path to the folder with fonts or to change the priority for system fonts. For advanced search font management can be created a class derived from
FileFontProgramsController,
FileFontProgramsControllerBase or
FontProgramsControllerBase class.
To reach the optimal performance it is recommended to create and use a single instance of external fonts controller for all PDF documents.
Here is C#/VB.NET code that demonstrates how to change the font search algorithm and search for fonts in a custom folder:
/// <summary>
/// Loads the PDF document and assigns custom fonts directory.
/// </summary>
/// <param name="filename">The name of PDF document.</param>
/// <returns>Loaded PDF document.</returns>
public Vintasoft.Imaging.Pdf.PdfDocument LoadPdfDocumentAndSetFontsDictionary(string filename)
{
// load PDF document
Vintasoft.Imaging.Pdf.PdfDocument pdfDocument = new Vintasoft.Imaging.Pdf.PdfDocument(filename);
// define path to directory with custom fonts
string directoryWithFonts = @"d:\Environment\CustomFonts\";
// assign custom fonts directory
pdfDocument.FontProgramsController =
new Vintasoft.Imaging.Fonts.FileFontProgramsControllerWithFallbackFont(true, directoryWithFonts);
return pdfDocument;
}
''' <summary>
''' Loads the PDF document and assigns custom fonts directory.
''' </summary>
''' <param name="filename">The name of PDF document.</param>
''' <returns>Loaded PDF document.</returns>
Public Function LoadPdfDocumentAndSetFontsDictionary(filename As String) As Vintasoft.Imaging.Pdf.PdfDocument
' load PDF document
Dim pdfDocument As New Vintasoft.Imaging.Pdf.PdfDocument(filename)
' define path to directory with custom fonts
Dim directoryWithFonts As String = "d:\Environment\CustomFonts\"
' assign custom fonts directory
pdfDocument.FontProgramsController = New Vintasoft.Imaging.Fonts.FileFontProgramsControllerWithFallbackFont(True, directoryWithFonts)
Return pdfDocument
End Function
Here is C#/VB.NET code that demonstrates how to change the font search algorithm and use Calibri font instead of not found fonts:
/// <summary>
/// Loads the PDF document and uses Calibri font instead of not found fonts.
/// </summary>
/// <param name="filename">The name of PDF document.</param>
/// <returns>Loaded PDF document.</returns>
public Vintasoft.Imaging.Pdf.PdfDocument LoadPdfDocumentAndUseCalibriAsDefaultFont(string filename)
{
// load PDF document
Vintasoft.Imaging.Pdf.PdfDocument pdfDocument = new Vintasoft.Imaging.Pdf.PdfDocument(filename);
// create a font program controller, which uses the default ("Arial") font
// instead of not found fonts
Vintasoft.Imaging.Fonts.FileFontProgramsControllerWithFallbackFont fontProgramsController =
new Vintasoft.Imaging.Fonts.FileFontProgramsControllerWithFallbackFont(true, "fonts");
// specify that "Calibri" must be used as the default font
fontProgramsController.DefaultFallbackFontName = "Calibri";
// set the font program controller for PDF document
pdfDocument.FontProgramsController = fontProgramsController;
return pdfDocument;
}
''' <summary>
''' Loads the PDF document and uses Calibri font instead of not found fonts.
''' </summary>
''' <param name="filename">The name of PDF document.</param>
''' <returns>Loaded PDF document.</returns>
Public Function LoadPdfDocumentAndUseCalibriAsDefaultFont(filename As String) As Vintasoft.Imaging.Pdf.PdfDocument
' load PDF document
Dim pdfDocument As New Vintasoft.Imaging.Pdf.PdfDocument(filename)
' create a font program controller, which uses the default ("Arial") font
' instead of not found fonts
Dim fontProgramsController As New Vintasoft.Imaging.Fonts.FileFontProgramsControllerWithFallbackFont(True, "fonts")
' specify that "Calibri" must be used as the default font
fontProgramsController.DefaultFallbackFontName = "Calibri"
' set the font program controller for PDF document
pdfDocument.FontProgramsController = fontProgramsController
Return pdfDocument
End Function
Here is C#/VB.NET code that demonstrates how to change the font search algorithm if a PDF document is loaded using ImageCollection class:
/// <summary>
/// Saves pages of PDF document to files.
/// </summary>
public static void SavePdfPages()
{
// open stream
using (System.IO.Stream stream = System.IO.File.Open(@"d:\document.pdf", System.IO.FileMode.Open))
{
// create image collection
Vintasoft.Imaging.ImageCollection images = new Vintasoft.Imaging.ImageCollection();
// add PDF document to the image collection
images.Add(stream);
// get reference to the PDF document
Vintasoft.Imaging.Pdf.PdfDocument pdfDocument =
Vintasoft.Imaging.Pdf.PdfDocumentController.OpenDocument(stream);
// for each image in collection (PDF page)
for (int i = 0; i < images.Count; i++)
{
// save image as PNG file
images[i].Save(string.Format("page{0}.png", i));
}
// close PDF document
Vintasoft.Imaging.Pdf.PdfDocumentController.CloseDocument(pdfDocument);
}
}
''' <summary>
''' Saves pages of PDF document to files.
''' </summary>
Public Shared Sub SavePdfPages()
' open stream
Using stream As System.IO.Stream = System.IO.File.Open("d:\document.pdf", System.IO.FileMode.Open)
' create image collection
Dim images As New Vintasoft.Imaging.ImageCollection()
' add PDF document to the image collection
images.Add(stream)
' get reference to the PDF document
Dim pdfDocument As Vintasoft.Imaging.Pdf.PdfDocument = Vintasoft.Imaging.Pdf.PdfDocumentController.OpenDocument(stream)
' for each image in collection (PDF page)
For i As Integer = 0 To images.Count - 1
' save image as PNG file
images(i).Save(String.Format("page{0}.png", i))
Next
' close PDF document
Vintasoft.Imaging.Pdf.PdfDocumentController.CloseDocument(pdfDocument)
End Using
End Sub
View font symbols in WinForms
PdfFontViewerControl control is intended for viewing PDF font symbols in WinForms application. Also this control provides the ability to choose a symbol of font using mouse.
View font symbols in WPF
WpfPdfFontViewerControl control is intended for viewing PDF font symbols in WPF application. Also this control provides the ability to choose a symbol of font using mouse.
Embed external and standard fonts into PDF document
The
PdfFontManager.EmbedAllFonts method allows to embed all external and standard fonts in a PDF document.
The
PdfFontManager.EmbedFont method allows to embed the specified font in a PDF document.
The program font controller of PDF document (
PdfDocument.FontProgramsController property) is used for searching the font program. Font will not be embedded in PDF document in the font program is not found.
The SDK can embed an external font only in case the font is a TrueType, OpenType font or a collection of TrueType fonts. Standard fonts after embedding are becoming TrueType fonts.
Here is C#/VB.NET code that demonstrates how to embed all external and standard fonts in a PDF document:
/// <summary>
/// Embeds all fonts into PDF document.
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
/// <param name="pathToFonts">The path to available fonts.</param>
/// <param name="resultFilename">The filename of resulting PDF document.</param>
public static void EmbedAllFontsIntoDocument(string pdfFilename, string pathToFonts, string resultFilename)
{
using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// set a font programs controller
document.FontProgramsController = new Vintasoft.Imaging.Fonts.FileFontProgramsController(true, pathToFonts);
// embed all fonts
document.FontManager.EmbedAllFonts();
// pack and save document to new location
document.Pack(resultFilename);
}
}
''' <summary>
''' Embeds all fonts into PDF document.
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
''' <param name="pathToFonts">The path to available fonts.</param>
''' <param name="resultFilename">The filename of resulting PDF document.</param>
Public Shared Sub EmbedAllFontsIntoDocument(pdfFilename As String, pathToFonts As String, resultFilename As String)
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' set a font programs controller
document.FontProgramsController = New Vintasoft.Imaging.Fonts.FileFontProgramsController(True, pathToFonts)
' embed all fonts
document.FontManager.EmbedAllFonts()
' pack and save document to new location
document.Pack(resultFilename)
End Using
End Sub
Pack embedded fonts of PDF document
The packing of embedded fonts allows to reduce the size of PDF file. PDF document size is reduced because SDK deletes unused symbols from the font program.
The
PdfFontManager.PackAllFonts method allows to pack all embedded fonts of PDF document.
The
PdfFontManager.PackFont method allows to pack the specified font of PDF document.
It is recommended to perform the packing of fonts after embedding, because the font programs may include a very broad variety of symbols and so significantly increase the size of PDF document.
Here is C#/VB.NET code that demonstrates how to pack the embedded fonts of PDF document:
/// <summary>
/// Removes all unused characters from fonts of PDF document.
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
/// <param name="resultFilename">The filename of resulting PDF document.</param>
public static void PackAllFontsOfDocument(string pdfFilename, string resultFilename)
{
using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// pack all fonts using progress controller
document.FontManager.PackAllFonts();
// pack and save document to new location
document.Pack(resultFilename);
}
}
''' <summary>
''' Removes all unused characters from fonts of PDF document.
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
''' <param name="resultFilename">The filename of resulting PDF document.</param>
Public Shared Sub PackAllFontsOfDocument(pdfFilename As String, resultFilename As String)
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' pack all fonts using progress controller
document.FontManager.PackAllFonts()
' pack and save document to new location
document.Pack(resultFilename)
End Using
End Sub
Here is C#/VB.NET code that demonstrates how to pack the embedded fonts of PDF document and output the detailed information to console:
/// <summary>
/// Stores current action description of level 1.
/// </summary>
static string _currentActionDescriptionLevel1 = null;
/// <summary>
/// Stores current action description of level 2.
/// </summary>
static string _currentActionDescriptionLevel2 = null;
/// <summary>
/// Stores current action description of level 3.
/// </summary>
static string _currentActionDescriptionLevel3 = null;
/// <summary>
/// Removes all unused characters from fonts of PDF document
/// and outputs detailed progress info to the console.
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
/// <param name="resultFilename">The filename of resulting PDF document.</param>
public static void PackAllFontsOfDocumentWithDetailedInfo(string pdfFilename, string resultFilename)
{
using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// create progress handler which handles 3 levels of progress
Vintasoft.Imaging.Utils.IActionProgressHandler actionProgressHandler =
Vintasoft.Imaging.Utils.ActionProgressHandlers.CreateActionProgressHandler(
OnPackProgressLevel1, OnPackProgressLevel2, OnPackProgressLevel3);
// create progress controller
Vintasoft.Imaging.Utils.ActionProgressController progressController =
new Vintasoft.Imaging.Utils.ActionProgressController(actionProgressHandler);
// pack all fonts using progress controller
document.FontManager.PackAllFonts(progressController);
// pack and save document to new location
document.Pack(resultFilename);
}
}
/// <summary>
/// Outputs description of level 1 actions of font packing.
/// </summary>
private static void OnPackProgressLevel1(object sender, Vintasoft.Imaging.ProgressEventArgs e)
{
string actionDescription = e.Description;
// if action is finished
if (e.Progress == 100)
{
// output action description with small indent
System.Console.WriteLine(" Finished ({0}).", actionDescription);
}
// if action is started
else if (actionDescription != _currentActionDescriptionLevel1)
{
// remember action description
_currentActionDescriptionLevel1 = actionDescription;
// output action description with small indent
System.Console.WriteLine("{0}...", actionDescription);
}
}
/// <summary>
/// Outputs description of level 2 actions of font packing.
/// </summary>
private static void OnPackProgressLevel2(object sender, Vintasoft.Imaging.ProgressEventArgs e)
{
string actionDescription = e.Description;
// if action is finished
if (e.Progress == 100)
{
// output action description with medium indent
System.Console.WriteLine(" Finished ({0}).", actionDescription);
}
// if action is started
else if (actionDescription != _currentActionDescriptionLevel2)
{
// remember action description
_currentActionDescriptionLevel2 = actionDescription;
// output action description with medium indent
System.Console.WriteLine(" {0}...", actionDescription);
}
}
/// <summary>
/// Outputs description of level 3 actions of font packing.
/// </summary>
private static void OnPackProgressLevel3(object sender, Vintasoft.Imaging.ProgressEventArgs e)
{
string actionDescription = e.Description;
// if action is finished
if (e.Progress == 100)
{
// output action description with large indent
System.Console.WriteLine(" Finished ({0}).", actionDescription);
}
// if action is started
else if (actionDescription != _currentActionDescriptionLevel3)
{
// remember action description
_currentActionDescriptionLevel3 = actionDescription;
// output action description with large indent
System.Console.WriteLine(" {0}...", actionDescription);
}
}
''' <summary>
''' Stores current action description of level 1.
''' </summary>
Shared _currentActionDescriptionLevel1 As String = Nothing
''' <summary>
''' Stores current action description of level 2.
''' </summary>
Shared _currentActionDescriptionLevel2 As String = Nothing
''' <summary>
''' Stores current action description of level 3.
''' </summary>
Shared _currentActionDescriptionLevel3 As String = Nothing
''' <summary>
''' Removes all unused characters from fonts of PDF document
''' and outputs detailed progress info to the console.
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
''' <param name="resultFilename">The filename of resulting PDF document.</param>
Public Shared Sub PackAllFontsOfDocumentWithDetailedInfo(pdfFilename As String, resultFilename As String)
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' create progress handler which handles 3 levels of progress
Dim actionProgressHandler As Vintasoft.Imaging.Utils.IActionProgressHandler = Vintasoft.Imaging.Utils.ActionProgressHandlers.CreateActionProgressHandler(AddressOf OnPackProgressLevel1, AddressOf OnPackProgressLevel2, AddressOf OnPackProgressLevel3)
' create progress controller
Dim progressController As New Vintasoft.Imaging.Utils.ActionProgressController(actionProgressHandler)
' pack all fonts using progress controller
document.FontManager.PackAllFonts(progressController)
' pack and save document to new location
document.Pack(resultFilename)
End Using
End Sub
''' <summary>
''' Outputs description of level 1 actions of font packing.
''' </summary>
Private Shared Sub OnPackProgressLevel1(sender As Object, e As Vintasoft.Imaging.ProgressEventArgs)
Dim actionDescription As String = e.Description
' if action is finished
If e.Progress = 100 Then
' output action description with small indent
System.Console.WriteLine(" Finished ({0}).", actionDescription)
' if action is started
ElseIf actionDescription <> _currentActionDescriptionLevel1 Then
' remember action description
_currentActionDescriptionLevel1 = actionDescription
' output action description with small indent
System.Console.WriteLine("{0}...", actionDescription)
End If
End Sub
''' <summary>
''' Outputs description of level 2 actions of font packing.
''' </summary>
Private Shared Sub OnPackProgressLevel2(sender As Object, e As Vintasoft.Imaging.ProgressEventArgs)
Dim actionDescription As String = e.Description
' if action is finished
If e.Progress = 100 Then
' output action description with medium indent
System.Console.WriteLine(" Finished ({0}).", actionDescription)
' if action is started
ElseIf actionDescription <> _currentActionDescriptionLevel2 Then
' remember action description
_currentActionDescriptionLevel2 = actionDescription
' output action description with medium indent
System.Console.WriteLine(" {0}...", actionDescription)
End If
End Sub
''' <summary>
''' Outputs description of level 3 actions of font packing.
''' </summary>
Private Shared Sub OnPackProgressLevel3(sender As Object, e As Vintasoft.Imaging.ProgressEventArgs)
Dim actionDescription As String = e.Description
' if action is finished
If e.Progress = 100 Then
' output action description with large indent
System.Console.WriteLine(" Finished ({0}).", actionDescription)
' if action is started
ElseIf actionDescription <> _currentActionDescriptionLevel3 Then
' remember action description
_currentActionDescriptionLevel3 = actionDescription
' output action description with large indent
System.Console.WriteLine(" {0}...", actionDescription)
End If
End Sub
Obfuscate the font text encoding in PDF document
Obfuscating information about text encoding allows to secure a PDF document against text extraction. A PDF document with obfuscated fonts looks the same way as the original document, but the text search and text extraction is becoming impossible - the extracted text will contain lots of "garbage".
The
PdfTextEncodingObfuscator class is intended for obfuscating the font encoding of PDF document. Current version of SDK can obfuscate text encoding of the TrueType fonts only. Other font types are being considered for support in further releases.
The obfuscation includes:
- randomization of glyphs of font characters
- duplication of glyphs of font characters
- erasing information about Unicode codes corresponding to the characters in the font
- erasing information about encoding used in the font
The text obfuscation is performed using
PdfTextEncodingObfuscator.Obfuscate methods and is possible for:
- single or multiple pages of PDF document
- the whole PDF document
The
PdfTextEncodingObfuscator.MinSymbolDuplicateCount and
PdfTextEncodingObfuscator.MaxSymbolDuplicateCount properties allows to specify the number of duplicates, which must be created for each character of font. The number of duplicates equals a random value from the specified range.
The
PdfTextEncodingObfuscator.DuplicateFonts property allows to specify whether each font should be replaced by a separate obfuscated font for each page (value=True) or by one obfuscated font for all pages (value=False).
The obfuscation of PDF page is possible only in case when all fonts used on the page are embedded. So before obfuscating it is recommended to perform embedding of external and standard fonts of PDF document.
Important! After the obfuscation the document must be packed, otherwise the source fonts can be retrieved from the document.
Here is C#/VB.NET code that demonstrates how to obfuscate the encoding of embedded fonts of PDF document and output the detailed information to console:
/// <summary>
/// Obfuscates encoding of all fonts of PDF document.
/// </summary>
/// <param name="pdfFilename">The filename of PDF document.</param>
/// <param name="resultFilename">The filename of resulting PDF document.</param>
public static void ObfuscateEncodingOfAllFonts(string pdfFilename, string resultFilename)
{
using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
{
// create obfuscator
Vintasoft.Imaging.Pdf.PdfTextEncodingObfuscator textEncodingObfuscator =
new Vintasoft.Imaging.Pdf.PdfTextEncodingObfuscator();
try
{
// obfuscate all fonts
textEncodingObfuscator.Obfuscate(document);
// pack and save document to new location
document.Pack(resultFilename);
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
}
}
}
''' <summary>
''' Obfuscates encoding of all fonts of PDF document.
''' </summary>
''' <param name="pdfFilename">The filename of PDF document.</param>
''' <param name="resultFilename">The filename of resulting PDF document.</param>
Public Shared Sub ObfuscateEncodingOfAllFonts(pdfFilename As String, resultFilename As String)
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename)
' create obfuscator
Dim textEncodingObfuscator As New Vintasoft.Imaging.Pdf.PdfTextEncodingObfuscator()
Try
' obfuscate all fonts
textEncodingObfuscator.Obfuscate(document)
' pack and save document to new location
document.Pack(resultFilename)
Catch ex As System.Exception
System.Console.WriteLine(ex.Message)
End Try
End Using
End Sub