如何通过PDFBox库为PDF设置wordSpacing(Tw)
如何通过PDFBox库为PDF设置wordSpacing(Tw)
刚好遇到过类似的问题,我来给你拆解下原因和解决办法:
问题根源
你设置的wordSpacing(也就是PDF里的Tw参数)只对PDF内容中实际存在的空格字符(U+0020)生效,但PDFBox的showText()方法在处理带空格的文本时,尤其是使用TrueType这类复合字体时,会自动把空格当成文本分隔符,不会将空格字符编码到最终的Tj指令里——你贴出的PDF指令里看不到空格,就是这个原因,自然Tw就没效果了。
解决方案
这里给你两种可行的办法,根据你的字体需求选就行:
方案一:改用Type1内置字体(最简单)
PDFBox内置的Type1字体(比如PDType1Font.HELVETICA、PDType1Font.TIMES_ROMAN)默认编码包含空格字符,showText()会正确保留空格,此时setWordSpacing()就能直接生效。修改你的代码:
try (PDPageContentStream stream = new PDPageContentStream( pdf, page, PDPageContentStream.AppendMode.APPEND, false, true) ) { stream.saveGraphicsState(); // 替换成Type1字体,这里用Helvetica举例 PDType1Font font = PDType1Font.HELVETICA; float fontSize = 12; // 按需调整字号 stream.setFont(font, fontSize); stream.setNonStrokingColor(Color.BLACK); // 按需调整颜色 stream.beginText(); stream.newLineAtOffset(100, 100); stream.setWordSpacing(50); // 字间距设置现在会生效 stream.showText("HELLO WORLD"); stream.endText(); stream.restoreGraphicsState(); }
方案二:手动处理空格(适用于必须用自定义字体的场景)
如果你一定要用TrueType这类复合字体,可以手动拆分文本并输出空格,或者直接编码带空格的字符串用原始指令输出,确保PDF里有实际的空格字符:
try (PDPageContentStream stream = new PDPageContentStream( pdf, page, PDPageContentStream.AppendMode.APPEND, false, true) ) { stream.saveGraphicsState(); stream.setFont(font, fontSize); stream.setNonStrokingColor(color); stream.beginText(); stream.newLineAtOffset(100, 100); stream.setWordSpacing(50); // 方法1:拆分文本,手动输出空格 stream.showText("HELLO"); // 用字体编码空格,确保能被PDF识别 byte[] spaceBytes = font.encode(" "); stream.addRawCommand(String.format("(%s) Tj", new String(spaceBytes))); stream.showText("WORLD"); // 方法2:直接编码整个带空格的字符串,用原始指令输出 // byte[] fullTextBytes = font.encode("HELLO WORLD"); // stream.addRawCommand(String.format("(%s) Tj", new String(fullTextBytes))); stream.endText(); stream.restoreGraphicsState(); }
验证效果
修改后你再查看PDF的内容指令,应该能看到包含空格的Tj片段,比如:
BT 78.3975 777.75494 Td 50 Tw (HELLO) Tj ( ) Tj (WORLD) Tj ET
这时候Tw参数就会作用在空格上,实现你想要的字间距调整效果。
备注:内容来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

