RTL not working in pdf generation with itext 5.5 for Arabic text

两盒软妹~` 提交于 2019-11-27 16:19:25

As documented, this is not supposed to work:

writer.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);

Arabic (and Hebrew) can only be rendered correctly in the context of ColumnText and PdfPCell. In other words: if you want to use Arabic from XML Worker, you need to create an ElementList and then add the elments to a ColumnText object as is done here.

You need to set the run direction at the level of the ColumnText object.

//This solution works for me: :)

// document
        Document document = new Document(PageSize.LEGAL);

        //fonts
        XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
        fontProvider.register("/Users/ibrahimbakhsh/Library/Fonts/tradbdo.ttf", BaseFont.IDENTITY_H);
        fontProvider.register("/Users/ibrahimbakhsh/Library/Fonts/trado.otf", BaseFont.IDENTITY_H);
        fontProvider.register("/Users/ibrahimbakhsh/Library/Fonts/tahoma.ttf", BaseFont.IDENTITY_H);
        CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

        // CSS
        CSSResolver cssResolver =
                XMLWorkerHelper.getInstance().getDefaultCssResolver(true);



        // Pipelines
        ElementList elements = new ElementList();
        ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null);
        HtmlPipeline html = new HtmlPipeline(htmlContext, end);
        CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

        // HTML
        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
        htmlContext.autoBookmark(false);


        // XML Worker
        XMLWorker worker = new XMLWorker(css, true);
        XMLParser p = new XMLParser(worker);
        p.parse(new FileInputStream(HTML));


        //writer
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
        writer.setInitialLeading(12.5f);
        writer.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);


        // step 4
        document.open();


        // step 5

        for (Element e : elements) {
            //out.println(e.toString());
            if(e instanceof PdfPTable){
                PdfPTable t = (PdfPTable) e;
                t.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
                ArrayList<PdfPRow> rows = t.getRows();
                for(PdfPRow row:rows){
                    PdfPCell[] cells = row.getCells();
                    for(PdfPCell cell:cells){
                        cell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
                    }
                }
                e = t;
            }
            document.add(e);
        }


        //try adding new table 

        PdfPTable table = new PdfPTable(1);
        table.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
        Font f = new Font(BaseFont.createFont("/Users/ibrahimbakhsh/Library/Fonts/trado.otf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED));
        PdfPCell cell = new PdfPCell(new Paragraph("تجربة نص عربي",f));
        table.addCell(cell);
        document.add(table);

        // step 6
        document.close();

For developers that need an straightforward solution

I used this trick and output is very clean and nice!

  1. create a PDFPTable with 1 column
  2. for every paragraph of your content, create a Paragraph object and set its alignment to Paragraph.ALIGN_JUSTIFIED (I don't know why but it causes to paragraph align to right of page!!!)
  3. create a PDFPCell and remove its borders using setBorder(Rectangle.NO_BORDER) and add the paragraph to cell
  4. add the cell to the table

here is a code sample to your convenience.

public void main(){
    /*
    * create and initiate document
    * */
    // repeat this for all your paragraphs
    PdfPTable pTable = new PdfPTable(1);
    Paragraph paragraph = getCellParagraph();
    paragraph.add("your RTL content");
    PdfPCell cell = getPdfPCellNoBorder(paragraph);
    pTable.addCell(cell);

    // after add all your content
    document.add(pTable);
}

private Paragraph getCellParagraph() {
    Paragraph paragraph = new Paragraph();
    paragraph.setAlignment(Paragraph.ALIGN_JUSTIFIED);
    // set other styles you need like custom font
    return paragraph;
}

private PdfPCell getPdfPCellNoBorder(Paragraph paragraph) {
    PdfPCell cell = new PdfPCell();
    cell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
    cell.setPaddingBottom(8);
    cell.setBorder(Rectangle.NO_BORDER);
    cell.addElement(paragraph);
    return cell;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!