如果pdfStamper.AcroFields.GenerateAppearances 是true,则通过Matrix 属性将现有外观旋转的表单字段展平时,iText(Sharp) 中会出现问题。
原版
用GenerateAppearances == true 展平后看起来像这样:
解决方法
由于文档已有外观流,您可以关闭GenerateAppearances:
stamper.AcroFields.GenerateAppearances = false;
stamper.AnnotationFlattening = true;
stamper.FormFlattening = true;
你现在得到的结果:
问题
如果GenerateAppearances == true,则 iTextSharp(在展平表单时)首先查看字段是否已经有外观。如果该字段有一个,iTextSharp 只会尝试将现有外观整齐地适合表单字段的矩形。不幸的是,它 (a) 忽略了现有的表单字段 Matrix 条目,并且 (b) 用一个新的矩阵替换它来进行拟合。如果外观通过其Matrix 进行旋转,则该旋转将丢失,而是将值拉伸以适合方向错误的矩形。
if (acroFields.GenerateAppearances) {
if (appDic == null || as_n == null) {
[...]
} else if (as_n.IsStream()) {
PdfStream stream = (PdfStream) as_n;
PdfArray bbox = stream.GetAsArray(PdfName.BBOX);
PdfArray rect = merged.GetAsArray(PdfName.RECT);
if (bbox != null && rect != null) {
float rectWidth = rect.GetAsNumber(2).FloatValue - rect.GetAsNumber(0).FloatValue;
float bboxWidth = bbox.GetAsNumber(2).FloatValue - bbox.GetAsNumber(0).FloatValue;
float rectHeight = rect.GetAsNumber(3).FloatValue - rect.GetAsNumber(1).FloatValue;
float bboxHeight = bbox.GetAsNumber(3).FloatValue - bbox.GetAsNumber(1).FloatValue;
float widthCoef = Math.Abs(bboxWidth != 0 ? rectWidth / bboxWidth : float.MaxValue);
float heightCoef = Math.Abs(bboxHeight != 0 ? rectHeight / bboxHeight : float.MaxValue);
if (widthCoef != 1 || heightCoef != 1)
{
NumberArray array = new NumberArray(widthCoef, 0, 0, heightCoef, 0, 0);
stream.Put(PdfName.MATRIX, array);
MarkUsed(stream);
}
}
}
}
(PdfStamperImp 方法FlatFields)
背景
iTextSharp之所以忽略矩阵的外观是因为在表单填写过程中的外观生成不应该使用这样的矩阵值:
对于非富文本字段,外观流(与所有外观流一样,是一个表单 XObject)的表单字典的内容初始化如下:
-
资源字典 (Resources) 应使用交互式表单字典的 DR 条目中的资源创建(参见表 218)。
-
边界框(BBox)的左下角设置为表单坐标系中的坐标(0, 0)。框的顶部和右侧坐标取自注释矩形的尺寸(小部件注释字典中的 Rect 条目)。
-
外观流的表单字典中的所有其他条目都设置为其默认值(参见 8.10,“表单 XObjects”)。
(ISO 32000-1 的第 12.7.3.3 节“可变文本”)
这意味着矩阵:
Matrix 数组 (可选) 一个包含六个数字的数组,指定表单矩阵,将表单空间映射到用户空间(参见 8.3.4,“转换矩阵”) .默认值:单位矩阵[1 0 0 1 0 0]。
(表 95 – 特定于类型 1 表单字典的附加条目 - 在第 8.10.2 节“表单字典”中,ibidem)
因此,根据规范在填写期间创建的表单字段外观流可以假定具有标识 Matrix 值,并且没有旋转。
所以 iTextSharp 中的问题实际上只是反映了表单字段出现是由于表单填写而产生的假设。