iText 7指定坐标放置文本问题求助(从iTextSharp迁移)
iText7 指定坐标放置文本块的正确方法
问题背景
之前使用iTextSharp时,可通过ColumnText在指定坐标放置文本:
ColumnText ct = new ColumnText(cb); ct.SetSimpleColumn(DrawingSpace.llx, DrawingSpace.lly, DrawingSpace.urx, DrawingSpace.ury);
还能模拟计算文本高度:
ct.Go(SimulateOnlyForHeight); var lowestText = ct.YLine + (float)Math.Floor(ListFont.GetCalculatedBaseFont(false).GetFontDescriptor(BaseFont.DESCENT, ListFont.Size)); return DrawingSpace.y - lowestText;
迁移到iText7后遇到以下问题:
- Canvas关联的Rectangle定位逻辑不符合预期,文本无法在指定区域内正确排列
- Paragraph默认边距会被自动添加,导致定位混乱
- 使用
SetFixedPosition(llx, lly, width)时文本位置过低,改用ury则位置过高
测试代码如下:
static void Main(string[] args) { float llx = 71.001f; float urx = 720.9f; float lly = 495f; float ury = 561; float calcwidth = urx - llx; // 649.9f float calcheight = ury - lly; // 66f float PageMarginSize = 35; float PageTopMarginSize = 38; string filePath = "PATH TO FILE EXAMPLE"; string fontpath = "PATH TO FONT EXAMPLE"; PdfFont font = PdfFontFactory.CreateFont(fontpath + "Trade Bold.ttf", "CP1252", PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED); PdfDocument pdfdocument = new PdfDocument(new PdfWriter(filePath)); Document document = new Document(pdfdocument, PageSize.LETTER.Rotate()); document.SetMargins(PageTopMarginSize, PageMarginSize, PageMarginSize, PageMarginSize); PdfPage page = pdfdocument.AddNewPage(); PdfCanvas pdfCanvas = new PdfCanvas(page); DrawHorizontalDottedLine(ref pdfdocument, new DeviceRgb(0, 0, 0), llx, lly, 400f); DrawHorizontalDottedLine(ref pdfdocument, new DeviceRgb(0, 0, 255), llx, lly, 400f); Rectangle rectangle = new Rectangle(llx, lly, calcwidth, 52f); pdfCanvas.SetFillColor(new DeviceRgb(255, 250, 250)); pdfCanvas.Rectangle(rectangle); pdfCanvas.FillStroke(); Canvas canvas = new Canvas(pdfCanvas, rectangle); Paragraph paragraph = new Paragraph().Add("Example Text") .SetFontSize(52f).SetFontColor(new DeviceRgb(204, 0, 0)) .SetFixedLeading(52f) .SetFont(font); paragraph.SetProperty(Property.MARGIN_TOP, UnitValue.CreatePointValue(0)); paragraph.SetProperty(Property.MARGIN_BOTTOM, UnitValue.CreatePointValue(0)); canvas.Add(paragraph); canvas.Close(); pdfdocument.Close(); } public static void DrawHorizontalDottedLine( ref PdfDocument pdfDocument, DeviceRgb lineColor, float x, float y, float width, float weight = 1f) { PdfCanvas canvas = new PdfCanvas(pdfDocument.GetLastPage()); canvas.SetTextRenderingMode(0); canvas.SetStrokeColor(lineColor); canvas.SetLineDash(0); canvas.MoveTo(x, y) .LineTo(x + width, y); canvas.SetLineWidth(weight); canvas.Stroke(); }
解决方案
1. 明确iText7的坐标逻辑
PDF坐标系统原点在页面左下角,Y轴向上延伸:
Rectangle(x, y, width, height)中,(x,y)是矩形左下角坐标,height是向上延伸的高度- 旧iTextSharp的
SetSimpleColumn(llx, lly, urx, ury)对应iText7中Rectangle(llx, lly, urx-llx, ury-lly)
2. 移除Paragraph的默认边距与内边距
Paragraph默认存在margin和padding,需要完全清除才能精准定位:
Paragraph paragraph = new Paragraph("Example Text") .SetFont(font) .SetFontSize(52f) .SetFontColor(new DeviceRgb(204, 0, 0)) .SetFixedLeading(52f) // 清除所有边距 .SetMarginTop(0) .SetMarginBottom(0) .SetMarginLeft(0) .SetMarginRight(0) // 清除所有内边距 .SetPaddingTop(0) .SetPaddingBottom(0) .SetPaddingLeft(0) .SetPaddingRight(0);
3. 精准固定文本位置
如果直接使用SetFixedPosition,需注意参数是文本块的左下角坐标,同时要考虑字体的基线偏移:
// 直接将Paragraph添加到Document,指定固定位置 Paragraph fixedPara = new Paragraph("Fixed Position Text") .SetFont(font) .SetFontSize(52f) .SetMargin(0) .SetPadding(0) // llx: 左侧X坐标, lly: 文本块左下角Y坐标, width: 文本宽度 .SetFixedPosition(llx, lly, calcwidth); document.Add(fixedPara);
4. 模拟计算文本所需高度
对应旧iTextSharp的SimulateOnlyForHeight,使用iText7的Layout API模拟布局获取高度:
// 创建模拟布局的上下文 Document doc = new Document(pdfdocument); Paragraph para = new Paragraph("Example Text") .SetFont(font) .SetFontSize(52f) .SetMargin(0) .SetPadding(0); // 定义可用宽度 LayoutResult result = para.CreateRendererSubTree().SetParent(doc.GetRenderer()) .Layout(new LayoutContext(new LayoutArea(1, new Rectangle(llx, 0, calcwidth, float.MaxValue)))); // 获取文本实际占用的高度 float textHeight = result.GetOccupiedArea().GetBBox().GetHeight(); // 计算基线到文本底部的距离(descent) float descent = font.GetDescent(52f); // 总高度包含descent float totalHeight = textHeight + descent;
修正后的完整测试代码
static void Main(string[] args) { float llx = 71.001f; float urx = 720.9f; float lly = 495f; float ury = 561; float calcwidth = urx - llx; float calcheight = ury - lly; float PageMarginSize = 35; float PageTopMarginSize = 38; string filePath = "PATH TO YOUR OUTPUT FILE"; string fontpath = "PATH TO YOUR FONT FOLDER"; PdfFont font = PdfFontFactory.CreateFont(fontpath + "Trade Bold.ttf", "CP1252", PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED); PdfDocument pdfdocument = new PdfDocument(new PdfWriter(filePath)); Document document = new Document(pdfdocument, PageSize.LETTER.Rotate()); document.SetMargins(PageTopMarginSize, PageMarginSize, PageMarginSize, PageMarginSize); PdfPage page = pdfdocument.AddNewPage(); PdfCanvas pdfCanvas = new PdfCanvas(page); // 绘制参考线(底部和顶部) DrawHorizontalDottedLine(ref pdfdocument, new DeviceRgb(0, 0, 0), llx, lly, 400f); DrawHorizontalDottedLine(ref pdfdocument, new DeviceRgb(0, 0, 255), llx, ury, 400f); // 绘制目标区域矩形 Rectangle targetRect = new Rectangle(llx, lly, calcwidth, calcheight); pdfCanvas.SetFillColor(new DeviceRgb(255, 250, 250)); pdfCanvas.Rectangle(targetRect); pdfCanvas.FillStroke(); // 创建Canvas并添加文本 Canvas canvas = new Canvas(pdfCanvas, targetRect); Paragraph paragraph = new Paragraph("Example Text") .SetFont(font) .SetFontSize(52f) .SetFontColor(new DeviceRgb(204, 0, 0)) .SetFixedLeading(52f) .SetMargin(0) .SetPadding(0); canvas.Add(paragraph); canvas.Close(); document.Close(); } public static void DrawHorizontalDottedLine( ref PdfDocument pdfDocument, DeviceRgb lineColor, float x, float y, float width, float weight = 1f) { PdfCanvas canvas = new PdfCanvas(pdfDocument.GetLastPage()); canvas.SetTextRenderingMode(PdfCanvasConstants.TextRenderingMode.FILL); canvas.SetStrokeColor(lineColor); canvas.SetLineDash(3, 3); // 虚线样式更明显 canvas.MoveTo(x, y) .LineTo(x + width, y); canvas.SetLineWidth(weight); canvas.Stroke(); }
内容的提问来源于stack exchange,提问作者Charles Corio
相关产品推荐
相关产品推荐

