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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:29:56