2015-11-10 3 views
4

Я использую PDFBox 2.0.0-SNAPSHOT для создания PDF-файла на Java. Он отлично работает для очень простых символов (например, [a-zA-Z9-0]), но я получаю ошибки кодирования для более продвинутых символов, таких как (quoteright). Вот мой код:PDFBox «специальные» символы в Helvetica

PDDocument pdf = new PDDocument(); 
PDPage page = new PDPage(PDRectangle.A4); 
pdf.addPage(page); 

PDPageContentStream contents = new PDPageContentStream(pdf, page); 
PDFont font = PDType1Font.HELVETICA; 
contents.beginText(); 
contents.setFont(font, 12); 

// ... 

String text = "’"; 
contents.showText(text); 

contents.endText(); 
contents.close(); 

Я получаю это исключение:

не может кодировать U + 2019 в шрифт Helvetica. Type 1 шрифты поддерживают только 8-битные код точки

Я посмотрел поддерживаемые символы для не внедренных шрифтов в разделе D.1 из PDF specification, и этого символ должен быть поддержан.

В самом деле, если я использую this trick, я могу вставить нужный символ:

// ... 

// String text = "’"; 
// contents.showText(text); 
byte[] commands = "(x) Tj ".getBytes(); 
commands[1] = (byte)145; // = 221 octal = quoteright in WinAnsi 
contents.appendRawCommands(commands); 

// ... 

Но это на самом деле не является практичным решением. Помимо неудобства ручного поиска каждого символа, который может быть в строке, метод appendRawCommands теперь устарел.

Итак, что здесь происходит? От the answer from above подразумевается, что у showText не должно быть проблем со старым методом drawString, но что-то явно не работает.

EDIT: Как было предложено в комментариях, вот полный стек след за исключением:

Exception in thread "main" java.lang.IllegalArgumentException: Can't encode U+2019 in font Helvetica. Type 1 fonts only support 8-bit code points 
    at org.apache.pdfbox.pdmodel.font.PDType1Font.encode(PDType1Font.java:343) 
    at org.apache.pdfbox.pdmodel.font.PDFont.encode(PDFont.java:285) 
    at org.apache.pdfbox.pdmodel.font.PDFont.getStringWidth(PDFont.java:314) 
    at com.fatfractal.test.PDFBoxTest.textWidth(PDFBoxTest.java:148) 
    at com.fatfractal.test.PDFBoxTest.showFlowingTextAt(PDFBoxTest.java:128) 
    at com.fatfractal.test.PDFBoxTest.build(PDFBoxTest.java:73) 
    at com.fatfractal.test.PDFBoxTest.main(PDFBoxTest.java:97) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 
+0

Возможный дубликат: http://stackoverflow.com/questions/5425251/using-pdfbox-to-write-utf-8-encoded-strings-to-a-pdf –

+2

Это не дубликат, символы I ' о которых говорят в базовых шрифтах в соответствии со спецификацией. – shawkinaw

+0

Вы ссылаетесь на Adobe vs pdfbox, что вы ожидаете от ссылки на источник, например, https: //pdfbox.apache.org/2.0/... Вы знаете, что Adobe не делает PDFBox? Apache поддерживает pdfbox, почему вы ссылаетесь на то, что adobe может делать VS, что может делать pdfbox (когда эти два совершенно разные вещи)? –

ответ

5

Глядя на код PDFBox, это действительно похоже на ошибку. Если вы посмотрите на метод PDType1Font.encode(), он автоматически выдает, если точка кода> 0xFF. Однако, если бы логика в этом случае продолжалась, GlyphList преобразует символ «\ u2019» в «quoteright», который тогда будет правильным символом шрифта.

+0

[Подано сообщение] (https://issues.apache.org/jira/browse/PDFBOX-3184). – maaartinus

4

Как пояснил @jtahlborn в своем ответе, PDType1Font.encode() не работает в текущем релизе версии 2.0.0.

В отличие от метода 1.x.x PDPageContentStreamdrawString, тем не менее, способ выпуска версии 2.0.0 showText является кодировкой.

Таким образом, вы можете использовать составной шрифт с вложением подмножества, например. на стандартной установке MS Windows:

InputStream fontStream = new FileInputStream("c:/Windows/Fonts/ARIALUNI.TTF"); 
PDType0Font font = PDType0Font.load(pdf, fontStream); 

Используя этот шрифт ваш код не преминут для "’", поскольку составные классы шрифтов не ошибка наблюдается в PDType1Font здесь.

+0

Вы можете включить библиотеку шрифтов, которая будет иметь FontFileFinder для получения файлов шрифтов в зависимости от системы. – matt

+0

@matt Определенно хорошая идея для производственного кода. Кроме того, вы можете добавить свои собственные шрифты, например. как ресурсы, если вы не хотите зависеть от шрифтов, найденных на компьютере развертывания. – mkl

+2

Я просто посмотрел на 'FontFileFinder'; в случае компьютеров Windows он использует «RunTime.exec()». В зависимости от среды, в которой будет использоваться PDFBox, использование 'RunTime.exec()' может быть ограничено с помощью «SecurityManager». Поэтому, если вы планируете развертываться в защищенной среде, вы обязательно должны принести свои собственные шрифты. – mkl

Смежные вопросы