iText7 Canvas绘制网格无法填满Win10微软打印生成的A4 PDF页面
问题:Microsoft Print to PDF生成的PDF添加网格无法铺满页面
使用iText为现有A4 PDF添加全页网格时,代码在iText生成的PDF上运行正常,但Win10「Microsoft Print to PDF」驱动生成的A4 PDF会出现网格右侧和底部短几厘米、无法填满页面的问题。尽管不同PDF的fltWidth和fltHeight数值相近,但仅微软打印生成的PDF存在该异常。
原代码如下:
pdfDoc.SetDefaultPageSize(PageSize.A4); Document doc = new Document(pdfDoc, PageSize.A4); doc.SetMargins(0f, 0f, 0f, 0f); PdfDocument pdfDocData = new PdfDocument(new PdfReader(sourcePDF)); pdfDocData.CopyPagesTo(1, 1, pdfDoc); iText.Kernel.Colors.Color colorGrey = new DeviceRgb(112, 112, 112); float flt_02 = 0.2f; PdfPage page = pdfDoc.GetFirstPage(); iText.Kernel.Geom.Rectangle pageSize = doc.GetPdfDocument().GetFirstPage().GetPageSize(); float fltWidth = pageSize.GetWidth(); float fltHeight = pageSize.GetHeight(); PdfCanvas canvas = new PdfCanvas(page); for (int intIndex = 296; intIndex > 0; intIndex--) { float fltLineY = intIndex * 2.83464566929134f; canvas.SetStrokeColor(colorGrey); canvas.MoveTo(1, fltLineY); canvas.LineTo(fltWidth, fltLineY); canvas.SetLineWidth(flt_02); canvas.ClosePathStroke(); } for (int intIndex = 1; intIndex < 210; intIndex++) { float fltLineX = intIndex * 2.83464566929134f; canvas.SetStrokeColor(colorGrey); canvas.MoveTo(fltLineX, 1); canvas.LineTo(fltLineX, fltHeight); canvas.SetLineWidth(flt_02); canvas.ClosePathStroke(); } doc.Close(); pdfDoc.Close();
原因分析
Microsoft Print to PDF生成的PDF通常存在**媒体框(Media Box)与裁剪框(Crop Box)**不一致的情况。A4标准Media Box为792×1123pt(210×297mm),但该驱动会设置更小的Crop Box来模拟打印边距。原代码中通过doc.GetPdfDocument().GetFirstPage().GetPageSize()获取的是Crop Box尺寸,而非实际的Media Box,导致网格绘制范围被限制在裁剪框内,无法铺满整个页面。
解决方案
直接获取页面的Media Box作为绘制基准,并调整网格的起始/结束坐标,确保覆盖完整的Media Box区域:
修改后的代码
pdfDoc.SetDefaultPageSize(PageSize.A4); Document doc = new Document(pdfDoc, PageSize.A4); doc.SetMargins(0f, 0f, 0f, 0f); PdfDocument pdfDocData = new PdfDocument(new PdfReader(sourcePDF)); pdfDocData.CopyPagesTo(1, 1, pdfDoc); iText.Kernel.Colors.Color colorGrey = new DeviceRgb(112, 112, 112); float flt_02 = 0.2f; PdfPage page = pdfDoc.GetFirstPage(); // 直接获取页面的Media Box,而非默认的Crop Box iText.Kernel.Geom.Rectangle mediaBox = page.GetMediaBox(); float fltWidth = mediaBox.GetWidth(); float fltHeight = mediaBox.GetHeight(); // 获取Media Box的左下角坐标(部分PDF的Media Box可能不是从(0,0)开始) float mediaX = mediaBox.GetLeft(); float mediaY = mediaBox.GetBottom(); PdfCanvas canvas = new PdfCanvas(page); // 绘制水平网格线,从Media Box的左边缘到右边缘 for (int intIndex = 296; intIndex > 0; intIndex--) { float fltLineY = mediaY + intIndex * 2.83464566929134f; if (fltLineY > mediaBox.GetTop()) continue; // 超出Media Box顶部则跳过 canvas.SetStrokeColor(colorGrey); canvas.MoveTo(mediaX, fltLineY); canvas.LineTo(mediaBox.GetRight(), fltLineY); canvas.SetLineWidth(flt_02); canvas.ClosePathStroke(); } // 绘制垂直网格线,从Media Box的底部到顶部 for (int intIndex = 1; intIndex < 210; intIndex++) { float fltLineX = mediaX + intIndex * 2.83464566929134f; if (fltLineX > mediaBox.GetRight()) continue; // 超出Media Box右侧则跳过 canvas.SetStrokeColor(colorGrey); canvas.MoveTo(fltLineX, mediaY); canvas.LineTo(fltLineX, mediaBox.GetTop()); canvas.SetLineWidth(flt_02); canvas.ClosePathStroke(); } doc.Close(); pdfDoc.Close();
关键修改点
- 替换
GetPageSize()为GetMediaBox(),获取PDF页面的实际物理尺寸 - 以Media Box的左下角坐标(
mediaX,mediaY)作为绘制起点,避免因页面偏移导致的网格错位 - 添加判断逻辑,确保网格线不超出Media Box范围
内容的提问来源于stack exchange,提问作者kalpha
相关产品推荐
相关产品推荐

