How to use private fonts in PDFSharp
Asked Answered
S

3

6

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:

  1. Found the font family, i.e. this.family != null
  2. 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.

Scarab answered 11/3, 2015 at 20:17 Comment(0)
S
7

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.

  1. You MUST use the WPF version of 1.32, not the GDI+ version.
  2. 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.
  3. 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.
  4. 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!
  5. 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.

Scarab answered 12/3, 2015 at 18:13 Comment(4)
Re 1: As of now the Private Fonts sample in the Wiki was not yet updated for PDFsharp 1.50 and shows how to do it with PDFsharp 1.3x.Casa
Hi ThomasH, that is odd. The code inside the 1.32 code you pointed to isn't anything like the code on the PDFSharp private fonts link. Can you explain and then I will update my answer.Scarab
The Wiki contains a snippet and explains what is not obvious. It was written long ago when the PDFsharp team recommended downloading the source package and referencing the projects from the source (in the days of VS 2005/2008 before NuGet). It's confusing for those who get the NuGet package and look at the snippet. The sample will eventually be updated for PDFsharp 1.50 and then it will be written for the NuGet generation.Casa
Hi ThomasH. OK, I have updated my answer. Let me know if that makes more sense. I have to say the private font example doesn't bear any resemblance at all to the sample code in the actual code. It had me chasing all over the place.Scarab
C
5

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.

Casa answered 15/3, 2015 at 9:38 Comment(1)
Hi @ThomasH. Thanks for the very useful blog post. I am looking at swapping over to 1.50 Beta WPF version, which is working OK. One question: is the source available to inspect anywhere, or any release notes?Scarab
C
2

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://mcmap.net/q/1769840/-pdfsharp-add-private-installed-font

Complete source code for version 1.32:
http://pdfsharp.codeplex.com/releases

Casa answered 12/3, 2015 at 6:52 Comment(1)
Thanks ThomasH. Your prompt made me look at the source code and I found the answers I was looking for - see below.Scarab

© 2022 - 2024 — McMap. All rights reserved.