Windows机器上iText-PDF中的中文字体问题

时间:2014-05-30 15:49:36

标签: java pdf fonts itext

我正在使用Ubuntu-PC创建带有iText的PDF,部分是中文版。为了阅读它们,我使用了Evince。到目前为止几乎没有任何问题

在我的电脑上,我尝试了以下三个BaseFonts并且他们成功地工作了:

bf = BaseFont.createFont("MSungStd-Light", "UniCNS-UCS2-H", BaseFont.NOT_EMBEDDED); 
bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); 
bf = BaseFont.createFont("MSung-Light","UniCNS-UCS2-H", BaseFont.NOT_EMBEDDED); 

不幸的是,在使用Acrobat-Reader在Windows上打开最终PDF时,文档无法再正确显示。

在我搜索字体以获得解决方案后,我来到论坛,以可理解的方式解释问题(这里使用了MSung-Light):http://community.jaspersoft.com/questions/531457/chinese-font-cannot-be-seen

  

您正在使用PDF中的内置中文字体。我不确定   这种字体支持英文和中文,或混合的能力   语言无论如何。

     

使用Acrobat Reader内置字体的优点在于它   生成较小的PDF文件,因为它依赖于那些字体   可以在显示PDF的客户端计算机上通过   预装Acribat Asian Font Pack。

     

但是,使用PDF内置字体有一些缺点   通过在不同的机器上进行测试,我们进行了研究   与内置韩文字体相关的类似问题。

我该怎么办? 能够复制中文字母并不是那么重要。 iText可以将段落转换为图像吗?或者有更好的解决方案吗?

1 个答案:

答案 0 :(得分:5)

您正在使用CJK字体。 CJK字体从不嵌入,在Adobe Reader中打开这样的文件时需要字体包。通常,Adobe Reader会询问您是否要自动安装此类字体包。如果没有,您可以下载相应的字体包here

您似乎希望避免让最终用户安装字体包。这在某种程度上是可以理解的。真正糟糕的是,你建议避免使用字体并逐个绘制字形。这可以用iText(并在我的书中记录),但它带有严重的警告:不要这样做!您的文件将变得臃肿,打印结果可能会非常糟糕!

另一种方法是使用其他字体,例如arialuni.ttf,YaHei,SimHei,...这些字体包含中文字形,您可以将这些字体的子集嵌入到PDF中(嵌入整个字体会有点过分)。例如,请参阅FontTest示例。

如果您有字体程序,例如arialuni.ttf,则可以使用此代码创建BaseFont对象:

BaseFont.createFont("c:/windows/fonts/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

使用此字体,您可以显示在任何操作系统上使用任何查看器可见的中文字符。如果您没有arialuni.ttf,则需要查找其他字体并使用FontText示例来测试是否支持中文(如果您在&#34之后看不到任何文字;中文:",然后中文不受支持。

回复您的评论的额外答案:

请忘记iText-Asian,因为这是您想要使用CJK字体时需要的jar。您明确表示您不想使用CJK字体,因此您不需要使用iText-Asian。

如果要嵌入字体(而不是依赖字体包),则需要选择知道如何绘制中文字符的字体程序。这会立即引起你关于&#34的问题;你能指出一个绘制汉字的例子吗?" 无效。我可以指出你这样一个例子,但你还需要一个字体程序。

一旦你有了这个字体程序:为什么你不能以正确的方式使用它?您应该按照您应该使用的方式使用该字体程序。您不应该使用该字体程序将您的字形绘制为图像,因为这将导致PDF文件具有巨大的文件大小和错误的分辨率(字形的质量差,因为您绘制每个单独的字符而不是使用字体程序在PDF)。

您是否在寻找字体程序?前一段时间有一个类似的关于越南字体的问题:Can't export Vietnamese characters to PDF using iText我花了不到四分之一的时间去谷歌寻找可以使用的字体。为什么不花四分之一的时间来寻找支持中文的字体呢?

回复您的额外评论的额外答案:

  1. 当我们提到CJK时,我们指的是一种不嵌入字体的特定方法,但依赖于最终用户机器上安装的字体包,以便Adobe Reader可以使用该字体。你不想要这个,所以你所有关于使用itext asian jar和MSung-Light等的问题都无关紧要。
  2. 中文字符很大,很多电脑都没有任何中文字体(特别是在美国),所以你的问题的答案"没有办法使用内置字符在arialuni" "不,你不应该指望它!"
  3. 你对越南语的评价是无关紧要的。字体是字体是字体。一侧有字符代码,另一侧有字形。将一个与另一个连接的粘合剂是编码。例如:您有十六进制字符代码B2E2和十六进制字符代码CAD4。如果编码是GBK,则相应的字形是测试和试验。请注意,当您想要在UNICODE中表示相同的字符时,您可以使用字符6D4D和8BD5。与其他系统几乎没有什么区别。例如:您有十六进制字符代码41(十进制数为65),如果编码为Latin-1,则相应的字形为A.
  4. 我已经要求您搜索支持中文的字体。我打开谷歌,搜索了关键字"中文字体"。我找到了这个页面:http://www.freechinesefont.com/我选择了一个对我来说似乎没问题的字体:http://www.freechinesefont.com/simplified-hxb-mei-xin-download/
  5. 现在我使用此代码段:

    import java.io.FileOutputStream;
    import java.io.IOException;
    import com.itextpdf.text.Document;
    import com.itextpdf.text.DocumentException;
    import com.itextpdf.text.Font;
    import com.itextpdf.text.Paragraph;
    import com.itextpdf.text.pdf.BaseFont;
    import com.itextpdf.text.pdf.PdfWriter;
    
    public class ChineseTest {
        /** Path to the resulting PDF file. */
        public static final String DEST = "results/test.pdf";
        /** Path to the vietnamese font. */
        public static final String FONT = "resources/hxb-meixinti.ttf";
    
        /**
         * Creates a PDF file: hello.pdf
         * @param    args    no arguments needed
         */
        public static void main(String[] args) throws DocumentException, IOException {
            new ChineseTest().createPdf(DEST);
        }
    
        /**
         * Creates a PDF document.
         * @param filename the path to the new PDF document
         * @throws    DocumentException 
         * @throws    IOException 
         */
        public void createPdf(String filename) throws DocumentException, IOException {
            // step 1
            Document document = new Document();
            // step 2
            PdfWriter.getInstance(document, new FileOutputStream(filename));
            // step 3
            document.open();
            BaseFont bf = BaseFont.createFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            Font font = new Font(bf,15);
            // step 4
            document.add(new Paragraph("\u6d4b\u8bd5", font));
            // step 5
            document.close();
        }
    }
    

    结果在Windows上显示如下:

    enter image description here

    这与越南人有什么不同?单词测试用中文正确显示。嵌入了字体的子集,这意味着您可以保持较低的文件大小。文本不是作为图像嵌入的,这意味着文本的质量非常好。

    回答您额外评论的额外答案:在评论中,您声称使用文件hxb-meixinti.ttf的示例需要安装字体。那是不对的。 hxb-meixinti.ttf只是一个由iText读取的文件,用于将特定字形(字体的子集)的定义嵌入到PDF中。

    当您编写:与字体程序相关时:Java似乎能够在不使用外部软件的情况下完成。 Java能够使用字体,因为Java使用字体文件,只是以同样的方式因为iText使用字体文件。

    有关详细信息,请阅读Java手册中的Supported Fonts。我引用:

      

    物理字体需要安装在Java已知的位置   运行环境。 JRE在两个位置查找:lib / fonts   JRE本身内的目录,以及正常的字体位置   由主机操作系统定义。如果字体具有相同的名称   存在于两个位置,使用lib / fonts目录中的那个。

    我尝试解释(以及自此线程开始以来你一直忽略的)是iText需要访问物理字体。 iText可以接受来自文件或byte[]的字体,但您需要提供类似TTF,OTF,TTC,AFM + PFB的字体。这与的工作方式没有什么不同。

    在评论中,您还说您希望Adobe Reader接受字节流,而不是从文件中读取PDF。这是不可能的。 Adobe Reader始终要求在磁盘上存在PDF文件。即使PDF文件由浏览器提供服务,PDF的字节也会存储为临时文件。这是您要求在Adobe Reader中查看文件的固有要求。

    你的其他评论不清楚。您是什么意思如果每个人都只是上传任何他可能需要切换的东西会导致困难。您是在谈论下载而不是上传吗?另外:我给了你一个不需要在客户端下载任何额外内容的解决方案,但你继续唠叨没有人会在Acrobat上安装任何东西。

    关于你的评论对于BS我最近得到了一个解决方案,我不知道你对BS的意思。