You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 15:28:14