PDFBOX API中是否有任何功能可以使文本对齐,还是必须手动完成?如果必须手动完成,则如何使用Java进行文本对齐(其背后的逻辑是什么)
PDFBOX API中是否有任何功能可以使文本对齐,还是必须手动完成?如果必须手动完成,则如何使用Java进行文本对齐(其背后的逻辑是什么)
这篇旧回答展示了如何将字符串拆分成适合给定width
的子字符串。为了让那里的示例代码以一种填满整个行宽的方式绘制子字符串,请按以下方式替换(根据PDFBox版本):
替换最终循环
for (String line: lines)
{
contentStream.drawString(line);
contentStream.moveTextPositionByAmount(0, -leading);
}
使用这个更为详尽的版本:
for (String line: lines)
{
float charSpacing = 0;
if (line.length() > 1)
{
float size = fontSize * pdfFont.getStringWidth(line) / 1000;
float free = width - size;
if (free > 0)
{
charSpacing = free / (line.length() - 1);
}
}
contentStream.appendRawCommands(String.format("%f Tc\n", charSpacing).replace(',', '.'));
contentStream.drawString(line);
contentStream.moveTextPositionByAmount(0, -leading);
}
(来自于PDFBox 1.8.x的BreakLongString.java测试中的testBreakStringJustified方法,链接:BreakLongString.java)
如果您对replace(',', '.')
有疑问,请看下文。
contentStream.appendRawCommands(String.format("%f Tc\n", charSpacing).replace(',', '.'));
我的地区使用逗号作为小数分隔符,在第一次测试运行时,页面内容中出现了逗号,我有点懒,只是简单地添加了替换来修复问题...
替换最后一个循环
for (String line: lines)
{
contentStream.showText(line);
contentStream.newLineAtOffset(0, -leading);
}
用这个更加详细的:
for (String line: lines)
{
float charSpacing = 0;
if (line.length() > 1)
{
float size = fontSize * pdfFont.getStringWidth(line) / 1000;
float free = width - size;
if (free > 0)
{
charSpacing = free / (line.length() - 1);
}
}
contentStream.setCharacterSpacing(charSpacing);
contentStream.showText(line);
contentStream.newLineAtOffset(0, -leading);
}
(来源于 PDFBox 2.0.x 的 BreakLongString.java 测试中的 testBreakStringJustified 方法, 可查看此链接)
该解决方案仅使用额外的字符间距(操作符 Tc)进行两端对齐。您也可以使用额外的单词间距(操作符Tw),它仅扩展空格字符,或两者的组合; 但请注意: 单词间距无法与所有字体编码一起使用。有关这些操作数的详细信息,请参见 PDF 规范的第 105 表“文本状态操作符”,第 9.3.2 节“字符间距”和第 9.3.3 节“单词间距”。可查看 ISO 32000-1
相较于原来的
现在您将得到
如您所见,仍存在一个小缺陷,即段落的最后一行显然不应该两端对齐。因此,在最后一行中,使用 0
字符间距即可:
contentStream.appendRawCommands("0 Tc\n"); // PDFBox 1.8.x
contentStream.setCharacterSpacing(0); // PDFBox 2.0.x
PS 我刚刚发现 setCharacterSpacing
目前(2016年11月)只在 2.1.0-SNAPSHOT 开发版本中出现,而不是在 2.0.x 发行版本中。因此,在 2.0.x 中您可能需要改用 appendRawCommands
,即使它已被标记为过时。
if(line.length() >= <something>)
的情况下设置CharacterSpacing,并在其他情况下将其设置为0。这样,任何长度(以字符计)低于某个特定值的行都不会被调整。在我的情况下,我使用lines.get(0).length() / 1.5
作为参考(假设存在lines.get(0))。 - Matteo A