PDFBox Несоответствующий PDTextField Поведение Autosize после setValue - PullRequest
0 голосов
/ 08 июля 2019

Я использую Apache PDFBox для настройки PDTextField в документе PDF, где я загружаю Lato в документ, используя:

font = PDType0Font.load(
    @j_pd_document,
    java.io.FileInputStream.new('/path/to/Lato-Regular.ttf')
) # => Lato-Regular

font_name = pd_default_resources.add(font).get_name # => F4

Затем я передаю имя_ шрифта в default_appearance_stringдля PDTextField вот так:

j_text_field.set_default_appearance("/#{font_name} 0 Tf 0 g") # where font_name is
                                                              # passed in from above

Проблема теперь возникает, когда я продолжаю вызывать setValue на PDTextField.Поскольку я установил font_size в defaultAppearanceString на 0, в соответствии с примером библиотеки , текст должен масштабироваться так, чтобы вписаться в заданную область текстового поля.Однако поведение «масштабирования по размеру» несовместимо с определенными полями: он не всегда выбирает наибольший размер шрифта для размещения в PDTextField.Может ли быть какая-либо дальнейшая конфигурация, которая может позволить этому случиться?Ниже приведены файлы PDF, в которых я заметил, что эта проблема возникает.

Не заполнено, с загруженными шрифтами: http://www.filedropper.com/0postfontload

Заполнено, с несогласованным размером текста в текстовом поле: http://www.filedropper.com/file_327

Примечание : я использую PDFBox через jruby, который является просто интеграционным слоем, который позволяет Ruby вызывать библиотеки Java.Все Java-методы для библиотеки доступны;java-метод, такой как thisExampleMethod, будет иметь непосредственный перевод на ruby ​​this_example_method.


Обновления

В ответ на комментарииНеверные значения во втором примере загруженного файла:

  • Поле имени резидента 1-й страницы (два текстовых поля, текст которых слишком мал для данного размера поля ввода)
  • 2-я страница Телефонные поля (четыре текстовых поля, текст которых выходит за пределы заданного размера поля ввода)

1 Ответ

1 голос
/ 09 июля 2019

Особенно видны поля «Имя резидента», «Телефон» и «Адрес поставщика услуг». В ОП упоминаются только первые два.

Давайте проверим эти поля; все снимки экрана сделаны с использованием Adobe Reader DC на MS Windows:

Поля Имя резидента

Заполненные поля Resident Name выглядят следующим образом

screen shot

В то время как высота соответствует, глифы уже, чем они должны быть. На самом деле этот эффект уже можно увидеть в оригинальном PDF:

screen shot

Это горизонтальное сжатие вызвано тем, что прямоугольники виджета поля имеют соотношение сторон, отличающееся от соответственного соответствующего ограничивающего прямоугольника нормального вида:

  • Прямоугольники виджета: [ 45.72 601.44 118.924 615.24 ] и [ 119.282 601.127 192.486 614.927 ], т. Е. 73,204 * 13,8 в обоих случаях.
  • Внешний вид ограничивающей рамки: [ 0 0 147.24 13.8 ], т.е. 147,24 * 13,8.

Таким образом, они имеют одинаковую высоту, но ограничивающая рамка внешнего вида примерно в два раза шире прямоугольника виджета. Таким образом, текст, отображаемый в потоке внешнего вида, сжимается до половины его ширины, когда внешний вид отображается в прямоугольнике виджета.

При установке значения поля PDFBox, к сожалению, повторно использует поток внешнего вида как есть и обновляет только детали внешнего вида по умолчанию, то есть имя шрифта, размер шрифта и цвет, а также фактическое значение текста, очевидно, принимая другие свойства внешности, как они есть причина. Таким образом, вывод PDFBox также показывает это горизонтальное сжатие

Чтобы PDFBox создавал правильный внешний вид, необходимо удалить старые виды перед установкой нового значения.

Поля телефона

заполненные поля телефона выглядят так

screen shot

и снова есть аналогичное отображение в исходном файле

screen shot

То, что отображаются только первые две буквы, даже если для целого слова достаточно места, обусловлено конфигурацией этих полей: они настроены как поля гребня с максимальной длиной 2 символа.

Чтобы значение, установленное здесь, с PDFBox отображалось полностью, а не с интервалом, вы должны удалить максимальную длину (или, по крайней мере, сделать ее не меньше длины вашего значения) и сбросить флаг гребенки.

Поля адреса поставщиков услуг

заполнены они выглядят так:

screen shot

Изначально они похожи:

screen shot

Это вертикальное сжатие снова вызвано прямоугольниками виджета поля, имеющими другое соотношение сторон, чем у соответствующего ограничивающего прямоугольника нормального внешнего вида:

  • прямоугольник виджета: [ 278.6 642.928 458.36 657.96 ], т.е. 179,76 * 15,032.
  • Внешний вид ограничивающей рамки: [ 0 0 179.76 58.56 ], т. Е. 179,76 * 58,56.

Как и в случае с полями Resident Name, приведенными выше, необходимо удалить старые виды перед установкой нового значения, чтобы PDFBox создавал правильный внешний вид.

осложнение

На самом деле существует дополнительная проблема при заполнении полей Адрес поставщика услуг, после удаления старых появлений они выглядят так:

screen shot

Это связано с недостатком PDFBox: эти поля настроены как многострочные текстовые поля. В то время как PDFBox для однострочных текстовых полей правильно рассчитывает размер шрифта на основе содержимого, а затем точно обеспечивает точную подгонку текста по вертикали, он выполняется очень грубо для многострочных полей, он выбирает размер жестко закодированного шрифта 12 и не Точная настройка вертикального положения, см. код методов AppearanceGeneratorHelper calculateFontSize(PDFont, PDRectangle) и insertGeneratedAppearance(PDAnnotationWidget, PDAppearanceStream, OutputStream).

Так как в вашей форме эти поля адреса в любом случае имеют высоту всего в одну строку, очевидным решением будет сделать эти поля однострочными, то есть снять флажок Multiline .

Пример кода

Используя Java, можно реализовать описанные выше решения, например:

final int FLAG_MULTILINE = 1 << 12;
final int FLAG_COMB = 1 << 24;

PDDocument doc = PDDocument.load(originalStream);
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();

PDType0Font font = PDType0Font.load(doc, fontStream, false);
String font_name = acroForm.getDefaultResources().add(font).getName();

for (PDField field : acroForm.getFieldTree()) {
    if (field instanceof PDTextField) {
        PDTextField textField = (PDTextField) field;
        textField.getCOSObject().removeItem(COSName.MAX_LEN);
        textField.getCOSObject().setFlag(COSName.FF, FLAG_COMB | FLAG_MULTILINE, false);;
        textField.setDefaultAppearance(String.format("/%s 0 Tf 0 g", font_name));
        textField.getWidgets().forEach(w -> w.getAppearance().setNormalAppearance((PDAppearanceEntry)null));
        textField.setValue("Test");
    }
}

( FillInForm тест testFill0DropOldAppearanceNoCombNoMaxNoMultiLine)

Снимки экрана с выводом примера кода

Значение поля Resident Name теперь больше не сжимается по вертикали:

screen shot

Поля Адрес телефона и поставщика услуг теперь также выглядят подходящими:

screen shot

...