I discovered an issue with how font names are being constructed inside PdfSharp which affects the library from picking the appropriate font face. Also, when you examine the fonts embedded inside a PDF file (created from PdfSharp lib), Adobe does not recognize the font names correctly under the document properties or if you try to modify the document using Acrobat. I have a working solution below that addresses these font issues.
Code:
//File: PDFsharp/PdfSharp.Pdf.Advanced/PdfTrueTypeFont.cs
//Class: PdfSharp.Pdf.Advanced.PdfTrueTypeFont
//OLD CODE:
public PdfType0Font(PdfDocument document, XFont font, bool vertical)
: base(document)
{
Elements.SetName(Keys.Type, "/Font");
Elements.SetName(Keys.Subtype, "/Type0");
Elements.SetName(Keys.Encoding, vertical ? "/Identity-V" : "/Identity-H");
OpenTypeDescriptor ttDescriptor = (OpenTypeDescriptor)FontDescriptorStock.Global.CreateDescriptor(font);
this.fontDescriptor = new PdfFontDescriptor(document, ttDescriptor);
this.fontOptions = font.PdfOptions;
Debug.Assert(this.fontOptions != null);
this.cmapInfo = new CMapInfo(ttDescriptor);
this.descendantFont = new PdfCIDFont(document, this.fontDescriptor, font);
this.descendantFont.CMapInfo = this.cmapInfo;
// Create ToUnicode map
this.toUnicode = new PdfToUnicodeMap(document, this.cmapInfo);
document.Internals.AddObject(toUnicode);
Elements.Add(Keys.ToUnicode, toUnicode);
//if (this.fontOptions.BaseFont != "")
//{
// BaseFont = this.fontOptions.BaseFont;
//}
//else
{
BaseFont = font.Name.Replace(" ", "");
switch (font.Style & (XFontStyle.Bold | XFontStyle.Italic))
{
case XFontStyle.Bold:
this.BaseFont += ",Bold";
break;
case XFontStyle.Italic:
this.BaseFont += ",Italic";
break;
case XFontStyle.Bold | XFontStyle.Italic:
this.BaseFont += ",BoldItalic";
break;
}
}
// CID fonts are always embedded
BaseFont = PdfFont.CreateEmbeddedFontSubsetName(BaseFont);
this.fontDescriptor.FontName = BaseFont;
this.descendantFont.BaseFont = BaseFont;
PdfArray descendantFonts = new PdfArray(document);
Owner.irefTable.Add(descendantFont);
descendantFonts.Elements.Add(descendantFont.Reference);
Elements[Keys.DescendantFonts] = descendantFonts;
}
Code:
//NEW CODE:
public PdfTrueTypeFont(PdfDocument document, XFont font)
: base(document)
{
Elements.SetName(Keys.Type, "/Font");
Elements.SetName(Keys.Subtype, "/TrueType");
// TrueType with WinAnsiEncoding only
OpenTypeDescriptor ttDescriptor = (OpenTypeDescriptor)FontDescriptorStock.Global.CreateDescriptor(font);
this.fontDescriptor = new PdfFontDescriptor(document, ttDescriptor);
this.fontOptions = font.PdfOptions;
Debug.Assert(this.fontOptions != null);
this.cmapInfo = new CMapInfo(ttDescriptor);
if (ttDescriptor.fontData.name != null && !string.IsNullOrEmpty(ttDescriptor.fontData.name.Name))
{
BaseFont = ttDescriptor.fontData.name.Name.Replace(" ", "");
}
else
{
BaseFont = font.Name.Replace(" ", "");
switch (font.Style & (XFontStyle.Bold | XFontStyle.Italic))
{
case XFontStyle.Bold:
BaseFont += ",Bold";
break;
case XFontStyle.Italic:
BaseFont += ",Italic";
break;
case XFontStyle.Bold | XFontStyle.Italic:
BaseFont += ",BoldItalic";
break;
}
}
// CID fonts are always embedded
BaseFont = PdfFont.CreateEmbeddedFontSubsetName(BaseFont);
this.fontDescriptor.FontName = BaseFont;
this.descendantFont.BaseFont = BaseFont;
PdfArray descendantFonts = new PdfArray(document);
Owner.irefTable.Add(descendantFont);
descendantFonts.Elements.Add(descendantFont.Reference);
Elements[Keys.DescendantFonts] = descendantFonts;
}
Similar code change is required for the following class.
File: PDFsharp/PdfSharp.Pdf.Advanced/PdfType0Font.cs
Class: PdfSharp.Pdf.Advanced.PdfType0Font
Actual code is not shown here.
Code:
//File: PDFSharp/PdfSharp.Fonts.OpenType/OpenTypeDescriptor.cs
//Class: PdfSharp.Fonts.OpenType.OpenTypeDescriptor
//OLD CODE:
public OpenTypeDescriptor(XFont font, XPdfFontOptions options)
{
try
{
this.fontData = new FontData(font, options);
this.fontName = font.Name;
Initialize();
}
catch
{
throw;
}
}
//NEW CODE:
public OpenTypeDescriptor(XFont font, XPdfFontOptions options)
{
try
{
this.fontData = new FontData(font, options);
if (this.fontData.name != null && !string.IsNullOrEmpty(this.fontData.name.Name))
{
this.fontName = this.fontData.name.Name;
}
else
{
this.fontName = font.Name;
}
this.fontStretch = font.Stretch;
Initialize();
}
catch
{
throw;
}
}
The FontSeclector class should include XFontStretch property as a member variable. Also need an accessor method.
Code:
//File: PDFSharp/PdfSharp.Fonts/FontDescriptorStock.cs
//Class: PdfSharp.Fonts.FontSelector
//OLD CODE:
public FontSelector(XFontFamily family, XFontStyle style)
{
this.name = family.Name;
this.style = style;
this.fontType = FontType.Type0;
}
public override int GetHashCode()
{
return this.name.GetHashCode() ^ this.style.GetHashCode();
}
//NEW CODE:
public FontSelector(XFontFamily family, XFontStyle style, XFontStretch stretch)
{
this.name = family.Name;
this.style = style;
this.fontType = FontType.Type0;
this.stretch = stretch;
}
public override int GetHashCode()
{
return this.name.GetHashCode() ^ this.style.GetHashCode() ^ this.stretch.GetHashCode();
}