मैं पीडीएफ बॉक्स के साथ एक पीडीएफ फॉर्म भरता हूं जिसे मैं इसे सहेजने से पहले समतल करता हूं। प्रपत्र में टेक्स्ट और प्रपत्र फ़ील्ड के लिए एक कस्टम फ़ॉन्ट है। जब मैं किसी ऐसे डिवाइस पर आउटपुट दस्तावेज़ (चपटा फ़ील्ड के साथ) खोलता हूं जिसमें यह कस्टम फ़ॉन्ट स्थापित नहीं है, तो सामान्य टेक्स्ट का फ़ॉन्ट अभी भी सही है, लेकिन फ़्लैट किए गए फ़ील्ड का फ़ॉन्ट फ़ॉलबैक (?) फ़ॉन्ट के साथ प्रदर्शित होता है। एक डिवाइस पर जिसने इस कस्टम फ़ॉन्ट को स्थापित किया है, सब कुछ अपेक्षित दिखता है।

क्या प्रपत्र को समतल करने के बाद सभी पाठों के लिए समान कस्टम फ़ॉन्ट का उपयोग करने के लिए बाध्य करने का कोई तरीका है?

पीडीएफ बॉक्स के साथ पीडीएफ फॉर्म भरने के लिए इस्तेमाल किया गया कोड (सरलीकृत):

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();
    }
}

पीडीएफ: इनपुट आउटपुट

अपेक्षित होना:

Expected

परिणाम जब सिस्टम पर फ़ॉन्ट स्थापित नहीं होता है:

Result when font is not installed on system

1
uwolfer 29 पद 2018, 12:29

2 जवाब

सबसे बढ़िया उत्तर

आपके पीडीएफ के लिए कुछ अवलोकन (उपर्युक्त एन्कोडिंग समस्याएं कोई नहीं हैं - मेरी ओर से केवल सादा अज्ञानता):

  1. SansDroid फ़ॉन्ट PDF में एम्बेड नहीं किया गया है। यह F2 फ़ॉन्ट को नए एम्बेडेड F5 फ़ॉन्ट के साथ बदलकर तय किया गया है।

  2. NeedAppearances ध्वज सेट है जिसका अर्थ है कि प्रपत्र फ़ील्ड के लिए कोई उपस्थिति नहीं है। किसी भी पाठक को उन्हें (पुनः) बनाना होगा। यह चपटे करने से पहले PDFBox द्वारा स्वचालित रूप से नहीं किया जाता है इसलिए मैंने इस भाग को जोड़ा

  3. लापता फोंट के बारे में और कोई चेतावनी न देने के लिए मैंने F2 फ़ॉन्ट को पूरी तरह से हटा दिया।

  4. मैं प्रीफ्लाइट के माध्यम से मूल पीडीएफ चलाता हूं और इसने मुझे निम्नलिखित चेतावनी दी: "आवश्यक कुंजी / उपप्रकार गायब है। पथ: -> पृष्ठ-> बच्चे-> [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 के लिए काम करता है अन्य मामलों में यह नहीं होगा। इसके लिए आपको अधिक सामान्य समाधान लागू करना होगा...

4
Lonzak 4 जिंदा 2019, 12:49

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 ~
0
Sean Daru 12 अगस्त 2020, 12:05