Add Text Elements to PDF Document

The PdfDocument class allows you to create PDF documents from scratch and add various content elements using a simple programmatic interface.

The PDF text element is represented by the EvoPdf.ChromiumPdfTextElement class and can be added to a PdfDocument using the PdfDocumentAddText(PdfTextElement) method.

Create and Render PDF Text Elements

A PDF text element requires at least a text string to be rendered and a PDF font when it is created. The steps below describe how to create text elements and render them in a PDF document.

Create a PDF Font

A PDF font, represented by the EvoPdf.ChromiumPdfFont class, can be created using the static methods of the EvoPdf.ChromiumPdfFontManager class. You can create either standard built-in fonts or TrueType fonts from external files. Standard fonts are available in any PDF viewer and are typically used for ASCII text. You can create a standard font using the PdfFontManagerCreateStandardFont(PdfStandardFont, Single, PdfFontStyle, PdfColor) method. The example below shows how to create a standard font with a specific family, size, style and color.

Create a Standard PDF Font
// Create a standard Courier font
PdfFont fontCourier = PdfFontManager.CreateStandardFont(PdfStandardFont.Courier, 16f, PdfFontStyle.Bold | PdfFontStyle.Italic, PdfColor.Green);

To render arbitrary Unicode text, you must use a TrueType or OpenType font, which is automatically embedded in the PDF document. You can create such a font using the PdfFontManagerCreateFont(String, Single, PdfFontStyle, PdfColor) method. The example below creates a TrueType font from a .ttf file with the specified size, style and color.

Create a Unicode TrueType PDF Font
string dejaVuRegularFontFile = Path.Combine(fontsPath, "DejaVuSerif.ttf");

// Create a Unicode TrueType font from file
PdfFont trueTypeFont = PdfFontManager.CreateFont(dejaVuRegularFontFile, 16f, PdfFontStyle.Normal, PdfColor.Black);

Create the Text Element

Besides the required text string and font parameters, the PdfTextElement class also includes properties to specify the X and Y coordinates, which define the location of the text element relative to the top-left corner of the PDF page, excluding page margins. These properties default to zero. The example below creates a text element using a standard font, positioned at the specified coordinates on the PDF page.

Create a Text Element
PdfTextElement pdfText = new PdfTextElement("The text element string", fontCourier)
{
  X = crtXPos,
  Y = crtYPos
};

Positioning and Size

The X and Y properties define the location of the text element relative to the top-left corner of the PDF page. The page margins are excluded when positioning the element.

If the Width and Height properties are specified, they will be used to determine the element's bounds on the page. If the width is not specified, the text will extend to the available space on the right. If the height is not specified, the element will extend downward to the available height. By default, both width and height are zero and automatic resizing is applied.

Text Horizontal Alignment

You can use the Alignment property to specify the text alignement inside the bounds. You can align the text to the right or left, center or justify it inside the bounds. By default the text is aligned to the left.

Render Text Element

To render the text element in the current PDF page, use the PdfDocumentAddText(PdfTextElement) method. The example below renders the created text element in the current page.

Render Text Element in Current PDF Page
PdfTextRenderInfo textRenderInfo = pdfDocument.AddText(pdfTitle1);

The AddText(PdfTextElement) method returns a EvoPdf.ChromiumPdfTextRenderInfo object, which provides information about the rendered text, such as the bounding rectangle on each PDF page. This information is useful for document layout, as it allows you to position the next element relative to the previous one. For example, the vertical position for the next element can be updated as shown below.

Update Location after Text Rendering
// Update the Y position after rendering the title
crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

Automatically Continue Rendering on Next Page

An advanced feature is the automatic continuation of text rendering on the next page when there is not enough space left on the current one. This behavior is controlled by the PdfTextElementContinueOnNextPage property, which is false by default.

When ContinueOnNextPage is set to true and the rendering continues on the next page, an optional handler is invoked that allows you to render other elements on the current page before moving on. The handler can be assigned to the PdfTextElementOnPageRendered property. It receives the current PDF page number and the bounding rectangle of the rendered text as parameters. In the demo application, this handler is used to draw a blue border around the rendered text on each page, as shown in the sample below.

Continue Text Rendering on Next PDF Page
string dejaVuRegularFontFile = Path.Combine(fontsPath, "DejaVuSerif.ttf");

// Create a Unicode TrueType font from file
PdfFont trueTypeFont = PdfFontManager.CreateFont(dejaVuRegularFontFile, 16f,
    PdfFontStyle.Normal, PdfColor.Black);

// Add long Unicode text using the TrueType font, allowing continuation on next pages
PdfTextElement pdfText1 = new PdfTextElement(alfabetString, trueTypeFont)
{
    X = crtXPos,
    Y = crtYPos,
    Alignment = PdfTextAlignment.Left,
    ContinueOnNextPage = true
};

// Draw a rectangle around rendered text in each page
pdfText1.OnPageRendered = (pageNumber, boundingBox) =>
{
    PdfRectangleElement border = new PdfRectangleElement(boundingBox.X, boundingBox.Y,
        boundingBox.Width, boundingBox.Height + 5)
    {
        BorderColor = PdfColor.Blue,
    };
    pdfDocument.AddRectangle(border);
};

textRenderInfo = pdfDocument.AddText(pdfText1);

Set the Text Leading

Leading is an important feature of the text element that controls the spacing between text lines. It can be specified as a factor of the font size used by the text element. By default, the leading factor is 1.2.

Text Direction

The PDF text element can also handle text in right-to-left languages such as Arabic. The text direction can be specified using the PdfTextElementDirection property. By default, the direction is LeftToRight. In the code sample below, a right-to-left Arabic text is rendered using a TrueType font that supports the language.

Render Right to Left Text
// Create a Unicode font that supports Arabic (RTL)
string notoSansArabicRegularFontFile = Path.Combine(fontsPath, "NotoSansArabic-Regular.ttf");

PdfFont trueTypeFontArabic = PdfFontManager.CreateFont(notoSansArabicRegularFontFile, 16f,
    PdfFontStyle.Normal, PdfColor.Black);

string rtlFilePath = Path.Combine(textsPath, "RightToLeft.txt");
string rtlString = System.IO.File.ReadAllText(rtlFilePath);

// Render the right-to-left text
PdfTextElement pdfTextRtl = new PdfTextElement(rtlString, trueTypeFontArabic)
{
    X = crtXPos,
    Y = crtYPos,
    Direction = PdfTextDirection.RightToLeft
};
textRenderInfo = pdfDocument.AddText(pdfTextRtl);

Code Sample - Create PDF Documents with Text and Images

C#
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

// Use EVO PDF Namespace
using EvoPdf.Chromium;

namespace EvoPdf_Chromium_AspNetDemo.Controllers.PDF_Creator
{
    public class Create_PDF_DocumentsController : Controller
    {
        private readonly IWebHostEnvironment m_hostingEnvironment;

        public Create_PDF_DocumentsController(IWebHostEnvironment hostingEnvironment)
        {
            m_hostingEnvironment = hostingEnvironment;
        }

        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult CreatePdf(IFormCollection collection)
        {
            // Set license key received after purchase to use the library in licensed mode
            // Leave it not set to use the library in demo mode
            Licensing.LicenseKey = "4W9+bn19bn5ue2B+bn1/YH98YHd3d3c=";

            PdfDocumentCreateSettings pdfCreateSettings = new PdfDocumentCreateSettings()
            {
                PageSize = PdfPageSize.A4,
                PageOrientation = PdfPageOrientation.Portrait,
                Margins = new PdfMargins(36, 36, 36, 36)
            };

            // Create a new PDF document with the specified settings
            using PdfDocument pdfDocument = new PdfDocument(pdfCreateSettings);

            const int startXPos = 0;
            const int startYPos = 0;
            const int ySeparator = 15;

            int currentPage = pdfDocument.PageNumber;
            int crtXPos = startXPos;
            int crtYPos = startYPos;

            // Create a standard Helvetica font
            PdfFont fontHelvetica = PdfFontManager.CreateStandardFont(PdfStandardFont.Helvetica, 16f,
                PdfFontStyle.Bold | PdfFontStyle.Underline, PdfColor.Black);

            // Add a title using the Helvetica font
            PdfTextElement pdfTitle1 = new PdfTextElement("Transparent PNG Image with Custom Width", fontHelvetica)
            {
                X = crtXPos,
                Y = crtYPos
            };
            PdfTextRenderInfo textRenderInfo = pdfDocument.AddText(pdfTitle1);

            // Update the Y position after rendering the title
            crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

            string imagesPath = GetDemoImagesPath();

            // Add a transparent PNG image with custom width
            PdfImageElement pdfPngImage = new PdfImageElement(Path.Combine(imagesPath, "transparent.png"))
            {
                X = crtXPos,
                Y = crtYPos,
                Width = 150
            };
            PdfImageRenderInfo imageRenderInfo = pdfDocument.AddImage(pdfPngImage);

            crtYPos = imageRenderInfo.BoundingBox.Bottom + ySeparator;

            // Create a standard Courier font
            PdfFont fontCourier = PdfFontManager.CreateStandardFont(PdfStandardFont.Courier, 16f,
                PdfFontStyle.Bold | PdfFontStyle.Italic, PdfColor.Green);

            // Add a title for the JPEG image
            PdfTextElement pdfTitle2 = new PdfTextElement("JPEG Image with Custom Height", fontCourier)
            {
                X = crtXPos,
                Y = crtYPos
            };
            textRenderInfo = pdfDocument.AddText(pdfTitle2);

            crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

            // Ensure there is enough vertical space on the current page for the image.
            // Add a new page and reset Y position if needed
            EnsureSpaceOnPage(ref crtYPos, 200, pdfDocument);

            // Add a JPEG image with custom height
            PdfImageElement pdfJpgImage = new PdfImageElement(Path.Combine(imagesPath, "image.jpg"))
            {
                X = crtXPos,
                Y = crtYPos,
                Height = 150
            };
            imageRenderInfo = pdfDocument.AddImage(pdfJpgImage);

            crtYPos = imageRenderInfo.BoundingBox.Bottom + ySeparator;

            string fontsPath = GetDemoFontsPath();
            string textsPath = GetDemoTextsPath();

            string alphabetFilePath = Path.Combine(textsPath, "Alphabet.txt");
            string alfabetString = System.IO.File.ReadAllText(alphabetFilePath);

            // Create a blue bold Courier font
            PdfFont fontCourier2 = PdfFontManager.CreateStandardFont(PdfStandardFont.Courier, 16f,
                PdfFontStyle.Bold, PdfColor.Blue);

            // Add a title for the Unicode text
            PdfTextElement pdfTitle3 = new PdfTextElement("Multi Page Unicode Text with Custom Font", fontCourier2)
            {
                Y = crtYPos,
                Alignment = PdfTextAlignment.Center
            };
            textRenderInfo = pdfDocument.AddText(pdfTitle3);

            crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

            string dejaVuRegularFontFile = Path.Combine(fontsPath, "DejaVuSerif.ttf");

            // Create an Unicode TrueType font from file
            PdfFont trueTypeFont = PdfFontManager.CreateFont(dejaVuRegularFontFile, 16f,
                PdfFontStyle.Normal, PdfColor.Black);

            // Add long Unicode text using the TrueType font, allowing continuation on next pages
            PdfTextElement pdfText1 = new PdfTextElement(alfabetString, trueTypeFont)
            {
                X = crtXPos,
                Y = crtYPos,
                Alignment = PdfTextAlignment.Left,
                ContinueOnNextPage = true
            };

            // Draw a rectangle around rendered text in each page
            pdfText1.OnPageRendered = (pageNumber, boundingBox) =>
            {
                PdfRectangleElement border = new PdfRectangleElement(boundingBox.X, boundingBox.Y,
                    boundingBox.Width, boundingBox.Height + 5)
                {
                    BorderColor = PdfColor.Blue,
                };
                pdfDocument.AddRectangle(border);
            };

            textRenderInfo = pdfDocument.AddText(pdfText1);

            // Set the next page to landscape A4
            pdfDocument.SetPageSize(PdfPageSize.A4, PdfPageOrientation.Landscape);

            // Add a new page
            pdfDocument.AddPage();

            // Reset positions
            crtXPos = 0;
            crtYPos = 0;

            // Add the same text again, with the same font, centered
            PdfTextElement pdfText2 = new PdfTextElement(alfabetString, trueTypeFont)
            {
                X = crtXPos,
                Y = crtYPos,
                Alignment = PdfTextAlignment.Center,
                ContinueOnNextPage = true
            };

            pdfText2.OnPageRendered = (pageNumber, boundingBox) =>
            {
                PdfRectangleElement border = new PdfRectangleElement(boundingBox.X, boundingBox.Y,
                    boundingBox.Width, boundingBox.Height + 5)
                {
                    BorderColor = PdfColor.Purple,
                };
                pdfDocument.AddRectangle(border);
            };

            textRenderInfo = pdfDocument.AddText(pdfText2);

            // Add a new page
            pdfDocument.AddPage();

            // Reset positions
            crtXPos = 0;
            crtYPos = 0;

            PdfFont rtlTileFont = PdfFontManager.CreateStandardFont(PdfStandardFont.Courier, 16f, 
                PdfFontStyle.Normal, PdfColor.Purple);

            PdfTextElement rtlTitle = new PdfTextElement("Add Right to Left Text", rtlTileFont)
            {
                X = crtXPos,
                Y = crtYPos
            };
            textRenderInfo = pdfDocument.AddText(rtlTitle);
            crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

            // Create a Unicode font that supports Arabic (RTL)
            string notoSansArabicRegularFontFile = Path.Combine(fontsPath, "NotoSansArabic-Regular.ttf");

            PdfFont trueTypeFontArabic = PdfFontManager.CreateFont(notoSansArabicRegularFontFile, 16f,
                PdfFontStyle.Normal, PdfColor.Black);

            string rtlFilePath = Path.Combine(textsPath, "RightToLeft.txt");
            string rtlString = System.IO.File.ReadAllText(rtlFilePath);

            // Render the right to left text
            PdfTextElement pdfTextRtl = new PdfTextElement(rtlString, trueTypeFontArabic)
            {
                X = crtXPos,
                Y = crtYPos,
                Direction = PdfTextDirection.RightToLeft
            };
            textRenderInfo = pdfDocument.AddText(pdfTextRtl);

            // Save to memory buffer
            byte[] outPdfBuffer = pdfDocument.Save();

            // Send PDF to browser
            FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
            fileResult.FileDownloadName = "PdfDocument.pdf";

            return fileResult;
        }

        private void EnsureSpaceOnPage(ref int crtYPos, int requestedHeight, PdfDocument pdfDocument)
        {
            if (crtYPos + requestedHeight > pdfDocument.ContentHeight)
            {
                pdfDocument.AddPage();
                crtYPos = 0;
            }
        }

        private string GetDemoFilesPath()
        {
            return m_hostingEnvironment.ContentRootPath + "/wwwroot" + "/DemoAppFiles/Input/";
        }

        private string GetDemoImagesPath()
        {
            return Path.Combine(GetDemoFilesPath(), "Image_Files");
        }

        private string GetDemoFontsPath()
        {
            return Path.Combine(GetDemoFilesPath(), "Font_Files");
        }

        private string GetDemoTextsPath()
        {
            return Path.Combine(GetDemoFilesPath(), "Text_Files");
        }
    }
}

See Also