itextarabicpdfstamperacrofields

Wrapping of Arabic text using Acrofields in Itext 5.5


I have made a pdf template with a multi-line textbox and have to set some Arabic data in the Acrofields using PDFStamper. The run direction of text is correct for the first line but it changes when text wrapping occurs.

Please guide.

package test;

import java.io.FileOutputStream;
import java.io.IOException;    
import com.itextpdf.text.DocumentException;    
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class TextFields{

    public static final String RESULT1 = "D:/template.pdf";
    public static final String RESULT2 = "D:/pdf/result.pdf";
    protected int tf;

    public TextFields(int tf) {
        this.tf = tf;
    }

    public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        FontFactory.registerDirectories();
        BaseFont unicode = null;
        unicode = BaseFont.createFont("D:/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        AcroFields form = stamper.getAcroFields();
          stamper.getAcroFields().addSubstitutionFont(unicode);
        form.setField("TextBox","اب اب اب اب اب اب اب اب اب اب اب اب اب اب اب اب اب");
        stamper.close();
        reader.close();
    }

    public static void main(String[] args) throws DocumentException, IOException {
        TextFields example = new TextFields(0);
        example.manipulatePdf(RESULT1, RESULT2);
    }
}

Solution

  • I see that you don't flatten the document. If it's your intention that the document remains interactive, you should instruct iText not to generate any appearances. This can be done like this:

    form.setGenerateAppearances(false);
    

    By doing so, you tell the PDF viewer to create the appearances. If the problem persists, the problem resides in the PDF viewer, not at the iText level.

    If it's your intention to flatten the form, I fear you've encountered a limitation in the current version of iText. You'll need to use a workaround. Please take a look at the FillFlattenMerge3 example. In this example, we get the position of each field:

    AcroFields form = reader.getAcroFields();
    positions = new HashMap<String, Rectangle>();
    Rectangle rectangle;
    Map<String, AcroFields.Item> fields = form.getFields();
    for (String name : fields.keySet()) {
        rectangle = form.getFieldPositions(name).get(0).position;
        positions.put(name, rectangle);
    }
    

    We use these positions to draw the contents of the fields at the appropriate place using the ColumnText object instead of using the setField() method:

    Rectangle rect = positions.get(name);
    Phrase p = new Phrase(value, FONT);
    ColumnText.showTextAligned(cb, Element.ALIGN_LEFT,
            p, rect.getLeft() + 2, rect.getBottom() + 2, 0);
    

    This doesn't solve your problem yet, because the showTextAligned() method doesn't wrap text. Instead of using the showTextAligned() method, you need to use the setRunDirection(), addElement(), setSimpleColumn() and go() method:

    ColumnText column = new ColumnText(writer.getDirectContent());
    column.setSimpleColumn(rect);
    column.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
    column.addElement(new Paragraph("اب اب اب اب اب اب اب اب اب اب اب اب اب اب اب اب اب", unicode));
    column.go();
    

    Now your text will be wrapped properly without breaking the ligatures.