Itext PDF无法正确显示缅甸Unicode字体

时间:2020-05-15 08:08:15

标签: java pdf itext

Myanmar Unicode fonts生成的pdf文件中,itext 5无法正确显示。

itext版本:5.5.13.1

期望结果:ဂဃနဏဖတ်ခဲ့သည်。

实际结果

enter image description here

Google Drive Link用于生成PDF。

我的测试字符串类似于英语中的“快速的棕色狐狸跳过懒狗”。它包含大多数缅甸字母。

我以前在pdf以上产品中使用的Java程序

    String fileName = "sample.pdf";
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
        Document doc = new Document();
        PdfWriter writer = PdfWriter.getInstance(doc, baos);
        writer.setCloseStream(false);

        BaseFont unicode = BaseFont.createFont("/fonts/NotoSansMyanmar-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        Font myanmarUniCodeFont = new Font(unicode, 11, Font.NORMAL, BaseColor.BLACK);
        Rectangle pageSize = new Rectangle(PageSize.A4);
        doc.setPageSize(pageSize);
        doc.open();
        String textStr = "သီဟိုဠ်မှ ဉာဏ်ကြီးရှင်သည်အာယုဝဎ္ဍနဆေးညွှန်းစာကို ဇလွန်ဈေးဘေးဗာဒံပင်ထက် အဓိဋ္ဌာန်လျက် ဂဃနဏဖတ်ခဲ့သည်။";
        doc.add(new Paragraph(textStr, myanmarUniCodeFont));
        doc.close();
    }
    catch (Exception e) {
        e.printStackTrace();
    }

    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
    response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
    response.setHeader("Pragma", "No-cache");
    response.setHeader("Content-Disposition", "inline; filename=" + fileName);
    response.setContentType("application/pdf");
    response.setContentLength(baos.size());
    OutputStream os = response.getOutputStream();
    baos.writeTo(os);
    os.flush();
    os.close();
    baos.close();

输出的文本是正确的(您可以将其复制并粘贴到记事本等文本编辑器中,然后查看结果),但在pdf文件中显示错误。

如何使用itext-pdf-5正确显示缅甸Unicode字体?

现在,我正在使用肮脏的方式来查看字体的可读性。我将所有unicode字符串转换为“ Zawgyi字体” (这是另一种缅甸字体和we should never use this。),并嵌入到pdf中。这不是一个好的解决方案,我们不能保证所有的unicode都可以正确转换为Zawgyi-One字体字符串,而且我也不想将unicode文本转换为非标准文本。这就是为什么我不想使用这种方式。

使用Itext编辑了有关ZawGyi字体的

某些文本也无法使用itext正确呈现。例如:သိန်နီ ဂွ

2 个答案:

答案 0 :(得分:3)

(完全公开:我为iText软件工作。)

iText 5不支持缅甸书写系统的基于Unicode的正确处理。尽管iText 5具有针对阿拉伯语的特定实现,但其字体基础结构的固有局限性阻止了对其他各种书写系统所需的字体功能的支持。

iText 7在此方面进行了改进,提供了新的字体实现和一个可选模块(pdfCalligraph,不是开放源代码),以支持不同的书写系统。但是,缅甸尚不支持。

相应的iText 7代码如下:

PdfWriter writer = new PdfWriter(baos);
PdfDocument pdfdoc = new PdfDocument(writer);
Document doc = new Document(pdfdoc);

PdfFont f = PdfFontFactory.createFont("/fonts/NotoSansMyanmar-Regular.ttf",
    PdfEncodings.IDENTITY_H, true);

String textStr =
    "သီဟိုဠ်မှ ဉာဏ်ကြီးရှင်သည်အာယုဝဎ္ဍနဆေးညွှန်းစာကို ဇလွန်ဈေးဘေးဗာဒံပင်ထက် အဓိဋ္ဌာန်လျက် ဂဃနဏဖတ်ခဲ့သည်။";
// Explicit writing system
//doc.add(new Paragraph(textStr).setFont(f).setFontScript(Character.UnicodeScript.MYANMAR));
// Rely on autodetection
doc.add(new Paragraph(textStr).setFont(f));
doc.close();

无论是否使用pdfCalligraph,渲染仍然是错误的:

Wrong Myanmar rendering

如果您可以选择使用商业许可,请提交此功能请求。仍在积极添加其他书写系统。如果不是这样,恐怕iText无法做到这一点,您将不得不寻找另一种解决方案。

答案 1 :(得分:0)

我也面临着同样的问题。但是我将百里香与iText一起使用。我使用该语言(不是unicode)的ttf字体包,并使用转换器将unicode转换为我的语言,并将其作为普通字符串附加到PDF中。它就像一个魅力。如果您有可能使用百里香叶,请尝试这种方法。

在样式标签内的CSS下方放置

@font-face {
    font-family: 'myfont-family';
    src: url('/fonts/myfont.ttf');
    -fs-pdf-font-embed: embed;
    -fs-pdf-font-encoding: Identity-H;
}

.mylanguage{
    font-family: 'myfontfamily';
}

<p class="mylanguage">your converted font text</p>

用于生成pdf的Java代码。

context.setVariable("myvariable", myvariable);
String html = templateEngine.process("mypdf", context);
html = templateEngine.process("mythymeleaf", context);
String fileName = "myfile.pdf";
PDFEncryption pdfEncryption  = new PDFEncryption();
String password = "0000";
pdfEncryption.setUserPassword(password.getBytes());

ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(html);
renderer.layout();
renderer.setPDFEncryption(pdfEncryption);
renderer.createPDF(outputStream);
outputStream.flush();
outputStream.close();

此处是有关此方法的完整教程的链接,其中包含有效的源代码。 https://medium.com/@natsucoder/create-pdf-in-different-language-fonts-using-spring-boot-thymeleaf-itext-cba7f8612c61

相关问题