2014-04-10 5 views
0

iTextPDF (Windows에서 직접 만든 COOPBL.TTF)가 아닌 글꼴을 사용하여 간단한 "Hello World"파일을 만들기 위해 iTextPDF를 사용하는 간단한 Java 프로그램이 있습니다.itextpdf 글꼴이 리눅스에 포함되어 있지 않습니다.

Windows 7-64에서 실행하면 정상적으로 실행되고 파일 모양에 반영된 Cooper Black 글꼴 서브 세트가 파일에 임베드 된 pdf 파일이 작성됩니다.

Linux에서 똑같은 클래스 파일을 실행 (다시 컴파일하지 않음)하면 아무 것도 포함시키지 않고 Helvetica를 사용합니다.

import java.io.ByteArrayInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 

import com.itextpdf.text.FontFactory; 
import com.itextpdf.text.Document; 
import com.itextpdf.text.PageSize; 
import com.itextpdf.text.DocumentException; 
import com.itextpdf.text.pdf.PdfWriter; 

import com.itextpdf.tool.xml.XMLWorkerHelper; 


public class iTextTest { 
    private void doit(String sOut) { 
    Document doc = new Document(PageSize.LETTER); 

    try { 
     FileOutputStream fOut = new FileOutputStream(sOut); 

     // Register a non-native font. 
     String sFontDir = "."; 
     int iResult = FontFactory.registerDirectory(sFontDir); 
     if(iResult == 0) { 
     System.out.println("TestPDF(): Could not register font directory " + sFontDir); 
     } else { 
     System.out.println("TestPDF(): Registered font directory " + sFontDir); 
     } 
     System.out.println(" Fonts registered:"); 
     for(String sFont:FontFactory.getRegisteredFonts()) { 
     System.out.println(" " + sFont); 
     } 

     PdfWriter pdfWriter = PdfWriter.getInstance(doc, fOut); 

     doc.open(); 

     XMLWorkerHelper helper = XMLWorkerHelper.getInstance(); 

     String htmlContent; 
     htmlContent = "<HTML><HEAD></HEAD><BODY>"; 
     htmlContent += "<P style=\"font-family: cooperblack;\">"; 
     htmlContent += "Hello World!"; 
     htmlContent += "</P>"; 
     htmlContent += "</BODY></HTML>"; 
     helper.parseXHtml(pdfWriter, doc, new ByteArrayInputStream(htmlContent.getBytes())); 

    } catch(IOException e) { 
     e.printStackTrace(); 
    } catch(DocumentException e) { 
     e.printStackTrace(); 
    } 

    if(doc != null) { 
     doc.close(); 
    } 
    } 


    public static void main(String[] args) { 
    if(args.length != 1) { 
     System.out.println("Usage: iTextTest outfile"); 
     return; 
    } 

    iTextTest test = new iTextTest(); 
    test.doit(args[0]); 
    } 
} 

내가 사용 : itextpdf-5.5.0 xmlworker-5.5.0 윈도우 자바 1.6.0_21 리눅스 자바 1.6.0_23

나는 것을 여기

프로그램입니다 글꼴의 복사본과 결과로 나오는 pdf 파일을 포함시키지 만 명백한 방법은 없습니다. 필자의 테스트를 위해 Windows 테스트와 Linux 테스트 모두를 위해 \ Windows \ fonts \ COOPBL.TTF를 테스트 디렉토리에 복사했다.

가치가있는 내용 : - 글꼴 파일의 보호/속성 플래그를 조정해도 아무런 차이가 없습니다. - 공개 도메인 글꼴이 아닙니다. 나는 그것을 시험을 위해서만 사용하고있다.

나는 모든 의견의 귀입니다.

덕분에, 척 윈도우와 리눅스 (윈도우 Ecplise 및 콘솔 JDB의 -ack!)에 나란히 디버깅 후

+0

'String sFontDir = ".";을 정의하지만''. "'은 리눅스와 비교할 때 Windows에서 다를 수 있습니다. ''. "'의 절대 경로를'System.out'에 적어주세요. 리눅스에서 기대했던 것이 아닐 것이라고 확신합니다. 'COOPBL.TTF' 파일을 리눅스가 반환 한 경로로 옮겨야합니다. –

+0

감사합니다, Bruno, 나는 getPath, getAbsolutePath 및 getCanonicalPath를 시도했으며, 두 OS 모두에서 테스트를 실행중인 현재 디렉토리에 대한 예상 결과를 모두 반환합니다. registerDirectory()를 호출 한 후 등록 된 글꼴을 나열합니다. FontFactory.getRegisteredFonts()에 따르면, 글꼴 파일이 등록되고 있으며 그 화신 중 하나의 정확한 이름 (cooperblack)을 사용하고 있습니다. –

+0

그건 이상합니다. 나는 전에 그 문제를 본 적이 없다. Windows와 Linux 모두에서 모든 예제를 실행합니다. 이 문제를 해결하려면 재현 할 수 있어야하지만 그렇게 할 수는 없습니다. –

답변

2

, 나는이 문제를 알아 냈어. 그것은 문서의 단점이나 내 부분에 대한 감독처럼 보인다. 나는 다른 사람이 비슷한 문제를 겪었을 때를 대비하여 여기에 수정 사항을 게시 할 것이라고 생각했습니다.

문제는 XMLWorkerHelper를 사용하여 파일을 구문 분석 할 때 기본 FontFactory를 사용하여 글꼴을 등록하지 않아야한다는 것입니다. 첫 번째 코드 샘플에서 사용한 XMLWorkerHelper.parseXHtml()의 풍미는 자체 FontFactoryImp, XMLWorkerFontProvider를 만듭니다. 그 프로 바이더는, 디폴트의 FontFactory에 의해 실행 된 등록을 무시합니다.

해결 방법은 두 가지입니다.
1) 고유 한 XMLWorkerFontProvider를 만듭니다. 글꼴 디렉토리를 입력 매개 변수로 사용하는 생성자를 사용하십시오.
2) 더 짧은 호출을 사용하지 않고 해당 제공자를 parseXHtml()에 전달합니다.

또한 FontFactory.setFontImp()를 사용하여 기본 FontFactory 공급자를 설정합니다. 나는 그 행동의 미묘한 함의를 연구하지는 않았지만, 그 단계를 건너 뛰어도 될지는 불확실하다.

그것은 원래의 프로그램이 윈도우에서 작동하는 유일한 이유는() parseXHtml에 안에 내 원래 통화를 제공 받고 기본 XMLWorkerFontProvider 모든 시스템 디렉토리에있는 모든 글꼴을 등록하는 것을 언급 할 가치가있다. Windows 측에서 이미 C :/Windows/fonts에있는 글꼴을 사용하고 있었기 때문에 로컬 디렉토리에있는 파일이 아니라 그 글꼴이 선택되었습니다. Windows에 등록되지 않은 새로운 글꼴을 사용했다면 Windows 테스트도 실패했을 것입니다.

다음은 작동하는 해결책입니다.Windows 및 Linux에서 동일한 pdf 파일을 생성합니다.

참고 : XMLWorkerHelper.parseXHtml() 대신 XMLParser.parse()를 사용하는 경우이 코드 블록 다음에 나오는 추가 주석을 확인하십시오.

import java.io.ByteArrayInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.File; 

import com.itextpdf.text.FontFactory; 
import com.itextpdf.text.Document; 
import com.itextpdf.text.PageSize; 
import com.itextpdf.text.DocumentException; 
import com.itextpdf.text.pdf.PdfWriter; 

import com.itextpdf.tool.xml.XMLWorkerHelper; 
import com.itextpdf.tool.xml.XMLWorkerFontProvider; 


public class iTextTest { 
    private void doit(String sOut) { 
    Document doc = new Document(PageSize.LETTER); 

    try { 
     FileOutputStream fOut = new FileOutputStream(sOut); 

     // Register non-native fonts in a directory. 
     String sFontDir = "."; 
     XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(sFontDir, null); 
     FontFactory.setFontImp(fontImp); 

     System.out.println(" Fonts registered before parsing:"); 
     for(String sFont:FontFactory.getRegisteredFonts()) { 
     System.out.println(" " + sFont); 
     } 

     PdfWriter pdfWriter = PdfWriter.getInstance(doc, fOut); 

     doc.open(); 

     XMLWorkerHelper helper = XMLWorkerHelper.getInstance(); 

     String htmlContent; 
     htmlContent = "<HTML><HEAD></HEAD><BODY>"; 
     htmlContent += "<P style=\"font-family: cooperblack;\">"; 
     htmlContent += "Hello World!"; 
     htmlContent += "</P>"; 
     htmlContent += "</BODY></HTML>"; 
     helper.parseXHtml(pdfWriter, 
         doc, 
         new ByteArrayInputStream(htmlContent.getBytes()), 
         XMLWorkerHelper.class.getResourceAsStream("/default.css"), 
         null, 
         fontImp); 

    } catch(IOException e) { 
     e.printStackTrace(); 
    } catch(DocumentException e) { 
     e.printStackTrace(); 
    } 

    if(doc != null) { 
     doc.close(); 
    } 
    } 


    public static void main(String[] args) { 
    if(args.length != 1) { 
     System.out.println("Usage: iTextTest outfile"); 
     return; 
    } 

    iTextTest test = new iTextTest(); 
    test.doit(args[0]); 
    } 
} 

최신 업데이트에서 XMLParser를 사용하는 코드도 수정해야했습니다. 문제는 비슷했다. 기본 HtmlPipelineContext는 자체 XMLWorkerFontProvider를 만듭니다. 위에서 설명한 경우와 마찬가지로 기본 FontFactory.registerDirectory()를 사용하여 등록한 글꼴은 무시됩니다. 다시 말하지만 해결 방법은 XMLWorkerFontProvider를 사용하여 HtmlPipelineContext에 제공하는 것입니다. 그런 다음 자신의 XMLWorker에 대한 새로운 CssResolverPipeline을 만들어야합니다. 그러면 XMLParser 생성자에 전달됩니다.

다음은이를 보여주는 코드의 작은 블록 (사용자 정의 이미지 처리기)입니다 :

htmlContext = new HtmlPipelineContext(new CssAppliersImpl(fontImp)); 
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); 

    pdfImageProvider = new PDFImageProvider(); // Optional 
    htmlContext.setImageProvider(pdfImageProvider); // Optional 

    Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipeline(doc, pdfWriter))); 
    xmlWorker = new XMLWorker(pipeline, true); 
    xmlParser = new XMLParser(true, xmlWorker, charsetUTF8); 

나는이가 나를 추적하는 데 걸린 여러 일이 사람을 절약 바랍니다!

+0

필자의 경우 (windows \ fonts), 시스템 글꼴 폴더에서 가져 왔지만 리눅스에 배포했을 때 ttf를 찾을 수 없다 –

관련 문제