Особенно видны поля «Имя резидента», «Телефон» и «Адрес поставщика услуг». В ОП упоминаются только первые два.
Давайте проверим эти поля; все снимки экрана сделаны с использованием Adobe Reader DC на MS Windows:
Поля Имя резидента
Заполненные поля Resident Name выглядят следующим образом
В то время как высота соответствует, глифы уже, чем они должны быть. На самом деле этот эффект уже можно увидеть в оригинальном PDF:
Это горизонтальное сжатие вызвано тем, что прямоугольники виджета поля имеют соотношение сторон, отличающееся от соответственного соответствующего ограничивающего прямоугольника нормального вида:
- Прямоугольники виджета:
[ 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 создавал правильный внешний вид, необходимо удалить старые виды перед установкой нового значения.
Поля телефона
заполненные поля телефона выглядят так
и снова есть аналогичное отображение в исходном файле
То, что отображаются только первые две буквы, даже если для целого слова достаточно места, обусловлено конфигурацией этих полей: они настроены как поля гребня с максимальной длиной 2 символа.
Чтобы значение, установленное здесь, с PDFBox отображалось полностью, а не с интервалом, вы должны удалить максимальную длину (или, по крайней мере, сделать ее не меньше длины вашего значения) и сбросить флаг гребенки.
Поля адреса поставщиков услуг
заполнены они выглядят так:
Изначально они похожи:
Это вертикальное сжатие снова вызвано прямоугольниками виджета поля, имеющими другое соотношение сторон, чем у соответствующего ограничивающего прямоугольника нормального внешнего вида:
- прямоугольник виджета:
[ 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 создавал правильный внешний вид.
осложнение
На самом деле существует дополнительная проблема при заполнении полей Адрес поставщика услуг, после удаления старых появлений они выглядят так:
Это связано с недостатком 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 теперь больше не сжимается по вертикали:
Поля Адрес телефона и поставщика услуг теперь также выглядят подходящими: