iText7中带背景色段落如何垂直居中?含中文字体适配
iText7 中文字体段落垂直居中问题解决方案
在iText7里用Canvas.ShowTextAligned设置段落垂直居中时,中文字体(如SimHei、微软雅黑)会出现明显下移,但自带西文字体正常。这是因为中文字体的排版基线、ascent/descent指标和西文字体存在差异,iText默认的居中计算逻辑没适配中文字体的特性。
下面提供两种适配所有字体的解决方案:
方案一:手动计算偏移修正居中位置
通过获取段落的实际布局尺寸,结合字体的排版参数,手动调整Y坐标来修正偏移:
string dest = "output.pdf"; using PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest)); Document doc = new Document(pdfDoc); PageSize pageSize = PageSize.A4; pdfDoc.SetDefaultPageSize(pageSize); Color backgroundColor = ColorConstants.LIGHT_GRAY; var currPage = pdfDoc.AddNewPage(); PdfCanvas pdfCanvas = new PdfCanvas(currPage); pdfCanvas.SaveState() .SetFillColor(backgroundColor) .Rectangle(0, 0, pageSize.GetWidth(), pageSize.GetHeight()) .Fill() .RestoreState(); string fontFolder = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); FontProgramFactory.RegisterFont($"{fontFolder}\\SIMHEI.TTF", "simhei"); FontProgramFactory.RegisterFont($"{fontFolder}\\msyh.ttc,0", "msyh"); // 可切换测试西文字体或中文字体 //var font = PdfFontFactory.CreateFont(StandardFonts.HELVETICA); var font = PdfFontFactory.CreateRegisteredFont("simhei", PdfEncodings.IDENTITY_H, false); Paragraph text = new Paragraph("你好Hello, World!A4_Blank_5P") .SetTextAlignment(TextAlignment.LEFT) .SetBackgroundColor(ColorConstants.WHITE) .SetFont(font); // 计算段落的实际布局尺寸 var renderer = text.CreateRendererSubTree().SetParent(doc.GetRenderer()); LayoutResult result = renderer.Layout(new LayoutContext(new LayoutArea(1, pageSize))); Rectangle rect = result.GetOccupiedArea().GetBBox(); // 计算需要调整的偏移:目标Y坐标减去段落高度的一半,再修正字体基线偏移 float targetY = 760f; float adjustedY = targetY - (rect.GetHeight() / 2) + (font.GetFontProgram().GetFontMetrics().GetDescent() / 1000 * font.GetSize()); var canvas = new Canvas(pdfCanvas, currPage.GetPageSize()); canvas.ShowTextAligned(text, 34, adjustedY, 1, TextAlignment.LEFT, VerticalAlignment.MIDDLE, 0); doc.Close();
核心逻辑是先通过布局渲染获取段落的实际占用区域,再结合字体的descent值调整Y坐标,抵消中文字体导致的下移。
方案二:使用Document布局引擎替代Canvas直接绘制
放弃Canvas.ShowTextAligned,改用iText的Document布局系统,让引擎自动处理字体差异:
string dest = "output.pdf"; using PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest)); Document doc = new Document(pdfDoc, PageSize.A4); // 设置页面背景 Color backgroundColor = ColorConstants.LIGHT_GRAY; doc.Add(new AreaBreak()); var currPage = pdfDoc.GetLastPage(); PdfCanvas pdfCanvas = new PdfCanvas(currPage); pdfCanvas.SaveState() .SetFillColor(backgroundColor) .Rectangle(0, 0, PageSize.A4.GetWidth(), PageSize.A4.GetHeight()) .Fill() .RestoreState(); string fontFolder = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); FontProgramFactory.RegisterFont($"{fontFolder}\\SIMHEI.TTF", "simhei"); FontProgramFactory.RegisterFont($"{fontFolder}\\msyh.ttc,0", "msyh"); // 可切换测试西文字体或中文字体 //var font = PdfFontFactory.CreateFont(StandardFonts.HELVETICA); var font = PdfFontFactory.CreateRegisteredFont("simhei", PdfEncodings.IDENTITY_H, false); // 创建一个固定位置的Div来承载段落,设置垂直居中 Div container = new Div() .SetWidth(PageSize.A4.GetWidth() - 68) // 左右边距34 .SetHeight(20) // 可根据需求调整高度 .SetBackgroundColor(ColorConstants.WHITE) .SetVerticalAlignment(VerticalAlignment.MIDDLE) .SetMarginLeft(34) .SetFixedPosition(1, 34, 760 - 10, PageSize.A4.GetWidth() - 68, 20); // 固定位置,Y坐标为目标中心减去容器高度一半 container.Add(new Paragraph("你好Hello, World!A4_Blank_5P") .SetTextAlignment(TextAlignment.LEFT) .SetFont(font)); doc.Add(container); doc.Close();
这种方式利用iText的布局容器(Div)的垂直居中属性,让引擎自动适配不同字体的排版规则,无需手动计算偏移。
内容的提问来源于stack exchange,提问作者zhusp
相关产品推荐
相关产品推荐

