import { WorkerCommunicator, type WorkerCommunicatorOptions } from './communicator.js'; import { type PdfCreatePagesFromImagesOptions, type PdfImageSource } from './image-source.js'; import { PdfPageRenderCancellationToken } from './render-queue.js'; import { type PdfPageContentSpec } from './page-content.js'; import { type PdfFreeTextAppearanceOptions } from './text-appearance.js'; import { type WorkerAnnotationSpec, type WorkerDocument, type WorkerFontQueries, type PdfRawObject, type PdfRawPatchValue, type PdfRawTarget, type WorkerPageInfo, type WorkerRect } from './protocol.js'; import { PdfImage, type PdfAnnotation, type PdfAnnotationObject, type PdfAnnotationChange, type PdfAnnotationMutationOptions, type PdfAnnotationSnapshot, type PdfAnnotationRenderingMode, type PdfAnnotationSpec, type PdfRestoreAnnotationsOptions, type PdfDest, type PdfDestOptions, type PdfDocumentEventMap, type PdfDocumentEventName, type PdfDownloadProgressCallback, type PdfFormField, type PdfFormFieldValue, type PdfFormMutationOptions, type PdfHighlightObject, type PdfLink, type PdfLinkTarget, type PdfLoadAnnotationsOptions, type PdfLoadHighlightsOptions, type PdfOutlineNode, type PdfPageRawText, type PdfPageMutationOptions, type PdfPageId, type PdfPageRotation, type PdfPasswordProvider, PdfPermissions, type PdfRect, type PdfResolvedDest } from './types.js'; import { type PdfrxFontCacheOptions, type PdfrxLocalFontsOptions } from './local-fonts.js'; interface PdfLinkSpec { readonly rect: PdfRect; readonly target: PdfLinkTarget; readonly id?: string; readonly annotation?: PdfAnnotation | null; } /** Converts the richer read model into the complete writable/persistable shape. */ export declare function annotationObjectToSpec(annotation: PdfAnnotationObject): PdfAnnotationSpec; /** Options for constructing a {@link PdfrxEngine}. */ export interface PdfrxEngineOptions extends WorkerCommunicatorOptions { /** * Discover and lazily register fonts from server-runtime filesystems. * Omit this in browsers and to retain the previous no-filesystem behavior. */ localFonts?: PdfrxLocalFontsOptions; /** Optional disk cache for local-font metadata and explicitly registered font bytes. */ fontCache?: PdfrxFontCacheOptions; } /** Common options for the document-opening methods of {@link PdfrxEngine}. */ export interface PdfOpenOptions { /** Supplies passwords for encrypted documents; see {@link PdfPasswordProvider} for retry semantics. */ passwordProvider?: PdfPasswordProvider; /** Try an empty password before consulting `passwordProvider`. Default: true. */ firstAttemptByEmptyPassword?: boolean; /** Load only the first page eagerly; call `PdfDocument.loadPagesProgressively` for the rest. */ useProgressiveLoading?: boolean; /** Identifier used in error messages and for caching purposes. */ sourceName?: string; } /** Options for {@link PdfrxEngine.openData}; extends {@link PdfOpenOptions} with ownership control. */ export interface PdfOpenDataOptions extends PdfOpenOptions { /** * Transfer ownership of a full input buffer to the worker. Default: true. * Set to false to keep the caller's buffer usable; the engine transfers an * internal copy instead. * */ transferData?: boolean; } /** Options for {@link PdfrxEngine.openUrl}; extends {@link PdfOpenOptions} with fetch-related settings. */ export interface PdfOpenUrlOptions extends PdfOpenOptions { /** Invoked as the document downloads (see {@link PdfDownloadProgressCallback}). */ progressCallback?: PdfDownloadProgressCallback; /** * Access the file via HTTP range requests instead of downloading it whole. * Requires a CORS-enabled server that honors range requests. * */ preferRangeAccess?: boolean; /** Extra HTTP headers for the fetch (e.g. authorization). */ headers?: Record; /** Whether the fetch includes credentials (cookies, HTTP auth). */ withCredentials?: boolean; } /** How {@link PdfDocument.encodePdf} obtains the document it serializes. */ export type PdfEncodeMode = 'in-place' | 'copy' | 'compact'; /** Options for {@link PdfDocument.encodePdf}. */ export interface PdfEncodeOptions { /** * `in-place` materializes the arrangement into the live document; `copy` * clones a catalog-preserving base first; `compact` rebuilds the arranged * pages and their reachable page-level objects in a fresh document. Defaults * to `in-place`. * */ readonly mode?: PdfEncodeMode; /** Requests incremental serialization. Not supported by `compact`. */ readonly incremental?: boolean; /** Removes document security while serializing. */ readonly removeSecurity?: boolean; } /** How {@link PdfDocument.createMaterializedCopy} treats the document catalog. */ export type PdfMaterializedCopyCatalog = 'preserve' | 'rebuild'; /** Options for {@link PdfDocument.createMaterializedCopy}. */ export interface PdfMaterializedCopyOptions { /** * `preserve` retains the selected base document's catalog; `rebuild` creates * a fresh catalog from the arranged pages and their reachable page-level * objects. Defaults to `preserve`. * */ readonly catalog?: PdfMaterializedCopyCatalog; } /** * Builds a batch of raw PDF-object edits for {@link PdfDocument.editRawObjects}. * * Methods only record operations while the callback runs. No document mutation * occurs until the callback completes. The batch is then sent in one worker * command, either directly or through the temporary-copy transaction selected * by {@link PdfRawObjectEditOptions.atomic}. * * A target says *where* to edit; a patch value says *what* to store. Use * {@link catalog} or {@link object} for a starting target and {@link at} for a * nested dictionary/array container. {@link createDictionary} returns a * {@link PdfRawCreatedObject}: pass it directly as a later target, or pass its * {@link PdfRawCreatedObject.reference | reference} property as a value in * another object. * */ export interface PdfRawObjectEditor { /** * Returns a target for the document catalog (`/Root`) dictionary. * * @returns The resulting PdfRawTarget. * */ catalog(): PdfRawTarget; /** * Returns a target for an existing indirect object. * @param objectNumber Positive PDF object number, as returned by * {@link PdfDocument.getRawObject} or an indirect `reference` value. * * @returns The resulting PdfRawTarget. * */ object(objectNumber: number): PdfRawTarget; /** * Returns a target for a nested container below `target`. * * String components select dictionary keys without the leading `/`; number * components select zero-based array items. Indirect references encountered * between components are dereferenced automatically. * * @example Target the first element of a nested array * ```ts * const firstKid = editor.at(editor.object(pagesObjectNumber), 'Kids', 0); * ``` * * @param target - The target value. * @param path - The path value (string or number[]). * @returns The resulting PdfRawTarget. * */ at(target: PdfRawTarget, ...path: (string | number)[]): PdfRawTarget; /** * Reserves a new indirect dictionary in this batch. * * The returned object is itself a target for further edits. Use its * {@link PdfRawCreatedObject.reference} property when storing an indirect * reference to it in another dictionary or array. * * @param entries - The entries value (Record). * @returns The resulting PdfRawCreatedObject. * */ createDictionary(entries?: Record): PdfRawCreatedObject; /** * Sets or replaces one dictionary entry; `key` omits the leading `/`. * * @param target - The target value. * @param key - The cache key. * @param value - The value to use. * */ setDictionaryValue(target: PdfRawTarget, key: string, value: PdfRawPatchValue): void; /** * Removes one dictionary entry; `key` omits the leading `/`. * * @param target - The target value. * @param key - The cache key. * */ removeDictionaryValue(target: PdfRawTarget, key: string): void; /** * Appends a value to the target array. * * @param target - The target value. * @param value - The value to use. * */ appendArrayValue(target: PdfRawTarget, value: PdfRawPatchValue): void; /** * Replaces the value at a zero-based array index. * * @param target - The target value. * @param index - The 0-based index. * @param value - The value to use. * */ setArrayValue(target: PdfRawTarget, index: number, value: PdfRawPatchValue): void; /** * Removes the value at a zero-based array index. * * @param target - The target value. * @param index - The 0-based index. * */ removeArrayValue(target: PdfRawTarget, index: number): void; /** * Replaces a stream's decoded bytes. PDFium updates the stream representation * when the document is encoded. * * @param target - The target value. * @param data - The input data. * */ setStreamData(target: PdfRawTarget, data: Uint8Array): void; } /** * Handle for an indirect dictionary reserved by * {@link PdfRawObjectEditor.createDictionary}. * * Pass the handle itself to editor methods to mutate the new dictionary. Pass * {@link reference} as a patch value to store an indirect reference to it in a * catalog, dictionary, or array. The final numeric PDF object number is assigned * inside the worker and intentionally hidden from the callback. * */ export interface PdfRawCreatedObject extends PdfRawTarget { /** Batch-local identity used internally; it is not a PDF object number. */ readonly localId: string; /** Patch value that stores an indirect reference to this newly-created dictionary. */ readonly reference: PdfRawPatchValue; } /** Options controlling how {@link PdfDocument.editRawObjects} commits its batch. */ export interface PdfRawObjectEditOptions { /** * Whether to provide complete all-or-nothing behavior by applying the batch to * an independent PDF copy and adopting it only after every operation succeeds. * * Default: `false`. Without this option, an exception thrown while the edit * callback is building the batch is still safe—the worker is never called and * no operation runs. Once the completed batch reaches PDFium, however, a later * failing operation can leave earlier operations applied. * * Set this to `true` when failure must also roll back errors encountered while * PDFium applies the batch. This copies and reloads the complete document, so * its time and peak-memory cost grow with the PDF size. * */ atomic?: boolean; } /** * Options for {@link PdfPage.render}. * * The page is conceptually scaled to `fullWidth` x `fullHeight` pixels, and the * `x`/`y`/`width`/`height` sub-rectangle of that scaled page is what gets * rendered. All values are in pixels unless noted otherwise. * */ export interface PdfPageRenderOptions { /** Left of the rendered region in the scaled page (pixels). Default: 0. */ x?: number; /** Top of the rendered region in the scaled page (pixels). Default: 0. */ y?: number; /** Width of the rendered region (pixels). Default: `fullWidth`. */ width?: number; /** Height of the rendered region (pixels). Default: `fullHeight`. */ height?: number; /** Width the whole page is scaled to (pixels). Default: page width in points. */ fullWidth?: number; /** Height the whole page is scaled to (pixels). Default: page height in points. */ fullHeight?: number; /** 32-bit ARGB background. Default: opaque white. */ backgroundColor?: number; /** Absolute rotation override for this render (in addition to the page's own rotation). */ rotationOverride?: PdfPageRotation; /** Whether/how annotations are drawn. Default: `'annotationAndForms'`. */ annotationRenderingMode?: PdfAnnotationRenderingMode; /** Advanced: low-level renderer flags (`FPDF_*`). */ flags?: number; /** * Cancels the render while it is still queued, making it resolve to `null`. * Create it with {@link PdfPage.createCancellationToken}. * */ cancellationToken?: PdfPageRenderCancellationToken; } /** * Entry point to the rendering engine. * * Construct one — in a browser, with the URL of the directory serving the * bundled WASM assets; on Node, Bun or Deno, with nothing at all, since the * assets ship inside this package — then open documents with {@link openUrl}, * {@link openData} or {@link createNew}. A single * engine owns one worker shared by all documents it opens; call {@link dispose} * to tear it down. * * @example * ```ts * const engine = new PdfrxEngine({ wasmModulesUrl: '/assets/pdfrx/' }); * const doc = await engine.openUrl('https://example.com/doc.pdf'); * const image = await doc.pages[0].render({ fullWidth: 1000, fullHeight: 1414 }); * if (image) { * canvas.getContext('2d')!.putImageData(image.toImageData(), 0, 0); * } * const text = await doc.pages[0].loadText(); * console.log(text?.fullText); * await doc.dispose(); * engine.dispose(); * ``` * */ export declare class PdfrxEngine { private communicator; private readonly options; private readonly localFontManager; private localFontsInitialized; /** * Creates an engine whose documents share one lazily initialized worker. * * @param options - Worker asset locations, factories, and host-specific configuration. */ constructor(options?: PdfrxEngineOptions); /** * Spawns the worker and initializes the engine. Called implicitly by the open functions. * * @returns The resulting Promise. * */ init(): Promise; /** * The active communicator, or throws if {@link init} has not run. * @internal * */ private get comm(); /** Terminates the worker; all documents opened by this engine become unusable. */ dispose(): void; /** * Opens a document from in-memory PDF bytes. * * Ownership of a full `ArrayBuffer` (or a full `Uint8Array` view) is * transferred to the worker, detaching it from the caller. Partial views are * first copied into a tightly sized buffer and that copy is transferred. * Password retries reuse the worker-owned bytes and transfer only the new * password. * * @param data - The input data. * @param options - Options that customize the operation. * @returns The resolved Promise. * */ openData(data: Uint8Array | ArrayBuffer, options?: PdfOpenDataOptions): Promise; /** * Opens a document by URL. The worker fetches the bytes, so the URL must be * reachable under the page's CORS policy; relative URLs are resolved against * {@link WorkerCommunicatorOptions.baseUrl} (`document.baseURI` by default). * Set {@link PdfOpenUrlOptions.preferRangeAccess} to stream the file via range * requests. * * @param url - The URL to use. * @param options - Options that customize the operation. * @returns The resolved Promise. * */ openUrl(url: string | URL, options?: PdfOpenUrlOptions): Promise; /** * Creates a new empty document. * * @param sourceName - The sourceName value (string). * @returns The resulting Promise. * */ createNew(sourceName?: string): Promise; /** * Registers font data used to substitute missing fonts, then re-render affected pages. * * @param face - The face value (string). * @param data - The input data. * @param resolvedFace - The resolvedFace value (string). * @returns The resulting Promise. * */ addFontData(face: string, data: Uint8Array, resolvedFace?: string): Promise; private addFontDataInternal; private resolveLocalFonts; /** * Re-applies registered font data across the worker (e.g. after adding fonts). * * @returns The resulting Promise. * */ reloadFonts(): Promise; /** * Discards all font data registered via {@link addFontData}. * * @returns The resulting Promise. * */ clearAllFontData(): Promise; /** * Drives the password-retry loop shared by {@link openData} and {@link openUrl}. * * If {@link PdfOpenOptions.firstAttemptByEmptyPassword} is set, the first * attempt uses an empty password; thereafter the {@link PdfPasswordProvider} * is consulted and the open is retried while the engine reports a password error. * Throws {@link PdfPasswordException} if the provider gives up. * @internal * */ private openByFunc; } /** * An open PDF document. * * Obtain instances from the opening methods of {@link PdfrxEngine}; do not * construct directly. Always {@link dispose} a document when finished to release * the underlying native handles. * */ /** * One page slot of an arrangement being written back to the PDF: which page to * place, from which document, at what rotation. * @internal * */ export interface PdfAssembleSource { /** * Source document to take the page from. Defaults to the document being * assembled; pass another {@link PdfDocument} to import one of its pages. * */ document?: PdfDocument; /** 1-based page number within {@link document}. */ pageNumber: number; /** Absolute rotation to apply, or `undefined` to keep the source page's own. */ rotation?: PdfPageRotation; } export declare class PdfDocument { /** Identifier of the document's source (e.g. `uri%...` or `data%...`); used in error messages. */ readonly sourceName: string; /** @internal */ constructor(comm: WorkerCommunicator, wire: WorkerDocument, /** Identifier of the document's source (e.g. `uri%...` or `data%...`); used in error messages. */ sourceName: string, onDispose: (() => void) | null); /** * Registers (once) the worker-side callback that relays form invalidate/change * notifications for this document, so interactive edits repaint and * `formFieldsChanged` fires. No-op for documents without a form environment. * @internal * */ private ensureFormNotify; /** * Dispatches a form notification relayed from the worker's form-fill callbacks. * @internal * */ private handleFormNotification; private captureInteractiveFormChange; /** * Reserved for internal use only (the viewer). Subscribes to form dirty-region * redraws (page number + rect in PDF page coordinates). Returns an unsubscribe. * @internal * */ addFormInvalidateListener(listener: (pageNumber: number, rect: PdfRect) => void): () => void; private readonly comm; /** * Reserved for internal use only. Native handle of the document in the worker. * @internal * */ docHandle: number; /** * Reserved for internal use only. Native handle of the document's form * environment in the worker. * @internal * */ formHandle: number; private formInfo; private readonly onDispose; private readonly listeners; private _pages; /** Number of pages in the underlying PDF, which {@link setPages} can make differ from `_pages.length`. */ private nativePageCount; private arrangementDirty; /** `undefined` means "read the physical PDF outline"; an array is a staged replacement. */ private pendingOutline; /** Staged Link-annotation replacements keyed by logical page identity. */ private readonly pendingLinks; /** Documents whose pages appear in this one's arrangement (see {@link setPages}). */ private borrowedFrom; /** Documents whose arrangement includes pages of this one; warned about on {@link dispose}. */ private readonly borrowers; private _isDisposed; private loadLock; /** Serializes form transactions so their before/after snapshots cannot overlap. */ private formMutationLock; /** Callback id registered with the worker to relay form invalidate/change notifications. */ private formNotifyCallbackId; /** Internal listeners (the viewer) wanting form dirty-region redraws. */ private readonly formInvalidateListeners; /** Cache of field name → physical page index, populated by {@link loadFormFields}. */ private readonly formFieldSourceIndex; /** Latest observed values, used as the before-state for native interactive edits. */ private lastFormValues; /** Suppresses worker notifications caused by a programmatic form transaction. */ private formApiMutationDepth; /** Lazily-loaded parsed `AFSimple_Calculate` specs (`null` until first needed). */ private calcSpecs; /** * Whether {@link setFormFieldValue} recomputes dependent calculated fields * (`AFSimple_Calculate`) after a change. Default `true`. * */ formCalculationEnabled: boolean; /** Encryption/permission info, or `null` if the document is not encrypted. */ readonly permissions: PdfPermissions | null; /** Whether the document is encrypted (equivalently, `permissions` is non-null). */ get isEncrypted(): boolean; /** Whether {@link dispose} has been called; further operations reject. */ get isDisposed(): boolean; /** Pages of the document. With progressive loading, unloaded pages have `isLoaded === false`. */ get pages(): readonly PdfPage[]; /** * Creates one unplaced page per image in a single worker round trip. The * returned pages do not change the document's logical {@link pages} * arrangement; place them with {@link setPages}. * * JPEG bytes are decoded natively by PDFium. Other encoded formats use the * supplied {@link PdfCreatePagesFromImagesOptions.decode} callback or the * runtime's `createImageBitmap` support. Page dimensions default to the image * pixel dimensions at 72 DPI and can be controlled with * {@link PdfCreatePagesFromImagesOptions.dpi} or * {@link PdfCreatePagesFromImagesOptions.pageSize}. * * @example Create and arrange image pages * ```ts * const document = await engine.createNew(); * const pages = await document.createPagesFromImages([pngBlob, jpegBytes]); * document.setPages(pages); * ``` * * @param images - Images to turn into pages, in the returned page order. * @param options - Image decoding and page-sizing options. * @returns Newly created, currently unplaced pages. */ createPagesFromImages(images: readonly PdfImageSource[], options?: PdfCreatePagesFromImagesOptions): Promise; /** * Creates page objects from declarative path, text, and image content in one * worker round trip. The returned pages are not added to the document's * logical {@link pages} arrangement; pass the desired final array to * {@link setPages}. * * Coordinates and matrices use PDF page space: points, a bottom-left origin, * and a y-axis pointing up. Fonts previously registered with * {@link PdfrxEngine.addFontData} are embedded when a text run names their * face. Image and emoji buffers are transferred to the worker and detached. * * @example Create and arrange a new document * ```ts * const document = await engine.createNew(); * const pages = await document.createPagesFromContents([{ * width: 595, * height: 842, * objects: [{ * kind: 'text', * runs: [{ text: 'Quarterly report', fontFace: null, x: 48, y: 790, fontSize: 24 }], * }], * }]); * document.setPages(pages); * const pdfBytes = await document.encodePdf(); * ``` * * Existing arranged pages remain unchanged until {@link setPages} is called, * so generated pages can be inserted, reordered, or discarded synchronously. * Multiple calls may accumulate source pages before one final arrangement. * * @param contents - One or more complete page specifications. * @returns Newly created, currently unplaced pages in specification order. * @see [Page-content authoring guide](https://github.com/espresso3389/pdfrx_web/blob/master/docs/PAGE-CONTENTS.md) */ createPagesFromContents(contents: readonly PdfPageContentSpec[]): Promise; /** Whether page, outline, or link edits are waiting to be {@link materialize | materialized}. */ get hasPendingChanges(): boolean; /** * Turns the Unicode `contents` of a FreeText spec into a stable PDF * appearance. Call this after constructing the spec and before passing that * same object to {@link PdfPage.addAnnotation} or * {@link PdfPage.updateAnnotation}. * * This step is necessary because a PDF cannot simply inherit browser text * rendering. Han characters can require different glyphs for Japanese, * Simplified Chinese, Traditional Chinese, and Korean, while modern color * emoji must be rasterized and embedded as image runs. The method also * measures the resolved fonts and wraps the text to the annotation rectangle. * * The supplied spec is mutated in place: `fontFace`, `appearanceLines`, and * `appearanceRuns` are replaced. * * `language` is optional. Kana and Hangul identify Japanese and Korean * without a hint, and a browser automatically contributes * `navigator.languages` / `navigator.language`. Pass an explicit BCP-47 * value when Han-only text is ambiguous, when the document language should * override the browser locale, or when running on a server. Server * integrations commonly use document metadata, the signed-in user's * locale, or a parsed `Accept-Language` preference. * * @example * ```ts * const spec: PdfAnnotationSpec = { * subtype: 'freeText', * rect: { left: 40, bottom: 700, right: 260, top: 750 }, * // Han-only text is ambiguous without a language or browser locale. * contents: '契約内容 😀', * fontSize: 14, * }; * * await document.prepareFreeTextAppearance(spec, { language: 'ja' }); * await document.pages[0]!.addAnnotation(spec); * ``` * * In a browser whose locale represents the intended reader, the explicit * option can be omitted: * * @example Use the browser language automatically * ```ts * await document.prepareFreeTextAppearance(spec); * ``` * * The default services work in browsers and server runtimes: browser-native * emoji is preferred, with a lazily downloaded, version-pinned Noto Emoji PNG * fallback. `@pdfrx/viewer` also supplies its browser font resolver and exact * Canvas measurement. Direct engine integrations can pass `services` for * private or offline fonts/assets, persistent server caches, or a different * text/emoji renderer. * * If `subtype` is not `freeText`, or `rect`/`contents` is absent, the method * returns without changing the spec. * * For runtime behavior and complete customization examples, read the * [Text, language, and emoji appearance guide](https://github.com/espresso3389/pdfrx_web/blob/master/docs/TEXT-APPEARANCE.md). * To turn the analyzed runs into ordinary PDF page text and images, see the * [practical multilingual Unicode page-content pipeline](https://github.com/espresso3389/pdfrx_web/blob/master/docs/PAGE-CONTENTS.md#practical-multilingual-unicode-pipeline). * * @param spec - The spec value (PdfAnnotationSpec). * @param options - Options that customize the operation. * @returns The resulting Promise. * */ prepareFreeTextAppearance(spec: PdfAnnotationSpec, options?: PdfFreeTextAppearanceOptions): Promise; /** * Replaces the page arrangement — the one way to reorder, rotate, remove, * duplicate, and import pages, and the cheap, synchronous counterpart to * {@link materialize}. * * Nothing is sent to the worker and the PDF is not rebuilt: the pages are * proxies (including those returned by {@link PdfPage.rotatedTo}) over pages * that stay loaded, so reordering and rotating are immediate and free, and * undo is just setting the previous array back. Page numbers are assigned * automatically from the array order. This is what GUI page editing wants; * call {@link encodePdf} (or {@link materialize}) when pending edits * finally have to become a real PDF. * * Pages may come from other documents — those must stay open for as long as * they are referenced. Page numbers are reassigned to match the new order, so * callers can pass pages in any arrangement. * * Reusing the same {@link PdfPage} in more than one slot also reuses its * logical identity, making ID-based destinations unable to distinguish those * placements. Use {@link PdfPage.duplicate} when each occurrence must have * its own destination identity; see that method for examples and details. * * Fires `pageStatusChanged` for every slot. * * @example * ```ts * const p = doc.pages; * doc.setPages([p[2]!, p[0]!.rotatedCW90(), p[1]!]); // reorder + rotate * doc.setPages(doc.pages.filter((x) => x !== p[2])); // remove * doc.setPages([...doc.pages, ...other.pages]); // import from another doc * await doc.encodePdf(); // now it becomes a PDF * ``` * @throws if `pages` is empty, or a page belongs to a disposed document. * * @param pages - The pages to process, in document order. * @param options - Options that customize the operation. * */ setPages(pages: readonly PdfPage[], options?: PdfPageMutationOptions): void; /** * Replaces a single slot (1-based), keeping every other page in place — the * common case for GUI editing (`doc.setPage(3, doc.pages[2]!.rotatedCW90())`). * Like {@link setPages}, this touches no PDF data. * * Setting a page that is already present elsewhere reuses its logical * identity, so ID-based destinations cannot distinguish the two placements. * Use {@link PdfPage.duplicate}; see that method for examples and details. * * @param pageNumber - The 1-based page number. * @param page - The page to process. * @param options - Options that customize the operation. * */ setPage(pageNumber: number, page: PdfPage, options?: PdfPageMutationOptions): void; private describePageArrangement; /** * Updates the two-way record of which other documents this arrangement borrows * pages from, so that disposing one of them can be reported instead of quietly * turning those pages blank. * @internal * */ private trackBorrowedDocuments; /** * Maps a zero-based physical page index in this document's native PDF to its * current 1-based position in {@link pages}, or returns `null` when that * physical page is not present. * * "Source" here means the page owned by this document before the lightweight * arrangement in {@link pages} is applied. It is the same distinction exposed * by {@link PdfPage.sourceDocument} and the internal * `PdfPage.sourcePageIndex`: PDFium reports outlines, links, and form * notifications against the native PDF page tree, while {@link setPages} * creates a separate in-memory order of placement proxies. * * This is how destinations from the PDF itself — outline entries and internal * links, which PDFium reports as physical page indices — are translated into * page numbers callers can navigate to after {@link setPages}. * * Two caveats are inherent rather than fixable: a page placed twice can only * resolve to one position (the first wins), and a page removed from the * arrangement has no position at all, so destinations into it become `null`. * * @param physicalPageIndex - The 0-based physical page index. * @returns The resulting number or `null`. * */ pageNumberOfSourceIndex(physicalPageIndex: number): number | null; /** * Resolves a destination against the current arrangement. When an ID occurs * more than once, one matching placement is selected; callers that need to * distinguish repeated pages should use {@link PdfPage.duplicate}. * * @param dest - The dest value (PdfDest). * @returns The resolved PdfResolvedDest or `null`. * */ resolveDest(dest: PdfDest): PdfResolvedDest | null; /** * Subscribes to a document event (see {@link PdfDocumentEventMap}) and returns * an unsubscribe function. * * For `missingFonts`, queries already discovered while the document was * opening are replayed to the new listener on a microtask, so late * subscribers do not miss them. * * @param event - The event name to subscribe to. * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ addEventListener(event: E, listener: (event: PdfDocumentEventMap[E]) => void): () => void; /** * Dispatches `payload` to every listener of `event`, isolating listener errors. * @internal * */ private emit; /** @internal */ notifyLinksChanged(pageNumbers: number[]): void; /** @internal */ pendingLinksFor(pageId: PdfPageId): readonly PdfLinkSpec[] | undefined; /** @internal */ stageLinks(pageId: PdfPageId, links: readonly PdfLinkSpec[], pageNumber: number): void; /** * Reserved for internal use only. Fires `loadComplete`; listen for the event * with {@link addEventListener} instead. * @internal * */ notifyLoadComplete(): void; /** All font queries reported so far; replayed to late subscribers. */ private readonly accumulatedFontQueries; private readonly accumulatedFontKeys; /** * Reserved for internal use only. Records the fonts the worker reported as * missing and fires `missingFonts`; listen for the event with * {@link addEventListener} instead. * @internal * */ updateMissingFonts(missingFonts: WorkerFontQueries | undefined): void; /** * Reserved for internal use only. Sends a raw worker command on behalf of this * document, rejecting once it is disposed. * @internal * */ sendCommand: WorkerCommunicator['sendCommand']; /** * Reserved for internal use only. Use {@link PdfPage.render} for normal purpose. * * Queues a render on the worker's render queue (shared by every document the * engine opened, since the worker is the contended resource). * @internal * */ enqueueRender(send: () => Promise, token?: PdfPageRenderCancellationToken): Promise; /** * Closes the document and releases its native handles (and the form * environment). Idempotent; after disposal all page operations resolve to * `null`/empty or reject. Runs the `onDispose` hook supplied at open time. * * @returns The resulting Promise. * */ dispose(): Promise; /** * True if `other` is a {@link PdfDocument} backed by the same native handle. * Note this compares handles, not document contents. * * @param other - The other value (unknown). * @returns Whether the condition is satisfied. * */ isIdenticalDocumentHandle(other: unknown): boolean; /** * Loads the logical document outline as a tree of {@link PdfOutlineNode}. * Returns the staged replacement when present; otherwise reads the physical * PDF outline from the worker. * * @returns The resolved Promise. * */ loadOutline(): Promise; /** * Stages an immutable replacement for the document outline. No worker or PDF * object mutation occurs until {@link materialize} or in-place * {@link encodePdf}. {@link createMaterializedCopy} applies the staged * outline only to the returned document and leaves this document pending. * * @param outline - The outline value. * */ setOutline(outline: readonly PdfOutlineNode[]): void; /** Writes one already-validated outline replacement into the physical PDF. */ private writeOutlineNow; /** * Recursively converts a wire outline node to the public {@link PdfOutlineNode}, * mapping physical page indices onto the current arrangement. * @internal * */ private outlineNodeFromWorker; /** * Loads remaining pages in chunks of roughly `loadUnitDurationMs` worth of work. * `onPageLoadProgress` can return `false` to stop loading further pages. * * @param onPageLoadProgress - The callback invoked when the corresponding event occurs. * @param loadUnitDurationMs - The loadUnitDurationMs value (number). * @returns The resolved Promise. * */ loadPagesProgressively(onPageLoadProgress?: (loadedPageCount: number, totalPageCount: number) => boolean | Promise, loadUnitDurationMs?: number): Promise; /** * Reloads page metadata (e.g. after document modification). * * @param pageNumbersToReload - The pageNumbersToReload value (number[]). * @returns The resulting Promise. * */ reloadPages(pageNumbersToReload?: number[]): Promise; /** * Merges freshly loaded page metadata into the current arrangement and emits * `pageStatusChanged`. * * `updated` is keyed by physical page index, while {@link pages} is keyed by * position, and {@link setPages} may have made the two disagree — so each slot * is matched by its source page and re-based, preserving proxy overrides. * @internal * */ private replacePages; /** * Rebuilds `_pages` from scratch after a structural change (assemble), fully * resizing the array. Not wrapped in {@link synchronized} — call from within a * synchronized block. * @internal * */ private refreshAllPages; /** * Rewrites the PDF to match the current {@link pages} arrangement, turning the * proxies {@link setPages} / {@link setPage} left behind into real pages — * pages of other documents are copied in, so the arrangement stops depending * on them. * * Called automatically by {@link encodePdf}; use it directly only when you * need the native document itself to be consistent (e.g. before * {@link loadOutline} or a raw worker operation). A no-op when the arrangement * is unmodified. After the rewrite the pages are reloaded and * `pageStatusChanged` fires. * */ private materializePageArrangement; /** * Writes every pending page, outline, and Link-annotation edit into the * physical PDF. In-place {@link encodePdf} calls this automatically. * {@link createMaterializedCopy} instead materializes only its returned * independent document. * * @returns The resulting Promise. * */ materialize(): Promise; /** * Serializes the current logical state to PDF bytes, including pending page, * outline, and Link-annotation edits. In-place encoding writes them into this * document with {@link materialize} first; copy and compact encoding * materialize only a temporary document. * * @param options - Options that customize the operation. * @returns The resulting Promise. * */ encodePdf(options?: PdfEncodeOptions): Promise; /** * Reads the document catalog as a structured value. * Indirect references remain references, so cyclic PDF graphs are never expanded. * Stream data is decoded; set `includeRawStreamData` to also receive its encoded bytes. * * This reads the physical PDF object graph in the worker, not pending logical * state created by {@link setPages}, {@link setPage}, {@link setOutline}, or * Link-annotation CRUD. When {@link hasPendingChanges} is `true`, call * {@link materialize} first (or use in-place {@link encodePdf}) before * interpreting affected page-tree dictionaries, page references, outlines, * annotations, or other catalog data. * * @param options - Options that customize the operation. * @returns The resolved Promise. * */ getCatalogObject(options?: { includeRawStreamData?: boolean; }): Promise<{ object: PdfRawObject | null; objectNumber: number; generationNumber: number; }>; /** * Reads one indirect PDF object as a structured value. * Indirect references remain references, so cyclic PDF graphs are never expanded. * Stream data is decoded; set `includeRawStreamData` to also receive its encoded bytes. * * Object numbers and references belong to the physical PDF object graph in * the worker. Pending edits from {@link setPages}, {@link setPage}, * {@link setOutline}, or Link-annotation edits exist only in logical state * and can disagree with that graph. Call {@link materialize} first (or use * in-place {@link encodePdf}) before reading affected objects or retaining * object numbers for later edits. * * @param objectNumber - The object number. * @param options - Options that customize the operation. * @returns The resolved Promise. * */ getRawObject(objectNumber: number, options?: { includeRawStreamData?: boolean; }): Promise<{ object: PdfRawObject | null; objectNumber: number; generationNumber: number; }>; /** Sends an editor's compiled operation batch to the worker. */ private applyRawPatchInternal; /** * Builds and applies a batch of convenient raw PDF-object edits. * * Raw targets and object numbers address the physical PDF object graph, not * pending edits created by {@link setPages}, {@link setPage}, * {@link setOutline}, or Link-annotation CRUD. Raw editing does not * materialize those edits automatically. Call {@link materialize} explicitly * before inspecting raw objects and constructing a related edit batch; * otherwise the batch can target the old page tree, outline, annotations, or * object numbers. Calling {@link encodePdf} first is also sufficient because * it calls {@link materialize}. * * The callback only records operations. If it throws or rejects, the worker is * never called and the document is unchanged. By default, the completed batch * is then applied directly in one worker command. This avoids copying the PDF, * but it is not a rollback boundary: if PDFium applies some operations and a * later operation fails, the earlier changes can remain. * * Pass `{ atomic: true }` for complete all-or-nothing behavior. That mode * applies the batch to an independent materialized copy and makes this * `PdfDocument` adopt the copy only after every operation succeeds. It keeps * the original native document on failure, at the cost of copying and * reloading the entire PDF (with time and peak-memory costs proportional to * document size). * * Atomic success replaces the native document and reconstructs {@link pages}. * Existing `PdfPage` references continue to address the same page indices, but * callers should prefer reading `document.pages` again afterward. * * Raw edits do not describe their GUI impact. A viewer displaying this * document must therefore be refreshed explicitly—for `@pdfrx/viewer`, use * {@link https://espresso3389.github.io/pdfrx_web/classes/_pdfrx_viewer.PdfrxViewer.html#refreshpages | PdfrxViewer.refreshPages()}, * {@link https://espresso3389.github.io/pdfrx_web/classes/_pdfrx_viewer.PdfrxViewer.html#refreshdocument | PdfrxViewer.refreshDocument()}, * or * {@link https://espresso3389.github.io/pdfrx_web/classes/_pdfrx_viewer.PdfrxViewer.html#reloaddocument | PdfrxViewer.reloadDocument()} * according to the scope and whether PDFium itself must be reconstructed. * * @example Add a ViewerPreferences indirect dictionary to the catalog * ```ts * await document.editRawObjects( * (editor) => { * const preferences = editor.createDictionary({ * HideToolbar: { kind: 'boolean', value: true }, * DisplayDocTitle: { kind: 'boolean', value: true }, * }); * editor.setDictionaryValue( * editor.catalog(), * 'ViewerPreferences', * preferences.reference, * ); * }, * { atomic: true }, * ); * * // The engine cannot infer which viewer caches the raw edit affects. * await viewer.refreshDocument(); * ``` * * @param edit - The edit value. * @param options - Options that customize the operation. * @returns The resulting Promise. * */ editRawObjects(edit: (editor: PdfRawObjectEditor) => void | Promise, options?: PdfRawObjectEditOptions): Promise; /** Replaces this instance's native document only after a prepared copy is complete. */ private adoptTransactionalCopy; /** * Creates an independent, fully materialized document from the current * logical state. The caller owns the returned document and must dispose it. * * Pending page, outline, and Link edits are applied to the returned document, * whose {@link hasPendingChanges} is therefore `false`. The source document * on which this method is called is not materialized or otherwise modified; * its pending state remains unchanged. * * `catalog: "preserve"` chooses the sole imported source as its base when * possible and preserves that source's catalog. `catalog: "rebuild"` imports * the arranged pages into a new empty PDF and omits objects not reachable * from those pages, whether they originated in the source PDF or from * subsequent edits. Rebuilding does not inherit existing physical * document-level outlines, metadata, name trees, signatures, or AcroForm * configuration. Pending logical page, outline, and Link edits are still * applied to the returned document. * * @param options - Options that customize the operation. * @returns The resulting Promise. * */ createMaterializedCopy(options?: PdfMaterializedCopyOptions): Promise; /** Imports the current arranged pages into a new empty PDF. */ private createCompactArrangementCopy; /** Creates a materialized copy of `pages` using this document as its catalog base. */ private createArrangementCopy; /** * Loads all AcroForm fields across the document's currently loaded pages, * grouped by fully-qualified name (widgets that share a name — e.g. a radio * group — merge into one field). Returns an empty array for documents without * a form. Reflects live values, including ones changed by * {@link setFormFieldValue} or interactive editing. * * @returns The resolved Promise. * */ loadFormFields(): Promise; /** * Returns the current value of the named field, or `undefined` if it is not found. * * @param name - The name to look up. * @returns The resolved Promise. * */ getFormFieldValue(name: string): Promise; /** * Sets the value of the field identified by fully-qualified `name`, routed * through the form-fill module so the widget appearance regenerates and the * change is visible on the next render. When {@link formCalculationEnabled} is * set (the default), dependent calculated fields (`AFSimple_Calculate`) are * recomputed afterwards. Fires one `formFieldsChanged` event using the * supplied mutation origin (`api` by default). The interpretation of `value` * depends on the field type — see {@link PdfFormFieldValue}. * * @param name - The name to look up. * @param value - The value to use. * @param options - Options that customize the operation. * @returns The resulting Promise. * */ setFormFieldValue(name: string, value: PdfFormFieldValue, options?: PdfFormMutationOptions): Promise; /** * Applies several field values as one form transaction, runs calculations * once, and emits one `formFieldsChanged` event containing the complete * direct + calculated before/after diff. * * @param values - The values to use. * @param options - Options that customize the operation. * @returns The resulting Promise. * */ setFormFieldValues(values: Readonly>, options?: PdfFormMutationOptions): Promise; private applyFormFieldValues; private snapshotFormValues; private diffFormValues; /** * Loads all content annotations (ink, shapes, text markup, notes, free text — * not widgets/links/popups) across the current page arrangement, including * imported pages. Each result is tagged with its 1-based arrangement * `pageNumber`. Use {@link PdfPage.loadAnnotations} when only one page is * needed. If the same physical source page is placed more than once, its * shared annotations appear once per placement. Returns `[]` for a disposed * document. * * @param options - Options that customize the operation. * @returns The resolved Promise. * */ loadAnnotations(options?: PdfLoadAnnotationsOptions): Promise; /** * Loads highlights across the current page arrangement. Use * {@link PdfPage.loadHighlights} for one page. Each result includes its * 1-based arrangement page number; imported and duplicate placements follow * the same semantics as {@link loadAnnotations}. * * @param options - Options that customize the operation. * @returns The resolved Promise. * */ loadHighlights(options?: PdfLoadHighlightsOptions): Promise; /** Applies a page-scoped add and emits the change from the arrangement document. @internal */ addAnnotationForPage(page: PdfPage, spec: PdfAnnotationSpec, options?: PdfAnnotationMutationOptions): Promise; /** Applies a page-scoped update and emits the change from the arrangement document. @internal */ updateAnnotationForPage(page: PdfPage, id: string, spec: PdfAnnotationSpec, options?: PdfAnnotationMutationOptions): Promise; /** Applies a page-scoped removal and emits the change from the arrangement document. @internal */ removeAnnotationForPage(page: PdfPage, id: string, options?: PdfAnnotationMutationOptions): Promise; /** * Exports a versioned, structured-cloneable snapshot across the current * arrangement. This stays on `PdfDocument` because snapshots can span pages; * use {@link PdfPage.loadAnnotations} for a single-page read. A physical * source page placed more than once is exported once, using its first * arrangement page number, because all placements share the same stable ids * and annotation state. * * @returns The resulting Promise. * */ exportAnnotations(): Promise; /** * Restores a document-wide snapshot while preserving ids and emitting one * `annotationsChanged` notification batch. The PDFium mutations are * sequential, not transactional: a later failure can leave earlier changes * applied. * * @param snapshot - The current immutable session snapshot. * @param options - Options that customize the operation. * @returns The resulting Promise. * */ restoreAnnotations(snapshot: PdfAnnotationSnapshot, options?: PdfRestoreAnnotationsOptions): Promise; /** * Routes a cross-page synchronization batch to its arrangement pages and * emits one `annotationsChanged` event after the applied operations. This is * a notification batch, not a rollback transaction: a later failure can * leave earlier PDFium mutations applied. Use page methods for independent * local CRUD on one page. * * @param changes - The changes to apply. * @param options - Options that customize the operation. * @returns The resulting Promise. * */ applyAnnotationChanges(changes: readonly PdfAnnotationChange[], options?: PdfAnnotationMutationOptions): Promise; private removeAnnotationRaw; private writeLinkAnnotationRaw; /** * Loads each physical page once, using its first arrangement placement for * the snapshot page number. Duplicate placements share annotation state and * must not produce duplicate stable ids in export/restore bookkeeping. * */ private loadUniqueSourceAnnotations; private emitAnnotationChanges; /** * Notifies every open arrangement that currently places one physical source * page. This keeps both the source document's viewer and all borrowing * document viewers current after page-scoped CRUD. * */ private emitAnnotationSourceChange; private loadAnnotationSpec; private annotationHistoryFromSnapshots; /** * Resolves a 1-based arrangement position to its physical page. Annotation * writes are dispatched to that page's owning document, so arrangements may * freely mix pages imported from other open documents. * @internal * */ private pageForAnnotation; /** * Sends one form-field write to the worker (find the field's page, dispatch * the typed command). No calculation or event — the primitive shared by * {@link setFormFieldValue} and {@link runFormCalculations}. * @internal * */ private sendSetFormFieldValue; /** * Loads (once) and caches the document's parsed `AFSimple_Calculate` specs. * @internal * */ private ensureCalcSpecs; /** * Recomputes calculated fields (`AFSimple_Calculate`) to a fixed point from the * current field values and writes back the ones that changed. A JS-free stand-in * for the calculate actions this PDFium build cannot run. * @internal * */ private runFormCalculations; /** * Reserved for internal use only (the viewer). Opens `page` for interactive * form editing so pointer/keyboard events can be routed to it. Idempotent. * @internal * */ formOpenPage(page: PdfPage): Promise; /** * Reserved for internal use only (the viewer). Closes an interactive form page. * @internal * */ formClosePage(page: PdfPage): Promise; /** * Reserved for internal use only (the viewer). Forwards a pointer event; `x`/`y` * are in the page's bounding-box-relative PDF coordinates (same space as * {@link PdfFormField.rects}), y-up. * @internal * */ formPointerEvent(page: PdfPage, type: 'down' | 'up' | 'move' | 'doubleClick', x: number, y: number, modifier?: number): Promise; /** * Reserved for internal use only (the viewer). Forwards a keyboard event. * @internal * */ formKeyEvent(page: PdfPage, type: 'char' | 'keyDown' | 'keyUp', code: number, modifier?: number): Promise; /** * Reserved for internal use only (the viewer). Clears the form keyboard focus. * @internal * */ formKillFocus(): Promise; /** * Serializes `action` against previously scheduled page-loading work so that * {@link loadPagesProgressively} and {@link reloadPages} never overlap. * @internal * */ private synchronized; /** * Builds {@link PdfPermissions} from wire fields, or `null` for unencrypted docs. * @internal * */ private static parsePermissions; } /** * Spec for constructing a *proxy* page: a stand-in that presents a different * page number and/or rotation for an existing page without touching the * underlying PDF. Built internally while arranging or rotating pages. * @internal * */ export interface PdfPageProxySpec { readonly basePage: PdfPage; readonly document: PdfDocument; readonly pageNumber: number; readonly rotation: PdfPageRotation; readonly id?: PdfPageId; } /** * A page of a document. Obtain instances via {@link PdfDocument.pages}; do not * construct directly. * * A page has two identities that usually coincide but need not: where it sits * in the document ({@link pageNumber}, its `rotation`) and which physical page * of which PDF it draws ({@link sourcePage}). {@link rotatedTo} returns a * *proxy* page that changes the effective rotation while sharing the physical * page. {@link PdfDocument.setPages} similarly assigns placement and page * numbers from array order, which is what makes rearrangement free. * */ export declare class PdfPage { /** The document holding the physical page this one draws. */ readonly sourceDocument: PdfDocument; /** @internal */ constructor( /** The document holding the physical page this one draws. */ sourceDocument: PdfDocument, src: WorkerPageInfo | PdfPageProxySpec, id?: PdfPageId); /** * Document whose current arrangement contains this page. * * For an imported page this differs from {@link sourceDocument}, which owns * the physical PDF page and its annotations and form widgets. * */ readonly document: PdfDocument; /** * Opaque logical-page identity. Placement and rotation proxies retain it; * {@link duplicate} creates a distinct identity without copying PDF data. * */ readonly id: PdfPageId; /** 1-based page number — the position in {@link PdfDocument.pages}, not in the PDF. */ readonly pageNumber: number; /** Page width in points (1/72 inch), at this page's `rotation`. */ readonly width: number; /** Page height in points (1/72 inch), at this page's `rotation`. */ readonly height: number; /** Effective page rotation (clockwise); on a rotated proxy this differs from the rotation baked into the PDF. */ readonly rotation: PdfPageRotation; /** False for pages not yet materialized during progressive loading. */ readonly isLoaded: boolean; /** The real page this one stands in for, or `null` if this *is* a real page. */ readonly basePage: PdfPage | null; /** Reserved for internal use only. 0-based index of the physical page within {@link sourceDocument}. @internal */ readonly sourcePageIndex: number; /** Reserved for internal use only. Rotation baked into the PDF for the physical page. @internal */ readonly sourceRotation: PdfPageRotation; /** Left of the page's bounding box; text/link rects are shifted by it internally. @internal */ private readonly bbLeft; /** Bottom of the page's bounding box; text/link rects are shifted by it internally. @internal */ private readonly bbBottom; /** Recreates the worker page metadata when a transactional document copy is adopted. */ /** @internal */ toWorkerInfo(): WorkerPageInfo; /** Whether this page is a proxy over {@link basePage} rather than a real page. */ get isProxy(): boolean; /** The real page backing this one; `this` when {@link isProxy} is false. */ get sourcePage(): PdfPage; /** * Whether `other` draws the same physical page of the same PDF, regardless of * page number or rotation. Useful for keying caches by content. * * @param other - The other value (PdfPage). * @returns Whether the condition is satisfied. * */ hasSameSource(other: PdfPage): boolean; /** * Identity of the physical page, independent of where it sits in the document. * Two pages with the same key produce the same text and links. * */ get sourceKey(): string; /** * Identity of what {@link render} draws — {@link sourceKey} plus rotation. * Cache bitmaps under this and moving a page around costs nothing. * */ get renderKey(): string; /** * Returns a lightweight proxy over the same physical page with a new logical * identity. No PDF data is copied or materialized, so this operation is * effectively free. The returned page still renders the same physical page; * only placement identity is separated. * * This matters when one {@link PdfPage} is placed more than once. Reusing the * same object also reuses its opaque {@link id}, so an ID-based {@link dest} * can identify the page but not a particular occurrence: * * ```ts * const [page, ...rest] = document.pages; * document.setPages([page!, ...rest, page!]); * * const ambiguous = page!.dest({ * by: 'id', * command: 'fit', * params: [], * }); * // Both placements have the same ID. Following `ambiguous` selects one * // matching placement; callers must not rely on which one is selected. * ``` * * Call `duplicate()` before arranging the second occurrence when destinations * must distinguish them: * * ```ts * const [page, ...rest] = document.pages; * const secondPlacement = page!.duplicate(); * document.setPages([page!, ...rest, secondPlacement]); * * const firstDest = page!.dest({ * by: 'id', * command: 'fit', * params: [], * }); * const secondDest = secondPlacement.dest({ * by: 'id', * command: 'fit', * params: [], * }); * ``` * * The two destinations now follow separate placements, while both pages * continue to use the same underlying PDF page data. * * @returns The resulting PdfPage. * */ duplicate(): PdfPage; /** * Creates an immutable destination for this logical page or its current * 1-based position. * * An ID-based destination is ambiguous when the same page identity occurs in * multiple arrangement slots. Use {@link duplicate} when destinations must * distinguish repeated placements; see that method for examples and details. * * @param options - Options that customize the operation. * @returns The resulting PdfDest. * */ dest(options: PdfDestOptions): PdfDest; /** Returns a placement proxy owned by `document`. @internal */ placedIn(document: PdfDocument, pageNumber: number, id?: PdfPageId): PdfPage; /** * Creates a page-placement proxy with the requested absolute rotation. * * Calling this method alone does **not** modify the PDF or * {@link PdfDocument.pages}. Pass the returned page to * {@link PdfDocument.setPage} to replace one placement, or include it in the * array passed to {@link PdfDocument.setPages}. Those methods update the * in-memory arrangement synchronously; {@link PdfDocument.encodePdf} or * {@link PdfDocument.materialize} later writes the arrangement into the * physical PDF. * * `rotation` is clockwise and absolute: `90` means the page is displayed at * 90 degrees regardless of the page's current `rotation` property. If it * already has the requested rotation, this method returns `this`. * * @example Rotate the third page to an absolute 90 degrees * ```ts * const page = doc.pages[2]!; * doc.setPage(3, page.rotatedTo(90)); * ``` * * @param rotation - The clockwise page rotation, in 90-degree steps. * @returns The resulting PdfPage. * */ rotatedTo(rotation: PdfPageRotation): PdfPage; /** * Creates a page-placement proxy rotated clockwise by `delta` relative to its * current `rotation` property. * * This does not modify the document by itself. Apply the returned proxy with * {@link PdfDocument.setPage} or {@link PdfDocument.setPages}; use * {@link PdfDocument.encodePdf} or {@link PdfDocument.materialize} only when * the in-memory arrangement must be written into the physical PDF. * * @example Rotate the current first-page placement by 90 degrees * ```ts * doc.setPage(1, doc.pages[0]!.rotatedBy(90)); * ``` * * @param delta - The amount of change to apply. * @returns The resulting PdfPage. * */ rotatedBy(delta: PdfPageRotation): PdfPage; /** * Creates a page-placement proxy rotated 90 degrees clockwise relative to * this page. * * Calling this method does not change {@link PdfDocument.pages}. Apply the * result with {@link PdfDocument.setPage} or {@link PdfDocument.setPages}. * * @example * ```ts * doc.setPage(1, doc.pages[0]!.rotatedCW90()); * ``` * * @returns The resulting PdfPage. * */ rotatedCW90(): PdfPage; /** * Creates a page-placement proxy rotated 90 degrees counter-clockwise * relative to this page. * * Calling this method does not change {@link PdfDocument.pages}. Apply the * result with {@link PdfDocument.setPage} or {@link PdfDocument.setPages}. * * @example * ```ts * doc.setPage(1, doc.pages[0]!.rotatedCCW90()); * ``` * * @returns The resulting PdfPage. * */ rotatedCCW90(): PdfPage; /** * Creates a page-placement proxy rotated 180 degrees relative to this page. * * Calling this method does not change {@link PdfDocument.pages}. Apply the * result with {@link PdfDocument.setPage} or {@link PdfDocument.setPages}. * * @example Rotate several placements in one arrangement update * ```ts * const pages = doc.pages.map((page, index) => * index === 0 || index === 2 ? page.rotated180() : page, * ); * doc.setPages(pages); * ``` * * @returns The resulting PdfPage. * */ rotated180(): PdfPage; /** * Reserved for internal use only. Re-points this page at a freshly loaded * `base` (same physical page, new metadata) while keeping any proxy overrides. * @internal * */ rebasedOn(base: PdfPage): PdfPage; /** * Reserved for internal use only. This page as a source slot for * {@link PdfDocument.materialize}. * @internal * */ toAssembleSource(): PdfAssembleSource; /** * Renders (a part of) the page to a {@link PdfImage} of RGBA8888 pixels * (Canvas/WebGL-ready; the worker converts from the engine's native BGRA). * * The page is scaled to `fullWidth` x `fullHeight` (defaulting to the page * size in points, i.e. 72 dpi) and the `x`/`y`/`width`/`height` sub-region of * that scaled page is returned. Use {@link PdfImage.toImageData} / * {@link PdfImage.toImageBitmap} to draw the result. Returns `null` if the * document is already disposed, or if * {@link PdfPageRenderOptions.cancellationToken} was cancelled. * * Renders are queued (one in the worker at a time by default) rather than all * posted at once, so a render that is no longer wanted can be dropped before * it starts — see {@link createCancellationToken}. * * @param options - Options that customize the operation. * @returns The rendered Promise. * */ render(options?: PdfPageRenderOptions): Promise; /** * Creates a token that cancels a {@link render} that has not started yet, * making it resolve to `null`. Use one per render call. * * @example * ```ts * const token = page.createCancellationToken(); * scrolledAway.then(() => token.cancel()); * const image = await page.render({ fullWidth, fullHeight, cancellationToken: token }); * ``` * * @returns The resulting PdfPageRenderCancellationToken. * */ createCancellationToken(): PdfPageRenderCancellationToken; /** * Loads the full text of the page with one bounding rect per UTF-16 code unit * (in page coordinates). Returns `null` if the document is disposed or the * page is not yet loaded (progressive loading). * * @returns The resolved Promise. * */ loadText(): Promise; /** * Loads link annotations on the page and, when * `enableAutoLinkDetection` is true (the default), URL-like text detected in * the page content. Pending annotation-CRUD changes are returned instead of * physical Link annotations while retaining transient detected URLs. * * @param options - Options that customize the operation. * @returns The resolved Promise. * */ loadLinks(options?: { enableAutoLinkDetection?: boolean; }): Promise; /** Loads only the physical PDF's links, bypassing staged replacements. */ private loadLinksFromWorker; /** * Stages the editable Link annotations on this logical page. Other annotation * subtypes and unsupported Link actions are preserved when * {@link PdfDocument.materialize} writes the pending change. * */ /** @internal Stages the complete Link list used by ordinary annotation CRUD. */ stageLinkAnnotations(links: readonly PdfLinkSpec[]): void; /** Writes staged Link annotations to the physical page represented by this page. @internal */ writeLinksNow(links: readonly PdfLinkSpec[]): Promise; /** * Loads the AcroForm fields whose widgets sit on this page, grouped by * fully-qualified name. Rects are in PDF page coordinates (bounding-box * relative, like {@link loadLinks}). Returns an empty array if the document is * disposed, has no form, or the page is not yet loaded. * * @returns The resolved Promise. * */ loadFormFields(): Promise; /** * Loads the editable annotations on this page (including Link annotations, * but not widgets/popups), with rects and geometry in * bounding-box-relative page coordinates (like {@link loadLinks}). Returns an * empty array if the document is disposed or the page is not yet loaded. * * @param options - Options that customize the operation. * @returns The resolved Promise. * */ loadAnnotations(options?: PdfLoadAnnotationsOptions): Promise; /** * Loads highlight annotations on this page. Unlike * {@link PdfDocument.loadHighlights}, this performs no document-wide scan. * With `includeText`, only this page's text is loaded and intersected with the * highlight quadpoints. * * @param options - Options that customize the operation. * @returns The resolved Promise. * */ loadHighlights(options?: PdfLoadHighlightsOptions): Promise; /** * Adds an annotation to this page and returns its id. * * The id is stored in the PDF annotation dictionary's `/NM` ("annotation * name") entry. `/NM` is a PDF-standard string intended to distinguish an * annotation from the other annotations on the same page; it is not the * visible annotation text or the page number. The engine generates one when * {@link PdfAnnotationSpec.id} is omitted. Keep the returned value to pass to * {@link updateAnnotation} or {@link removeAnnotation}, or to correlate the * annotation with another representation. It is preserved when the PDF is * encoded and opened again. * * The physical write is sent to {@link sourceDocument}; the * `annotationsChanged` event is emitted from the source document and every * open arrangement that places that source page. Duplicate placements share * annotation state and all of their page numbers are reported as affected. * * @param spec - The spec value (PdfAnnotationSpec). * @param options - Options that customize the operation. * @returns The resulting Promise. * */ addAnnotation(spec: PdfAnnotationSpec, options?: PdfAnnotationMutationOptions): Promise; /** * Replaces annotation `id` with a fresh annotation built from the complete * `spec`, preserving the id. PDFium has no in-place geometry setter. * * @param id The {@link PdfAnnotationObject.id} returned by * {@link loadAnnotations}, or the id returned by {@link addAnnotation}. * This is normally the annotation dictionary's `/NM` ("annotation name") * value: a PDF-standard string used to distinguish annotations on the * page. Existing PDFs whose annotation has no `/NM` use a page-local * `@` fallback; use * that fallback only with the unchanged result from the most recent * `loadAnnotations()` call because page mutations can change the index. * * @param spec - The spec value (PdfAnnotationSpec). * @param options - Options that customize the operation. * @returns The resulting Promise. * */ updateAnnotation(id: string, spec: PdfAnnotationSpec, options?: PdfAnnotationMutationOptions): Promise; /** * Removes the annotation identified by `id`; returns whether it was found. * * @param id The {@link PdfAnnotationObject.id} returned by * {@link loadAnnotations}, or the id returned by {@link addAnnotation}. * This is normally the annotation dictionary's stable `/NM` ("annotation * name") value, a PDF-standard string used to distinguish annotations on * the page. * For an existing annotation without `/NM`, `loadAnnotations()` returns a * page-local `@` fallback instead. Such a fallback is positional, * so use it before any other annotation is added, removed, or replaced on * this page; otherwise load the annotations again and use the new id. * * @param options - Options that customize the operation. * @returns The resulting Promise. * */ removeAnnotation(id: string, options?: PdfAnnotationMutationOptions): Promise; /** @internal Returns the complete writable Link-annotation list for CRUD. */ loadEditableLinkSpecs(): Promise; private annotationFromLink; /** @internal Converts a wire annotation (raw coords) to the public model (bbox-relative). */ private annotationFromWorker; /** @internal */ private annotationGeometryFromWorker; /** * @internal Converts an annotation spec (bbox-relative page coords) to the wire * form (raw page coords) the worker's create/replace commands expect. * */ annotationSpecToWorker(spec: PdfAnnotationSpec): WorkerAnnotationSpec; /** @internal */ private annotationGeometryToWorker; /** @internal */ private pointFromWorker; /** @internal */ private pointsFromFlat; /** @internal */ private quadFromWorker; /** @internal */ private flatFromPoints; /** @internal */ private quadToWorker; /** @internal Converts a bbox-relative {@link PdfRect} to a raw wire rect. */ private rectToWorker; /** * Converts a wire rect (raw page coordinates) to a {@link PdfRect} relative to * the page's bounding-box origin ({@link bbLeft} / {@link bbBottom}). * @internal * */ private rectFromWorker; /** * Reserved for internal use only. Converts a wire rect to a bounding-box-relative * {@link PdfRect}; used by the form invalidate relay. * @internal * */ WorkerRectToPdf(r: WorkerRect): PdfRect; /** * Reserved for internal use only. Converts a bounding-box-relative page point * (as used by {@link PdfFormField.rects} / {@link loadLinks}) back to raw PDF * page coordinates, which the form-fill `FORM_On*` input APIs expect. * @internal * */ toRawPagePoint(x: number, y: number): [number, number]; } export {}; //# sourceMappingURL=document.d.ts.map