iText7多Text元素场景下如何绘制指定波浪下划线?
iText7 多Text元素自定义下划线定位问题解决方案
问题根因
你把完整字符串拆分为单个字符对应的Text元素后,每个DashedLineTextRenderer拿到的getOccupiedAreaBBox()仅为单个字符的宽高,你原逻辑里固定画200单位长度的曲线,自然会出现定位错位、重复绘制的问题。同时单个字符的Renderer互相独立,无法感知相邻字符的位置,也就无法绘制连续的下划线。
方案1(优先推荐:无需拆分Text)
如果没有必须拆分单个字符的业务需求(比如不同字符要设置不同颜色/字体),直接给整段文本对应的单个Text设置自定义Renderer即可,原有绘制逻辑无需修改:
String s = "This text is underlined with a dashed line"; Paragraph paragraph = new Paragraph(); Text text = new Text(s); text.setNextRenderer(new DashedLineTextRenderer(text)); paragraph.add(text); doc.add(paragraph); doc.close();
该方案可以直接还原单个Text元素场景下的正常波浪线效果。
方案2(必须拆分多个Text场景)
如果确实需要拆分多个Text元素(比如单字符定制样式),需要通过自定义ParagraphRenderer收集同一行内所有需要加下划线的Text的位置,合并后统一绘制连续下划线:
第一步:修改自定义TextRenderer,仅做标记不做绘制
private static class DashedLineTextRenderer extends TextRenderer { // 标记是否需要绘制下划线 public boolean needUnderline = true; public DashedLineTextRenderer(Text textElement) { super(textElement); } @Override public IRenderer getNextRenderer() { return new DashedLineTextRenderer((Text) modelElement); } // 移除原draw方法里的下划线绘制逻辑,仅保留文本绘制 @Override public void draw(DrawContext drawContext) { super.draw(drawContext); } }
第二步:自定义ParagraphRenderer统一绘制下划线
private static class UnderlineParagraphRenderer extends ParagraphRenderer { public UnderlineParagraphRenderer(Paragraph modelElement) { super(modelElement); } @Override public IRenderer getNextRenderer() { return new UnderlineParagraphRenderer((Paragraph) modelElement); } @Override public void draw(DrawContext drawContext) { super.draw(drawContext); PdfCanvas canvas = drawContext.getCanvas(); // 按行处理,合并同一行内所有需要加下划线Text的占用区域 for (LineRenderer line : lines) { List<Rectangle> underlineRects = new ArrayList<>(); for (IRenderer child : line.getChildRenderers()) { if (child instanceof DashedLineTextRenderer && ((DashedLineTextRenderer) child).needUnderline) { underlineRects.add(child.getOccupiedAreaBBox()); } } if (!underlineRects.isEmpty()) { // 计算连续区域的左右边界与统一基线Y坐标 float left = underlineRects.stream().min(Comparator.comparing(Rectangle::getLeft)).get().getLeft(); float right = underlineRects.stream().max(Comparator.comparing(Rectangle::getRight)).get().getRight(); float bottomY = underlineRects.get(0).getBottom(); float totalWidth = right - left; // 基于完整区域绘制自适应长度的波浪线,可自行调整曲线参数匹配样式需求 canvas.moveTo(left, bottomY); canvas.curveTo(left + totalWidth * 0.25f, bottomY + 2, left + totalWidth * 0.5f, bottomY -2, left + totalWidth * 0.75f, bottomY +2, right, bottomY); canvas.stroke(); } } } }
第三步:调用时给Paragraph绑定自定义Renderer
String s = "This text is underlined with a dashed line"; Paragraph paragraph = new Paragraph(); // 给Paragraph设置自定义Renderer paragraph.setNextRenderer(new UnderlineParagraphRenderer(paragraph)); Text text; for (int i = 0; i <s.length() ; i++) { text = new Text(String.valueOf(s.charAt(i))); paragraph.add(text); text.setNextRenderer(new DashedLineTextRenderer(text)); } doc.add(paragraph); doc.close();
内容的提问来源于stack exchange,提问作者cixikoy607
相关产品推荐
相关产品推荐

