微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

itext7希伯来语反向发行

如何解决itext7希伯来语反向发行

我有一段简单的代码可以编写PDF,有时该PDF包含希伯来语或阿拉伯语等RTL语言。
我能够使用Bidi(Ibm lib)操纵文本并对其进行镜像
但是文字仍然反向运行

Here is the output comparison to the source

在英语中会是这样:

代替:

The quick 
brown fox 
jumps over 
the lazy dog

显示为:

the lazy dog
jumps over 
brown fox 
The quick 

完整代码

@Test
public void generatePdf()  {
    
      SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-hh.mm.ss");
        String dest = "c:\\temp\\" + formatter.format(Calendar.getInstance().getTime()) + ".pdf";
         String fontPath = "C:\\Windows\\Fonts\\ARIALUNI.TTF";
         FontProgramFactory.registerFont(fontPath,"arialUnicode");
        OutputStream pdfFile = null;
        Document doc = null;
    try {
        ByteArrayOutputStream output = new ByteArrayOutputStream();  
        PdfFont PdfFont  = PdfFontFactory.createRegisteredFont("arialUnicode",PdfEncodings.IDENTITY_H,true);      
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(output));
        pdfDoc.setDefaultPageSize(PageSize.A4);
        pdfDoc.addFont(PdfFont);
        doc = new Document(pdfDoc);
        doc.setBaseDirection(BaseDirection.RIGHT_TO_LEFT);

        String txt = "בתשרי נתן הדקל פרי שחום נחמד בחשוון ירד יורה ועל גגי רקד בכסלו נרקיס הופיע בטבת ברד ובשבט חמה הפציעה ליום אחד.  1234 באדר עלה ניחוח מן הפרדסים בניסן הונפו בכוח כל החרמשים";
        Bidi bidi = new Bidi();
        bidi.setPara(txt,Bidi.RTL,null);
        String mirrTxt = bidi.writeReordered(Bidi.DO_MIRRORING);
        Paragraph paragraph1 = new  Paragraph(mirrTxt)
                .setFont(PdfFont)
                .setFontSize(9)
                .setTextAlignment(TextAlignment.CENTER)
                .setHeight(200)
                .setWidth(70);
        paragraph1.setBorder(new SolidBorder(3));
        doc.add(paragraph1);  
                    
        Paragraph paragraph2 = new  Paragraph(txt)
                .setFont(PdfFont)
                .setFontSize(9)
                .setTextAlignment(TextAlignment.CENTER)
                .setHeight(200)
                .setWidth(70);
        paragraph2.setBorder(new SolidBorder(3));
        doc.add(paragraph2);  
        
        doc.close();
        doc.flush();
        pdfFile = new FileOutputStream(dest); 
        pdfFile.write(output.toByteArray()); 
        
        ProcessBuilder b = new ProcessBuilder("cmd.exe","/C","explorer " + dest);
        b.start();
        
        
    } catch (Exception e) {
        e.printstacktrace();
    }finally {          
        try {pdfFile.close();} catch (IOException e) {e.printstacktrace();}
    }
}

解决方法

在没有任何其他第三方库的情况下,使用iText7和IBM ICU4J找到的唯一解决方案是首先渲染线条,然后逐个镜像它们。这需要一个辅助类LineMirroring,它也不是最优雅的解决方案,但是会产生您期望的输出。

线镜像类

public class LineMirroring {

private final PageSize pageSize;
private final String fontName;
private final int fontSize;

public LineMirroring(PageSize pageSize,String fontName,int fontSize) {
    this.pageSize = pageSize;
    this.fontName = fontName;
    this.fontSize = fontSize;
}

public String mirrorParagraph(String input,int height,int width,Border border) {
    final StringBuilder mirrored = new StringBuilder();
    try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
        PdfFont font = PdfFontFactory.createRegisteredFont(fontName,PdfEncodings.IDENTITY_H,true);
        final PdfWriter writer = new PdfWriter(output);
        final PdfDocument pdfDoc = new PdfDocument(writer);
        pdfDoc.setDefaultPageSize(pageSize);
        pdfDoc.addFont(font);
        final Document doc = new Document(pdfDoc);
        doc.setBaseDirection(BaseDirection.RIGHT_TO_LEFT);
        final LineTrackingParagraph paragraph = new LineTrackingParagraph(input);
        paragraph.setFont(font)
                .setFontSize(fontSize)
                .setTextAlignment(TextAlignment.RIGHT)
                .setHeight(height)
                .setWidth(width)
                .setBorder(border);
        LineTrackingParagraphRenderer renderer = new LineTrackingParagraphRenderer(paragraph);
        doc.add(paragraph);
        Bidi bidi;
        for (LineRenderer lr : paragraph.getWrittenLines()) {
            bidi = new Bidi(((TextRenderer) lr.getChildRenderers().get(0)).getText().toString(),Bidi.RTL);
            mirrored.append(bidi.writeReordered(Bidi.DO_MIRRORING));
        }
        doc.close();
        pdfDoc.close();
        writer.close();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
    return mirrored.toString();
}

private class LineTrackingParagraph extends Paragraph {

    private List<LineRenderer> lines;

    public LineTrackingParagraph(String text) {
        super(text);
    }

    public void addWrittenLines(List<LineRenderer> lines) {
        this.lines = lines;
    }

    public List<LineRenderer> getWrittenLines() {
        return lines;
    }

    @Override
    protected IRenderer makeNewRenderer() {
        return new LineTrackingParagraphRenderer(this);
    }
}

private class LineTrackingParagraphRenderer extends ParagraphRenderer {
    public LineTrackingParagraphRenderer(LineTrackingParagraph modelElement) {
        super(modelElement);
    }

    @Override
    public void drawChildren(DrawContext drawContext) {
        ((LineTrackingParagraph)modelElement).addWrittenLines(lines);
        super.drawChildren(drawContext);
    }

    @Override
    public IRenderer getNextRenderer() {
        return new LineTrackingParagraphRenderer((LineTrackingParagraph) modelElement);
    }
}

}

最低JUnit测试

public class Itext7HebrewTest {

@Test
public void generatePdf() {

    final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-hh.mm.ss");
    final String dest = "F:\\Temp\\" + formatter.format(Calendar.getInstance().getTime()) + ".pdf";
    final String fontPath = "C:\\Windows\\Fonts\\ARIALUNI.TTF";
    final String fontName = "arialUnicode";
    FontProgramFactory.registerFont(fontPath,"arialUnicode");

    try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
        PdfFont arial = PdfFontFactory.createRegisteredFont(fontName,true);

        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(output));
        pdfDoc.setDefaultPageSize(PageSize.A4);
        pdfDoc.addFont(arial);
        LineMirroring mirroring = new LineMirroring(pdfDoc.getDefaultPageSize(),fontName,9);

        Document doc = new Document(pdfDoc);
        doc.setBaseDirection(BaseDirection.RIGHT_TO_LEFT);

        final String txt = "בתשרי נתן הדקל פרי שחום נחמד בחשוון ירד יורה ועל גגי רקד בכסלו נרקיס הופיע בטבת ברד ובשבט חמה הפציעה ליום אחד.  1234 באדר עלה ניחוח מן הפרדסים בניסן הונפו בכוח כל החרמשים";

        final int height = 200;
        final int width = 70;
        final Border border = new SolidBorder(3);

        Paragraph paragraph1 = new Paragraph(mirroring.mirrorParagraph(txt,height,width,border));
        paragraph1.setFont(arial)
                .setFontSize(9)
                .setTextAlignment(TextAlignment.RIGHT)
                .setHeight(height)
                .setWidth(width)
                .setBorder(border);
        doc.add(paragraph1);

        doc.close();
        doc.flush();
        try (FileOutputStream pdfFile = new FileOutputStream(dest)) {
            pdfFile.write(output.toByteArray());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

,

检查页面内容上的属性dir="rtl" CSS。

参考:https://kb.itextpdf.com/home/it5kb/faq/how-to-set-rtl-direction-for-hebrew-when-converting-html-to-pdf

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。