Skip to content

PDF-SDK 2.4.1 is out.See what’s new

PDF-SDK
Skip to Content
Docs

Web API reference

Generated from the type declarations in the published package. For a guided introduction, start with the Web guide.

233 public members of PDFEditor, the 13 types declared next to it, and the package's 13 other exports (digital signatures and the engine loader), generated from the shipped .d.ts files.

Static members

create

static create(canvas: HTMLCanvasElement, opts?: PDFEditorOptions): Promise<PDFEditor>

DEFAULT_MIN_ZOOM

static readonly DEFAULT_MIN_ZOOM = 0.5

licenseInfo

static licenseInfo(opts?: { wasmUrl?: string; }): Promise<LicenseInfo>

The current license verdict (loads the engine if needed).

MAX_ZOOM

static readonly MAX_ZOOM = 6

refreshLicense

static refreshLicense(opts?: { wasmUrl?: string; }): Promise<LicenseInfo>

Online keys: ask the license server now and resolve to the verdict afterwards. Offline keys resolve at once.

setLicenseKey

static setLicenseKey(key: string | null, opts?: { wasmUrl?: string; }): Promise<LicenseInfo>

Set (or with null clear) the license key for this page. Resolves to the verdict.

VERSION

static readonly VERSION: string

The SDK's version, stamped from package.json by scripts/gen-bindings.mjs — do not edit.

Instance members

abortPageRenders

abortPageRenders(): void

Abort any in-flight page raster. The header is specific about when: at the START of a new pinch, because the previous settle's crisp render is stale the moment a new gesture begins and letting it finish holds the engine lock against the gesture's first frames — the "cannot pinch again until the zoom settles" stall.

activePage

get activePage(): number

applyEmbeddedFont

applyEmbeddedFont(name: string): boolean

Apply one of the document's own embedded fonts by name.

armReplace

armReplace(): void

backspace

backspace(): void

beginFieldDrag

beginFieldDrag(): void

Live field drag. mode 8 = move, 0-7 = a resize handle; deltas are TOTAL since begin.

beginTextEdit

beginTextEdit(x: number, y: number): boolean

Begin editing the text LINE under a point (a double-click). Returns false if the point missed text, which is the shell's cue to treat the gesture as an ordinary tap.

beginTextEditOnSelection

beginTextEditOnSelection(): boolean

Open a session on the CURRENT selection, rather than at a point (the double-click path).

canPaste

get canPaste(): boolean

canRedo

get canRedo(): boolean

canRedoHere

get canRedoHere(): boolean

canUndo

get canUndo(): boolean

Is there anything to undo (resp. redo) ANYWHERE in the document?

canUndoHere

get canUndoHere(): boolean

Undo/redo restricted to the page on screen — the engine's own rule, kept for a host that wants it.

caretOffset

get caretOffset(): number

caretView

caretView(): { x: number; y: number; h: number; } | null

Caret position and height in canvas px, for drawing a host caret or an IME box.

caretViewAt

caretViewAt(off: number): { x: number; y: number; h: number; } | null

clearClipboard

clearClipboard(): void

clearFieldSelection

clearFieldSelection(): void

clearHover

clearHover(): void

Drop the hover outline — the pointer left, or something else took over.

clearMaterializedAnnots

clearMaterializedAnnots(): void

Finish restoring ALL note/sound glyphs on this page; clears their annotations and restoration history.

clipboardData

clipboardData(): Uint8Array<ArrayBuffer> | null

commonKind

get commonKind(): number

The kind every member of the selection shares, or -1 when they differ. The property bar should only offer a type's controls when this is >= 0 — otherwise a group of a text layer and an image gets a font picker.

consumePageOp

consumePageOp(): { kind: number; a: number; b: number; } | null

Did the last undo/redo replay a structural PAGE op, and what did it do? Page ops interleave with the content history, so an undo can change the page SET — the rail has to be told, or it shows pages that no longer exist.

consumeReplace

consumeReplace(): void

consumeWrap

consumeWrap(): boolean

1 once when typing WRAPPED to a new line, so the shell can react (scroll, resize).

contentDY

get contentDY(): number

The live keyboard-lift offset in canvas px (<= 0 when lifted).

contentLift

get contentLift(): number

The live keyboard-lift offset, the companion to contentDY.

copy

copy(): boolean

currentPageHasText

get currentPageHasText(): boolean

0 = a scanned page with no selectable text — worth warning before a markup tool.

currentPageSizePoints

currentPageSizePoints(): { w: number; h: number; } | null

The CURRENT page's size in points (pre-rotation source box).

cut

cut(): boolean

debugFlags

get debugFlags(): number

deleteField

deleteField(): boolean

deletePage

deletePage(index: number): boolean

deleteSelection

deleteSelection(): void

deselect

deselect(): void

destroy

destroy(): void

disarmReplace

disarmReplace(): void

document

get document(): PDFDocumentEditor

The open document from code (the programmatic document API): read every layer, change and add them, fill forms, edit metadata and pages. Changes show at once and the user can undo them. Survives open() — it always addresses the document currently open.

documentPageSizePoints

documentPageSizePoints(): { w: number; h: number; } | null

The document's own page size in points, independent of the render surface.

documentTextClass

documentTextClass(pdf: Uint8Array, password?: string): 'text' | 'scanned' | 'empty'

What a WHOLE document is made of, for the heads-up at open time.

dragField

dragField(mode: number, dx: number, dy: number): void

dragScaleField

dragScaleField(factor: number): boolean

Scale the selected FIELD about its centre, uniformly.

duplicateField

duplicateField(): boolean

duplicatePage

duplicatePage(index: number): boolean

editLayerHitsAt

editLayerHitsAt(x: number, y: number): boolean

Is a point inside the EDITED layer's true oriented footprint?

editLineRect

editLineRect(): { x: number; y: number; w: number; h: number; } | null

editSelRect

editSelRect(): { x: number; y: number; w: number; h: number; } | null

The selected RANGE's rect, and the edited LINE's rect.

editText

editText(): string

The edited paragraph's text. Empty outside a session.

embeddedFonts

embeddedFonts(): string[]

The DISTINCT fonts already embedded on this page, by stripped BaseFont name. Applying one of these reuses the live font — no re-embed, no subset growth — which is why they belong at the top of any font picker rather than mixed in with system faces.

endFieldDrag

endFieldDrag(commit?: boolean): void

endTextEdit

endTextEdit(): void

fieldBorderWidth

get fieldBorderWidth(): number

fieldBoxAt

fieldBoxAt(x: number, y: number): HoverBox | null

The box of the form field under a point, for a hover highlight in Form Editor — non-mutating, unlike selectFieldAt. Returns a HoverBox (device px, the space drawHover draws in) tagged with the field's kind, or null when no field is there. The engine returns the field's viewport rect the same way the selected-field ring reads it, so the highlight and the ring line up exactly.

fieldColor

fieldColor(which: 0 | 1 | 2): number

fieldHandleAt

fieldHandleAt(x: number, y: number): number

Which field handle a point is on, in the FIELD convention, or 8 for the body, or -1.

fieldOutlineBoxes

fieldOutlineBoxes(): OutlineBox[]

The same, for form-field widgets.

fillSelectedField

fillSelectedField(): number

Exercise the SELECTED field in place — iOS's fillSelectedField (PDFEditorUI.swift ~11093), the first row of its widget menu. FormTap at the field's centre: a text field takes focus (type it), a combo/list focuses and the shell opens its option picker off the formfocuschange event, and a check box / radio toggles on the tap itself. Returns the field type, or -1 if nothing is selected.

flattenForms

flattenForms(): boolean

Bake every form field into page content — one undo step. Each field becomes a layer of its own that looks exactly like it did; nothing else on the page (comments, stamps) is touched.

formCommit

formCommit(): void

formFieldIsMultiline

get formFieldIsMultiline(): boolean

formFieldOptions

formFieldOptions(x: number, y: number): string[]

Options of a combo/list field at a point, for the shell's picker.

formFieldTypeAt

formFieldTypeAt(x: number, y: number): number

Non-mutating hit-test — safe on hover, unlike FormTap. -1 when there is no field.

formFocused

get formFocused(): boolean

formInsertText

formInsertText(text: string): void

formKey

formKey(code: number): void

Raw key into the focused field. Backspace is 8, as the header specifies.

formSelectOption

formSelectOption(x: number, y: number, index: number): boolean

formsInteractive

get formsInteractive(): boolean

glyphCount

get glyphCount(): number

groupCount

get groupCount(): number

How many layers are in the current group (1 for a single selection, 0 for none).

hasForm

get hasForm(): boolean

Does this document have an AcroForm at all?

heapBytes

get heapBytes(): number

Size of the wasm heap in bytes.

highlightQuads

highlightQuads(x0: number, y0: number, x1: number, y1: number, multiLine?: boolean): number[][]

The live markup QUADS for a swept range — the same geometry HighlightCommit will apply, so a preview drawn from these is WYSIWYG.

insertImage

insertImage(img: ImageData, at: { x: number; y: number; }, size: { w: number; h: number; }, kind?: 0 | 1 | 2 | 3 | 4, note?: string): boolean

Place an RGBA bitmap as a layer. img_kind tags the subtype the engine stores with it: 0 photo, 1 note, 2 signature, 3 drawing, 4 sound glyph — so a note stays re-editable as a note, a signature is recognisable on reopen, and a speaker glyph offers playback.

insertImagePageSpace

insertImagePageSpace(img: ImageData, box: { left: number; bottom: number; right: number; top: number; }, kind?: 0 | 1 | 2 | 3 | 4, note?: string): boolean

Place an image by PAGE-space rect (left, bottom, right, top in points, y-UP) rather than viewport px. The y axis is flipped relative to insertImage — page space is PDF space.

insertLinkText

insertLinkText(uri: string, at: { x: number; y: number; }): boolean

Drop a NEW text layer reading uri at at (canvas px) and attach uri to it as a link — the Link tool with nothing selected. iOS's insertLinkTextLayer: the prompt already has the URL, so there is nothing to type; the text is seeded through the same edit session the keyboard would use, committed, and the link attached over the layer's bounds.

insertPage

insertPage(pageIndex?: number, wPt?: number, hPt?: number): boolean

Insert a blank page AT pageIndex — the new page takes that index and everything from there on shifts up one — sized in POINTS. Pass 0 for either dimension to get the CURRENT page's size, which is what both defaults now do.

insertTextBox

insertTextBox(at: { x: number; y: number; }): boolean

Place a text box at at (canvas px) and OPEN IT FOR TYPING, with the placeholder selected so the first keystroke replaces it. This is the whole "add text" gesture, and it is public because the shell needs it WITHOUT a click: arming Text inserts the box straight away rather than loading the next click (see armTool). The click path calls the same method, so both routes place identically.

invalidate

invalidate(): void

Ask for a frame.

isEditing

get isEditing(): boolean

isPointInSelection

isPointInSelection(xCss: number, yCss: number): boolean

isPointOverText

isPointOverText(x: number, y: number): boolean

Is a point on — or within snapping range of — selectable text? Probed with a 4px span, exactly as the iOS shell does, so a markup drag that starts on empty page PANS instead of marking nothing.

knobRect

knobRect(): { x: number; y: number; w: number; h: number; } | null

The rotate knob's rect in canvas pixels, or null. Pure read.

layerBoxAt

layerBoxAt(x: number, y: number): HoverBox | null

The box of whatever a press at this point would select — or null.

layers

layers(): { index: number; kind: LayerKind; objectCount: number; x: number; y: number; w: number; h: number; }[]

Every layer on the page: kind and page-space box. Enough to build a layer list.

layerText

layerText(): string

The SELECTED LAYER's whole text, and a replacement for it (same font, size and position). These live on the document handle and are NOT the edit session's range — to replace a range, set the range and type over it.

license

get license(): LicenseInfo

The license verdict this editor is running under.

linkUriAt

linkUriAt(x: number, y: number): string

The link URI under a point, or '' — for a hover tooltip or a click-through.

markupColor

get markupColor(): number

The colour the armed markup tool will commit with — the preview must paint in it.

markupOpacity

get markupOpacity(): number

maxZoom

get maxZoom(): number

minZoom

get minZoom(): number

The zoom range in force, after the engine's clamping — not the options as written. A host greying out its zoom buttons reads these, and an option the engine corrected (minZoom: 2, maxZoom: 9) would otherwise leave a button lit that can no longer move anything.

moveCaret

moveCaret(x: number, y: number): boolean

moveField

moveField(dx: number, dy: number): boolean

movePage

movePage(from: number, to: number): boolean

nearestOffset

nearestOffset(x: number, y: number): number

The offset nearest a point — for click-to-place and drag-to-select.

noteAnnots

noteAnnots(): { x: number; y: number; w: number; h: number; color: number; text: string; }[]

The note ANNOTATIONS on the active page: the ones stored in the PDF. A shell that wants every note has to read both, and they are disjoint: after a save-and-reopen the image layer is gone and the annotation is all that is left.

noteCount

get noteCount(): number

nudge

nudge(dx: number, dy: number): void

Nudge the selection by whole canvas pixels — one keypress, one undo step.

open

open(pdf: Uint8Array, pageIndex?: number, password?: string): void

Open a PDF. The bytes are copied into wasm memory and owned by the editor.

outlineBoxes

outlineBoxes(): OutlineBox[]

outlineBoxToView

outlineBoxToView(box: OutlineBox): { x: number; y: number; w: number; h: number; } | null

An OutlineBox (from outlineBoxes / fieldOutlineBoxes) to canvas pixels, doing the y-flip those boxes need: they are centre-origin and y-DOWN from the page top, while pageToView wants a bottom-left corner y-UP from the page bottom. Null on the same pages pageToView gives up on. The angle is not applied — a rotated box is not an axis-aligned rectangle; read it off the box.

overlayResReady

overlayResReady(w: number, h: number): boolean

pageContentClass

get pageContentClass(): number

0 = the page is a scan with no selectable text.

pageCount

get pageCount(): number

pageRect

pageRect(): { x: number; y: number; w: number; h: number; } | null

pageSizePoints

pageSizePoints(index: number): { w: number; h: number; } | null

Displayed size of a page in POINTS, post-rotation — so a /Rotate 90 page reports landscape.

pageToView

pageToView(x: number, y: number, w: number, h: number): { x: number; y: number; w: number; h: number; } | null

Page points (y-UP, as layers() reports them) to CANVAS PIXELS — the backing-store space the pointer pipeline and tapSelect use, NOT CSS pixels. (It said "CSS pixels" and that was wrong: the canvas is sized r.width * devicePixelRatio, so a caller who believed the docstring and multiplied by devicePixelRatio probed at twice the offset on every Retina display. Divide by devicePixelRatio to position a DOM element, as drawPlacement does.)

panBy

panBy(dx: number, dy: number): void

Pan the canvas by a delta in canvas px, self-clamping at the page's edges.

panY

get panY(): number

Vertical pan of a tall page, and how far it can travel.

pasteAt

pasteAt(x: number, y: number): boolean

placementPoints

get placementPoints(): { x0: number; y0: number; x1: number; y1: number; } | null

The placement drag AS IT WAS MADE — where it started and where the pointer is now — rather than the normalised box placementRect reports.

placementRect

get placementRect(): { x: number; y: number; w: number; h: number; } | null

The rectangle a place-tool drag has swept so far, in canvas px — for the shell's preview.

prepareOverlayRes

prepareOverlayRes(w: number, h: number): void

Pre-render the overlay at a target resolution, and ask whether it is ready.

probe

probe(pdf: Uint8Array, password?: string): 'ok' | OpenFailure

Classify a PDF without opening it — encrypted, damaged, or fine.

radioGroups

radioGroups(): string[]

readOnly

get readOnly(): boolean

reanchorTop

reanchorTop(): void

Re-anchor the view to the page top (after a rotation or a page change).

recolorHighlights

recolorHighlights(rgba: number): void

Recolour the markup attached to the selected TEXT layer (not the text itself).

redo

redo(): void

redoPage

get redoPage(): number

renderPageThumbnail

renderPageThumbnail(pageIndex: number, w: number, h: number): ImageData | null

Rasterise one page for a thumbnail. CPU-only and safe off the render path — this is the same call the mobile shells use to fill their page rails.

replaceRange

replaceRange(a: number, b: number, text: string): number

Replace [a, b) with text; returns the caret offset afterwards.

resetForm

resetForm(): boolean

Clear every field back to its default — one undo step.

resizeField

resizeField(which: number, dx: number, dy: number): boolean

One-shot resize by a handle delta.

revealSearchHit

revealSearchHit(margin?: number): void

Scroll the current match into view on the active page — the web half of iOS's ensureSearchHitVisible. A hit below the fold of a zoomed page is as invisible as one on another page. CanvasPanBy self-clamps, so a page that already fits simply does not move.

rotatePage

rotatePage(index: number, quarterCw?: number): boolean

quarterCw: 1 = 90° clockwise, -1 = anticlockwise, 2 = 180°.

rotateSelectionBy

rotateSelectionBy(deg: number): void

Turn the selection by deg (clockwise, screen degrees) about its centre — ONE undo step, the way nudge moves it. A crop or a replace re-inserts an image upright; this puts a rotated one back at the angle it had. (Within 5° of a multiple of 45° the engine's angle snap takes it the rest of the way.)

save

save(): Uint8Array<ArrayBuffer> | null

scaleField

scaleField(factor: number): boolean

The one-shot convenience: the whole drag lifecycle in one call, one undo step.

searchClose

searchClose(): void

searchCurrentRect

searchCurrentRect(): { x: number; y: number; w: number; h: number; } | null

The current search hit's rect, so the shell can scroll it into view.

searchInfo

searchInfo(): { current: number; total: number; done: boolean; } | null

searchNav

searchNav(dir: number): number

Step to the next (dir 1) or previous (dir -1) match and GO TO ITS PAGE.

searchStart

searchStart(query: string, matchCase?: boolean): boolean

selectedFieldKind

get selectedFieldKind(): number

selectedFieldRect

selectedFieldRect(): { x0: number; y0: number; x1: number; y1: number; } | null

selectedImage

selectedImage(wantOriginal?: boolean): ImageData | null

The selected image's pixels as straight-alpha RGBA. wantOriginal returns the stashed pre-crop copy, which is what makes cropping non-destructive: stash once, then every later crop starts from the full image rather than from the last crop.

selectedLink(): string

The URI on the SELECTED layer. This is the read-back for setLink; LinkUriAt is a different question — it reads link annotations the DOCUMENT ARRIVED WITH, and an authored link only becomes one of those on Save.

selectedNoteText

selectedNoteText(): string

The selected note's stored text, so a note stays re-editable rather than being a picture.

selectedProps

selectedProps(): SelectedProps | null

Read the selection's properties back from the engine. This is what makes the contextual toolbar real rather than a guess: the shell does not track what kind of layer is selected, it asks.

selectedRadioGroup

selectedRadioGroup(): string

selectedSound

selectedSound(): Uint8Array<ArrayBuffer> | null

The selected sound's bytes, or null.

selectFieldAt

selectFieldAt(x: number, y: number): number

Select the widget at a point. Returns its FPDF_FORMFIELD_* kind, or -1.

selectionBox

selectionBox(): { cx: number; cy: number; w: number; h: number; angle: number; } | null

The selection's oriented box in canvas pixels, or null. Pure read.

selectionRange

get selectionRange(): [number, number] | null

The live range as [a, b), or null when the selection is a plain caret.

selectionViewRect

selectionViewRect(): { x: number; y: number; w: number; h: number; } | null

The selection's AXIS-ALIGNED screen rect, which is what a menu anchors to.

setActivePage

setActivePage(index: number): boolean

setBottomInset

setBottomInset(px: number): void

The height (px) a FLOATING tool picker covers at the bottom of the canvas. While something is being drawn near the page's foot, the page lifts to clear it, the way it lifts for a keyboard; 0 clears it. This does not re-centre the page — setInsets does that for chrome that overlays the canvas.

setCanvasColor

setCanvasColor(css: string): void

Set the surround colour behind the page. The engine paints it, not CSS, so a theme change has to reach it — otherwise the page floats on last theme's ground. Accepts anything getComputedStyle returns: rgb(r, g, b) or #rrggbb.

setCaretOffset

setCaretOffset(off: number): void

setChromeZoom

setChromeZoom(z: number): void

Keeps selection chrome a fixed SCREEN size as the canvas zooms.

setCJKFallbackFont

setCJKFallbackFont(bytes: Uint8Array): void

A pan-CJK fallback face for RENDERING non-embedded CJK text the platform cannot cover. PROCESS-GLOBAL — it takes no editor handle — so register it once at startup, before opening anything. Pass an empty array to clear it.

setClipboardData

setClipboardData(bytes: Uint8Array): boolean

setCornerHandlesOnly

setCornerHandlesOnly(on: boolean): void

Restrict a selection to CORNER handles only (as text already is). Holds across open().

setDocumentViewport

setDocumentViewport(w: number, h: number): void

The DOCUMENT-level viewport, in device px.

setDrawPageShadow

setDrawPageShadow(on: boolean): void

The drop shadow under the page. Holds across open().

setFaux

setFaux(bold: boolean, italic: boolean): void

FAUX bold/italic — synthesised on the CURRENT face, so an embedded subset keeps its outlines.

setFieldBorderWidth

setFieldBorderWidth(w: number): boolean

setFieldColor

setFieldColor(which: 0 | 1 | 2, rgba: number): boolean

which: 0 background, 1 border, 2 text — the engine's convention. Alpha 0 means "none" (0 and 1 only).

setFieldOptions

setFieldOptions(options: string[]): boolean

setFillColor

setFillColor(rgba: number): void

setFloatingCursor

setFloatingCursor(on: boolean, x?: number, y?: number, h?: number): void

The free-flying "floating cursor" — a caret bar that follows a pointer without snapping to glyphs. Purely visual; the real caret is committed once, on release.

setFont

setFont(family: 0 | 1 | 2, bold: boolean, italic: boolean): void

setFontData

setFontData(bytes: Uint8Array, postScriptName: string): boolean

Rebuild the selected text in an ARBITRARY font from its TTF/OTF bytes.

setFontFamily

setFontFamily(family: 0 | 1 | 2): void

A standard family (0 Helvetica, 1 Times, 2 Courier) for every selected run, each keeping ITS OWN bold and italic — unlike setFont, which gives the whole selection one style, so a group of a bold heading and plain text came out all one weight. One undo step.

setFontProvider

setFontProvider(provide: ((codepoint: number, style: number) => Uint8Array | null) | null): void

Supply fallback faces on demand: the engine calls back with a codepoint and a style (bit0 bold, bit1 italic) and the host returns a face that matches, so typed fallback text keeps the surrounding weight instead of flattening to regular.

setFontSize

setFontSize(pt: number): void

setFormsInteractive

setFormsInteractive(on: boolean): void

Let a READ-ONLY document's form fields still be focused and filled.

setGpuCacheBudget

setGpuCacheBudget(bytes: number): void

Cap the renderer's GPU resource cache, in bytes. A plain number is fine — it's converted for the engine here, so callers never deal with BigInt.

setInkStyle

setInkStyle(rgba: number, width: number): void

Colour and width of the freehand stroke, 0xRRGGBBAA and canvas px.

setInsets

setInsets(top: number, bottom: number): void

Chrome insets. The page centres between them, so a toolbar that OVERLAYS the canvas tells the engine its height here rather than shrinking the viewport — that is what lets the page reveal itself behind the chrome instead of jumping.

setKeyboardInset

setKeyboardInset(px: number): void

setLayerText

setLayerText(text: string): boolean

setLiftFrozen

setLiftFrozen(on: boolean): void
setLink(uri: string): boolean

Attach a URI to the current selection (the Link tool). An EMPTY uri removes the link.

setLoupe

setLoupe(on: boolean, x?: number, y?: number): void

setLoupeHighlight

setLoupeHighlight(on: boolean, at: { x: number; y: number; }, from: { x: number; y: number; }, to: { x: number; y: number; }, rgba: number, markupKind: number): void

The loupe with a live markup preview inside it, and its sampled row LOCKED to the start line — so a drag along a paragraph cannot let the magnifier drift onto the line above or below while you are aiming at a word.

setMarkupColor

setMarkupColor(rgba: number): void

Colour used by the markup tools, 0xRRGGBBAA.

setMarkupOpacity

setMarkupOpacity(a01: number): void

Opacity alone, 0..1. The RGB is kept, exactly as the mobile shells store the two.

setNewTextFont

setNewTextFont(bytes: Uint8Array | null, postScriptName?: string): void

A font for NEW text boxes (TTF/OTF bytes): a placed box is set in it, while its size and colour still follow the text around it. postScriptName is the face's name — the same key {@link setFontData} caches by, so picking that font later embeds one copy. Loaded when the first box is placed; a file that won't load is dropped and new text uses the standard face. null clears it. Holds across open().

setNewTextPlaceholder

setNewTextPlaceholder(text: string): void

The word a NEW text box starts with — "Text" in your app's language. It is selected when the box is placed, so the user types over it. Used when the box's font can draw every letter of it, else "Text". '' restores "Text". Holds across open().

setNoteColors

setNoteColors(card: number, text: number): void

setOpacity

setOpacity(a01: number): void

setPreviewPan

setPreviewPan(dx: number, dy: number): boolean

setPreviewZoom

setPreviewZoom(scaleFromStart: number, ax: number, ay: number): void

setRadioGroup

setRadioGroup(name: string): boolean

setReadOnly

setReadOnly(on: boolean): void

Viewer mode: render, zoom, page and search still work; the document cannot be edited.

setRotateIcon

setRotateIcon(icon: ImageData | null): boolean

The glyph inside the rotation knob, drawn as a template — its alpha filled with the selection colour — and fitted into the knob. At most 512×512. null restores the built-in arrow. Returns false (and changes nothing) for a bad size. Holds across open().

setScrollQuality

setScrollQuality(level: number): void

Lower-quality raster while a scroll is in flight; restore on settle.

setSearchHighlightColors

setSearchHighlightColors(colors: { match?: string; current?: string; }): void

The search highlights' colours: every match, and the current one. CSS colours; only the colour is used — the translucency is the engine's, so the text under a highlight always reads. Leave one out for the default (yellow / orange). Holds across open().

setSelectionRange

setSelectionRange(a: number, b: number): void

Select a character range in the live session; offsets are UTF-16 code units. b <= a clears it back to a plain caret. The engine only DRAWS this — see replaceRange for who acts on it.

setSelectionStyle

setSelectionStyle(style: PDFSelectionStyle): void

The selection's look: the box, its handles and rotation knob, the text caret and selection band, and the page-alignment guide. Every field is optional and falls back to the shipped look; sizes are clamped the way the engine clamps them (handleScale 0.75–1.5, borderWidth 1–3 CSS px). Colours are drawn opaque. A mouse's reach for the handles follows handleScale. Holds across open().

setShapeColors

setShapeColors(fill: number, stroke: number): void

setShapeStrokeWidth

setShapeStrokeWidth(px: number): void

Stroke width for the NEXT shape, in CSS px. The shapes were inserted with a hardcoded 2 * devicePixelRatio no matter what the shell's draw controls said, so a Draw toolbar reading "12" produced a 2px rectangle — the control described something the insert never read. (A SELECTED shape's width is setStrokeWidth; this one is the tool's own default.)

setShowAllLayerOutlines

setShowAllLayerOutlines(on: boolean): void

Dashed hint boxes around every selectable layer. Holds across open().

setSound

setSound(data: Uint8Array, name: string): boolean

Attach sound bytes to the current selection (the Sound tool).

setStrikethrough

setStrikethrough(on: boolean): void

setStrokeColor

setStrokeColor(rgba: number): void

setStrokeWidth

setStrokeWidth(w: number): void

setTextStyle

setTextStyle(bold: boolean | null, italic: boolean | null): void

The B and I buttons: make EVERY selected run bold / italic, or not, whatever its face. One undo step. null leaves that style as each run has it — a press of I must not decide the bold of a group that is only partly bold.

setUnderline

setUnderline(on: boolean): void

sha256

sha256(data: Uint8Array): Uint8Array

SHA-256 of a buffer — needed to VERIFY a signature's ByteRange yourself.

shapeStrokeWidth

get shapeStrokeWidth(): number

signatureCertLevel

signatureCertLevel(pdf: Uint8Array, index: number): number

0 approval; 1/2/3 a DocMDP certification level. Editing breaks certification.

signatureCount

signatureCount(pdf: Uint8Array): number

How many signatures a document already carries.

signatureData

signatureData(pdf: Uint8Array, index: number): { byteRange: [number, number, number, number]; cms: Uint8Array; } | null

A signature's /ByteRange and its raw CMS, for host-side verification.

signatureInfo

signatureInfo(pdf: Uint8Array, index: number): { subFilter: string; reason: string; time: string; coversWholeFile: boolean; } | null

signPDF

signPDF(pdf: Uint8Array, sign: (digest: Uint8Array) => Uint8Array | null, opts?: { reason?: string; location?: string; name?: string; contact?: string; fieldName?: string; signingTime?: string; pageIndex?: number; rect?: { x: number; y: number; w: number; h: number; }; cmsCapacity?: number; }): { bytes: Uint8Array | null; code: number; }

Sign a document. sign receives the SHA-256 digest and must return a detached PKCS#7/CMS (DER), or null to abort.

soundAnnots

soundAnnots(): { x: number; y: number; w: number; h: number; data: Uint8Array; }[]

SDK-created sound attachments on the active page, with page-space bounds and copied audio.

soundCount

get soundCount(): number

stashImageOriginal

stashImageOriginal(img: ImageData): void

Stash a pre-crop original so the next crop starts from the full image.

swipeBegin

swipeBegin(dir: 1 | -1): boolean

swipeEnd

swipeEnd(commit: boolean): number

Commit (SetActivePage) or cancel. Returns the page now showing.

swipeMove

swipeMove(dxPx: number): void

switchEditLine

switchEditLine(x: number, y: number): boolean

Move the session to another LINE of the same paragraph without closing it.

tapSelect

tapSelect(x: number, y: number): boolean

Select whatever is at a point, exactly as a tap does.

toggleGroupAt

toggleGroupAt(x: number, y: number): number

Add or remove the layer at a point from the multi-select group; returns the new member count.

tool

get tool(): Tool
set tool(t: Tool)

The armed tool.

trimMemory

trimMemory(): void

Release caches under memory pressure.

typeText

typeText(text: string): void

undo

undo(): void

Undo/redo the next step in the DOCUMENT's history, turning to the page that owns it if needed.

undoPage

get undoPage(): number

The page owning the next undo (resp. redo) step, or -1. undoPage === activePage means it is local.

vScrollRange

get vScrollRange(): number

zoom

get zoom(): number

zoomBy

zoomBy(factor: number): void

Zoom about the canvas centre, the way the toolbar's -/+ do.

Types

HoverBox

export interface HoverBox { cx: number; cy: number; w: number; h: number; angle: number; kind: LayerKind; fieldType?: number; }

The box a hover outlines: centre-origin, in canvas CSS px, with the layer's rotation.

LayerKind

export type LayerKind = 'text' | 'image' | 'path'

LicenseInfo

export interface LicenseInfo { status: LicenseStatus; licensed: boolean; reason: string; licensee: string; licenseId: string; plan: string; keyId: string; issued: string; expires: string; updatesUntil: string; platform: string; identity: string; web: string[]; ios: string[]; macos: string[]; android: string[]; sdkVersion: string; sdkReleaseDate: string; online: boolean; server: string; paymentDue: boolean; leaseExpires: number; message: string; }

LicenseStatus

export type LicenseStatus = 'valid' | 'development' | 'unlicensed' | 'invalid' | 'expired' | 'wrongApp' | 'wrongPlatform' | 'versionNotCovered' | 'unknownSigningKey' | 'suspended' | 'verificationRequired'

The license verdict for this page, as the engine decided it.

OpenFailure

export type OpenFailure = 'password' | 'corrupt' | 'unreadable'

OutlineBox

export interface OutlineBox { cx: number; cy: number; w: number; h: number; angle: number; type: number; }

A layer hint box exactly as the engine reports it: page points, centre-origin, with a rotation.

PDFEditorOptions

export interface PDFEditorOptions { wasmUrl?: string; licenseKey?: string; minZoom?: number; maxZoom?: number; canvasColor?: string; }

PDFLicenseError

export declare class PDFLicenseError extends Error { readonly license: LicenseInfo; constructor(license: LicenseInfo); }

Thrown by create / open when this site has no valid license key. license.reason says why.

PDFOpenError

export declare class PDFOpenError extends Error { readonly reason: OpenFailure; constructor(reason: OpenFailure); }

PDFSelectionStyle

export interface PDFSelectionStyle { color?: string; handleFill?: string; handleShape?: 'rounded' | 'circle' | 'square'; handleScale?: number; borderWidth?: number; }

The selection's look ({@link PDFEditor.setSelectionStyle}). Anything left out keeps the shipped look.

SelectedProps

export interface SelectedProps { kind: LayerKind; imageKind: 0 | 1 | 2 | 3 | 4; noteCardColor: number; noteTextColor: number; objectCount: number; fontSize: number; fontName: string; fontEmbedded: boolean; bold: boolean; italic: boolean; underline: boolean; strikethrough: boolean; opacity: number; fillColor: number; strokeColor: number; strokeWidth: number; isShape: boolean; shapeKind: number; hasHighlight: boolean; highlightColor: number; }

Everything the property bar needs to decide what to OFFER is in here — a note's colours, whether a text layer carries markup, whether an image is a note or a signature — and reading half of it is how a shell ends up guessing the rest.

SelectionEvent

export interface SelectionEvent { selected: boolean; props?: SelectedProps; }

Tool

export type Tool = 'select' | 'multi' | 'text' | 'image' | 'link' | 'note' | 'sound' | 'signature' | 'stamp' | 'highlight' | 'underline' | 'strikeout' | 'squiggly' | 'freehand' | 'rect' | 'ellipse' | 'line' | 'arrow' | 'page' | 'field-text' | 'field-check' | 'field-radio' | 'field-list' | 'field-combo' | 'fields'

Every tool the SDK exposes. Which ones exist is not a UI decision — this list is the audited surface of the engine, and each entry below maps to an engine operation, not to a shell behaviour.

Digital signatures and the engine

createDigitalId

function createDigitalId(opts: { name: string; organization?: string; email?: string; persist?: boolean; }): Promise<DigitalId>

Create a digital ID: an RSA-2048 key pair (private key non-extractable) and a self-signed X.509 v3 certificate valid for ten years.

detachedCms

function detachedCms(id: DigitalId, messageDigest: Uint8Array, signingTime: Date): Promise<Uint8Array>

The detached PKCS#7/CMS over a SHA-256 message digest. The RSA signature covers the signed attributes encoded as a SET (tag 0x31) while they travel under an IMPLICIT [0] — swapping those is the classic reason a CMS verifies nowhere, so both encodings are built explicitly.

DigitalId

interface DigitalId { privateKey: CryptoKey; certificate: Uint8Array; issuer: Uint8Array; serial: Uint8Array; name: string; organization: string; email: string; createdAt: number; }

A self-signed identity: the key stays in the browser, the certificate travels in every signature.

loadDigitalId

function loadDigitalId(): Promise<DigitalId | null>

The ID saved in this browser, or null.

loadEngine

function loadEngine(wasmUrl?: string): Promise<PDFEditorModule>

pdfDate

function pdfDate(d: Date): string

PDF date syntax for /M.

PDFEditorModule

interface PDFEditorModule

The engine as loadEngine() resolves it — call that early to preload; PDFEditor.create loads it itself. Opaque: its members are internal.

SIGN_FAILURE

const SIGN_FAILURE: Record<number, string>

SignaturePlacement

type SignaturePlacement = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'invisible'

signatureRect

function signatureRect(placement: SignaturePlacement, pageW: number, pageH: number): { x: number; y: number; w: number; h: number; } | null

The visible box in page points (y up from the bottom-left), or null for an invisible signature.

SignatureStatus

interface SignatureStatus { index: number; signer: string; time: string; reason: string; valid: boolean; coversWholeFile: boolean; certLevel: number; summary: string; problem?: string; }

signDocument

function signDocument(editor: PDFEditor, pdf: Uint8Array, id: DigitalId, opts?: { reason?: string; location?: string; placement?: SignaturePlacement; pageIndex?: number; pageSize?: { w: number; h: number; }; signingTime?: Date; fieldName?: string; }): Promise<{ bytes: Uint8Array | null; code: number; }>

Sign pdf with id. Two passes over identical options (see the file comment); the result is the input bytes verbatim plus an incremental update, so existing signatures survive and this can be used to counter-sign.

verifySignatures

function verifySignatures(editor: PDFEditor, pdf: Uint8Array): Promise<SignatureStatus[]>

Verify every signature in pdf, in document order. Empty when the file carries none.

Document API

PDFDocumentEditor edits a PDF from code — headless, or the document an editor shows through editor.document. Its 59 members, then its 16 types.

PDFDocumentEditor.open

static open(pdf: Uint8Array, opts?: PDFDocumentOpenOptions): Promise<PDFDocumentEditor>

Open a PDF headless (no canvas).

PDFDocumentEditor.close

close(): void

Free a headless document's engine. A live document belongs to its editor and ignores this.

PDFDocumentEditor.pageCount

get pageCount(): number

PDFDocumentEditor.pageSize

pageSize(page: number): { width: number; height: number; }

The page's size in points (as displayed, i.e. after its rotation).

PDFDocumentEditor.save

save(): Uint8Array

The edited PDF.

PDFDocumentEditor.metadata

metadata(key: PDFMetadataKey): string

PDFDocumentEditor.setMetadata

setMetadata(key: PDFMetadataKey, value: string): void

Written into the file save() produces.

PDFDocumentEditor.text

text(page: number): string

The page's plain text.

PDFDocumentEditor.search

search(query: string, caseSensitive?: boolean): PDFSearchMatch[]

Every match of query in the document.

PDFDocumentEditor.renderPage

renderPage(page: number, width: number, height: number): ImageData | null

The page drawn into a width×height image (a thumbnail, a preview).

PDFDocumentEditor.canUndo

get canUndo(): boolean

PDFDocumentEditor.canRedo

get canRedo(): boolean

PDFDocumentEditor.undo

undo(): boolean

Undo the last change, the user's or this API's. A layer that comes back gets a NEW id — read the layers again.

PDFDocumentEditor.redo

redo(): boolean

PDFDocumentEditor.insertBlankPage

insertBlankPage(index: number, width?: number, height?: number): void

Insert a blank page at index (a zero size takes the neighbouring page's).

PDFDocumentEditor.deletePage

deletePage(index: number): void

PDFDocumentEditor.movePage

movePage(from: number, to: number): void

PDFDocumentEditor.duplicatePage

duplicatePage(index: number): void

PDFDocumentEditor.rotatePage

rotatePage(index: number, clockwise?: boolean): void

PDFDocumentEditor.importPages

importPages(pdf: Uint8Array, opts?: { password?: string; pages?: number[]; index?: number; }): void

Copy pages (all when omitted) of another PDF into this one at index (omitted = the end). This starts the undo history afresh, as a flatten does, and layer ids must be read again.

PDFDocumentEditor.extractPages

extractPages(pages: number[]): Uint8Array

pages of this document as a new PDF.

PDFDocumentEditor.layers

layers(page: number): PDFLayer[]

Every layer of the page, in reading order (top to bottom, then left to right) for a page read the first time.

PDFDocumentEditor.textBlocks

textBlocks(page: number): PDFLayer[]

PDFDocumentEditor.layer

layer(layer: PDFLayer): PDFLayer

The layer as it is now.

PDFDocumentEditor.image

image(layer: PDFLayer): ImageData | null

The picture of an image layer, at its own pixel size.

PDFDocumentEditor.sound

sound(layer: PDFLayer): Uint8Array | null

The audio of a sound layer.

PDFDocumentEditor.setText

setText(layer: PDFLayer, text: string, opts?: { shrinkToFit?: boolean; }): PDFTextResult

Replace a text layer's text, keeping its font, size, colour and position. A paragraph re-wraps at its own width; a single line may grow to the page margin. shrinkToFit lowers the size (to half at most) until the text is no taller than before. Scripts the layer's font lacks need a font provider.

PDFDocumentEditor.setFontSize

setFontSize(layer: PDFLayer, points: number): void

PDFDocumentEditor.setFont

setFont(layer: PDFLayer, family: PDFFontFamily, opts?: { bold?: boolean; italic?: boolean; }): void

PDFDocumentEditor.setFontData

setFontData(layer: PDFLayer, data: Uint8Array, name: string): void

Embed a font of your own (TTF/OTF bytes) and set the layer in it.

PDFDocumentEditor.setTextStyle

setTextStyle(layer: PDFLayer, opts: { bold?: boolean; italic?: boolean; }): void

Bold / italic of the current family; omitted leaves that one as it is.

PDFDocumentEditor.setUnderline

setUnderline(layer: PDFLayer, on: boolean): void

PDFDocumentEditor.setStrikethrough

setStrikethrough(layer: PDFLayer, on: boolean): void

PDFDocumentEditor.setFillColor

setFillColor(layer: PDFLayer, rgba: number): void

Text colour, or a shape's fill (0xRRGGBBAA).

PDFDocumentEditor.setStrokeColor

setStrokeColor(layer: PDFLayer, rgba: number): void

PDFDocumentEditor.setStrokeWidth

setStrokeWidth(layer: PDFLayer, points: number): void

PDFDocumentEditor.setOpacity

setOpacity(layer: PDFLayer, opacity: number): void

PDFDocumentEditor.setFrame

setFrame(layer: PDFLayer, f: PDFRect): void

Move and resize (text scales uniformly).

PDFDocumentEditor.setRotation

setRotation(layer: PDFLayer, degrees: number): void

Degrees, clockwise as seen.

PDFDocumentEditor.setZOrder

setZOrder(layer: PDFLayer, order: PDFZOrder): void
setLink(layer: PDFLayer, url: string | null): void

null removes the link.

PDFDocumentEditor.setSound

setSound(layer: PDFLayer, audio: Uint8Array, name: string): void

PDFDocumentEditor.replaceImage

replaceImage(layer: PDFLayer, image: ImageData): void

Swap an image layer's picture, keeping its frame and kind.

PDFDocumentEditor.setMarkup

setMarkup(layer: PDFLayer, kind: PDFMarkupKind, rgba: number): void

Mark a whole text layer up.

PDFDocumentEditor.removeMarkup

removeMarkup(layer: PDFLayer): void

Remove a text layer's highlight / strikeout / squiggly.

PDFDocumentEditor.delete

delete(layer: PDFLayer): void

PDFDocumentEditor.duplicate

duplicate(layer: PDFLayer, dx?: number, dy?: number): PDFLayer

A copy offset by (dx, dy) points.

PDFDocumentEditor.copy

copy(layer: PDFLayer, toPage: number, x: number, y: number): PDFLayer

A copy on another page, its top-left at (x, y) there.

PDFDocumentEditor.addText

addText(text: string, page: number, x: number, y: number, opts?: { fontSize?: number; color?: number; family?: PDFFontFamily; }): PDFLayer

A text layer with its top-left at (x, y).

PDFDocumentEditor.addImage

addImage(image: ImageData, page: number, frame: PDFRect, opts?: { kind?: PDFImageKind; note?: string; }): PDFLayer

An image layer filling frame. A signature, a hand drawing or a stamp is an image of that kind.

PDFDocumentEditor.addShape

addShape(shape: PDFShape, page: number, from: { x: number; y: number; }, to: { x: number; y: number; }, opts?: { fill?: number; stroke?: number; strokeWidth?: number; }): PDFLayer

A rectangle or ellipse filling the rect from start to end, or a line / arrow from start to end.

PDFDocumentEditor.markupText

markupText(page: number, from: { x: number; y: number; }, to: { x: number; y: number; }, opts?: { kind?: PDFMarkupKind; color?: number; }): void

Mark up the text between two points of the page, as a drag with the tool would.

PDFDocumentEditor.formFields

formFields(): PDFFormField[]

PDFDocumentEditor.setFormValue

setFormValue(field: string, value: string): void

Fill a field: its text, an option's label, "true"/"false" for a check box, or the export value of the radio button to turn on.

PDFDocumentEditor.fillForm

fillForm(values: Record<string, string>): void

Fill several fields at once.

PDFDocumentEditor.addFormField

addFormField(kind: PDFNewFieldKind, page: number, frame: PDFRect, opts?: { name?: string; options?: string[]; }): string

A new field; returns its name (name, or one the editor made up). Radios that share a name are one set.

PDFDocumentEditor.deleteFormField

deleteFormField(name: string): void

Remove every widget called name (a whole radio set).

PDFDocumentEditor.resetForm

resetForm(): void

PDFDocumentEditor.flattenForm

flattenForm(): void

Bake the fields into the pages (their values stay, they stop being editable).

PDFDocumentError

class PDFDocumentError extends Error { readonly code: 'cannotOpen' | 'notFound' | 'unsupportedGlyphs' | 'failed'; constructor( code: 'cannotOpen' | 'notFound' | 'unsupportedGlyphs' | 'failed', message?: string); }

Why a document call failed.

PDFDocumentOpenOptions

interface PDFDocumentOpenOptions { password?: string; wasmUrl?: string; fontProvider?: (codepoint: number, style: number) => Uint8Array | null; }

PDFFontFamily

type PDFFontFamily = 'sans' | 'serif' | 'mono'

The built-in families every PDF reader has.

PDFFormField

interface PDFFormField { name: string; kind: PDFFormFieldType; page: number; frame: PDFRect; value: string; checked?: boolean; exportValue?: string; options: string[]; readOnly: boolean; }

PDFFormFieldType

type PDFFormFieldType = 'text' | 'checkbox' | 'radio' | 'combobox' | 'listbox' | 'button' | 'signature' | 'unknown'

PDFImageKind

type PDFImageKind = 'photo' | 'note' | 'signature' | 'drawing'

What an image layer is to the editor: a signature, a hand drawing and a stamp are images it knows by kind.

PDFLayer

interface PDFLayer { page: number; id: number; kind: PDFLayerKind; frame: PDFRect; rotation: number; opacity: number; zIndex: number; link?: string; text?: string; fontName?: string; fontSize?: number; bold: boolean; italic: boolean; underline: boolean; strikethrough: boolean; fontEmbedded: boolean; symbolic: boolean; textColor?: number; highlightColor?: number; pixelWidth?: number; pixelHeight?: number; note?: string; noteColor?: number; noteTextColor?: number; shape?: PDFShape; fillColor?: number; strokeColor?: number; strokeWidth?: number; }

One layer of a page, as data. Read again after a change — a layer's properties are a snapshot.

PDFLayerKind

type PDFLayerKind = 'text' | 'image' | 'note' | 'signature' | 'drawing' | 'sound' | 'shape' | 'vector'

PDFMarkupKind

type PDFMarkupKind = 'highlight' | 'strikeout' | 'squiggly'

PDFMetadataKey

type PDFMetadataKey = 'Title' | 'Author' | 'Subject' | 'Keywords' | 'Creator' | 'Producer'

PDFNewFieldKind

type PDFNewFieldKind = 'text' | 'checkbox' | 'radio' | 'listBox' | 'dropdown'

PDFRect

interface PDFRect { x: number; y: number; width: number; height: number; }

A rectangle in page points, top-left origin.

PDFSearchMatch

interface PDFSearchMatch { page: number; rects: PDFRect[]; }

PDFShape

type PDFShape = 'rectangle' | 'ellipse' | 'line' | 'arrow'

PDFTextResult

type PDFTextResult = 'replaced' | 'overflow'

How a text replacement went: it fits where the old text was, or it is taller (may run into what is below).

PDFZOrder

type PDFZOrder = 'toBack' | 'backward' | 'forward' | 'toFront'