2017-11-03 63 views
1

私は最終的に私のユニコードをPDFBoxで印刷することに成功しました。 しかし、今私は、私が思いついた解決策を理解したいと思います。 以下のコードが動作し、がページに印刷されます。PDFBox 2.0でのフォントの読み込みの理解

2つのことは動作しません:

  • final PDFont robotoLight = loadFont("Roboto-Light.ttf");

final PDFont robotoLight = loadFontAlternative("Roboto-Light.ttf"); を変更 PDType0Font.load(documentMock, systemResourceAsStream, false);

  • PDType0Font.load(documentMock, systemResourceAsStream, true); を変更します

    最初の変更では、文字の代わりに2つのドットが印刷されます。 偽に設定されていると動作しないため、embedSubsetは何をしますか? 私が理解するにはドキュメンテーションがあまりにも疎です。

    2番目の変更により、次の例外が発生します。Exception in thread "main" java.lang.IllegalArgumentException: U+2265 is not available in this font's encoding: WinAnsiEncoding この問題は、ユニコードの処理にバグがあったPDFBox 2.0より前の多くの他の質問に記載されています。 したがって、彼らは直接質問に答えません。 これ以外にも、問題は明らかです。エンコードをWinAnsiEncodingに設定するのではなく、別のものを設定するべきです。 エンコードはどうすればよいですか?なぜUTF-8エンコーディングなどはありませんか? COSNameには多くのオプションについてのドキュメントはありません。

    public class SimpleReportUnicode { 
        public static void main(String[] args) throws IOException { 
         PDDocument report = createReport(); 
         final String fileLocation = "c:/SimpleFormUnicode.pdf"; 
         report.save(fileLocation); 
         report.close(); 
        } 
    
        private static PDDocument createReport() throws IOException { 
         PDDocument document = new PDDocument(); 
         PDPage page = new PDPage(); 
         document.addPage(page); 
    
         PDPageContentStream contentStream = new PDPageContentStream(document, page); 
         final PDFont robotoLight = loadFontAlternative("Roboto-Light.ttf"); 
         writeText(contentStream, robotoLight, 100, 650); 
    
         contentStream.close(); 
         return document; 
        } 
    
        private static void writeText(PDPageContentStream contentStream, PDFont font, double x, double y) { 
         try { 
          contentStream.beginText(); 
          contentStream.setFont(font, 12); 
          contentStream.moveTextPositionByAmount((float) x, (float) y); 
          String unicode = "≥"; 
          contentStream.showText(unicode); 
          contentStream.endText(); 
         } 
         catch (IOException e) { 
         } 
        } 
    
        private static PDFont loadFont(String location) { 
         PDFont font; 
         try { 
          PDDocument documentMock = new PDDocument(); 
          InputStream systemResourceAsStream = ClassLoader.getSystemResourceAsStream(location); 
          Encoding encoding = Encoding.getInstance(COSName.WIN_ANSI_ENCODING); 
          font = PDTrueTypeFont.load(documentMock, systemResourceAsStream, encoding); 
         } 
         catch (IOException e) { 
          throw new RuntimeException("IO exception"); 
         } 
         return font; 
        } 
    
        private static PDFont loadFontAlternative(String location) { 
         PDDocument documentMock = new PDDocument(); 
         InputStream systemResourceAsStream = ClassLoader.getSystemResourceAsStream(location); 
         PDFont font; 
         try { 
          font = PDType0Font.load(documentMock, systemResourceAsStream, true); 
         } 
         catch (IOException e) { 
          throw new RuntimeException("IO exception"); 
         } 
         return font; 
        } 
    } 
    

    EDIT あなたはコードのように同じフォントを使用したい場合は、Robotoは、ここで提供されています: https://fonts.google.com/specimen/Roboto クラスパスにあなたにRoboto-Light.ttfを追加し、コードが箱から出して動作するはずです。

  • +0

    どのPDFBoxのバージョンを使用していますか? –

    +0

    "U + 2265はこのフォントのエンコーディングでは利用できません:WinAnsiEncoding"については、FAQ:https://pdfbox.apache.org/2.0/faq.html#fontencodingで説明しています。 'PDType0Font.load()'は、最後のパラメータがtrueかfalseであっても関係なく動作します。 Trueはサブセット、falseはフォント全体が使用されることを意味します(つまり、ファイルが大きくなる:4KBではなく100KB)。 –

    +0

    _why UTF-8エンコーディングなどはありませんか?_これはPDF仕様にはありません。 –

    答えて

    2

    コメントで述べたように:

    • embedSubsetsの問題は、バージョン2.0.7を使用して去っていきました。 (Btw 2.0.8が今日リリースされた)。
    • 「このフォントのエンコードではU + 2265が利用できません:WinAnsiEncoding」はFAQで説明されています。解決策は、あなたの作業バージョンで既に行ったPDType0Font.load()を使用することです。
    • PDF仕様では使用できないため、フォントのUTF-8エンコーディングはありません。
    • embedSubsets trueを使用すると4KBのファイルが生成されますが、完全なフォントが埋め込まれているため、ファイルが100KBであるためfalseが通常は最善です。
    関連する問題