我有一个简单的Java程序,它使用iTextPDF创建一个简单的" Hello World"文件,使用的字体不是iTextPDF(COOPBL.TTF,直接来自Windows)。
在Windows 7-64上运行它运行正常并创建一个pdf文件,其中包含文件中嵌入的Cooper Black字体的子集,反映在文件外观中。
在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 Windows Java 1.6.0_21 Linux Java 1.6.0_23
我会包含字体副本和生成的pdf,但是看不到明显的方法。对于我的测试,我只是将\ Windows \ fonts \ COOPBL.TTF复制到测试目录中,用于Windows测试和Linux测试。
它的价值: - 调整字体文件中的保护/属性标志没有区别。 - 我知道这不是一个公共域名字体。我只是用它进行测试。
我对所有评论都赞不绝口!
谢谢, 卡盘
答案 0 :(得分:2)
在Windows和Linux(Windows Ecplise和控制台jdb -ack!)上并排调试后,我发现了问题。这似乎是一个文档缺点,或者是我的疏忽。我以为我会在这里发布修复程序以防其他人遇到类似的问题。
问题是,如果我打算使用XMLWorkerHelper来解析文件,我不应该使用默认的FontFactory来注册字体。我在第一个代码示例中使用的XMLWorkerHelper.parseXHtml()的风格创建了自己的FontFactoryImp,XMLWorkerFontProvider。该提供程序忽略默认FontFactory执行的任何注册。
修复是双重的:
1)创建自己的XMLWorkerFontProvider。使用将字体目录作为输入参数的构造函数
2)将该提供者传递给parseXHtml(),而不是使用较短的调用。
我还使用FontFactory.setFontImp()设置了默认的FontFactory提供程序。我没有研究过这个动作的微妙含义,但是很容易跳过这个步骤。
值得一提的是,原始程序在Windows中工作的唯一原因是,在内部提供的默认XMLWorkerFontProvider 我对parseXHtml()的原始调用会记录所有系统目录中的所有字体。因为,在Windows端,我使用的是已经在C:/ Windows / fonts中的字体,这是被拾取的字体,而不是本地目录中的文件。如果我使用了未在Windows中注册的新字体,则Windows测试也会失败。
这是工作解决方案。它在Windows和Linux上生成相同的pdf文件:
注意:如果您使用的是XMLParser.parse()而不是XMLWorkerHelper.parseXHtml(),请在此代码块之后查看其他注释。
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);
我希望这可以节省一些人,因为我花了几天的时间来追踪!