मैं पीडीएफ बॉक्स के साथ एक पीडीएफ फॉर्म भरता हूं जिसे मैं इसे सहेजने से पहले समतल करता हूं। प्रपत्र में टेक्स्ट और प्रपत्र फ़ील्ड के लिए एक कस्टम फ़ॉन्ट है। जब मैं किसी ऐसे डिवाइस पर आउटपुट दस्तावेज़ (चपटा फ़ील्ड के साथ) खोलता हूं जिसमें यह कस्टम फ़ॉन्ट स्थापित नहीं है, तो सामान्य टेक्स्ट का फ़ॉन्ट अभी भी सही है, लेकिन फ़्लैट किए गए फ़ील्ड का फ़ॉन्ट फ़ॉलबैक (?) फ़ॉन्ट के साथ प्रदर्शित होता है। एक डिवाइस पर जिसने इस कस्टम फ़ॉन्ट को स्थापित किया है, सब कुछ अपेक्षित दिखता है।
क्या प्रपत्र को समतल करने के बाद सभी पाठों के लिए समान कस्टम फ़ॉन्ट का उपयोग करने के लिए बाध्य करने का कोई तरीका है?
पीडीएफ बॉक्स के साथ पीडीएफ फॉर्म भरने के लिए इस्तेमाल किया गया कोड (सरलीकृत):
public class App
{
public static void main(String[] args) throws IOException {
String formTemplate = "src/main/resources/fonts.pdf";
String filledForm = "src/main/resources/fonts_out.pdf";
PDDocument pdfDocument = PDDocument.load(new File(formTemplate));
PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();
acroForm.getField("text").setValue("Same font in form text field (updated with PDFBox)");
acroForm.setNeedAppearances(true);
acroForm.refreshAppearances();
acroForm.flatten();
pdfDocument.save(filledForm);
pdfDocument.close();
}
}
अपेक्षित होना:
परिणाम जब सिस्टम पर फ़ॉन्ट स्थापित नहीं होता है:
2 जवाब
आपके पीडीएफ के लिए कुछ अवलोकन (उपर्युक्त एन्कोडिंग समस्याएं कोई नहीं हैं - मेरी ओर से केवल सादा अज्ञानता):
SansDroid फ़ॉन्ट PDF में एम्बेड नहीं किया गया है। यह
F2
फ़ॉन्ट को नए एम्बेडेडF5
फ़ॉन्ट के साथ बदलकर तय किया गया है।NeedAppearances
ध्वज सेट है जिसका अर्थ है कि प्रपत्र फ़ील्ड के लिए कोई उपस्थिति नहीं है। किसी भी पाठक को उन्हें (पुनः) बनाना होगा। यह चपटे करने से पहले PDFBox द्वारा स्वचालित रूप से नहीं किया जाता है इसलिए मैंने इस भाग को जोड़ालापता फोंट के बारे में और कोई चेतावनी न देने के लिए मैंने F2 फ़ॉन्ट को पूरी तरह से हटा दिया।
मैं प्रीफ्लाइट के माध्यम से मूल पीडीएफ चलाता हूं और इसने मुझे निम्नलिखित चेतावनी दी: "आवश्यक कुंजी / उपप्रकार गायब है। पथ: -> पृष्ठ-> बच्चे-> [0] -> एनोटेशन-> [0] -> AP->N " कुंजी मौजूद है लेकिन ऐसा लगता है कि प्रपत्र फ़ील्ड की उपस्थिति में कोई त्रुटि है। अगर मैं /N dict हटा देता हूं तो त्रुटि समाप्त हो जाती है। स्ट्रीम "/Tx BMC EMC" है - शायद कुछ EOL गुम है? लेकिन चूंकि उपस्थिति फिर से उत्पन्न होती है, वैसे भी त्रुटि बाद में चली जाती है।
निम्नलिखित कोड के साथ DroidSans फ़ॉन्ट पीडीएफ में एम्बेड किया गया है:
File pdf = new File("Fonts.pdf");
final PDDocument document = PDDocument.load(pdf);
FileInputStream fontFile = new FileInputStream(new File("DroidSans.ttf"));
PDFont font = PDType0Font.load(document, fontFile, false);
//1. embedd and register the font (Catalog dict)
PDAcroForm pDAcroForm = document.getDocumentCatalog().getAcroForm();
//create a new font resource
PDResources res = pDAcroForm.getDefaultResources();
if (res == null) res = new PDResources();
COSName fontName = res.add(font);
pDAcroForm.setDefaultResources(res);
//2. Now change the font of form field to the newly added font
PDField field = pDAcroForm.getField("text");
//field.setValue("Same font in form text field (updated with PDFBox)");
COSDictionary dict = field.getCOSObject();
COSString defaultAppearance = (COSString) dict.getDictionaryObject(COSName.DA);
if (defaultAppearance != null){
String currentValue = dict.getString(COSName.DA);
//replace the font - this should be improved with a more general version
dict.setString(COSName.DA,currentValue.replace("F2", fontName.getName()));
//remove F2 completely
COSDictionary resources = res.getCOSObject();
for(Entry<COSName, COSBase> resource : resources.entrySet()) {
if(resource.getKey().equals(COSName.FONT)) {
COSObject fonts = (COSObject)resource.getValue();
COSDictionary fontDict = (COSDictionary)fonts.getObject();
COSName toBeRemoved=null;
for(Entry<COSName, COSBase> item : fontDict.entrySet()) {
if(item.getKey().getName().equals("F2")) {
toBeRemoved = item.getKey();
}
}
if(toBeRemoved!=null) {
fontDict.removeItem(toBeRemoved);
}
}
}
if(pDAcroForm.getNeedAppearances()) {
pDAcroForm.refreshAppearances();
pDAcroForm.setNeedAppearances(false);
}
//Flatten the document
pDAcroForm.flatten();
//Save the document
document.save("Form-Test-Result.pdf");
document.close();
कृपया ध्यान दें कि उपरोक्त कोड काफी स्थिर है - F2
नामक फ़ॉन्ट को खोजना और बदलना केवल आपूर्ति किए गए PDF के लिए काम करता है अन्य मामलों में यह नहीं होगा। इसके लिए आपको अधिक सामान्य समाधान लागू करना होगा...
PDFont font = PDType0Font.load(document, fontFile, false);
मैं बात करता हूं कि अंतिम तर्क ('झूठा') सभी वर्णों को एक फ़ॉन्ट में एम्बेड करता है। जापानी फोंट जैसे बड़े फ़ॉन्ट का उपयोग करते समय भारी आकार का पीडीएफ बनाएं। तो, मैंने निम्नलिखित कोड की कोशिश की और यह मेरे लिए काम किया।
(* स्काला, पीडीएफबॉक्स 2.0.20)
// val font = PDType0Font.load(document, fontFile, true);
// form.flatten()
// hack for embed minimul font?
val page = new PDPage(PDRectangle.A6) // any page size.
val stream = new PDPageContentStream(document, page)
stream.beginText()
stream.setFont(font, 0)
stream.showText(allChars) // `allChars` are inputed all characters in forms in the creating pdf.
stream.endText()
stream.close()
// NOTE: I did NOT add the page to the PDF but worked.
// Save the document ~
संबंधित सवाल
नए सवाल
java
जावा एक उच्च स्तरीय प्रोग्रामिंग भाषा है। इस टैग का उपयोग तब करें जब आपको भाषा का उपयोग करने या समझने में समस्या हो। इस टैग का उपयोग शायद ही कभी किया जाता है और इसका उपयोग अक्सर [वसंत], [वसंत-बूट], [जकार्ता-ई], [Android], [javafx], [हडूप], [श्रेणी] और [मावेन] के साथ किया जाता है।