如何在iText 7的ISplitCharacters中设置拆分字符优先级
实现iText 7优先级字符拆分方案
要实现优先按连字符、空格拆分,无此类字符时允许任意拆分的需求,需要自定义SplitCharacters和LineSplitter调整拆分逻辑,核心是优先识别高优先级拆分点并选择这些位置拆分。
步骤1:自定义SplitCharacters类
这个类负责标记可拆分的字符位置,同时区分高优先级(连字符、空格)和普通拆分点:
import com.itextpdf.layout.splitting.DefaultSplitCharacters; import com.itextpdf.layout.splitting.GlyphLine; import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class PrioritySplitCharacters extends DefaultSplitCharacters { private static final Set<Character> HIGH_PRIORITY_CHARS = new HashSet<>(Arrays.asList('-', ' ')); @Override public boolean isSplitCharacter(GlyphLine text, int glyphPos) { // 优先标记连字符、空格为可拆分位置 if (glyphPos < text.size() - 1) { char c = text.get(glyphPos).getUnicode(); if (HIGH_PRIORITY_CHARS.contains(c)) { return true; } } // 无高优先级字符时,允许任意字符后拆分 return glyphPos < text.size() - 1; } // 辅助方法:判断当前位置是否为高优先级拆分点 public boolean isHighPrioritySplit(GlyphLine text, int glyphPos) { if (glyphPos < text.size() - 1) { char c = text.get(glyphPos).getUnicode(); return HIGH_PRIORITY_CHARS.contains(c); } return false; } }
步骤2:自定义LineSplitter类
重写拆分位置查找逻辑,优先选择高优先级拆分点,而非默认的从后往前找第一个可拆分点:
import com.itextpdf.layout.splitting.DefaultLineSplitter; import com.itextpdf.layout.splitting.GlyphLine; public class PriorityLineSplitter extends DefaultLineSplitter { private final PrioritySplitCharacters splitChars; public PriorityLineSplitter(PrioritySplitCharacters splitChars) { this.splitChars = splitChars; } @Override protected int findSplitPosition(GlyphLine line, float availableWidth, float em, float emSquare, boolean isLastLine) { // 先找到刚好适配可用宽度的字符位置 int startPos = findGlyphPositionFittingWidth(line, availableWidth, em, emSquare); // 从适配位置往前遍历,优先找高优先级拆分点 for (int i = startPos; i > 0; i--) { if (splitChars.isHighPrioritySplit(line, i)) { return i + 1; // 返回拆分后下一行的起始位置 } } // 无高优先级拆分点时,找任意可拆分位置 for (int i = startPos; i > 0; i--) { if (splitChars.isSplitCharacter(line, i)) { return i + 1; } } // 极端情况:无法拆分时截断第一个字符 return 1; } }
步骤3:在文档中应用自定义拆分规则
将自定义的拆分类绑定到Document对象,即可生效:
import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.Document; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.properties.PageSize; public class PrioritySplitDemo { public static void main(String[] args) throws Exception { PrioritySplitCharacters splitChars = new PrioritySplitCharacters(); PriorityLineSplitter lineSplitter = new PriorityLineSplitter(splitChars); PdfDocument pdfDoc = new PdfDocument(new PdfWriter("priority_split_demo.pdf")); Document doc = new Document(pdfDoc, PageSize.A4); // 绑定自定义拆分规则 doc.setLineSplitter(lineSplitter); doc.setSplitCharacters(splitChars); // 添加测试文本(模拟8字符宽度限制) Paragraph testPara = new Paragraph("a-1234567890") .setWidth(80); // 假设每个字符宽度约10,总宽度80对应8字符 doc.add(testPara); doc.close(); } }
效果说明
对于示例字符串a-1234567890,在8字符宽度限制下,会优先在连字符-处拆分,得到:
- 第一行:
a- - 第二行:
12345678 - 第三行:
90
完全符合需求。
内容的提问来源于stack exchange,提问作者TPancakes
相关产品推荐
相关产品推荐

