Docotic.Pdf Library Help > Samples > Pages and Navigation > Extract text, paths and images

This sample shows how to extract page objects (text, paths and images) from PdfDocument. The sample draws extracted objects on the drawing surface of a System.Drawing.Graphics.

Use PdfPage.GetObjects() method to get all text, paths and images drawn on the page.

The result of this method is an ordered collection. Each subsequent object in the collection is drawn after the previous one.

C#
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using BitMiracle.Docotic.Pdf;

namespace BitMiracle.Docotic.Pdf.Samples
{
    public static class ExtractPageObjects
    {
        public static void Main()
        {
            // NOTE: 
            // When used in trial mode, the library imposes some restrictions.
            // Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx
            // for more information.

            const string PathToFile = "ExtractPageObjects.png";

            using (var pdf = new PdfDocument(@"Sample Data\gmail-cheat-sheet.pdf"))
            {
                PdfPage page = pdf.Pages[0];

                const float TargetResolution = 300;
                double scaleFactor = TargetResolution / page.Canvas.Resolution;
                using (Bitmap bitmap = new Bitmap((int)(page.Width * scaleFactor), (int)(page.Height * scaleFactor)))
                {
                    bitmap.SetResolution(TargetResolution, TargetResolution);

                    using (var gr = Graphics.FromImage(bitmap))
                    {
                        gr.SmoothingMode = SmoothingMode.HighQuality;
                        gr.PageUnit = GraphicsUnit.Point;

                        gr.SetClip(page.CropBox.ToRectangleF(), CombineMode.Intersect);

                        foreach (PdfPageObject obj in page.GetObjects())
                        {
                            switch (obj.Type)
                            {
                                case PdfPageObjectType.Text:
                                    drawText(gr, (PdfTextData)obj);
                                    break;

                                case PdfPageObjectType.Image:
                                    drawImage(gr, (PdfPaintedImage)obj);
                                    break;

                                case PdfPageObjectType.Path:
                                    drawPath(gr, (PdfPath)obj);
                                    break;
                            }
                        }
                    }

                    bitmap.Save(PathToFile, ImageFormat.Png);
                }
            }

            Process.Start(PathToFile);
        }

        private static void drawText(Graphics gr, PdfTextData td)
        {
            if (td.RenderingMode == PdfTextRenderingMode.NeitherFillNorStroke ||
                td.RenderingMode == PdfTextRenderingMode.AddToPath)
                return;

            if (Math.Abs(td.FontSize) < 0.001)
                return;

            if (Math.Abs(td.Bounds.Width) < 0.001 || Math.Abs(td.Bounds.Height) < 0.001)
                return;

            saveStateAndDraw(gr, td.ClipRegion, () =>
            {
                using (Font font = toGdiFont(td.Font, td.FontSize))
                {
                    using (Brush brush = toGdiBrush(td.Brush))
                    {
                        gr.TranslateTransform((float)td.Position.X, (float)td.Position.Y);
                        concatMatrix(gr, td.TransformationMatrix);

                        gr.DrawString(td.Text, font, brush, PointF.Empty);
                    }
                }
            });
        }

        private static void drawImage(Graphics gr, PdfPaintedImage image)
        {
            // Do not render images with zero width or height. GDI+ throws OutOfMemoryException
            // in x86 processes for regular image size (e.g. 1x51) and very small transformation
            // matrix (e.g. { 0.000005, 0, 0, 0.003, x, y }).
            PdfSize paintedImageSize = image.Bounds.Size;
            if (Math.Abs(paintedImageSize.Width) < 0.001 || Math.Abs(paintedImageSize.Height) < 0.001)
                return;

            // ignore mask images in this sample
            if (image.Image.IsMask)
                return;

            using (var stream = new MemoryStream())
            {
                image.Image.Save(stream);
                using (Bitmap bitmap = (Bitmap)Image.FromStream(stream))
                {
                    saveStateAndDraw(gr, image.ClipRegion, () =>
                    {
                        gr.TranslateTransform((float)image.Position.X, (float)image.Position.Y);
                        concatMatrix(gr, image.TransformationMatrix);

                        // Important for rendering of neighbour image tiles
                        gr.PixelOffsetMode = PixelOffsetMode.Half;

                        PdfSize imageSize = new PdfSize(image.Image.Width, image.Image.Height);
                        if (imageSize.Width < bitmap.Width && imageSize.Height < bitmap.Height)
                        {
                            // the bitmap produced from the image is larger than the image.
                            // usually this happens when image has a mask image which is larger than the image itself.
                            InterpolationMode current = gr.InterpolationMode;
                            gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
                            gr.DrawImage(bitmap, 0, 0, (float)imageSize.Width, (float)imageSize.Height);
                            gr.InterpolationMode = current;
                        }
                        else
                        {
                            // bitmap has the same size 
                            // or one of it's dimensions is longer than the corresponding image dimension
                            gr.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
                        }
                    });
                }
            }
        }

        private static void drawPath(Graphics gr, PdfPath path)
        {
            if (!path.PaintMode.HasValue)
                return;

            saveStateAndDraw(gr, path.ClipRegion, () =>
            {
                concatMatrix(gr, path.TransformationMatrix);

                using (var gdiPath = new GraphicsPath())
                {
                    toGdiPath(path, gdiPath);

                    fillStrokePath(gr, path, gdiPath);
                }
            });
        }

        private static void saveStateAndDraw(Graphics gr, PdfClipRegion clipRegion, Action draw)
        {
            var state = gr.Save();
            try
            {
                setClipRegion(gr, clipRegion);

                draw();
            }
            finally
            {
                gr.Restore(state);
            }
        }

        private static void setClipRegion(Graphics gr, PdfClipRegion clipRegion)
        {
            if (clipRegion.IntersectedPaths.Count == 0)
                return;

            Matrix transformationBefore = gr.Transform;
            try
            {
                gr.Transform = new Matrix();
                foreach (PdfPath clipPath in clipRegion.IntersectedPaths)
                {
                    using (var gdiPath = new GraphicsPath())
                    {
                        toGdiPath(clipPath, gdiPath);
                        gdiPath.Transform(toGdiMatrix(clipPath.TransformationMatrix));

                        gdiPath.FillMode = (FillMode)clipPath.ClipMode.Value;
                        gr.SetClip(gdiPath, CombineMode.Intersect);
                    }
                }
            }
            finally
            {
                gr.Transform = transformationBefore;
            }
        }

        private static void toGdiPath(PdfPath path, GraphicsPath gdiPath)
        {
            foreach (PdfSubpath subpath in path.Subpaths)
            {
                gdiPath.StartFigure();

                foreach (PdfPathSegment segment in subpath.Segments)
                {
                    switch (segment.Type)
                    {
                        case PdfPathSegmentType.Point:
                            // A singlepoint open subpath produces no output.
                            break;

                        case PdfPathSegmentType.Line:
                            PdfLineSegment line = (PdfLineSegment)segment;
                            gdiPath.AddLine(line.Start.ToPointF(), line.End.ToPointF());
                            break;

                        case PdfPathSegmentType.Bezier:
                            PdfBezierSegment bezier = (PdfBezierSegment)segment;
                            gdiPath.AddBezier(bezier.Start.ToPointF(),
                                bezier.FirstControl.ToPointF(),
                                bezier.SecondControl.ToPointF(),
                                bezier.End.ToPointF()
                            );
                            break;

                        case PdfPathSegmentType.Rectangle:
                            RectangleF rect = ((PdfRectangleSegment)segment).Bounds.ToRectangleF();

                            // GDI+ does not render rectangles with negative or very small width and height. Render such
                            // rectangles by lines, but respect direction. Otherwise non-zero winding rule for
                            // path filling will not work.
                            gdiPath.AddLines(new PointF[]
                            {
                                rect.Location,
                                new PointF(rect.X + rect.Width, rect.Y),
                                new PointF(rect.X + rect.Width, rect.Y + rect.Height),
                                new PointF(rect.X, rect.Y + rect.Height),
                                rect.Location
                            });
                            break;

                        case PdfPathSegmentType.CloseSubpath:
                            gdiPath.CloseFigure();
                            break;
                    }
                }
            }
        }

        private static void fillStrokePath(Graphics gr, PdfPath path, GraphicsPath gdiPath)
        {
            PdfDrawMode paintMode = path.PaintMode.Value;
            if (paintMode == PdfDrawMode.Fill || paintMode == PdfDrawMode.FillAndStroke)
            {
                using (var brush = toGdiBrush(path.Brush))
                {
                    gdiPath.FillMode = (FillMode)path.FillMode.Value;
                    gr.FillPath(brush, gdiPath);
                }
            }

            if (paintMode == PdfDrawMode.Stroke || paintMode == PdfDrawMode.FillAndStroke)
            {
                using (var pen = toGdiPen(path.Pen))
                {
                    gr.DrawPath(pen, gdiPath);
                }
            }
        }

        private static void concatMatrix(Graphics gr, PdfMatrix transformation)
        {
            using (var m = toGdiMatrix(transformation))
            {
                using (Matrix current = gr.Transform)
                {
                    current.Multiply(m, MatrixOrder.Prepend);
                    gr.Transform = current;
                }
            }
        }

        private static Matrix toGdiMatrix(PdfMatrix matrix)
        {
            return new Matrix(
                (float)matrix.M11,
                (float)matrix.M12,
                (float)matrix.M21,
                (float)matrix.M22,
                (float)matrix.OffsetX,
                (float)matrix.OffsetY
            );
        }

        private static Brush toGdiBrush(PdfBrushInfo brush)
        {
            return new SolidBrush(toGdiColor(brush.Color, brush.Opacity));
        }

        private static Pen toGdiPen(PdfPenInfo pen)
        {
            return new Pen(toGdiColor(pen.Color, pen.Opacity), (float)pen.Width)
            {
                LineJoin = toGdiLineJoin(pen.LineJoin),
                EndCap = toGdiLineCap(pen.EndCap),
                MiterLimit = (float)pen.MiterLimit
            };
        }

        private static Color toGdiColor(PdfColor pdfColor, int opacityPercent)
        {
            if (pdfColor == null)
                return Color.Empty;

            // NOTE: PdfColor.ToColor() method is not supported in version for .NET Standard
            Color color = pdfColor.ToColor();

            int alpha = 255;
            if (opacityPercent < 100 && opacityPercent >= 0)
                alpha = (int)(255.0 * opacityPercent / 100.0);

            return Color.FromArgb(alpha, color.R, color.G, color.B);
        }

        private static Font toGdiFont(PdfFont font, double fontSize)
        {
            string fontName = getFontName(font);
            FontStyle fontStyle = getFontStyle(font);

            return new Font(fontName, (float)fontSize, fontStyle);
        }

        private static LineCap toGdiLineCap(PdfLineCap lineCap)
        {
            switch (lineCap)
            {
                case PdfLineCap.ButtEnd:
                    return LineCap.Flat;

                case PdfLineCap.Round:
                    return LineCap.Round;

                case PdfLineCap.ProjectingSquare:
                    return LineCap.Square;

                default:
                    throw new InvalidOperationException("We should never be here");
            }
        }

        private static LineJoin toGdiLineJoin(PdfLineJoin lineJoin)
        {
            switch (lineJoin)
            {
                case PdfLineJoin.Miter:
                    return LineJoin.Miter;

                case PdfLineJoin.Round:
                    return LineJoin.Round;

                case PdfLineJoin.Bevel:
                    return LineJoin.Bevel;

                default:
                    throw new InvalidOperationException("We should never be here");
            }
        }

        private static string getFontName(PdfFont font)
        {
            // A trick to load a similar font for system. Ideally we should load font from raw bytes. Use PdfFont.Save()
            // method for that.
            string fontName = font.Name;
            if (fontName.Contains("Times"))
                return "Times New Roman";

            if (fontName.Contains("Garamond"))
                return "Garamond";

            if (fontName.Contains("Arial") && !fontName.Contains("Unicode"))
                return "Arial";

            return font.Name;
        }

        private static FontStyle getFontStyle(PdfFont font)
        {
            FontStyle fontStyle = FontStyle.Regular;

            if (font.Bold)
                fontStyle |= FontStyle.Bold;

            if (font.Italic)
                fontStyle |= FontStyle.Italic;

            return fontStyle;
        }
    }
}
VB
Imports System
Imports System.Diagnostics
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.IO
Imports BitMiracle.Docotic.Pdf

Namespace BitMiracle.Docotic.Pdf.Samples
    Public NotInheritable Class ExtractPageObjects
        Public Shared Sub Main()
            ' NOTE: 
            ' When used in trial mode, the library imposes some restrictions.
            ' Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx
            ' for more information.

            Const PathToFile As String = "ExtractPageObjects.png"

            Using pdf = New PdfDocument("Sample Data\gmail-cheat-sheet.pdf")
                Dim page As PdfPage = pdf.Pages(0)

                Const TargetResolution As Single = 300
                Dim scaleFactor As Double = TargetResolution / page.Canvas.Resolution
                Using bitmap As New Bitmap(CInt(page.Width * scaleFactor), CInt(page.Height * scaleFactor))
                    bitmap.SetResolution(TargetResolution, TargetResolution)

                    Using gr = Graphics.FromImage(bitmap)
                        gr.SmoothingMode = SmoothingMode.HighQuality
                        gr.PageUnit = GraphicsUnit.Point

                        gr.SetClip(page.CropBox.ToRectangleF(), CombineMode.Intersect)

                        For Each obj As PdfPageObject In page.GetObjects()
                            Select Case obj.Type
                                Case PdfPageObjectType.Text
                                    drawText(gr, DirectCast(obj, PdfTextData))
                                    Exit Select

                                Case PdfPageObjectType.Image
                                    drawImage(gr, DirectCast(obj, PdfPaintedImage))
                                    Exit Select

                                Case PdfPageObjectType.Path
                                    drawPath(gr, DirectCast(obj, PdfPath))
                                    Exit Select
                            End Select
                        Next
                    End Using

                    bitmap.Save(PathToFile, ImageFormat.Png)
                End Using
            End Using

            Process.Start(PathToFile)
        End Sub

        Private Shared Sub drawText(gr As Graphics, td As PdfTextData)
            If td.RenderingMode = PdfTextRenderingMode.NeitherFillNorStroke OrElse td.RenderingMode = PdfTextRenderingMode.AddToPath Then
                Return
            End If

            If Math.Abs(td.FontSize) < 0.001 Then
                Return
            End If

            If Math.Abs(td.Bounds.Width) < 0.001 OrElse Math.Abs(td.Bounds.Height) < 0.001 Then
                Return
            End If

            saveStateAndDraw(gr, td.ClipRegion,
                Sub()
                    Using font As Font = toGdiFont(td.Font, td.FontSize)
                        Using brush As Brush = toGdiBrush(td.Brush)
                            gr.TranslateTransform(td.Position.X, td.Position.Y)
                            concatMatrix(gr, td.TransformationMatrix)

                            gr.DrawString(td.Text, font, brush, PointF.Empty)
                        End Using
                    End Using
                End Sub
            )
        End Sub

        Private Shared Sub drawImage(gr As Graphics, im As PdfPaintedImage)
            ' Do not render images with zero width or height. GDI+ throws OutOfMemoryException
            ' in x86 processes for regular image size (e.g. 1x51) and very small transformation
            ' matrix (e.g. { 0.000005, 0, 0, 0.003, x, y }).
            Dim paintedImageSize As PdfSize = im.Bounds.Size
            If Math.Abs(paintedImageSize.Width) < 0.001 OrElse Math.Abs(paintedImageSize.Height) < 0.001 Then
                Return
            End If

            ' ignore mask images in this sample
            If im.Image.IsMask Then
                Return
            End If

            Using stream = New MemoryStream()
                im.Image.Save(stream)
                Using bitmap As Bitmap = DirectCast(Image.FromStream(stream), Bitmap)
                    saveStateAndDraw(gr, im.ClipRegion,
                        Sub()
                            gr.TranslateTransform(im.Position.X, im.Position.Y)
                            concatMatrix(gr, im.TransformationMatrix)

                            ' Important for rendering of neighbour image tiles
                            gr.PixelOffsetMode = PixelOffsetMode.Half

                            Dim imageSize As New PdfSize(im.Image.Width, im.Image.Height)
                            If imageSize.Width < bitmap.Width AndAlso imageSize.Height < bitmap.Height Then
                                ' the bitmap produced from the image is larger than the image.
                                ' usually this happens when image has a mask image which is larger than the image itself.
                                Dim current As InterpolationMode = gr.InterpolationMode
                                gr.InterpolationMode = InterpolationMode.HighQualityBicubic
                                gr.DrawImage(bitmap, 0, 0, CSng(imageSize.Width), CSng(imageSize.Height))
                                gr.InterpolationMode = current
                            Else
                                ' bitmap has the same size 
                                ' or one of it's dimensions is longer than the corresponding image dimension
                                gr.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height)
                            End If

                        End Sub
                    )
                End Using
            End Using
        End Sub

        Private Shared Sub drawPath(gr As Graphics, path As PdfPath)
            If Not path.PaintMode.HasValue Then
                Return
            End If

            saveStateAndDraw(gr, path.ClipRegion,
                Sub()
                    concatMatrix(gr, path.TransformationMatrix)

                    Using gdiPath = New GraphicsPath()
                        toGdiPath(path, gdiPath)

                        fillStrokePath(gr, path, gdiPath)
                    End Using
                End Sub
            )
        End Sub

        Private Shared Sub saveStateAndDraw(gr As Graphics, clipRegion As PdfClipRegion, draw As Action)
            Dim state = gr.Save()
            Try
                setClipRegion(gr, clipRegion)

                draw()
            Finally
                gr.Restore(state)
            End Try
        End Sub

        Private Shared Sub setClipRegion(gr As Graphics, clipRegion As PdfClipRegion)
            If clipRegion.IntersectedPaths.Count = 0 Then
                Return
            End If

            Dim transformationBefore As Matrix = gr.Transform
            Try
                gr.Transform = New Matrix()
                For Each clipPath As PdfPath In clipRegion.IntersectedPaths
                    Using gdiPath = New GraphicsPath()
                        toGdiPath(clipPath, gdiPath)
                        gdiPath.Transform(toGdiMatrix(clipPath.TransformationMatrix))

                        gdiPath.FillMode = DirectCast(clipPath.ClipMode.Value, FillMode)
                        gr.SetClip(gdiPath, CombineMode.Intersect)
                    End Using
                Next
            Finally
                gr.Transform = transformationBefore
            End Try
        End Sub

        Private Shared Sub toGdiPath(path As PdfPath, gdiPath As GraphicsPath)
            For Each subpath As PdfSubpath In path.Subpaths
                gdiPath.StartFigure()

                For Each segment As PdfPathSegment In subpath.Segments
                    Select Case segment.Type
                        Case PdfPathSegmentType.Point
                            ' A singlepoint open subpath produces no output.
                            Exit Select

                        Case PdfPathSegmentType.Line
                            Dim line As PdfLineSegment = DirectCast(segment, PdfLineSegment)
                            gdiPath.AddLine(line.Start.ToPointF(), line.[End].ToPointF())
                            Exit Select

                        Case PdfPathSegmentType.Bezier
                            Dim bezier As PdfBezierSegment = DirectCast(segment, PdfBezierSegment)
                            gdiPath.AddBezier(bezier.Start.ToPointF(), bezier.FirstControl.ToPointF(), bezier.SecondControl.ToPointF(), bezier.[End].ToPointF())
                            Exit Select

                        Case PdfPathSegmentType.Rectangle
                            Dim rect As RectangleF = DirectCast(segment, PdfRectangleSegment).Bounds.ToRectangleF()

                            ' GDI+ does not render rectangles with negative or very small width and height. Render such
                            ' rectangles by lines, but respect direction. Otherwise non-zero winding rule for
                            ' path filling will not work.
                            gdiPath.AddLines(New PointF() {rect.Location, New PointF(rect.X + rect.Width, rect.Y), New PointF(rect.X + rect.Width, rect.Y + rect.Height), New PointF(rect.X, rect.Y + rect.Height), rect.Location})
                            Exit Select

                        Case PdfPathSegmentType.CloseSubpath
                            gdiPath.CloseFigure()
                            Exit Select
                    End Select
                Next
            Next
        End Sub

        Private Shared Sub fillStrokePath(gr As Graphics, path As PdfPath, gdiPath As GraphicsPath)
            Dim paintMode As PdfDrawMode = path.PaintMode.Value
            If paintMode = PdfDrawMode.Fill OrElse paintMode = PdfDrawMode.FillAndStroke Then
                Using brush = toGdiBrush(path.Brush)
                    gdiPath.FillMode = DirectCast(path.FillMode.Value, FillMode)
                    gr.FillPath(brush, gdiPath)
                End Using
            End If

            If paintMode = PdfDrawMode.Stroke OrElse paintMode = PdfDrawMode.FillAndStroke Then
                Using pen = toGdiPen(path.Pen)
                    gr.DrawPath(pen, gdiPath)
                End Using
            End If
        End Sub

        Private Shared Sub concatMatrix(gr As Graphics, transformation As PdfMatrix)
            Using m = toGdiMatrix(transformation)
                Using current As Matrix = gr.Transform
                    current.Multiply(m, MatrixOrder.Prepend)
                    gr.Transform = current
                End Using
            End Using
        End Sub

        Private Shared Function toGdiMatrix(matrix As PdfMatrix) As Matrix
            Return New Matrix(matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.OffsetX, matrix.OffsetY)
        End Function

        Private Shared Function toGdiBrush(brush As PdfBrushInfo) As Brush
            Return New SolidBrush(toGdiColor(brush.Color, brush.Opacity))
        End Function

        Private Shared Function toGdiPen(pen As PdfPenInfo) As Pen
            Dim gdiPen As Pen = New Pen(toGdiColor(pen.Color, pen.Opacity), pen.Width)
            gdiPen.LineJoin = toGdiLineJoin(pen.LineJoin)
            gdiPen.EndCap = toGdiLineCap(pen.EndCap)
            gdiPen.MiterLimit = CSng(pen.MiterLimit)
            Return gdiPen
        End Function

        Private Shared Function toGdiColor(pdfColor As PdfColor, opacityPercent As Integer) As Color
            If pdfColor Is Nothing Then
                Return Color.Empty
            End If

            ' NOTE: PdfColor.ToColor() method is not supported in version for .NET Standard
            Dim gdiColor As Color = pdfColor.ToColor()

            Dim alpha As Integer = 255
            If opacityPercent < 100 AndAlso opacityPercent >= 0 Then
                alpha = CInt(255.0 * opacityPercent / 100.0)
            End If

            Return Color.FromArgb(alpha, gdiColor.R, gdiColor.G, gdiColor.B)
        End Function

        Private Shared Function toGdiFont(font As PdfFont, fontSize As Double) As Font
            Dim fontName As String = getFontName(font)
            Dim fontStyle As FontStyle = getFontStyle(font)

            Return New Font(fontName, CSng(fontSize), fontStyle)
        End Function

        Private Shared Function toGdiLineCap(pdfLineCap As PdfLineCap) As LineCap
            Select Case pdfLineCap
                Case PdfLineCap.ButtEnd
                    Return LineCap.Flat

                Case PdfLineCap.Round
                    Return LineCap.Round

                Case PdfLineCap.ProjectingSquare
                    Return LineCap.Square
                Case Else

                    Throw New InvalidOperationException("We should never be here")
            End Select
        End Function

        Private Shared Function toGdiLineJoin(pdfLineJoin As PdfLineJoin) As LineJoin
            Select Case pdfLineJoin
                Case PdfLineJoin.Miter
                    Return LineJoin.Miter

                Case PdfLineJoin.Round
                    Return LineJoin.Round

                Case PdfLineJoin.Bevel
                    Return LineJoin.Bevel
                Case Else

                    Throw New InvalidOperationException("We should never be here")
            End Select
        End Function

        Private Shared Function getFontName(font As PdfFont) As String
            ' A trick to load a similar font for system. Ideally we should load font from raw bytes. Use PdfFont.Save()
            ' method for that.
            Dim fontName As String = font.Name
            If fontName.Contains("Times") Then
                Return "Times New Roman"
            End If

            If fontName.Contains("Garamond") Then
                Return "Garamond"
            End If

            If fontName.Contains("Arial") AndAlso Not fontName.Contains("Unicode") Then
                Return "Arial"
            End If

            Return font.Name
        End Function

        Private Shared Function getFontStyle(font As PdfFont) As FontStyle
            Dim gdiFontStyle As FontStyle = FontStyle.Regular

            If font.Bold Then
                gdiFontStyle = gdiFontStyle Or FontStyle.Bold
            End If

            If font.Italic Then
                gdiFontStyle = gdiFontStyle Or FontStyle.Italic
            End If

            Return gdiFontStyle
        End Function
    End Class
End Namespace