我有几个带有一些嵌入字体的pdf / a文档,现在我要使用iText对这些文档进行后期处理以添加水印。
我知道可以使用iText嵌入字体:
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
但我想使用已经嵌入文档中的字体来添加文本水印(类似“SAMPLE COPY”)。
我该怎么做?
答案 0 :(得分:2)
你想要的是DocumentFont
。你不能直接创建它们,构造函数是包私有的,但BaseFont.createFont(PRIndirectReference)
可以解决这个问题。
所以你只需要PRIndirectReference
得到你想要的字体。 “PR”来自PdfReader。有两种方法可以找到您正在寻找的字体并获得对它的引用:
1)枚举PdfReader中的每个对象,过滤掉所有不是PRStream
的对象,从那里删除所有不是/Type /Font
的对象,并查找具有正确名称的字体。
public PRIndirectReference findNamedFont( PdfReader myReader, String desiredFontName) {
int objNum = 0;
PdfObject curObj;
do {
//The "Release" version doesn't keep a reference
//to the object so it can be GC'd later. Quite Handy
//when dealing with Really Big PDFs.
curObj = myReader.getPdfObjectRelease( objNum++ );
if (curObj instanceof PRStream) {
PRStream stream = (PRStream)curObj;
PdfName type = stream.getAsName(PdfName.TYPE);
if (PdfName.FONT.equals(type)) {
PdfString fontName = stream.getAsString(PdfName.BASEFONT);
if (desiredFontName.equals(fontName.toString())) {
return curObj.getIndRef();
}
}
}
} while (curObj != null);
return null;
}
2)检查您网页的资源词典/Font <<>>
,查找具有正确名称的字体。请记住,XObject Form资源拥有自己需要检查的资源:
public PRIndirectReference findFontInPage(PdfReader reader, String desiredName, int i) {
PdfDictionary page = reader.getPageN(i);
return findFontInResources(page.getAsDict(PdfName.RESOURCES), desiredName);
}
public PRIndirectReference findFontInResources(PdfDictionary resources, String desiredName) {
if (resources != null) {
PdfDictionary fonts = resources.getAsDict(PdfName.FONTS);
if (fonts != null) {
for (PdfName curFontName : fonts.keySet()) {
PRStream curFont (PRStream)= fonts.getAsStream(curFontName);
if (desiredName.equals(curFont.getAsString(PdfName.BASEFONT).toString()) {
return (PRIndirectReference) curFont.getIndirectReference();
}
}
}
PdfDictionary xobjs = resources.getAsDict(PdfName.XOBJECTS);
if (xobjs != null) {
for (PdfName curXObjName : xobjs.keySet()) {
PRStream curXObj = (PRStream)xobjs.getAsStream(curXObjName);
if (curXObj != null && PdfName.FORM.equals(curXObj.getAsName(PdfName.SUBTYPE)) {
PdfDictionary resources = curXObj.getAsDict(PdfName.RESOURCES);
PRIndirectReference ref = findFontInResources(resources, desiredName);
if (ref != null) {
return ref;
}
}
}
}
}
return null;
}
其中任何一个都会让你获得PRIndirectReference
。然后,您拨打BaseFont.createFont(myPRRef)
,即可获得所需的DocumentFont
。第一种方法将在PDF中找到任何字体,而第二种方法只能找到实际使用的字体。
此外,子集化字体应该在字体名称前加上“6-random-letters-plus-sign”标签。不要使用字体子集。您正在使用的字符可能不在子集中,导致我称之为“arry ole”的问题。这听起来不错又脏,但它实际上只是我们的销售人员的名字:“Harry Vole”错过了大写字母,因为我将一些字体分类,我不应该拥有许多月之前。
PS:永远不会嵌入您打算在表单字段中使用的字体子集。没有布埃诺。
通常的“我在这里的答案框中写了所有代码”免责声明适用,但我写了很多这样的代码,所以它可能开箱即用。交叉你的手指。 ;)
答案 1 :(得分:1)
完全不同的方法:使用Line Art而不是Text。
如果您从页面的overContent创建“仅限艺术线条”的PdfGraphics2D对象,则可以使用AWT字体,而无需担心嵌入。使用相对较短的字符串,您不必担心PDF的大小会爆炸。
PdfContentByte overcontent = stamper.getOverContent(1);
Graphics2D g2d = overcontent.createGraphicsShapes(pageWid, pageHei);
drawStuffToTheGraphic(g2d);
g2d.dispose();
这将导致“文本”实际上是艺术线条。它无法被选中,搜索等。这可能是好的或坏的,取决于你所追求的。
答案 2 :(得分:0)
使用普通的jPod(BSD,SourceForge),您可以基于“水印”示例。与
PDFontTools.getFonts(doc)
你可以枚举字体,然后在“createForm”方法中使用其中一种......