UNPKG

@syncfusion/ej2-pdf

Version:

Feature-rich JavaScript PDF library with built-in support for loading and manipulating PDF document.

858 lines (857 loc) 30.3 kB
import { _PdfDictionary, _PdfName, _PdfReference } from './../pdf-primitives'; import { _PdfCrossReference } from './../pdf-cross-reference'; import { PdfField, PdfCheckBoxField } from './field'; import { PdfFormFieldsTabOrder, _SignatureFlag } from './../enumerator'; import { PdfPage } from './../pdf-page'; import { PdfFont } from './../fonts/pdf-standard-font'; /** * Represents a PDF form. * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Access the form of the PDF document * let form: PdfForm = document.form; * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` */ export declare class PdfForm { /** * Cross-reference of the owning PDF document. * * @private */ _crossReference: _PdfCrossReference; /** * AcroForm dictionary containing form-wide entries. * * @private */ _dictionary: _PdfDictionary; /** * References to top-level fields in the form. * * @private */ _fields: Array<_PdfReference>; /** * References to widget annotations associated with form fields. * * @private */ _widgetReferences: Array<_PdfReference>; /** * Cache of parsed fields keyed by index. * * @private */ _parsedFields: Map<number, PdfField>; /** * Indicates whether the viewer should generate appearances. * * @private */ _needAppearances: boolean; /** * Indicates use of a default appearance for widgets. * * @private */ _isDefaultAppearance: boolean; /** * Indicates whether the form contains fields with kids. * * @private */ _hasKids: boolean; /** * Indicates whether to generate appearance streams for fields. * * @private */ _setAppearance: boolean; /** * Exports fields even if they are empty. * * @private */ _exportEmptyFields: boolean; /** * Field names in the order they were parsed. * * @private */ _fieldNames: Array<string>; /** * Indexed field names. * * @private */ _indexedFieldNames: Array<string>; /** * Actual field names without indices or suffixes. * * @private */ _actualFieldNames: Array<string>; /** * Indexed actual field names list. * * @private */ _indexedActualFieldNames: Array<string>; /** * Global tab order setting for form fields. * * @private */ _tabOrder: PdfFormFieldsTabOrder; /** * Collection of parsed field instances. * * @private */ _fieldCollection: PdfField[]; /** * Terminal field dictionaries discovered during form field parsing. * * @private */ _terminalFields: _PdfDictionary[]; /** * Map from terminal field dictionary to its indirect reference. * * @private */ _fieldsMap: Map<_PdfDictionary, _PdfReference>; /** * Grouped widget dictionaries organized by field name. * Stores multiple widget dictionaries that share the same field name, * primarily used for radio button groups. * * @private */ _widgetDictionary: Map<string, _PdfDictionary[]>; /** * Set of field names that have been added during form field creation. * Used to track and avoid duplicate field names when processing widgets. * * @private */ _addedFieldNames: Set<string>; /** * Per page tab order map. * * @private */ _tabCollection: Map<number, PdfFormFieldsTabOrder>; /** * Signature flag indicating required usage or certification. * * @private */ _signFlag: _SignatureFlag; /** * Cached indicator for NeedAppearances usage. * * @private */ _isNeedAppearances: boolean; /** * List of form names in document order. * * @private */ _formNames: Array<string>; /** * Enables automatic naming for newly added fields. * * @private */ _fieldAutoNaming: boolean; /** * Generated or user-specified field names. * * @private */ _fieldName: Array<string>; /** * Cache of fonts used across fields keyed by font name. * * @private */ _fontCache: Map<string, PdfFont>; /** * Cache of fonts used across fields keyed by font name. * * @private */ _fontResources: _PdfDictionary; /** * Indicates whether additional post-processing is required. * * @private */ _requiresPostProcessing: boolean; /** * Indicates whether the kids are valid or not. * * @private */ _isValidKids: boolean; /** * Indicates page widget references. * * @private */ _pageWidgetReference: Map<_PdfReference, _PdfDictionary>; /** * Represents a loaded from the PDF document. * * @private * @param {_PdfDictionary} dictionary Form dictionary. * @param {_PdfCrossReference} crossReference Cross reference object. */ constructor(dictionary: _PdfDictionary, crossReference: _PdfCrossReference); /** * Gets the fields count (Read only). * * @returns {number} Fields count. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Access loaded form * let form: PdfForm = document.form; * // Gets the fields count * let count: number = form.count; * // Destroy the document * document.destroy(); * ``` */ readonly count: number; /** * Gets a value indicating whether need appearances (Read only). * * @returns {boolean} Need appearances. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Access loaded form * let form: PdfForm = document.form; * // Gets the boolean flag indicating need appearances * let needAppearances: number = form.needAppearances; * // Destroy the document * document.destroy(); * ``` */ readonly needAppearances: boolean; /** * Gets a value indicating whether allow to export empty fields or not. * * @returns {boolean} Export empty fields. * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Access loaded form * let form: PdfForm = document.form; * // Gets a value indicating whether allow to export empty fields or not. * let exportEmptyFields: boolean = form.exportEmptyFields; * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` */ /** * Sets a value indicating whether allow to export empty fields or not. * * @param {boolean} value Export empty fields. * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Access loaded form * let form: PdfForm = document.form; * // Sets a value indicating whether allow to export empty fields or not. * form.exportEmptyFields = false; * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` */ exportEmptyFields: boolean; /** * Gets the current signature flags of the form (`SigFlags`). * * @private * @returns {_SignatureFlag} The active signature flags bitmask. */ /** * Sets the form's signature flags and updates the `SigFlags` entry in the AcroForm dictionary. * * @private * @param {_SignatureFlag} value The signature flags bitmask to set. * @returns {void} */ _signatureFlag: _SignatureFlag; /** * Gets a value indicating whether the automatic field naming is enabled for form fields. * * @returns {boolean} Indicates if field auto naming is enabled. * * ```typescript * // Create new document. * let document: PdfDocument = new PdfDocument(); * // Access loaded form * let form: PdfForm = document.form; * // Gets the value indicating if automatic field naming is enabled * let fieldAutoNaming: boolean = form.fieldAutoNaming; * // Destroy the document * document.destroy(); * ``` */ /** * Sets a value indicating whether field auto-naming is enabled for form fields. * * @param {boolean} value Enable or disable field auto naming. The default value is false. * ```typescript * // Create a new document * let document: PdfDocument = new PdfDocument(); * // Access loaded form * let form: PdfForm = document.form; * // Enable automatic field naming for new form fields. * form.fieldAutoNaming = true; * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` */ fieldAutoNaming: boolean; /** * Gets the `PdfField` at the specified index. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Access the loaded form field * let field: PdfField = document.form.fieldAt(0); * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` * * @param {number} index Field index. * @returns {PdfField} Loaded PDF form field at the specified index. */ fieldAt(index: number): PdfField; /** * Builds a map of widget annotation references from all pages in the document. * This collection is used to associate terminal fields with their corresponding * page-level widget annotations, enabling proper field-to-page linkage. * * @private * @returns {void} */ _getPageWidgetCollection(): void; /** * Retrieves a form field by its index within the terminal fields collection. * Resolves the field dictionary with its associated page widget reference when available. * * @private * @param {number} index The index of the field in the terminal fields array. * @returns {PdfField} The parsed PDF form field, or `null` if not found or out of range. */ _getField(index: number): PdfField; /** * Parses a form field from a given field dictionary, resolving page widget associations * and constructing the appropriate PDF field type via `_parseFields`. * * @private * @param {_PdfDictionary} fieldDictionary The field dictionary to parse. * @returns {PdfField} The constructed PDF form field, or `null` if parsing fails. */ _getFieldFromDictionary(fieldDictionary: _PdfDictionary): PdfField; /** * Parses a terminal form field from its dictionary and reference, instantiating the appropriate * field type based on `FT` and `Ff` (e.g., text, button, choice, signature). * * @private * @param {_PdfDictionary} dictionary The field dictionary to parse. * @param {_PdfReference} reference The indirect reference of the field. * @returns {PdfField} The constructed field instance. */ _parseFields(dictionary: _PdfDictionary, reference: _PdfReference): PdfField; /** * Add a new `PdfField`. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Add a new form field * let index: number = document.form.add(field); * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` * * @param {PdfField} field Field object to add. * @returns {number} Field index. */ add(field: PdfField): number; /** * Adds a field to the form, updates the AcroForm `Fields` array, caches the parsed field, * and sets appearance/signature flags when applicable. * * @private * @param {PdfField} field The field to add to the form. * @returns {number} The index of the added field in the form. */ _doAdd(field: PdfField): number; /** * Groups a new field with an existing field having the same name by wiring widget parents, * merging kids, syncing flags/appearance, and handling radio options/selection where needed. * * @private * @param {PdfField} field The new field to group. * @param {PdfField} oldField The existing field with the same name. * @returns {number} The index of the grouped field (existing field’s index). */ _groupingFormFields(field: PdfField, oldField: PdfField): number; /** * Finds the first item index within a checkbox field that has an `exportValue` * matching the provided `value`. * * @private * @param {PdfCheckBoxField} field The checkbox field to search. * @param {string} value The export value to match. * @returns {number} The index of the first matching item, or `-1` when not found. */ _findFirstByExportValue(field: PdfCheckBoxField, value: string): number; /** * Returns the export value of the currently selected item in a checkbox field. * If the field dictionary contains a `/V` entry it is returned first; otherwise * the checked state of individual `PdfStateItem`s is consulted. * * @private * @param {PdfCheckBoxField} field The checkbox field to query. * @returns {string} The selected export value, or `undefined` if none. */ _getSelectedExportValue(field: PdfCheckBoxField): string; /** * Converts a standalone field into a parent with `Kids` by creating a new parent dictionary, * moving relevant entries, and attaching both the old and new field widgets under it. * * @private * @param {PdfField} oldField The existing field that will become the parent. * @param {PdfField} newField The new field whose first widget is added as a kid. * @returns {void} */ _updateFieldsKids(oldField: PdfField, newField: PdfField): void; /** * Populates the `Opt` array for a radio button group when duplicate export values are present, * ensuring unique option entries for appearance resolution. * * @private * @param {PdfField} baseField The radio button field used to derive option values. * @returns {void} */ _addItemsToOptionsArray(baseField: PdfField): void; /** * Computes a unique field name by appending a generated identifier when the base name already exists. * * @private * @param {string} name The proposed field name. * @returns {string} A unique field name derived from the input. */ _getCorrectName(name: string): string; /** * Generates a simple pseudo-random identifier string for field auto-naming. * * @private * @returns {string} The generated identifier. */ _generateUniqueIdentifier(): string; /** * Remove the specified PDF form field. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Access the loaded form field * let field: PdfField = document.form.fieldAt(3); * // Remove the form field * document.form.removeField(field); * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` * * @param {PdfField} field Field object to remove. * @returns {void} Nothing. */ removeField(field: PdfField): void; /** * Remove the PDF form field from specified index. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Remove the form field from the specified index * document.form.removeFieldAt(3); * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` * * @param {number} index Field index to remove. * @returns {void} Nothing. */ removeFieldAt(index: number): void; /** * Rebuilds the parsed fields cache after a removal, compacting indices above the removed position. * * @private * @param {number} index The removed field index. * @returns {void} */ _reorderParsedAnnotations(index: number): void; /** * Sets the flag to indicate the new appearance creation * If true, appearance will not be created. Default appearance has been considered. * If false, new appearance stream has been created from field values and updated as normal appearance. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Set boolean flag to create a new appearance stream for form fields. * document.form.setDefaultAppearance(false); * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` * * @param {boolean} value Set default appearance. * @returns {void} Nothing. */ setDefaultAppearance(value: boolean): void; /** * Order the form fields. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Order the form fields. * document.form.orderFormFields(); * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` * * @returns {void} */ orderFormFields(): void; /** * Order the form fields based on page tab order. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * // Order the form fields based on page tab order. * document.form.orderFormFields(PdfFormFieldsTabOrder.row); * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` * * @param {PdfFormFieldsTabOrder} tabOrder tab order types for form fields. * @returns {void} */ orderFormFields(tabOrder: PdfFormFieldsTabOrder): void; /** * Order the form fields based on tab collection. * * ```typescript * // Load an existing PDF document * let document: PdfDocument = new PdfDocument(data, password); * //Set the tab collection to order the form fields. * let values: Map<number, PdfFormFieldsTabOrder> = new Map<number, PdfFormFieldsTabOrder>(); * // Set the tab order for the page index 1. * values.set(1, PdfFormFieldsTabOrder.column); * // Set the tab order for the page index 2. * values.set(2, PdfFormFieldsTabOrder.row); * // Order the form fields based on tab collection. * document.form.orderFormFields(values); * // Save the document * document.save('output.pdf'); * // Destroy the document * document.destroy(); * ``` * * @param {Map<number, PdfFormFieldsTabOrder>} tabCollection collection of tab order with page index. * @returns {void} */ orderFormFields(tabCollection: Map<number, PdfFormFieldsTabOrder>): void; /** * Traverses the AcroForm field tree, collects terminal fields, repairs missing `Parent` links, * and initializes the form's field list and known form names. * * @private * @returns {void} */ _createFields(): void; private _createFieldCollection; private _processRemainingWidgets; /** * Checks whether a field dictionary contains a non-empty `Kids` array. * * @private * @param {_PdfDictionary} dictionary The field dictionary to inspect. * @returns {boolean} Returns `true` if `Kids` exists and is non-empty; otherwise, `false`. */ _hasValidKids(dictionary: _PdfDictionary): boolean; /** * Validates a field (and its descendants) against the page widget lists, removing any invalid * kid references and determining whether the field has at least one valid descendant. * * @private * @param {_PdfDictionary} dictionary The field or node dictionary. * @param {Map<number, _PdfDictionary[]>} pageWidgets A mapping of page index to widget dictionaries. * @param {_PdfReference} ref The reference of the current field/widget. * @param {_PdfReference[]} widgetCollection Flat list of widget references found in pages. * @returns {boolean} Returns `true` if the field or any child remains valid; otherwise, `false`. */ _removeInvalidFields(dictionary: _PdfDictionary, pageWidgets: Map<number, _PdfDictionary[]>, ref: _PdfReference, widgetCollection: _PdfReference[]): boolean; /** * Determines whether a terminal field dictionary represents a valid widget by checking for * page and rectangle entries or by matching against known page widgets. * * @private * @param {_PdfDictionary} fieldDictionary The terminal field dictionary to validate. * @param {Map<number, _PdfDictionary[]>} pageWidgets A mapping of page index to widget dictionaries. * @param {_PdfReference} ref The reference of the field/widget under validation. * @param {_PdfReference[]} widgetCollection Flat list of widget references found in pages. * @returns {boolean} Returns `true` if the field is valid; otherwise, `false`. */ _validateField(fieldDictionary: _PdfDictionary, pageWidgets: Map<number, _PdfDictionary[]>, ref: _PdfReference, widgetCollection: _PdfReference[]): boolean; _compareWidgets(widget: _PdfDictionary, annotDictionary: _PdfDictionary): boolean; /** * Create form fields from previously discovered terminal widgets starting at index. * Mirrors the C# CreateFormFieldsFromWidgets logic: add terminal fields not yet added * and merge radio-group items when multiple widgets share the same name. * * @private * @param {number} startIndex The starting index into terminal fields. * @returns {void} */ _createFormFieldsFromWidgets(startIndex: number): void; /** * Process terminal fields starting from the specified index. * Adds fields to the form, tracking added field names to avoid duplicates. * * @private * @param {number} startIndex The starting index into terminal fields. * @returns {void} */ private _processTerminalFields; /** * Process widget dictionary to handle radio button groups and single widgets. * Merges radio button items when multiple widgets share the same name. * * @private * @returns {void} */ private _processWidgetDictionary; /** * Process multiple widgets with the same name, merging radio button items. * * @private * @param {_PdfDictionary[]} list The list of widget dictionaries with the same name. * @returns {void} */ private _processMultipleWidgets; /** * Merge radio button items from one field into another. * * @private * @param {PdfRadioButtonListField} targetField The target radio button field to merge into. * @param {PdfRadioButtonListField} sourceField The source radio button field to merge from. * @returns {void} */ private _mergeRadioButtonItems; /** * Handle field naming by either correcting duplicate names or adding to the field name list. * * @private * @param {PdfField} field The field to process for naming. * @returns {void} */ private _handleFieldNaming; /** * Process a single widget dictionary entry. * * @private * @param {_PdfDictionary} dict The widget dictionary to process. * @returns {void} */ private _processSingleWidget; /** * Validates whether a field name is unique within the form. * * @private * @param {PdfField} field The field to validate. * @returns {boolean} Returns `true` if the field name is valid (unique); otherwise, `false`. */ _validFieldName(field: PdfField): boolean; /** * Determines whether the provided `Kids` collection represents a non widget node * (i.e., its first child is not a `Widget` subtype). * * @private * @param {any[]} kids The array of kid dictionaries or references. * @returns {boolean} Returns `true` if the entry is a non terminal node; otherwise, `false`. */ _isNode(kids: Array<any>): boolean; /** * Enumerates and collects all widget annotation references for the form's fields, * traversing each field’s `Kids` or the field itself when no children are present. * * @private * @returns {Array<_PdfReference>} The array of widget references. */ _parseWidgetReferences(): Array<_PdfReference>; /** * Performs post-processing for all fields: applies tab order re arrangement (when manual), * generates appearances or flattens as required, and removes fields flattened for the specified page. * * @private * @param {boolean} isFlatten When `true`, flatten field appearances into the page content. * @param {PdfPage} [pageToImport] Optional page context to restrict processing/removal. * @returns {void} */ _doPostProcess(isFlatten: boolean, pageToImport?: PdfPage): void; /** * Resolves a field's index by matching against stored names, indexed names, actual names, * and indexed actual names. * * @private * @param {string} name The field name to locate. * @returns {number} The matching field index, or `-1` if not found. */ _getFieldIndex(name: string): number; /** * Materializes and returns all parsed `PdfField` instances for the current form. * * @private * @returns {PdfField[]} The array of loaded fields. */ _getFields(): PdfField[]; /** * Maps a tab order enumeration to its corresponding name object (`'R'`, `'C'`, `'S'`), or `null` for `none`. * * @private * @param {PdfFormFieldsTabOrder} tabOrder The tab order mode. * @returns {_PdfName} The corresponding name entry, or `null` if none. */ _getOrder(tabOrder: PdfFormFieldsTabOrder): _PdfName; /** * Compares two fields for ordering based on page index and the current tab order mode * (`row`, `column`, `manual`, `none`, `structure`, `widget`). * * @private * @param {any} field1 The first field to compare. * @param {any} field2 The second field to compare. * @returns {number} A negative value if `field1` precedes `field2`, positive if after, or `0` if equal. */ _compareFields(field1: any, field2: any): number; /** * Retrieves the `Rect` array from the specified dictionary. * * @private * @param {_PdfDictionary} dictionary The dictionary containing a `Rect` entry. * @returns {number[]} The rectangle `[x1, y1, x2, y2]`, or `undefined` if absent. */ _getRectangle(dictionary: _PdfDictionary): number[]; /** * Gets a representative widget rectangle for a field with kids, preferring the parent field's * rectangle first. * * @private * @param {PdfField} field The field whose widget rectangle is requested. * @returns {number[]} The widget rectangle `[x1, y1, x2, y2]`, or `undefined` if unavailable. */ _getItemRectangle(field: PdfField): number[]; /** * Compares two numeric values. * * @private * @param {number} x The first number. * @param {number} y The second number. * @returns {number} Returns `1` if `x > y`, `-1` if `x < y`, otherwise `0`. */ _compare(x: number, y: number): number; /** * Compares two widget references by their rectangles according to the current tab order. * * @private * @param {_PdfReference} x The first widget reference. * @param {_PdfReference} y The second widget reference. * @returns {number} A negative, positive, or zero value indicating relative order. */ _compareKidsElement(x: _PdfReference, y: _PdfReference): number; /** * Sorts a field's items by page/tab order and returns the effective page used for ordering. * * @private * @param {PdfField} field The field whose items should be sorted. * @param {boolean} hasPageTabOrder When `true`, uses the page's tab order for sorting. * @returns {PdfPage} The page used to determine ordering. */ _sortItemByPageIndex(field: PdfField, hasPageTabOrder: boolean): PdfPage; /** * Sorts the parsed items of supported fields (text, list box, checkbox, radio) using * the current tab order comparator. * * @private * @param {PdfField} field The field whose items are to be sorted. * @returns {void} */ _sortFieldItems(field: PdfField): void; /** * Compares two field items by page index and rectangle, honoring the current tab order * `row` or `column`. * * @private * @param {any} item1 The first item to compare. * @param {any} item2 The second item to compare. * @returns {number} A negative, positive, or zero value indicating relative order. */ _compareFieldItem(item1: any, item2: any): number; /** * Clears the form’s field reference list and the parsed field cache. * * @private * @returns {void} */ _clear(): void; /** * Checks whether two fields are of the same field class (e.g., both text, both radio). * * @private * @param {PdfField} field1 The first field. * @param {PdfField} field2 The second field. * @returns {boolean} Returns `true` if the field types are compatible; otherwise, `false`. */ _checkType(field1: PdfField, field2: PdfField): boolean; }