2016-08-05 11 views
4

以前に読んだ文書(https://www.dropbox.com/s/ttxiv0dq3abh5kj/Test.pdf?dl=0)の要素からpdf文書を作成する際に問題があります。すべて私は前にout.setFont(textState.getFont(), textState.getFontSize())(INFORMATIONログを参照)でフォントを設定したPDPageContentStreamにshowTextを呼び出し、フォントはComicSansMSまたはArialBlackです。 textStateは、以前に読み取られた文書からの状態(のクローン)です。 HelveticaやTimes-Romanでテキストを書くのはうまくいきます。pdfbox:...このフォントのエンコーディングでは利用できません

INFORMATION: set font PDTrueTypeFont RXNQOL+ComicSansMS,Bold/18.0 embedded  
SEVERE: error writing <w>U+0077 is not available in this font's encoding: built-in (TTF) 

フォント名にハイフンや空白がないことが原因で問題が発生している可能性がありますが、これを解決する手掛かりはありません。

ここでは完全なコードは

import java.awt.Point; 
import java.awt.geom.Point2D; 
import java.io.File; 
import java.io.IOException; 
import org.apache.pdfbox.contentstream.PDFGraphicsStreamEngine; 
import org.apache.pdfbox.cos.COSName; 
import org.apache.pdfbox.pdmodel.PDDocument; 
import org.apache.pdfbox.pdmodel.PDPage; 
import org.apache.pdfbox.pdmodel.PDPageContentStream; 
import org.apache.pdfbox.pdmodel.font.PDFont; 
import org.apache.pdfbox.pdmodel.graphics.image.PDImage; 
import org.apache.pdfbox.pdmodel.graphics.state.PDTextState; 
import org.apache.pdfbox.util.Matrix; 
import org.apache.pdfbox.util.Vector; 

public class Test extends PDFGraphicsStreamEngine { 

public static void main(String[] args) throws IOException { 
    test(); 
} 

public static void test() throws IOException { 
    PDDocument document = PDDocument.load(new File("Test.pdf")); 
    PDPage pageIn = document.getPage(0); 
    PDDocument saveDoc = new PDDocument(); 
    PDPage savePage = new PDPage(pageIn.getMediaBox()); 
    saveDoc.addPage(savePage); 
    try (PDPageContentStream out = new PDPageContentStream(saveDoc, savePage)) { 
     Test test = new Test(pageIn, out); 
     test.processPage(pageIn); 
    } 
} 

private final PDPageContentStream out; 

public Test(PDPage pageIn, PDPageContentStream out) { 
    super(pageIn); 
    this.out = out; 
} 

@Override 
public void appendRectangle(Point2D p0, Point2D p1, Point2D p2, Point2D p3) throws IOException { 
} 

@Override 
public void clip(int windingRule) throws IOException { 
} 

@Override 
public void closePath() throws IOException { 
} 

@Override 
public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) throws IOException { 
} 

@Override 
public void drawImage(PDImage pdImage) throws IOException { 
} 

@Override 
public void endPath() throws IOException { 
} 

@Override 
public void fillAndStrokePath(int windingRule) throws IOException { 
} 

@Override 
public void fillPath(int windingRule) throws IOException { 
} 

@Override 
public Point2D getCurrentPoint() { 
    return new Point(0, 0); 
} 

@Override 
public void lineTo(float x, float y) throws IOException { 
} 

@Override 
public void moveTo(float x, float y) throws IOException { 
} 

@Override 
public void shadingFill(COSName shadingName) throws IOException { 
} 

@Override 
protected void showGlyph(Matrix textRenderingMatrix, PDFont font, int code, String unicode, Vector displacement) throws IOException { 
    super.showGlyph(textRenderingMatrix, font, code, unicode, displacement); 
    PDTextState textState = getGraphicsState().getTextState(); 
    out.beginText(); 
    out.setTextMatrix(getTextMatrix()); 
    out.setFont(textState.getFont(), textState.getFontSize()); 
    out.showText(unicode); 
    out.endText(); 
} 

@Override 
public void strokePath() throws IOException { 
} 

} 

任意の提案ですか?

おかげで、 ユルゲン

+0

問題の再現を可能にするために、重要なコードを示し、サンプルソースPDFにリンクしてください。 – mkl

答えて

4

TL; DR:そのフォントがエンコーディングをサポートしていません。

問題の原因は、ご使用のComic Sansサブセットフォントに「ポスト」(ポストスクリプト)テーブルがあり、そのglyphNamesテーブルがnullであることです。私。あなたのフォントにグリフ名はありません。 A-Z、a-zの場合、名前はこれらの文字に似ています。 PDFBoxはPDTrueType.readEncodingFromFontの2番目の部分で "w"の代わりに "90"( "w"の代わりに)のようなグリフIDから擬似名を作成します。 "("グリフ名は "parenleft"しかし)。

enter image description here

ときエンコーディング、フォントがエンコーディングエントリを持っていないようPDFBoxは、アドビGlyphlistを使用しています。あなたは他のフォント、例えばR18でPDFDebuggerで見れば、あなたは見つけることができます「エンコーディング:WinAnsiEncoding ":

enter image description here

あなたは明らかに何をしているがクリートすることですeテキストのみの新しいページ。これを行う別の方法は、コンテンツストリームを分析し、テキスト以外のものをペイントするすべてのトークンを単純に削除することです。まず、ソースコードのダウンロードでRemoveAllTextの例を見て、PDF 32000仕様をダウンロードして、「演算子サマリー」の部分を見て、削除するものに注意してください。たとえば、 "Do"は画像を描画したり、コンテンツストリームでもあるXObjectフォームを描画するために使用されます。

はこちらをご覧ください: How can I remove all images/drawings from a PDF file and leave text only in Java?

どちらのソリューションが間違っているが、最初のものだけで足の下からすべての画像を引き出し、もう一つは良いスタートですが、パラメータが画像であるかどうかを確認するために世話をしていませんか否か。

+0

1.それは私がやっていることではありません。これは、問題を再現するためにサンプルを取り除いたものに過ぎませんでした。 2.あなたが、このフォントを使用してPDFBoxを持つ(新しい)pdfページを作成する方法がないと言います - 少なくとも、含まれている文字のグリフを表示するためにソースドキュメント内に埋め込まれていますか? 3.そうであれば、ソース文書で使用されているフォントをエンコードに使用できるかどうか、および/またはそのようなフォントをロードしてから使用する方法をプログラムで確認することができます(Arial BlackとComis Sans MS少なくともほとんどのWindowsインストールで利用できるでしょうか?) – Juergen

+0

2.簡単にはありません。私はPDFBoxを変更しようと考えていましたが、ちょっと試しましたが、これは思ったよりずっと多くの作業に進化しました。それでも、場合によっては失敗することもあります。合字でPDFの1つのコードが複数のユニコードを意味する場合そして、あなたは「ユニコード」があると確信することはできません。いくつかのPDFファイルにはそれがありません。もう一つの解決策は生のコマンドを使用することですが、それもやりにくく、コードによっては2バイトで1つではありません。 –

+0

3.フォントでgetEncoding()を呼び出し、その型で使用可能な場合は、contains(code)またはgetName(int code)でチェックしてみることができます。あなたは 'PDType0Font.load()'でTrueTypeフォントを使うことができますが、ユニコードが利用可能な場合には(ソリューション内でのみ)動作します。 –

関連する問題