I am trying to use PDFSharp in an Azure Function to produce a sales proposal document. The marketing department want me to use the Montserrat font to write to the document. I discovered that I need to use a FontResolver to enable this. I have added the font to the embedded resources of the project and got the resource name using JetBrains dotPeek. I have implemented a Resolver Class as below and I instantiate the class using
GlobalFontSettings.FontResolver = new MyFontResolver();
The local Azure emulator on my laptop works without issue, however as soon as I publish to Azure I get the following error when I try to call the function.
Microsoft Azure returns STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) from GetFontData. This is a bug in Azure. You must implement a FontResolver to circumvent this issue.
Am I missing something here?
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 "montserrat": if (isBold) { if (isItalic) return new FontResolverInfo("Montserrat#"); return new FontResolverInfo("Montserrat#"); } if (isItalic) return new FontResolverInfo("Montserrat#"); return new FontResolverInfo("Montserrat#"); }
// 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); }
public byte[] GetFont(string faceName) { switch (faceName) { case "Montserrat#": return LoadFontData("CreateProposalDocument.Resources.Montserrat-Regular.ttf");
}
return null; }
/// <summary> /// Returns the specified font from an embedded resource. /// </summary> private byte[] LoadFontData(string name) { var assembly = Assembly.GetExecutingAssembly();
// Test code to find the names of embedded fonts - put a watch on "ourResources" //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; } }
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; } } }
|