【问题标题】:How to embed all fonts from other PDF iText 7如何嵌入来自其他 PDF iText 7 的所有字体
【发布时间】:2019-04-22 10:50:33
【问题描述】:

我正在尝试使用 iText7/C# 覆盖两个 PDF 文件。 第一个是背景,第二个是包含表单字段。 一切正常,唯一的问题是我从第二个文件中丢失了字体。

我尝试如下:

static public bool Overlay(string back_path, string front_path, string merge_path)
{
    PdfReader reader;
    PdfDocument pdf = null, front;
    try
    {
        reader = new PdfReader(back_path);
        pdf = new PdfDocument(reader, new PdfWriter(merge_path));
        front = new PdfDocument(new PdfReader(front_path));

        var form = PdfAcroForm.GetAcroForm(front, false);
        PdfAcroForm dform = PdfAcroForm.GetAcroForm(pdf, true);
        IDictionary<String, PdfFormField> fields = form.GetFormFields();

        // copy styles
        dform.SetDefaultResources(form.GetDefaultResources());
        dform.SetDefaultAppearance(form.GetDefaultAppearance().GetValue());

        // do overlay
        foreach (KeyValuePair<string, PdfFormField> pair in fields)
        {
            try
            {
                var field = pair.Value;
                PdfPage page = field.GetWidgets().First().GetPage();

                int pg_no = front.GetPageNumber(page);
                if (pg_no < front_start_page || pg_no > front_end_page)
                    continue;
                PdfObject copied = field.GetPdfObject().CopyTo(pdf, true);
                PdfFormField copiedField = PdfFormField.MakeFormField(copied, pdf);

                // The following returns null. If it returns something, I think I could use copiedField.setFont(font). 
                // var font = field.GetFont(); 

                dform.AddField(copiedField, pdf.GetPage(pg_no));
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Overlaying field {pair.Key} failed. ({ex.Message})");
            }
        }

        pdf.Close();
        return true;
    }
    catch (Exception ex)
    {
        throw new OverlayException(ex.Message);
    }
}

public static PdfDictionary get_font_dict(PdfDocument pdfDoc)
{
    PdfDictionary acroForm = pdfDoc.GetCatalog().GetPdfObject().GetAsDictionary(PdfName.AcroForm);
    if (acroForm == null)
    {
        return null;
    }
    PdfDictionary dr = acroForm.GetAsDictionary(PdfName.DR);
    if (dr == null)
    {
        return null;
    }
    PdfDictionary font = dr.GetAsDictionary(PdfName.Font);
    return font;
}

所以基本上我从第二个 PDF 中获取所有字体并将它们复制到最终 PDF。 但它不起作用。

从逻辑上讲,我认为将原始字段的字体设置为复制的字体是正确的方法。 我的意思是 PdfFormField.GetFont() 和 SetFont()。 但它总是返回 null。

【问题讨论】:

  • 仅复制 PDF 对象是不够的。您还必须正确引用它们,这不会自动发生。向我们展示您合并文件的方式,并在可能的情况下显示示例 PDF 以重现问题
  • 嗨,阿列克谢。感谢您的回复。请检查编辑。我尽可能多地添加。抱歉,我无法添加示例 PDF。期待您的回答。
  • 背景 PDF 是否包含任何表单域或其他注释?如果没有,解决问题的最简单方法是将背景添加到表单域 PDF,而不是将表单域和全局 AcroForm 信息添加到背景 PDF。此外,表单 PDF 是否包含任何静态内容?
  • 谢谢,@mkl。我会试试你的建议。为了您的信息,可以假定背景 PDF 没有表单域或注释。我的意思是我们可以假设背景 PDF 只包含静态内容(扫描表单),而前面的 PDF 只包含表单域。我最好奇的是为什么 field.GetFont() 返回 null。如果没有,这似乎很简单。

标签: c# pdf fonts pdf-generation itext7


【解决方案1】:

在您澄清的评论中:

可以假定背景 PDF 没有表单域或注释。我的意思是我们可以假设背景 PDF 只包含静态内容(扫描的表单),而前面的 PDF 只包含表单域。

在这种情况下,实现您的方法的最简单方法是将背景作为 xobject 添加到表单 PDF,而不是将表单添加到背景 PDF。

你可以这样做:

PdfReader formReader = new PdfReader(front_path);
PdfReader backReader = new PdfReader(back_path);
PdfWriter writer = new PdfWriter(merge_path);

using (PdfDocument source = new PdfDocument(backReader))
using (PdfDocument target = new PdfDocument(formReader, writer))
{
    PdfFormXObject xobject = source.GetPage(1).CopyAsFormXObject(target);
    PdfPage targetFirstPage = target.GetFirstPage();
    PdfStream stream = targetFirstPage.NewContentStreamBefore();
    PdfCanvas pdfCanvas = new PdfCanvas(stream, targetFirstPage.GetResources(), target);
    Rectangle cropBox = targetFirstPage.GetCropBox();
    pdfCanvas.AddXObject(xobject, cropBox.GetX(), cropBox.GetY());
}

根据背景和 PDF 表单的确切静态内容,您可能希望使用 NewContentStreamAfter 而不是 NewContentStreamBefore,甚至使用一些漂亮的混合模式来获得您想要的确切静态内容外观。

【讨论】:

  • 感谢您的回答。我成功地解决了我的问题。唯一的副作用是我必须从背景插入一些页面到目标 pdf。 (我没有提到让问题变得简单,但是应该考虑页面范围参数)虽然我仍然想要一种正常和下降的方式(复制字段并放置它们),但我必须将您的答案标记为已接受。再次感谢。
  • “我仍然想要一种正常和下降的方式(复制字段并放置它们)” - 恐怕这通常比人们想要的更复杂,因为可能的冲突 - 源 PDF 和目标 PDF 默认表单资源中可能已经存在同名字体 - 需要重写某些表单字段属性。
  • 有道理。 @mkl。再次感谢!
猜你喜欢
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 2015-12-04
  • 2016-08-29
  • 2011-06-06
  • 2010-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多