EZFontResolver: a generic font resolver for PDFsharp and MigraDoc

EZFontResolver implements the IFontResolver interface that PDFsharp uses.

In your program, you simply call the AddFont method of EZFontResolver. You simply pass the filename of your font or a byte array containing the font data.
EZFontResolver just needs a little help: you have to specify a family name and you also have to indicate the style of the font you pass (regular, bold, italic, bold italic) and whether you want to enable simulation of bold and italic in PDFsharp.

Let’s look at some code. This is the code that creates an instance of EZFontResolver and assigns it to PDFsharp:

// Get the EZFontResolver.
EZFontResolver fontResolver = EZFontResolver.Get;
// Assign it to PDFsharp.
GlobalFontSettings.FontResolver = fontResolver;

One sample font I tried is Janitor. There is only a single file with Janitor Regular, therefore I enable simulation of bold and italic in PDFsharp:

// We only have Janitor Regular, no Bold, no Italic.
// We allow PDFsharp to simulate Bold and Italic for us.
fontResolver.AddFont("Janitor", XFontStyle.Regular,
    @"......fontsjanitorjanitor.ttf", true, true);

I also tested with four font faces from the Ubuntu family. Since I have faces for bold and italic, simulation is not needed here:

// The Ubuntu family has many font faces, so we do not need simulation here.
fontResolver.AddFont("Ubuntu", XFontStyle.Regular,
    @"......fontsubuntufontfamily0.80ubuntu-R.ttf");
fontResolver.AddFont("Ubuntu", XFontStyle.Italic,
    @"......fontsubuntufontfamily0.80ubuntu-RI.ttf");
fontResolver.AddFont("Ubuntu", XFontStyle.Bold,
    @"......fontsubuntufontfamily0.80ubuntu-B.ttf");
fontResolver.AddFont("Ubuntu", XFontStyle.BoldItalic,
    @"......fontsubuntufontfamily0.80ubuntu-BI.ttf");

When the fonts are registered, you can use them with PDFsharp or MigraDoc like you use any other font.

A final note: EZFontResolver is implemented as a singleton. Only one object of class will be created and each call of Get will return the same object. You can add the fonts only once and you will get an exception if a font with the same name already exists. If your program creates several documents, then register all fonts that are needed before creating the first PDF file.

You can download the complete EZFontResolver class as a ZIP file (about 2041 kiB in size).
Download EZFontResolver.zip.

The ZIP file contains a solution with a sample program and requires the PDFsharp package from NuGet. To use EZFontResolver with your project, just copy the file EZFontResolver.cs into your folder and add it to your project.

EZFontResolver is meant to make using private fonts more easy. Complete source code is in the ZIP file.
There is another example that implements IFontResolver: Sample that implements IFontResolver.

9 thoughts on “EZFontResolver: a generic font resolver for PDFsharp and MigraDoc”

  1. I noticed this somehow causes issues when trying to resolve.
    This is a small fix, making it so it wont append the “|b” multiple times.

    EzFontResolver:125

    public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
    {
    string faceName = familyName.ToLower() +
    (isBold && !familyName.Contains(“|b”) ? “|b” : “”) +
    (isItalic && !familyName.Contains(“|i”) ? “|i” : “”);
    EZFontInfo item;
    if (_fonts.TryGetValue(faceName, out item))
    {
    var result = new FontResolverInfo(item.FaceName, item.SimulateBold, item.SimulateItalic);
    return result;
    }
    return null;
    }

    Means you wont be getting duplicate “|b” and causing the PdfDocumentRenderer.RenderDocument(); to fail.

    1. IMHO the fix is not needed and does not do any good, so I will not include it in my code (unless I see code that causes RenderDocument() to fail).

    2. The check for duplicate “|b” and “|i” is currently needed because there is a bug in PDFsharp/MigraDoc 1.50 beta 3. It will be obsolete after the next PDFsharp/MigraDoc release. And I do not know when it will be published.

  2. Here’s an example using MigraDocs:

    EZFontResolver fontResolver = EZFontResolver.Get;
    // Assign it to PDFsharp.
    GlobalFontSettings.FontResolver = fontResolver;

    // We only have Janitor Regular, no Bold, no Italic.
    // We allow PDFsharp to simulate Bold and Italic for us.
    fontResolver.AddFont(“Janitor”, XFontStyle.Regular,
    @”……fontsjanitorjanitor.ttf”, true, true);

    Document _document = new Document();

    var font = “Janitor”;
    var style = _document.Styles[“Normal”];
    style.Font.Name = font;
    style.Font.Size = 9;

    var section = _document.AddSection();
    var table = section.AddTable();
    table.Style = “Table”;

    var column = table.AddColumn(“5cm”);
    var row = table.AddRow();

    row.HeadingFormat = true;
    row.Format.Alignment = ParagraphAlignment.Center;
    row.Format.Font.Bold = true;
    row.Cells[0].AddParagraph(“HeyHey”);

    var pdfRenderer = new PdfDocumentRenderer(true) { Document = _document };
    const string filename = “HelloWorld.pdf”;
    pdfRenderer.RenderDocument();
    pdfRenderer.Save(filename);

    // Save the document…

    pdfRenderer.PdfDocument.Save(“HelloWorld.pdf”);

    // …and start a viewer.
    Process.Start(filename);

    1. Woops, didn’t take out alot of code there.

      static void Main()
      {
      // Get the EZFontResolver.
      EZFontResolver fontResolver = EZFontResolver.Get;
      // Assign it to PDFsharp.
      GlobalFontSettings.FontResolver = fontResolver;

      // We only have Janitor Regular, no Bold, no Italic.
      // We allow PDFsharp to simulate Bold and Italic for us.
      fontResolver.AddFont(“Janitor”, XFontStyle.Regular,
      @”……fontsjanitorjanitor.ttf”, true, true);

      Document _document = new Document();

      var font = “Janitor”;
      var style = _document.Styles[“Normal”];
      style.Font.Name = font;

      var section = _document.AddSection();
      var table = section.AddTable();
      table.Style = “Table”;

      table.AddColumn(“5cm”);
      var row = table.AddRow();

      row.Format.Font.Bold = true;
      row.Cells[0].AddParagraph(“HeyHey”);

      var pdfRenderer = new PdfDocumentRenderer(true) { Document = _document };
      const string filename = “HelloWorld.pdf”;
      pdfRenderer.RenderDocument();
      pdfRenderer.Save(filename);

      // …and start a viewer.
      Process.Start(filename);
      }

  3. Thanks for providing this, and for your other information about PdfSharp.

    One change I made in my implementation, was to default to PlatformFontResolver when a font was not found. This enables us to load additional fonts but fall back to system fonts.

    var result = (_fonts.TryGetValue(faceName, out item)) ?
    new FontResolverInfo(item.FaceName, item.SimulateBold, item.SimulateItalic) :
    PlatformFontResolver.ResolveTypeface(familyName, isBold, isItalic);

    We also removed the exception when a font has already been added:

    var test = GetFont(fi.FaceName);
    if (test != null)
    return;

  4. Hi Thomas, I am facing a problem of

    {“Must not change font resolver after is was once used.”}

    in the using the EZFontResolver class embedded into my project

    Project Details are: MVC-5, **pdfSharp 1.50.3915-beta2**

    Error caused by: GlobalFontSettings.FontResolver = fontResolver;

    Please guide me to resolve this, as i am new to Invoice Generation

Leave a Reply

Your email address will not be published. Required fields are marked *