使用 pdfbox - 如何从 COSName 获取字体?
Using pdfbox - how to get the font from a COSName?
如何从 COSName 获取字体?
我正在寻找的解决方案看起来像这样:
COSDictionary dict = new COSDictionary();
dict.add(fontname, something); // fontname COSName from below code
PDFontFactory.createFont(dict);
如果您需要更多背景知识,我在下面添加了整个故事:
我尝试替换 pdf 中的一些字符串。这会成功(只要所有文本都存储在一个标记中)。为了保持格式,我喜欢重新居中文本。据我所知,我可以通过获取旧字符串和新字符串的宽度,做一些简单的计算并设置新位置来做到这一点。
我在 Whosebug 上找到了一些替换 (yes it has some issues, but works for my simple pdf's. And How to center a text using PDFBox 的灵感。不幸的是,这个例子使用了一个字体常量。
因此,使用第一个 link 的代码,我得到了对运算符 'TJ' 的处理和对 'Tj'.
的处理。
PDFStreamParser parser = new PDFStreamParser(page);
parser.parse();
java.util.List<Object> tokens = parser.getTokens();
for (int j = 0; j < tokens.size(); j++)
{
Object next = tokens.get(j);
if (next instanceof Operator)
{
Operator op = (Operator) next;
// Tj and TJ are the two operators that display strings in a PDF
if (op.getName().equals("Tj"))
{
// Tj takes one operator and that is the string to display so lets
// update that operator
COSString previous = (COSString) tokens.get(j - 1);
String string = previous.getString();
String replaced = prh.getReplacement(string);
if (!string.equals(replaced))
{ // if changes are there, replace the content
previous.setValue(replaced.getBytes());
float xpos = getPosX(tokens, j);
//if (true) // center the text
if (6 * xpos > page.getMediaBox().getWidth()) // check if text starts right from 1/xth page width
{
float fontsize = getFontSize(tokens, j);
COSName fontname = getFontName(tokens, j);
// TODO
PDFont font = ?getFont?(fontname);
// TODO
float widthnew = getStringWidth(replaced, font, fontsize);
setPosX(tokens, j, page.getMediaBox().getWidth() / 2F - (widthnew / 2F));
}
replaceCount++;
}
}
考虑到 TODO 标签之间的代码,我将从令牌列表中获取所需的值。 (是的,这段代码很糟糕,但现在让我专注于主要问题)
有了字符串、大小和字体,我应该能够从示例代码中调用 getWidth(..) 方法。
不幸的是,我 运行 在从 COSName 变量创建字体时遇到了麻烦。
PDFont 不提供按名称创建字体的方法。
PDFontFactory 看起来不错,但需要一个 COSDictionary。这是我放弃的点,请求你的帮助。
名称与页面资源中的字体对象相关联。
假设您使用 PDFBox 2.0.x 并且 page
是一个 PDPage
实例,您可以使用以下方法解析名称 fontname
:
PDFont font = page.getResources().getFont(fontname);
但是评论中对您提到的问题的警告仍然存在:这种方法仅适用于非常简单的 PDF,甚至可能会损坏其他 PDF。
try {
//Loading an existing document
File file = new File("UKRSICH_Mo6i-Spikyer_z1560-FAV.pdf");
PDDocument document = PDDocument.load(file);
PDPage page = document.getPage(0);
PDResources pageResources = page.getResources();
System.out.println(pageResources.getFontNames() );
for (COSName key : pageResources.getFontNames())
{
PDFont font = pageResources.getFont(key);
System.out.println("Font: " + font.getName());
}
document.close();
}
如何从 COSName 获取字体?
我正在寻找的解决方案看起来像这样:
COSDictionary dict = new COSDictionary();
dict.add(fontname, something); // fontname COSName from below code
PDFontFactory.createFont(dict);
如果您需要更多背景知识,我在下面添加了整个故事:
我尝试替换 pdf 中的一些字符串。这会成功(只要所有文本都存储在一个标记中)。为了保持格式,我喜欢重新居中文本。据我所知,我可以通过获取旧字符串和新字符串的宽度,做一些简单的计算并设置新位置来做到这一点。
我在 Whosebug 上找到了一些替换 (yes it has some issues, but works for my simple pdf's. And How to center a text using PDFBox 的灵感。不幸的是,这个例子使用了一个字体常量。
因此,使用第一个 link 的代码,我得到了对运算符 'TJ' 的处理和对 'Tj'.
的处理。 PDFStreamParser parser = new PDFStreamParser(page);
parser.parse();
java.util.List<Object> tokens = parser.getTokens();
for (int j = 0; j < tokens.size(); j++)
{
Object next = tokens.get(j);
if (next instanceof Operator)
{
Operator op = (Operator) next;
// Tj and TJ are the two operators that display strings in a PDF
if (op.getName().equals("Tj"))
{
// Tj takes one operator and that is the string to display so lets
// update that operator
COSString previous = (COSString) tokens.get(j - 1);
String string = previous.getString();
String replaced = prh.getReplacement(string);
if (!string.equals(replaced))
{ // if changes are there, replace the content
previous.setValue(replaced.getBytes());
float xpos = getPosX(tokens, j);
//if (true) // center the text
if (6 * xpos > page.getMediaBox().getWidth()) // check if text starts right from 1/xth page width
{
float fontsize = getFontSize(tokens, j);
COSName fontname = getFontName(tokens, j);
// TODO
PDFont font = ?getFont?(fontname);
// TODO
float widthnew = getStringWidth(replaced, font, fontsize);
setPosX(tokens, j, page.getMediaBox().getWidth() / 2F - (widthnew / 2F));
}
replaceCount++;
}
}
考虑到 TODO 标签之间的代码,我将从令牌列表中获取所需的值。 (是的,这段代码很糟糕,但现在让我专注于主要问题)
有了字符串、大小和字体,我应该能够从示例代码中调用 getWidth(..) 方法。
不幸的是,我 运行 在从 COSName 变量创建字体时遇到了麻烦。
PDFont 不提供按名称创建字体的方法。 PDFontFactory 看起来不错,但需要一个 COSDictionary。这是我放弃的点,请求你的帮助。
名称与页面资源中的字体对象相关联。
假设您使用 PDFBox 2.0.x 并且 page
是一个 PDPage
实例,您可以使用以下方法解析名称 fontname
:
PDFont font = page.getResources().getFont(fontname);
但是评论中对您提到的问题的警告仍然存在:这种方法仅适用于非常简单的 PDF,甚至可能会损坏其他 PDF。
try {
//Loading an existing document
File file = new File("UKRSICH_Mo6i-Spikyer_z1560-FAV.pdf");
PDDocument document = PDDocument.load(file);
PDPage page = document.getPage(0);
PDResources pageResources = page.getResources();
System.out.println(pageResources.getFontNames() );
for (COSName key : pageResources.getFontNames())
{
PDFont font = pageResources.getFont(key);
System.out.println("Font: " + font.getName());
}
document.close();
}