Itext7希伯来语反转问题

huangapple go评论57阅读模式
英文:

Itext7 Hebrew reverse issue

问题

@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();
        }
    }
}
英文:

I have simple piece of code that writes a PDF sometime this PDF will contain RTL languages like Hebrew or Arabic.
I was able to manipulate the text and mirror it using Bidi (Ibm lib)
But the text is still running in reverse

Itext7希伯来语反转问题

In English it would be something like:

instead of:

The quick 
brown fox 
jumps over 
the lazy dog

It appears as:

the lazy dog
jumps over 
brown fox 
The quick 

Complete code:

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

答案1

得分: 3

以下是您提供的内容的翻译:

唯一使用 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) {
        // ...
    }

    public String mirrorParagraph(String input, int height, int width, Border border) {
        final StringBuilder mirrored = new StringBuilder();
        // ...
        return mirrored.toString();
    }

    private class LineTrackingParagraph extends Paragraph {
        // ...
    }

    private class LineTrackingParagraphRenderer extends ParagraphRenderer {
        // ...
    }
}

最小 JUnit 测试

public class Itext7HebrewTest {

    @Test
    public void generatePdf() {
        // ...
        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
            // ...
            FontProgramFactory.registerFont(fontPath, "arialUnicode");
            PdfFont arial = PdfFontFactory.createRegisteredFont(fontName, PdfEncodings.IDENTITY_H, true);
            // ...
            LineMirroring mirroring = new LineMirroring(pdfDoc.getDefaultPageSize(), fontName, 9);
            // ...
            final String txt = "בתשרי נתן הדקל פרי שחום נחמד בחשוון ירד יורה ועל גגי רקד בכסלו נרקיס הופיע בטבת ברד ובשבט חמה הפציעה ליום אחד.  1234 באדר עלה ניחוח מן הפרדסים בניסן הונפו בכוח כל החרמשים";
            // ...
            Paragraph paragraph1 = new Paragraph(mirroring.mirrorParagraph(txt, height, width, border));
            // ...
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
英文:

The only solution that I have found with iText7 and IBM ICU4J without any other third party libraries is to first render the lines and then mirror them one by one. This requires a helper class LineMirroring and it's not precisely the most elegant solution, but will produce the output that you expect.

Lines mirroring class:

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

}

Minimal JUnit Test:

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, PdfEncodings.IDENTITY_H, 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();
}
}

}

huangapple
  • 本文由 发表于 2020年9月16日 10:13:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/63912180.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定