noelicus
noelicus

Reputation: 15055

How to use Fonts in PDFsharp in my Website?

I am just using the Arial font on an Azure WebApplication web site but when I get to this line:

MainFont = new XFont("Arial", FontSize);

it throws an exception reading: Font data could not retrieved.

I would have thought Arial would have been installed on the server ... and I also tried changing it to Sans-Serif to match the default font of the Microsoft generated web-site ... but it still fails.

I have also tried adding Arial.ttf to the project, but that hasn't worked.

Upvotes: 2

Views: 12562

Answers (2)

noelicus
noelicus

Reputation: 15055

Thanks for the pointers @PDFSharp Team. Here is my implementation for PdfSharp 1.5 beta3b:

Add the fonts you want to your project - in my example below I put Arial in MyProject\fonts\arial\arial.ttf etc. Set each font file as an embedded resource (properties -> build action).

Apply the font resolver only once using the static call like this:

MyFontResolver.Apply(); // Ensures it's only applied once

Here's the font resolver class:

class MyFontResolver : IFontResolver
{
    public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
    {
        // Ignore case of font names.
        var name = familyName.ToLower().TrimEnd('#');

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

        // 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 PlatformFontResolver.ResolveTypeface(familyName, isBold, isItalic);
    }

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

            case "Arial#b":
                return FontHelper.ArialBold;

            case "Arial#i":
                return FontHelper.ArialItalic;

            case "Arial#bi":
                return FontHelper.ArialBoldItalic;
        }

        return null;
    }


    internal static MyFontResolver OurGlobalFontResolver = null;

    /// <summary>
    /// Ensure the font resolver is only applied once (or an exception is thrown)
    /// </summary>
    internal static void Apply()
    {
        if (OurGlobalFontResolver == null || GlobalFontSettings.FontResolver == null)
        {
            if (OurGlobalFontResolver == null)
                OurGlobalFontResolver = new MyFontResolver();

            GlobalFontSettings.FontResolver = OurGlobalFontResolver;
        }
    }
}


/// <summary>
/// Helper class that reads font data from embedded resources.
/// </summary>
public static class FontHelper
{
    public static byte[] Arial
    {
        get { return LoadFontData("MyProject.fonts.arial.arial.ttf"); }
    }

    public static byte[] ArialBold
    {
        get { return LoadFontData("MyProject.fonts.arial.arialbd.ttf"); }
    }

    public static byte[] ArialItalic
    {
        get { return LoadFontData("MyProject.fonts.arial.ariali.ttf"); }
    }

    public static byte[] ArialBoldItalic
    {
        get { return LoadFontData("MyProject.fonts.arial.arialbi.ttf"); }
    }

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

        // Test code to find the names of embedded fonts
        //var ourResources = assembly.GetManifestResourceNames();

        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;
        }
    }
}

This is a single, complete and working class based on these two almost identical posts: this blog and this forum.

Upvotes: 9

Use the latest version of PDFsharp (currently 1.50 beta 3) and implement IFontResolver.

See also:
https://stackoverflow.com/a/32489271/162529
https://stackoverflow.com/a/29059207/162529

The font may be installed on the server, but PDFsharp cannot read it.

Upvotes: 0

Related Questions