MigraDoc/PDFsharp выбрасывает исключения с китайским шрифтом YaHei
Недавно после перемещения нашего веб-сайта с Windows Server 2008 на Server 2016 у нас возникли проблемы с экспортом документов PDF из нашего кода C#, в котором используется библиотека MigraDoc/PDFsharp.
Проблема также может быть воспроизведена на Windows 10. Точно такой же код прекрасно работает на Windows 7 или, как упоминалось ранее, на любой серверной ОС до Server 2016.
Ранее мы получали это исключение:
Ошибка при разборе шрифта OpenType. InnerException: InvalidOperationException: у шрифта нет используемой платформы или идентификатора кодировки. Он не может быть использован с PDFsharp.
Поэтому мы попытались обновить ссылки на последнюю версию сборки, и теперь мы получаем другую ошибку:
Шрифты коллекции TrueType еще не поддерживаются PDFsharp.
Пожалуйста, не прыгайте с пистолетом и пометьте это как дубликат некоторых других проблем, где китайские иероглифы отображаются в виде квадратов или??? в экспортированном PDF. Это не проблема встраивания шрифта. Это отличается от этого. Почему-то в Windows 10 и Server 2016, если вы попытаетесь использовать шрифт Microsoft Ya Hei (微软雅黑), он просто не будет работать. Достаточно странно, что все работало нормально с тем же кодом в той же сборке версии перед миграцией на Server 2016. Вот соответствующий код без атрибутики
.
.
.
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
.
.
Document document = new Document();
document.Info.Title = "Report";
document.Styles["Normal"].Font.Name = "微软雅黑"; // Microsoft YaHei Chinese Font
Section section = document.AddSection();
document.LastSection.AddParagraph("### This font is: 微软雅黑");
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true);
renderer.Document = document;
renderer.RenderDocument();
renderer.PdfDocument.Save(@"Test.pdf");
Может ли кто-нибудь помочь мне понять общую картину: что изменилось в отношении китайских шрифтов и что именно здесь происходит?
2 ответа
Сообщение об ошибке сообщает: коллекции шрифтов (расширение.ttc) еще не поддерживаются, шрифты TrueType (расширение.ttf) поддерживаются.
Таким образом, в качестве обходного пути можно использовать файлы шрифтов из более старой версии Windows, так как они кажутся совместимыми с текущей версией PDFsharp.
Могут возникнуть проблемы при установке шрифтов из более старых версий Windows в папке "Шрифты" Windows.IFontResolver
Интерфейс WPF сборки PDFsharp/MigraDoc позволяет использовать шрифты, которые не установлены на компьютере. Может быть, попробуйте EZFontResolver для простоты: forum.pdfsharp.net/viewtopic.php?f=8&t=3244
Добавление поддержки для коллекций шрифтов, кажется, не очень сложно, но кто-то должен реализовать это. Текущая версия 1.50.4845-RC2a пока не поддерживает их.
Основной причиной является изменение шрифта на формат ttcf. В windows есть 2 типа шрифта: TrueType, расширение .ttf. и TrueType Collection, расширение ttc. вы можете перейти в папку \Windows\Fonts и указать файл шрифта, чтобы подтвердить его. файл шрифта должен быть msyh.ttc.
PdfSharp использует Windows API GetFontData для получения данных шрифта.
// Get size of the font file.
bool isTtcf = false;
int size = NativeMethods.GetFontData(hdc, 0, 0, null, 0);
if (size == NativeMethods.GDI_ERROR)
{
// Assume that the font file is a true type collection.
size = NativeMethods.GetFontData(hdc, ttcf, 0, null, 0);
isTtcf = true;
}
byte[] bytes = new byte[size];
int effectiveSize = NativeMethods.GetFontData(hdc, isTtcf ? ttcf : 0, 0, bytes, size);
См.: https://github.com/empira/PDFsharp/blob/master/src/PdfSharp/Drawing/XFontSource.cs#L147 .
Но Windows API не работает должным образом. если шрифт ttcf, Windows API не возвращает GDI_ERROR, он возвращает недопустимые данные истинного типа с неправильным смещением.
GetFontData Windows API не уверен, являются ли возвращенные данные полными данными для файла TrueType или частью коллекции шрифтов TrueType. Это хуже. См.: https://www.google.com/books/edition/Windows_Graphics_Programming/-O92IIF1Bj4C?hl=en&gbpv=1&dq=how+to+identify+windows+font+is+ttcf&pg=PA883&printsec=frontcover .
Это основная причина.