I have a WinForms application, and I'm trying to get private fonts to work using the new FontResolver interface in 1.50.3638-beta.
I have modeled my code on
TH-Soft's sample, which uses the WPF version of PDFsharp.
Here's my code:
Code:
// In the static constructor:
// GlobalFontSettings.FontResolver = new FontResolver();
void GetPrivateFont() {
var dataFont = new XFont( "Avenir Medium", 10, XFontStyle.Regular, fontOptions );
Debug.WriteLine( "Got font " + dataFont.FontFamily.Name );
}
class FontResolver : FontResolverBase {
public override FontResolverInfo ResolveTypeface( string familyName, bool isBold, bool isItalic ) {
Debug.WriteLine( "ResolveTypeface: " + familyName );
switch ( familyName.ToLowerInvariant() ) {
case "avenir medium":
return new FontResolverInfo( "Avenir Medium/" );
}
return base.ResolveTypeface( familyName, isBold, isItalic );
}
public override byte[] GetFont( string faceName ) {
Debug.WriteLine( "GetFont: " + faceName );
var assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
switch ( faceName.ToLowerInvariant() ) {
case "avenir medium/":
Debug.WriteLine( "Getting Avenir Medium" );
return LoadFontData( assemblyName + ".Fonts.Avenir-Medium.ttf" );
}
Debug.WriteLine( "faceName not found" );
return base.GetFont( faceName );
}
static byte[] LoadFontData( string name ) {
using ( var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream( name ) ) {
if ( resourceStream == null )
throw new ArgumentException( "No resource with name " + name );
var fontBytes = new byte[resourceStream.Length];
resourceStream.Read( fontBytes, 0, fontBytes.Length );
Debug.WriteLine( name + " " + fontBytes.Length );
return fontBytes;
}
}
}
This outputs:
Code:
ResolveTypeface: Avenir Medium
GetFont: Avenir Medium/
Getting Avenir Medium
MyAssembly.Fonts.Avenir-Medium.ttf 138892
Got font Microsoft Sans Serif
Note that everything in the FontResolver class
appears to be working fine, but I finally end up with Microsoft Sans Serif instead of the font I wanted.
Also, if I actually install the font to my system (and disable the FontResolver by commenting out the
GlobalFontSettings.FontResolver = new FontResolver() line), then I get the correct font. So that tells me that my
var dataFont = new XFont(...) line is probably fine as well (including requesting the correct font name).
Meanwhile,
TH-Soft's WPF version works fine.
Am I missing something, or is this a bug in the GDI version of PDFsharp? If the latter, is there a workaround?
UpdateFrom spelunking around with .NET Reflector and run-time reflection, I have found the following:
The constructor of XFont calls XFont.Initialize(), which in turn calls XPrivateFontCollection.TryCreateFont(). If XPrivateFontCollection.TryCreateFont() returns null, XFont.Initialize() initializes itself with System.Drawing.Font(familyName, ...). Since this is a private font, the System.Drawing.Font constructor doesn't find it, and I get the default Microsoft Sans Serif.
Meanwhile, XPrivateFontCollection.TryCreateFont() is returning null because XPrivateFontCollection.Global._privateFontCollection.Families.Count == 0. So the private collection is empty, despite having (tried to) add a font to it via the FontResolver class.