iText 7渲染超长文本至固定矩形时抛出异常的解决方法
问题:iText 7 在固定矩形中绘制超长字符串抛出异常
我需要用iText 7将可变长度的字符串添加到固定的绘制矩形中,示例代码如下:
try (PdfWriter writer = new PdfWriter("test.pdf"); PdfDocument pdf = new PdfDocument(writer)) { // Create a page PdfPage currentPage = pdf.addNewPage(PageSize.A4); // Create the position rectangle Rectangle rect = new Rectangle( 75f, currentPage.getPageSize().getHeight() - 315f - 22f, 75f, 22f ); // Create the font PdfFont currentFont = PdfFontFactory.createFont( "Helvetica", "Cp1252" ); // Create the paragraph Paragraph p = (new Paragraph("Some longer value")) .setFont(currentFont) .setFontSize(12f) .setWidth(75f) .setHeight(22f) .setTextAlignment(TextAlignment.LEFT); // Add the paragraph (new Canvas(new PdfCanvas(currentPage), pdf, rect)) .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)
将"Some longer value"替换为"test"时一切正常,说明向小绘制区域添加超长字符串会失败。实际场景中仅知晓目标绘制区域,无法预知待处理字符串的长度,请问如何无需预测量即可将超长字符串绘制到PDF中?
更新:即使扩大段落尺寸,仍会出现相同异常,因此推测问题并非出在段落上,而是用于限制绘制范围的Canvas(避免覆盖矩形外内容)。
解决方案
方法1:自动缩小字体适配矩形
通过动态调整字体大小,确保内容能完整放入目标矩形内,无需提前预估长度:
try (PdfWriter writer = new PdfWriter("test.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"); String content = "Some longer value that needs to fit into the small rectangle"; Paragraph p = new Paragraph(content) .setFont(currentFont) .setTextAlignment(TextAlignment.LEFT); Canvas canvas = new Canvas(new PdfCanvas(currentPage), pdf, rect); // 从初始字体大小逐步缩小,直到内容适配矩形 float fontSize = 12f; boolean fits = false; while (fontSize > 4f && !fits) { p.setFontSize(fontSize); LayoutResult result = p.createRendererSubTree() .setParent(canvas.getRenderer()) .layout(new LayoutContext(new LayoutArea(1, rect))); fits = result.getStatus() == LayoutResult.FULL; if (!fits) fontSize -= 0.5f; } canvas.add(p); }
方法2:裁剪超出矩形的内容
如果不需要完整显示内容,直接裁剪超出矩形的部分,通过PdfCanvas的裁剪路径实现:
try (PdfWriter writer = new PdfWriter("test.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"); PdfCanvas pdfCanvas = new PdfCanvas(currentPage); // 绘制裁剪路径并启用裁剪 pdfCanvas.rectangle(rect); pdfCanvas.clip(); pdfCanvas.newPath(); Paragraph p = new Paragraph("Some longer value") .setFont(currentFont) .setFontSize(12f) .setTextAlignment(TextAlignment.LEFT); Canvas canvas = new Canvas(pdfCanvas, pdf, rect); canvas.add(p); }
关键说明
原异常是由于段落内容超出Canvas可用空间时,iText布局渲染器处理子元素列表时出现索引错误。上述两种方法分别通过适配内容到矩形或裁剪溢出内容的方式避免该异常,可根据业务需求选择。
内容的提问来源于stack exchange,提问作者nd_
相关产品推荐
相关产品推荐

