对于阿拉伯文本,RTL不能使用itext 5.5生成pdf

时间:2014-05-27 12:30:14

标签: java itext arabic right-to-left xmlworker

我有java代码在itext 5.5和xmlworker jars的帮助下编写阿拉伯字符,但是即使在使用了 writer.setRunDirection(PdfWriter.RUN_DIRECTION_RTL)之后它也是从左到右编写的。

使用的代码是:

public class CreateArabic extends DefaultHandler {
    /** Paths to and encodings of fonts we're going to use in this example */
    public static String[][] FONTS = {
        {"C:/arialuni.ttf", BaseFont.IDENTITY_H},
        {"C:/abserif4_5.ttf", BaseFont.IDENTITY_H},
        {"C:/damase.ttf", BaseFont.IDENTITY_H},
        {"C:/fsex2p00_public.ttf", BaseFont.IDENTITY_H}

    };



    /** Holds he fonts that can be used for the peace message. */
    public FontSelector fs;

     public CreateArabic() {
            fs = new FontSelector();
            for (int i = 0; i < FONTS.length; i++) {
                fs.addFont(FontFactory.getFont(FONTS[i][0], FONTS[i][1], BaseFont.EMBEDDED));
            }
        }



    public static void main(String args[]) {

        try {

            // step 1
            Rectangle pagesize = new Rectangle(8.5f * 72, 11 * 72);

            Document document = new Document();//pagesize, 72, 72, 72, 72);// step1

            PdfWriter writer = PdfWriter.getInstance(document,
                    new FileOutputStream("c:\\report.pdf"));
            writer.setInitialLeading(200.5f);

            //writer.getAcroForm().setNeedAppearances(true);
            //writer.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
            document.open();

            FontFactory.registerDirectories();
            Font font = FontFactory.getFont("C:\\damase.ttf",
                    BaseFont.IDENTITY_H, true, 22, Font.BOLD);



            // step 3
            document.open();

            // step 4

             XMLWorkerHelper helper = XMLWorkerHelper.getInstance();

             // CSS
             CSSResolver cssResolver = new StyleAttrCSSResolver();
             CssFile cssFile = helper.getCSS(new FileInputStream(
             "D:\\Itext_Test\\Test\\src\\test.css"));
             cssResolver.addCss(cssFile);

             // HTML
             XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider();


             // fontProvider.addFontSubstitute("lowagie", "garamond");
             CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);

             HtmlPipelineContext htmlContext = new HtmlPipelineContext(
             cssAppliers);

             htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

//           // Pipelines
             PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
             HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
             CssResolverPipeline css = new CssResolverPipeline(cssResolver,
             html);


             writer.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);

             System.out.println("RUN DIRECTION --> "+writer.getRunDirection());

             XMLWorker worker = new XMLWorker(css, true);

             XMLParser p = new XMLParser(worker,Charset.forName("UTF-8"));


             String htmlString2 = "<html><body style=\"color:red;\">Hello"+"??"+"</body></html>";
             String htmlString = "<body  style='font-family:arial;'>h"+"??"+"<p  style='font-family:arial;' > ????? </p></body>";
             String html1 ="<html><head></head><body>Hello <p style=\"color:red\" >oo  ??</p>   World! \u062a\u0639\u0637\u064a \u064a\u0648\u0646\u064a\u0643\u0648\u062f \u0631\u0642\u0645\u0627 \u0641\u0631\u064a\u062f\u0627 \u0644\u0643\u0644 \u062d\u0631\u0641 "+htmlString+"Testing</body></html>";



             ByteArrayInputStream is = new ByteArrayInputStream(htmlString.getBytes("UTF-8"));

             p.detectEncoding(is);


             p.parse(is, Charset.forName("UTF-8"));//.parse(is, "UTF-8");//parse(is);//ASMO-708


            // step 5

             document.close();
        } catch (Exception ex) {
            ex.printStackTrace();

        }

    }
}

还附加了输出文件。PDF Output

3 个答案:

答案 0 :(得分:5)

如记录所述,这不应该起作用:

writer.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);

阿拉伯语(和希伯来语)只能在ColumnTextPdfPCell的上下文中正确呈现。换句话说:如果您想使用XML Worker中的阿拉伯语,您需要创建一个ElementList,然后像here一样将元素添加到ColumnText对象。

您需要在ColumnText对象的级别设置运行方向。

答案 1 :(得分:1)

//此解决方案适用于我::)

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

答案 2 :(得分:0)

对于需要直接解决方案的开发人员

我用过这个技巧,输出非常干净漂亮!

  1. 使用PDFPTable
  2. 创建1
  3. 对于您内容的每个段落,创建一个Paragraph对象并将其对齐设置为Paragraph.ALIGN_JUSTIFIED(我不知道原因,但它会导致段落对齐到页面右侧! )
  4. 使用PDFPCell创建setBorder(Rectangle.NO_BORDER)并删除其边框,并将段落添加到单元格
  5. 将单元格添加到表格
  6. 这是一个方便的代码示例。

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