
在使用 iText 7 处理 PDF 文档时,将可变长度文本内容渲染到固定尺寸的绘制区域内是一个常见需求。然而,当文本内容超出预设区域长度时,iText 7 可能会抛出 `IllegalArgumentException`。本文将详细介绍如何通过更新 iText 版本并结合自定义 `ParagraphRenderer` 来解决此问题,确保长文本在指定区域内被正确渲染或裁剪,而无需预先测量文本长度。
在 iText 7 中,开发者常通过 Paragraph 配合 Canvas 来将文本内容放置到 PDF 页面上的特定矩形区域内。然而,当尝试将一个包含过长文本的 Paragraph 添加到一个尺寸受限的 Canvas 或直接设置了 setWidth/setHeight 的 Paragraph 时,可能会遇到 java.lang.IllegalArgumentException: fromIndex(0) > toIndex(-1) 异常。
考虑以下代码片段,它尝试将一个较长的字符串渲染到一个宽度和高度都非常有限的矩形区域内:
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.BlockElement;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.io.font.PdfFontFactory;
import com.itextpdf.kernel.font.PdfFont;
import java.io.IOException;
public class ITextLongTextProblem {
public static void main(String[] args) throws IOException {
try (PdfWriter writer = new PdfWriter("test_problem.pdf");
PdfDocument pdf = new PdfDocument(writer)) {
// 创建页面
PdfPage currentPage = pdf.addNewPage(PageSize.A4);
// 定义绘制矩形区域
Rectangle rect = new Rectangle(
75f,
currentPage.getPageSize().getHeight() - 315f - 22f,
75f, // 宽度
22f // 高度
);
// 创建字体
PdfFont currentFont = PdfFontFactory.createFont(
"Helvetica",
"Cp1252"
);
// 创建段落,并设置宽度和高度
Paragraph p = (new Paragraph("Some longer value that will definitely overflow the small rectangle"))
.setFont(currentFont)
.setFontSize(12f)
.setWidth(75f)
.setHeight(22f)
.setTextAlignment(TextAlignment.LEFT);
// 将段落添加到 Canvas
// 在 iText 7.0.1 等早期版本中,当文本过长时,此行会抛出异常
(new Canvas(new PdfCanvas(currentPage), pdf, rect))
.add((BlockElement)p);
}
}
}当上述代码中的字符串 "Some longer value that will definitely overflow the small rectangle" 超过 Paragraph 定义的 75f 宽度时,程序在执行 (new Canvas(...)).add((BlockElement)p); 时会抛出以下异常:
Exception in thread "main" java.lang.IllegalArgumentException: fromIndex(0) > toIndex(-1)
at java.base/java.util.AbstractList.subListRangeCheck(AbstractList.java:509)
at java.base/java.util.ArrayList.subList(ArrayList.java:1138)
at com.itextpdf.layout.renderer.ParagraphRenderer.layout(ParagraphRenderer.java:235)
at com.itextpdf.layout.renderer.RootRenderer.addChild(RootRenderer.java:84)
at com.itextpdf.layout.renderer.CanvasRenderer.addChild(CanvasRenderer.java:86)
at com.itextpdf.layout.RootElement.add(RootElement.java:98)
at itext.bug.reproduce.ITextBugReproduce.main(ITextBugReproduce.java:50)这个异常表明 iText 内部在计算段落布局时,由于文本内容无法完全适应其指定的尺寸,导致了列表索引计算错误。即使 Canvas 旨在限制绘制区域,但 Paragraph 自身的布局计算机制在遇到溢出时仍可能失效。
解决此问题的关键在于两点:
以下是结合这两个策略的解决方案代码:
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.BlockElement;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.io.font.PdfFontFactory;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.layout.renderer.LayoutArea;
import com.itextpdf.layout.renderer.ParagraphRenderer;
import org.apache.log4j.BasicConfigurator; // 用于满足日志要求,可选
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ITextLongTextSolution {
public static void main(String[] args) throws IOException {
BasicConfigurator.configure(); // 初始化日志,避免控制台警告,可选
try (PdfWriter writer = new PdfWriter("test_solution.pdf");
PdfDocument pdf = new PdfDocument(writer)) {
// 创建页面
PdfPage currentPage = pdf.addNewPage(PageSize.A4);
// 定义绘制矩形区域
Rectangle rect = new Rectangle(
75f,
currentPage.getPageSize().getHeight() - 315f - 22f,
75f, // 宽度
22f // 高度
);
// 创建字体
PdfFont currentFont = PdfFontFactory.createFont(
"Helvetica",
"Cp1252"
);
// 创建段落
Paragraph p = (new Paragraph("Some longer value that will definitely overflow the small rectangle"))
.setFont(currentFont)
.setFontSize(12f)
.setWidth(75f)
.setHeight(22f)
.setTextAlignment(TextAlignment.LEFT);
// 关键步骤:重写渲染器以显式定义布局区域
p.setNextRenderer(new ParagraphRenderer(p) {
@Override
public List<LayoutArea> initElementAreas(LayoutArea area) {
List<LayoutArea> list = new ArrayList<>();
// 将预定义的矩形作为段落的唯一布局区域
list.add(new LayoutArea(0, rect)); // 使用rect作为布局区域
return list;
}
});
// 将段落添加到 Canvas,注意这里 Canvas 的构造函数也传入了 rect
// 这样 Canvas 自身也会限制绘制到这个区域
(new Canvas(new PdfCanvas(currentPage), rect))
.add((BlockElement) p);
}
}
}通过上述方法,开发者可以在 iText 7 中有效地解决固定区域内长文本渲染引发的 IllegalArgumentException,实现对文本内容在指定矩形区域内的可靠渲染和裁剪。
以上就是iText 7 固定区域长文本渲染异常解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号