2016-08-05 2 views
4

이전에 읽은 문서의 요소 (https://www.dropbox.com/s/ttxiv0dq3abh5kj/Test.pdf?dl=0)에서 pdf 문서를 작성하는 데 문제가 있습니다. 모든 것은 잘 작동합니다. 이전에 out.setFont(textState.getFont(), textState.getFontSize()) (INFORMATION LOG 참조)으로 글꼴을 설정 한 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의 두 번째 부분에서 "w"대신 "90"("w"대신)과 같은 글리프 ID로 가상 이름을 만듭니다. "("글리프 이름은 "parenleft").

enter image description here

글꼴 인코딩 항목이없는 것처럼. 당신은 다른 글꼴에 PDFDebugger로 보면 인코딩, PDFBox는, 어도비 Glyphlist를 사용하는 경우에는, 예를 들어 R18, 당신은 찾을 수

"인코딩 : WinAnsiEncoding는 "

enter image description here

당신은 무엇을 분명히하고있는 것은 creat에하는 것입니다 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 문서를 만들 수있는 방법이 없다고합니다. 적어도 포함 된 문자에 대한 글리프 (glyph)를 표시하기 위해 원본 문서 내에서 사용 가능/내장되어 있더라도 말이죠. 3. 그렇다면 소스 문서에서 사용 된 글꼴이 인코딩에 사용되는지 여부 및/또는 해당 글꼴을로드 한 다음 다시 사용하는 방법 (Arial Black 및 Comis Sans MS 모두 사용 가능)을 프로그래밍 방식으로 확인할 수 있습니까? 적어도 대부분의 Windows 설치에서 사용할 수 있습니까?) – Juergen

+0

2. 쉽지 않습니다. PDFBox를 변경하려고 생각하고 조금만 시도해 보았지만 생각보다 훨씬 많은 작업으로 발전했습니다.심지어 일부 경우에는 실패 할 수도 있습니다. PDF에서 한 코드가 여러 유니 코드를 의미하는 합자를 사용합니다. 그리고 당신은 "유니 코드"가 전혀 없다는 것을 확신 할 수 없으며, 일부 PDF 파일은 그것을 가지고 있지 않습니다. 또 다른 해결책은 원시 명령어를 사용하는 것이지만, 너무 까다로울 수 있으며, 일부 코드는 2 바이트가 아니라 하나입니다. –

+0

3. 글꼴에서 getEncoding()을 호출하고 (해당 유형에 사용할 수있는 경우) contains (code) 또는 getName (int code)을 사용하여 확인할 수 있습니다. TrueType 글꼴을'PDType0Font.load()'와 함께 사용할 수는 있지만 유니 코드를 사용할 수있는 경우에만 솔루션에서 작동합니다. –

관련 문제