Skip to content

Make working with AcroForms more user-friendly and allow creating PDFs with minmal size #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

packdat
Copy link

@packdat packdat commented Feb 3, 2025

This PR is an attempt to make working with AcroForms easier and user-friendly.

Notable changes:

  • The 14 standard-fonts defined in the Pdf-Specification are now embedded in the library.
    There is a test-case (RenderGlyphsOfStandardFonts) that was used to inspect the fonts by rendering all glyphs into a Pdf (one for each font) here.
    These fonts are freely distributable as they are licensed under the OFL License.
    To use them, utilize the new StandardFontResolver, e.g.

    GlobalFontSettings.FontResolver = new StandardFontResolver();
    var textFont = new XFont(StandardFontNames.Helvetica, 12, XFontStyleEx.Regular,
      new XPdfFontOptions(PdfFontEncoding.Unicode, PdfFontEmbedding.EmbedCompleteFontFile));

    The StandardFontResolver also has methods that allow registering own fonts:

    • Register -> registers a font from a byte-array (e.g. a font that is stored in you application-resources)
    • RegisterFolder -> registers all fonts from a specified folder and all its subfolders
  • A new method PdfDocument.ImportAcroForm was added to import AcroFields from existing documents.
    This method also allows filtering of fields during the import.

  • An new method PdfDocument.GetOrCreateAcroForm was added which allows creating new AcroForms.

  • New methods were added that allow creating new AcroForms from scratch.
    Example:

    var document = new PdfDocument();
    var page1 = document.AddPage();
    var page2 = document.AddPage();
    var acroForm = document.GetOrCreateAcroForm();
    
    var lastNameField = acroForm.AddTextField(field =>
    {
        field.Name = "LastName";
        field.Font = textFont;
        field.Text = lastNameValue;
        // note we're creating 2 annotations, one on each page.
        // when you open the document in a pdf-reader and change the value of one annotation, the other will update automatically.
        field.AddAnnotation(annot =>
        {
            annot.AddToPage(page1, new PdfRectangle(new XRect(x, y, 100, 20)));
        });
        field.AddAnnotation(annot =>
        {
            annot.AddToPage(page2, new PdfRectangle(new XRect(x, y, 100, 20)));
        });
    });

    See full example in method CanCreateNewForm here

  • There is now a distinction between a field (which is only metadata regarding the Pdf-Specification) and it's appearance (which is the visual part of a field).
    The appearances of AcroFields are defined by PdfWidgetAnnotations.
    A field may have multiple annotations (e.g. a contract-number that is repeated on every page of a contract-document; each visual is a PdfWidgetAnnotation associated with the same PdfAcroField).
    The annotations of fields can be retrieved by PdfAcroField.Annotations

  • Each field type has it's own renderer which is used to create the visual appearances for the fields.
    These renderers may be overridden by the user to customize the rendering.
    See PdfAcroFieldRenderer as a starting point.
    An instance of this class is available in PdfAcroForm.FieldRenderer

  • PdfAcroForm has a new method GetAllFields for easily retrieving the complete field-hierarchy as a flattened collection.

  • AcroForms can be flattened by the new method PdfDocument.FlattenAcroForm
    (the old method PdfDocument.Flatten, wich was just setting the "ReadOnly"-flag for AcroFields, was removed)
    Note that annotations not related to AcroFields are unaffected by this (as the name implies).

I'm pretty sure there's room for further improvement; some feedback would be useful for that and is highly appreciated !

@packdat
Copy link
Author

packdat commented Feb 3, 2025

Some test-cases require documents to work with.
I used those attached here:
AcroTestDocuments.zip

They should be extracted into PDFsharp's asset-folder, e.g. /assets/pdfsharp-6.x/pdfs

@packdat packdat changed the title Make working with AcroForms more user-friendly Make working with AcroForms more user-friendly and allow creating PDFs with minmal size Mar 6, 2025
@packdat
Copy link
Author

packdat commented Mar 6, 2025

Unfortunately, i was not able to create a separate PR for the latest changes, sorry for that.

There are use-cases where you don't care about PDF/A conformance or the like, you just want to create documents quickly and with minimal size.
(e.g. when creating documents on the fly, sending them to a print-queue and throwing them away afterwards)

The latest commit added support for this scenario.
It builds on the previous changes of this PR by utilizing the Standard-Fonts defined in the PDF-spec.
Usage is shown in this test-case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants