Как встроить все шрифты из других PDF iText 7 - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь наложить два файла PDF с помощью iText7 / C #.Первый вид фона, а второй содержит поля формы.Все работает нормально, и единственная проблема заключается в том, что я теряю шрифты из второго файла.

Я пытаюсь сделать следующее:

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 ().Но он всегда возвращает ноль.

1 Ответ

0 голосов
/ 20 ноября 2018

В комментарии вы уточнили:

можно предположить, что фоновый 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 или даже использовать какой-нибудь изящный режим наложения, чтобы получить желаемый статический контент.

...