PdfBox встраивает шрифты в существующий документ

У меня есть файл PDF, который показывает свойства шрифта в Okular (или любом другом средстве просмотра PDF), например:

Name: Helvetica 
Type: Type1
File: /usr/share/fonts/truetype/liberation2/LiberationSans-regular.ttf
Embedded: No

Я хочу встроить Helvetica в PDFBox 2xx без изменения самого содержимого файла (текста), чтобы он всегда был доступен с файлом. Это вообще возможно? Я пробовал что-то вроде:

PDDocument document = PDDocument.load(myFile);

InputStream stream = new FileInputStream(new File("/home/user/fonts_temp/Helvetica.ttf"));
PDFont fontToEmbed = PDType0Font.load(document, stream, true);              
PDResources resources = document.getPage(pageNumber).getResources();
resources.add(fontToEmbed);
//or use the font from pdfbox:
resources.add(PDType1Font.HELVETICA);

document.save(somewhere);
document.close();

Я также пытался позвонить

COSName fontCosName = resources.add(PDType1Font.HELVETICA);
resources.put(fontCosName, font);

Что я делаю не так?

Редактировать:

@TilmanHausherr спасибо за подсказку! Но мне все еще чего-то не хватает. В настоящее время мой код выглядит так:

PDFont helvetica = PDType0Font.load(document, new FileInputStream(new File("/path/Helvetica.ttf")), false);
...
PDResources resources = page.getResources();
for (COSName fontCosName : resources.getFontNames()){
    if(resources.getFont(fontCosName).getName().equals("Helvetica")) {
        resources.put(fontCosName, helvetica);
    }
}

Конечный результат показывает Helvetica CID TrueType Fully Embedded Но теперь шрифт вообще не отображается в файле PDF. Я имею в виду те места, где используется шрифт, это буквально пустая, пустая страница... Все равно чего-то там нет. Сам шрифт был загружен с здесь


person jeffest    schedule 09.11.2020    source источник
comment
Вам нужно знать имя, которое в настоящее время используется в ресурсах, поэтому проверьте их с помощью resources.getFontNames(). Также не делайте подмножества, поэтому последний параметр должен быть ложным.   -  person Tilman Hausherr    schedule 09.11.2020
comment
@TilmanHausherr большое спасибо. Но я обновил пост со следующей проблемой - шрифт вообще не отображается в документе.   -  person jeffest    schedule 10.11.2020
comment
Пожалуйста, поделитесь PDF до и после   -  person Tilman Hausherr    schedule 10.11.2020
comment
Понятно... проблема с кодами, начинающимися с 0... попробуйте использовать PDTrueTypeFont вместо PDType0Font. PDTrueTypeFont.load(document, file, WinAnsiEncoding.INSTANCE);   -  person Tilman Hausherr    schedule 10.11.2020
comment
Оно работает! Но в чем была проблема? Почему PDType0Font не подошел? Если я сейчас вызываю resources.getFont(<"F1" means Helvetica which is used in an original file>).getSubType(), он возвращает Type0. Как тогда понять, как правильно загружать шрифты?   -  person jeffest    schedule 10.11.2020
comment
System.out.println(doc.getPage(0).getResources().getFont(COSName.getPDFName("F1")).getSubType()); дает мне Type1. С новым файлом он получает тип 0. Проблема в том, что этот шрифт начинает числа с 1, в то время как старый класс truetype начинает их с 32, что также делал стандартный шрифт 14. Можно шрифт посмотреть с помощью PDFDebugger, тогда будет понятнее.   -  person Tilman Hausherr    schedule 10.11.2020
comment
@TilmanHausherr Спасибо. Теперь это более ясно. Но как в коде отличить, что в документе этот шрифт TrueType, а тот Type1? Моя конечная цель — встроить шрифты с определенной логикой, где мне нужно знать тип шрифта. Поскольку в настоящее время getSubType() является Type1, и это очень запутанно, как вы видите, я не смог правильно встроить Helvetica.   -  person jeffest    schedule 11.11.2020
comment
Это сложно... на этот раз получилось хорошо. Возможно, для других файлов это не сработает. Если перед вами стоит задача конвертировать файлы в PDF/A, то я бы посоветовал купить коммерческий продукт. Решение, скорее всего, будет работать только для невстраиваемых систем типа 1. как различать в коде ну у вас получилось, т.е. getSubType, или сам класс.   -  person Tilman Hausherr    schedule 11.11.2020
comment
@TilmanHausherr Я немного запутался. :) Исходный файл показал Type1. В то время как процесс загрузки выполняется через PDTrueTypeFond.load(), а не через PDType0Font.load(). Но getSubType() вернул Type1, а не TrueType - не противоречит ли здесь логика? Моя задача — просто встроить шрифты и отправить документы в полиграфию. Я не думаю, что PDF/A — это то, что мне нужно.   -  person jeffest    schedule 11.11.2020
comment
Я пробовал. У меня получается Type1, а после замены TrueType. System.out.println(doc.getPage(0).getResources().getFont(COSName.getPDFName("F1")).getSubType());   -  person Tilman Hausherr    schedule 11.11.2020
comment
@TilmanHausherr, но разве это не должно быть TrueType перед заменой? Потому что Helvetica — это шрифт TTF? Или мне все еще не хватает логики здесь?   -  person jeffest    schedule 12.11.2020
comment
Helvetica доступна как для type1, так и для truetype. Это относится ко многим шрифтам. В стандарте PDF 14 шрифтов (Times-Roman, Helvetica, Courier, Symbol, Times-Bold, Helvetica-Bold, Courier-Bold, ZapfDingbats, Times-Italic, Helvetica-Oblique, Courier-Oblique, Times-BoldItalic, Helvetica-BoldOblique, Courier-BoldOblique) все type1, но эти же шрифты доступны как TrueType на многих компьютерах (и в PDF, но тогда они не стандартные 14 а просто какой-то шрифт)   -  person Tilman Hausherr    schedule 12.11.2020


Ответы (1)


Вам нужно знать имя, которое в настоящее время используется в ресурсах, поэтому проверьте его с помощью resources.getFontNames()

2. Чтобы заменить стандартный шрифт 14, используйте этот объект шрифта:

PDTrueTypeFont.load(document, file, oldFont.getEncoding() /* or WinAnsiEncoding.INSTANCE which is usually right */ );

это гарантирует, что используется та же кодировка, что и для стандартного шрифта 14. (Это отличается для Zapf Dingbats и шрифта Symbol)

person Tilman Hausherr    schedule 10.11.2020
comment
это гарантирует, что используется та же кодировка, что и для стандартного шрифта 14 - Ну... нет. Он не гарантирует, он просто делает очень вероятным. Стандартные 14 шрифтов можно использовать и с другими кодировками, даже с пользовательскими; просто мало кто так делает. По сути, вам нужно сохранить исходную кодировку, чтобы обеспечить ту же кодировку. - person mkl; 10.11.2020
comment
Я отметил этот ответ как действительный, но на самом деле в комментариях после вопроса есть отличная дискуссия. - person jeffest; 12.11.2020