I am trying to add text to a PDF document using private, i.e. not installed on the system, TrueType fonts and having trouble. I am using PDFSharp + MigraDoc WPF version 1.32.2608.0 from NuGet.
I have found numerous items on the forum and on StackOverFlow. The latest is this stackoverflow article which refers to this example on the PdfSharp site. However this example contains the code:
this.fontFamilies.Add(key, fontFamily);
on line 22, but I cannot find any reference to fontFamilies in assembly.
I therefore have followed what looked like an excellent example, but it does not work for me. When I use this approach I can successfully add the font but when I come to use the command:
var font = new XFont(fontStyle.Name, new XUnit(fontStyle.SizePt, XGraphicsUnit.Point), XFontStyle.Regular, _fontOptions);
Where fontStyle.Name
is the name of the font without the # on the front. At this point PdfSharp breaks inside the private void Initialise()
method inside the PdfSharp.Drawing namespace.
Inspecting the variables inside the Initialise
method at this point it has:
- Found the font family, i.e.
this.family != null
- Found the typeface, i.e.
this.typeface != null
I am assuming it break on the line if (!typeface2.TryGetGlyphTypeface(out typeface))
but I can't be sure.
Note: I have tried both a .ttf and a .otf font to no avail.
Could someone point me in the right direction please?
Update
In the end I swapped to PDFSharp WPF 1.50 beta as its font handling is MUCH better. See this SO post on my second issues and information on the new font resolver which solved my problem. Everything is working well now.
Ok, the answer to this is fairly complex, but in case it helps someone else then here is the answer.
If you want to use private fonts, i.e. fonts not already installed on you system, with PDFSharp then you need to do the following.
At this point in time, March 2015, the only released NuGet library that works with private fonts is the PDFsharp + MigraDoc (WPF) 1.32.2608 release. There are plenty of beta releases for 1.50 but this answer is about 1.32 version.
- You MUST use the WPF version of 1.32, not the GDI+ version.
- I found the code in the PDFSharp page called 'Private Fonts' misleading. According to ThomasH the PDFSharp team expected people to download the sample, which has a very different piece of code in its sample.
- The best example of how to write the code can be found at http://forum.pdfsharp.net/viewtopic.php?f=2&t=1880#p5395 .
Note: the author's note about loading a font twice causes an exception is correct. His method of handling this works, but it is slow. I pre-scan all my fonts and group them by name so that only add them once.
- Be VERY careful about the name of the font (see note at end). It is very easy to get the name wrong and if you do you get into all sorts of trouble. The released NuGet version has a nasty
Debugger.Break
instead of an exception and in released code it just stalls - In my Unit Tests I have to close Visual Studio to get out of it!
- Be aware that TrueType (.ttf) fonts can come in MAC or Windows format - that threw me. OpenType (.otf) fonts are fine.
NOTE: On the name of the font the best way to find it in Windows is to double click the font file. Windows then shows you the font with the name on the first line. As I say, get that wrong and you can get a stalled system.
Finally I should say thank you to @ThomasH who directed me to the PDFSharp 1.32 source code. This has the 'proper' example for private fonts and also doesn't have that nasty Debugger.Break
but the proper exception when the name of the font you asked for isn't present.
Update
In the end I swapped to PDFSharp WPF 1.50 beta as its font handling is MUCH better. See this SO post on my problem and information on the new font resolver which helped.
And for PDFsharp 1.50 you have to implement the IFontResolver
interface and assign your implementation to a global PDFsharp property.
GlobalFontSettings.FontResolver = new DemoFontResolver();
PDFsharp provides a class FontResolverBase that you can use to derive your own class. Just add code for your private fonts and pass the call to the baseclass for other fonts.
The IFontResolver interface requires two methods: ResolveTypeface
and GetFont
.
More information can be found in my blog post:
http://developer.th-soft.com/developer/?p=11
A complete solution is provided there as a ZIP file.
Re "line 22": The PDFsharp forum just shows a snippet from the sample.
For PDFsharp 1.3x: You can download the complete sample code from CodePlex or SourceForge with the full working sample (project, solution, sample TTF files all included).
See also:
https://stackoverflow.com/a/21545488/1015447
Complete source code for version 1.32:
http://pdfsharp.codeplex.com/releases