VintaSoft Imaging .NET SDK v8.6
In This Topic
    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 an example that demonstrates how to obtain information about all fonts of PDF document:

    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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
    '
    
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <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
    */
                    
    



    Creation of new font

    PdfFontManager class is intended for creating fonts of PDF document and allows to:

    Here is an example that demonstrates how to create a font based on standard Times-Roman font:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <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);
            //...
        }
    }
                    
    

    Here is an example that demonstrates how to create a simple font based on TrueType font:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <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);
            //...
        }
    }
                    
    

    Here is an example that demonstrates how to create a CID font based on TrueType font:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <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);
            //...
        }
    }
                    
    

    Here is an example that demonstrates how to create a font based on subset of symbols of an existing PDF font:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging
    // - Vintasoft.Imaging.Pdf
    
    /// <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.ListPdfTextSymbol> necessarySymbols = 
                new System.Collections.Generic.ListPdfTextSymbol>();
            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);
        }
    }
                    
    



    Add a new font to PDF document

    To add a new font into PDF document it is necessary to:

    Here is an example that demonstrates how to add a text in English, Russian and Chinese languages onto a PDF page:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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 String() = Vintasoft.Imaging.Pdf.PdfFontManager.GetSystemTrueTypeFontNames()
    
            ' create fornt for English text
            Dim englishFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = Nothing
            ' if "Microsoft Himalaya" font exists
            If System.Array.IndexOf(fontNames, "Microsoft Himalaya") >= 0 Then
                ' create PDF font based on "Microsoft Himalaya" font
                englishFont = document.FontManager.CreateSimpleFontFromTrueTypeFont(Vintasoft.Imaging.Pdf.PdfFontManager.GetSystemTrueTypeFontFileName("Microsoft Himalaya"))
            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 System.Array.IndexOf(fontNames, "Times New Roman") >= 0 Then
                ' create PDF font based on "Times New Roman" font
                russianFont = document.FontManager.CreateCIDFontFromTrueTypeFont(Vintasoft.Imaging.Pdf.PdfFontManager.GetSystemTrueTypeFontFileName("Times New Roman"))
            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 System.Array.IndexOf(fontNames, "SimHei") >= 0 Then
                ' create PDF font based on "SimHei" font
                chineseFont = document.FontManager.CreateCIDFontFromTrueTypeFont(Vintasoft.Imaging.Pdf.PdfFontManager.GetSystemTrueTypeFontFileName("SimHei"))
            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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging
    // - Vintasoft.Imaging.Pdf
    
    /// <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
            string[] fontNames = Vintasoft.Imaging.Pdf.PdfFontManager.GetSystemTrueTypeFontNames();
    
            // create fornt for English text
            Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont englishFont = null;
            // if "Microsoft Himalaya" font exists
            if (System.Array.IndexOf(fontNames, "Microsoft Himalaya") >= 0)
            {
                // create PDF font based on "Microsoft Himalaya" font
                englishFont = document.FontManager.CreateSimpleFontFromTrueTypeFont(
                    Vintasoft.Imaging.Pdf.PdfFontManager.GetSystemTrueTypeFontFileName("Microsoft Himalaya"));
            }
            // 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 (System.Array.IndexOf(fontNames, "Times New Roman") >= 0)
            {
                // create PDF font based on "Times New Roman" font
                russianFont = document.FontManager.CreateCIDFontFromTrueTypeFont(
                    Vintasoft.Imaging.Pdf.PdfFontManager.GetSystemTrueTypeFontFileName("Times New Roman"));
            }
            // 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 (System.Array.IndexOf(fontNames, "SimHei") >= 0)
            {
                // create PDF font based on "SimHei" font
                chineseFont = document.FontManager.CreateCIDFontFromTrueTypeFont(
                    Vintasoft.Imaging.Pdf.PdfFontManager.GetSystemTrueTypeFontFileName("SimHei"));
            }
            // 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();
        }
    }
                    
    



    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, Arial font 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 an example that demonstrates how to change the font search algorithm and search for fonts in a custom folder:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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.Pdf.FileFontProgramsControllerWithFallbackFont(True, directoryWithFonts)
    
        Return pdfDocument
    End Function
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <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.Pdf.FileFontProgramsControllerWithFallbackFont(true, directoryWithFonts);
    
        return pdfDocument;
    }
                    
    

    Here is an example that demonstrates how to change the font search algorithm and use Calibri font instead of not found fonts:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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.Pdf.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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <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.Pdf.FileFontProgramsControllerWithFallbackFont fontProgramsController =
            new Vintasoft.Imaging.Pdf.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;
    }
                    
    

    Here is an example that demonstrates how to change the font search algorithm if a PDF document is loaded using ImageCollection class:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging
    // - Vintasoft.Imaging.Pdf
    
    /// <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);
        }
    }
                    
    



    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.



    Embedding of 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 an example that demonstrates how to embed all external and standard fonts in a PDF document:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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.Pdf.FileFontProgramsController(True, pathToFonts)
            ' embed all fonts
            document.FontManager.EmbedAllFonts()
            ' pack and save document to new location
            document.Pack(resultFilename)
        End Using
    End Sub
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <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.Pdf.FileFontProgramsController(true, pathToFonts);
            // embed all fonts
            document.FontManager.EmbedAllFonts();
            // pack and save document to new location
            document.Pack(resultFilename);
        }
    }
                    
    



    Packing 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 an example that demonstrates how to pack the embedded fonts of PDF document:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    
    ''' <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
    
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    
    /// <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);
        }
    }
    
                    
    


    Here is an example that demonstrates how to pack the embedded fonts of PDF document and output the detailed information to console:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging
    // - Vintasoft.Imaging.Pdf
    
    /// <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);
        }
    }
                    
    



    Obfuscating of 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:

    The text obfuscation is performed using PdfTextEncodingObfuscator.Obfuscate methods and is possible for:

    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 an example that demonstrates how to obfuscate the encoding of embedded fonts of PDF document and output the detailed information to console:
    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <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
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <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);
            }
        }
    }