PDFsharp & MigraDoc Foundation
https://forum.pdfsharp.net/

Using private fonts with PDFsharp 1.50 beta or MigraDoc
https://forum.pdfsharp.net/viewtopic.php?f=8&t=3073
Page 1 of 1

Author:  TH-Soft [ Sun Mar 15, 2015 9:28 am ]
Post subject:  Using private fonts with PDFsharp 1.50 beta or MigraDoc

PDFsharp 1.50 implements a new mechanism for private fonts (fonts that are not installed on the system). You simply implement IFontResolver and assign this to a global property:

Code:
// That's all it takes to register your own fontresolver
GlobalFontSettings.FontResolver = new DemoFontResolver();


The interesting part is IFontResolver and how you implement it.

The IFontResolver interface requires two methods: ResolveTypeface and GetFont.

I derived my class DemoFontResolver from PDFsharp’s class FontResolverBase. For this demo I downloaded two free font: Janitor (regular only) and Ubuntu (using regular, italic, bold, bold italic).

Here is the ResolveTypeface code:

Code:
public override FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
{
    // Ignore case of font names.
    var name = familyName.ToLower();

    // Deal with the fonts we know.
    switch (name)
    {
        case "ubuntu":
            if (isBold)
            {
                if (isItalic)
                    return new FontResolverInfo("Ubuntu#bi");
                return new FontResolverInfo("Ubuntu#b");
            }
            if (isItalic)
                return new FontResolverInfo("Ubuntu#i");
            return new FontResolverInfo("Ubuntu#");

        case "janitor":
            return new FontResolverInfo("Janitor#");
    }

    // We pass all other font requests to the default handler.
    // When running on a web server without sufficient permission, you can return a default font at this stage.
    return base.ResolveTypeface(familyName, isBold, isItalic);
}


The other method, GetFont, must return the TTF file in a byte array.

My implementation of GetFont looks like this:

Code:
/// <summary>
/// Return the font data for the fonts.
/// </summary>
public override byte[] GetFont(string faceName)
{
    switch (faceName)
    {
        case "Janitor#":
            return FontHelper.Janitor;

        case "Ubuntu#":
            return FontHelper.Ubuntu;

        case "Ubuntu#b":
            return FontHelper.UbuntuBold;

        case "Ubuntu#i":
            return FontHelper.UbuntuItalic;

        case "Ubuntu#bi":
            return FontHelper.UbuntuBoldItalic;
    }

    return base.GetFont(faceName);
}


The code that does the work of retrieving the fonts is hidden in a helper class. I added the fonts to the project using the "Embedded Resource" compile type. I then used the free dotPeek tool from JetBrains to find the names of the embedded resources.

Code:
/// <summary>
/// Helper class that reads font data from embedded resources.
/// </summary>
public static class FontHelper
{
    public static byte[] Janitor
    {
        get { return LoadFontData("MyFontResolver.fonts.janitor.Janitor.ttf"); }
    }

    // Tip: I used JetBrains dotPeek to find the names of the resources (just look how dots in folder names are encoded).
    // Make sure the fonts have compile type "Embedded Resource". Names are case-sensitive.
    public static byte[] Ubuntu
    {
        get { return LoadFontData("MyFontResolver.fonts.ubuntufontfamily0._80.Ubuntu-R.ttf"); }
    }

    public static byte[] UbuntuBold
    {
        get { return LoadFontData("MyFontResolver.fonts.ubuntufontfamily0._80.Ubuntu-B.ttf"); }
    }

    public static byte[] UbuntuItalic
    {
        get { return LoadFontData("MyFontResolver.fonts.ubuntufontfamily0._80.Ubuntu-RI.ttf"); }
    }

    public static byte[] UbuntuBoldItalic
    {
        get { return LoadFontData("MyFontResolver.fonts.ubuntufontfamily0._80.Ubuntu-BI.ttf"); }
    }

    /// <summary>
    /// Returns the specified font from an embedded resource.
    /// </summary>
    static byte[] LoadFontData(string name)
    {
        var assembly = Assembly.GetExecutingAssembly();

        using (Stream stream = assembly.GetManifestResourceStream(name))
        {
            if (stream == null)
                throw new ArgumentException("No resource with name " + name);

            int count = (int)stream.Length;
            byte[] data = new byte[count];
            stream.Read(data, 0, count);
            return data;
        }
    }
}


You can download the complete demo application as a ZIP file (about 2 MiB in size due to the embedded fonts).
http://pdfsharp.th-soft.com/pdfsharp/do ... erDemo.zip

The font resolver applies to PDFsharp and it will also be used when you create PDF files from MigraDoc.

The ZIP file contains two console applications, one demo for PDFsharp and one demo for MigraDoc.
The solution uses PDFsharp 1.50 beta from NuGet. In Visual Studio (I used the free Community Edition Visual Studio 2013) in the <strong>Solution Explorer</strong>, select <strong>Manage NuGet Packages for Solution</strong> from the context menu of the solution.

Sample also discussed in my blog:
http://developer.th-soft.com/developer/?p=11


A generic font resolver that implements IFontResolver and simplifies usage for inexperienced users can be found here:
viewtopic.php?p=9576#p9576

Author:  West.Ryan [ Mon Aug 01, 2016 2:08 pm ]
Post subject:  Re: Using private fonts with PDFsharp 1.50 beta or MigraDoc

Hi, I have tried your solution to embedding private fonts. This solution works when I open my pdf files in Adobe Acrobat. However, if I try to directly print the pdf files from my application, or save them to .png, my embedded fonts are not used. It uses a default font instead. Do you know how to make this work?

Author:  Thomas Hoevel [ Mon Aug 01, 2016 3:03 pm ]
Post subject:  Re: Using private fonts with PDFsharp 1.50 beta or MigraDoc

IFontResolver is a PDFsharp feature. Those fonts are not used when printing with GDI+.

Theoretically you can use the GDI+ build of PDFsharp and add the fonts to the XPrivateFontCollection - then they should also be used when printing to a physical printer or a file (PNG or TIFF).

Author:  West.Ryan [ Mon Aug 01, 2016 3:41 pm ]
Post subject:  Re: Using private fonts with PDFsharp 1.50 beta or MigraDoc

Could you explain how to load the fonts using XPrivateFontCollection? I have been searching for examples of how to do that for quite a while and have found nothing on the GDI+ side, only WPF.

I am using MigraDoc 1.5 beta3b because I need to use images from streams as well.

Thank you!

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/