mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-23 04:36:44 +08:00
#24 start adding classes for the acroform api
This commit is contained in:
49
src/UglyToad.PdfPig/AcroForms/AcroForm.cs
Normal file
49
src/UglyToad.PdfPig/AcroForms/AcroForm.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
namespace UglyToad.PdfPig.AcroForms
|
||||
{
|
||||
using System;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// A collection of interactive fields for gathering data from a user through dropdowns, textboxes, checkboxes, etc.
|
||||
/// Each <see cref="PdfDocument"/> with form functionality contains a single <see cref="AcroForm"/> spread across one or more pages.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The name AcroForm distinguishes this from the other form type called form XObjects which act as templates for repeated sections of content.
|
||||
/// </remarks>
|
||||
internal class AcroForm
|
||||
{
|
||||
/// <summary>
|
||||
/// The raw PDF dictionary which is the root form object.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DictionaryToken Dictionary { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Document-level characteristics related to signature fields.
|
||||
/// </summary>
|
||||
public SignatureFlags SignatureFlags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether all widget annotations need appearance dictionaries and streams.
|
||||
/// </summary>
|
||||
public bool NeedAppearances { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AcroForm"/>.
|
||||
/// </summary>
|
||||
public AcroForm(DictionaryToken dictionary, SignatureFlags signatureFlags, bool needAppearances)
|
||||
{
|
||||
Dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
|
||||
SignatureFlags = signatureFlags;
|
||||
NeedAppearances = needAppearances;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Dictionary.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
90
src/UglyToad.PdfPig/AcroForms/AcroFormFactory.cs
Normal file
90
src/UglyToad.PdfPig/AcroForms/AcroFormFactory.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
namespace UglyToad.PdfPig.AcroForms
|
||||
{
|
||||
using System;
|
||||
using Content;
|
||||
using Exceptions;
|
||||
using Filters;
|
||||
using Parser.Parts;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
using Util;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the <see cref="AcroForm"/> from the document, if available.
|
||||
/// </summary>
|
||||
internal class AcroFormFactory
|
||||
{
|
||||
private readonly IPdfTokenScanner tokenScanner;
|
||||
private readonly IFilterProvider filterProvider;
|
||||
|
||||
public AcroFormFactory(IPdfTokenScanner tokenScanner, IFilterProvider filterProvider)
|
||||
{
|
||||
this.tokenScanner = tokenScanner ?? throw new ArgumentNullException(nameof(tokenScanner));
|
||||
this.filterProvider = filterProvider ?? throw new ArgumentNullException(nameof(filterProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the <see cref="AcroForm"/> from the document, if applicable.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="AcroForm"/> if the document contains one.</returns>
|
||||
[CanBeNull]
|
||||
public AcroForm GetAcroForm(Catalog catalog)
|
||||
{
|
||||
if (!catalog.CatalogDictionary.TryGet(NameToken.AcroForm, out var acroRawToken) || !DirectObjectFinder.TryGet(acroRawToken, tokenScanner, out DictionaryToken acroDictionary))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var signatureFlags = (SignatureFlags)0;
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.SigFlags, tokenScanner, out NumericToken signatureToken))
|
||||
{
|
||||
signatureFlags = (SignatureFlags)signatureToken.Int;
|
||||
}
|
||||
|
||||
var needAppearances = false;
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.NeedAppearances, tokenScanner, out BooleanToken appearancesToken))
|
||||
{
|
||||
needAppearances = appearancesToken.Data;
|
||||
}
|
||||
|
||||
var calculationOrder = default(ArrayToken);
|
||||
acroDictionary.TryGetOptionalTokenDirect(NameToken.Co, tokenScanner, out calculationOrder);
|
||||
|
||||
var formResources = default(DictionaryToken);
|
||||
acroDictionary.TryGetOptionalTokenDirect(NameToken.Dr, tokenScanner, out formResources);
|
||||
|
||||
var da = default(string);
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Da, tokenScanner, out StringToken daToken))
|
||||
{
|
||||
da = daToken.Data;
|
||||
}
|
||||
else if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Da, tokenScanner, out HexToken daHexToken))
|
||||
{
|
||||
da = daHexToken.Data;
|
||||
}
|
||||
|
||||
var q = default(int?);
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Q, tokenScanner, out NumericToken qToken))
|
||||
{
|
||||
q = qToken.Int;
|
||||
}
|
||||
|
||||
var fieldsToken = acroDictionary.Data[NameToken.Fields.Data];
|
||||
|
||||
if (!DirectObjectFinder.TryGet(fieldsToken, tokenScanner, out ArrayToken fieldsArray))
|
||||
{
|
||||
throw new PdfDocumentFormatException($"Could not retrieve the fields array for an AcroForm: {acroDictionary}.");
|
||||
}
|
||||
|
||||
foreach (var fieldToken in fieldsArray.Data)
|
||||
{
|
||||
var fieldDictionary = DirectObjectFinder.Get<DictionaryToken>(fieldToken, tokenScanner);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return new AcroForm(acroDictionary, signatureFlags, needAppearances);
|
||||
}
|
||||
}
|
||||
}
|
21
src/UglyToad.PdfPig/AcroForms/SignatureFlags.cs
Normal file
21
src/UglyToad.PdfPig/AcroForms/SignatureFlags.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace UglyToad.PdfPig.AcroForms
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies document level characteristics for any signature fields in the document's <see cref="AcroForm"/>.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum SignatureFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// The document contains at least one signature field.
|
||||
/// </summary>
|
||||
SignaturesExist = 1 << 0,
|
||||
/// <summary>
|
||||
/// The document contains signatures which may be invalidated if the file is saved
|
||||
/// in a way which alters its previous content rather than simply appending new content.
|
||||
/// </summary>
|
||||
AppendOnly = 1 << 1
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user