簡體   English   中英

設置值后的 PDFBox 不一致的 PDTextField 自動調整大小行為

[英]PDFBox Inconsistent PDTextField Autosize Behavior after setValue

我正在使用 Apache PDFBox 在 PDF 文檔上配置PDTextField ,我使用以下方法將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

然后我將 font_name 傳遞到PDTextFielddefault_appearance_string中, PDTextField所示:

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

現在,當我繼續在PDTextField上調用setValue時會出現問題。 因為我將defaultAppearanceStringfont_size設置為0 ,根據庫的示例,文本應該自行縮放以適應文本框的給定區域。 但是,這種“按比例縮放”的行為對於某些字段是不一致的:它並不總是選擇適合PDTextField的最大字體大小。 是否有任何進一步的配置可能允許這種情況發生? 以下是我注意到發生此問題的 PDF。

未填充,已加載字體: http : //www.filedropper.com/0postfontload

填充,文本框文本大小不一致: http : //www.filedropper.com/file_327

邊注:我使用PDFBox的通過jruby這僅僅是一個集成層,使紅寶石調用Java庫。 庫的所有java方法可用; thisExampleMethod這樣的 java 方法將一對一轉換為 ruby this_example_method


更新

針對評論,第二個上傳文件示例中出現錯誤的表象是:

  • 第一頁居民姓名字段(兩個文本字段的文本對於給定的輸入字段大小來說太小)
  • 第二頁電話字段(四個文本字段的文本超出給定的輸入字段大小)

尤其是“居民姓名”字段、“電話”字段和“護理提供者地址”字段的出現顯得格外醒目。 OP只提到了前兩個。

讓我們檢查這些字段; 所有屏幕截圖都是在 MS Windows 上使用 Adob​​e Reader DC 制作的:

居民姓名字段

填寫的居民姓名字段如下所示

截屏

雖然高度合適,但字形比應有的要窄。 其實這個效果已經可以在原始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。

就像上面的居民姓名字段的情況一樣,在設置新值之前需要刪除舊的外觀,以使 PDFBox 創建正確的外觀。

並發症

實際上在填寫護理提供者地址字段時還有一個問題,在刪除舊外觀后,它們看起來像這樣:

截屏

這是由於 PDFBox 的一個缺點:這些字段被配置為多行文本字段。 雖然用於單行文本字段的 PDFBox 會根據內容正確計算字體大小,然后精細地確保文本垂直適合,但對於多行字段,它的處理非常粗糙,它選擇了 12 的硬編碼字體大小,並且不會微調垂直位置,參見AppearanceGeneratorHelper方法calculateFontSize(PDFont, PDRectangle)insertGeneratedAppearance(PDAnnotationWidget, PDAppearanceStream, OutputStream)

由於在您的表單中,這些地址字段無論如何都只有一行高,一個明顯的解決方案是使這些字段成為單行字段,即清除多行標志。

示例代碼

使用 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

示例代碼輸出的屏幕截圖

居民姓名字段值現在不再垂直壓縮:

截屏

電話和護理提供者地址字段現在看起來也很合適:

截屏

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM