PdfEditor
Writer for edits to an existing PDF. Open one with PdfDocument.edit.
val editor = doc.edit()
editor.setInfo(title = "New Title")
editor.stampPage(doc.pages[0]) {
setFillRgb(0.8, 0.1, 0.1)
text(StandardFont.HelveticaBold, 48.0, 120.0, 400.0, "DRAFT")
}
val bytes = editor.saveIncremental()Two save modes:
saveIncremental appends changes to the original bytes (ISO 32000-1 §7.5.6). The original content is preserved verbatim, only the new/changed objects, a fresh xref section and a trailer pointing back via
/Prevare written at the end. This is the right mode for ordinary edits and the foundation for digital signing (which signs the appended byte range).saveRewritten writes a fresh, garbage-collected file containing only objects reachable from the catalog, with edits applied and unreachable objects dropped. Required for redaction, since removed content is truly gone rather than retained in the original byte prefix.
Encrypted documents (V4 AES-128 and V5 AES-256) are supported when the password authenticated: every staged object is encrypted with the SAME parameters as the base document at saveIncremental time and the trailer keeps the original /Encrypt. Legacy RC4 documents are refused (read-only). Note saveRewritten instead emits a DECRYPTED file: the rewrite drops the /Encrypt dictionary and writes the resolved plain-text objects.
Functions
Stage a new /FlateDecode-compressed stream from uncompressed data (see PdfStreams.flate); returns the reference to it.
Stage a brand-new indirect object; returns the reference to it.
Reserve the next free object number (generation 0).
Rewrite page's content stream by transforming its parsed operations. The page's decoded content is parsed (see ContentStreamParser), passed to transform, re-serialized, written as a new compressed stream, and the page's /Contents is repointed at it. The original content objects are left in place (orphaned) per incremental-update semantics.
Deep-copy one page (and its full transitive object graph: resources, fonts, content streams, XObjects) from source into this editor under fresh object numbers, returning the new page reference. Inherited /MediaBox, /Resources, /Rotate are baked onto the copied page so it is self-contained, and /Parent is dropped (set later by applyPageOrder). Mirrors MuPDF's pdf_graft_page.
Insert a (grafted) page reference at zero-based position.
Append every page of source to this document (cross-document merge).
Redact a single rectangular region of page (see redactRegions).
Redact rectangular regions of page (rectangles in page user space).
Remove all text-showing operations (Tj, TJ, ', ") from page.
Remove page from the document.
Set the page /Rotate (clockwise, must be a multiple of 90). Normalised to 0/90/180/270.
Produce the updated document bytes: original + appended objects + new xref section + trailer. When nothing was staged or overridden this is a verbatim copy of the original.
Serialize a fresh, self-contained PDF containing only the objects reachable from the catalog (and /Info), with staged edits applied and objects renumbered densely. Unlike saveIncremental, the original bytes are NOT retained and unreachable objects (e.g. content streams replaced by an edit) are dropped, which is what makes it the correct method for redaction (the removed content is truly gone, not just superseded).
Set a button field (/Btn) to a named export value, the mechanism behind checkboxes and radio groups. The field's /V becomes the chosen on-state name; every widget's /AS is set to that name when the widget defines it as an appearance state, or to /Off otherwise (so sibling radios in the group are cleared). Pass "Off" to clear the field.
Check or uncheck a checkbox field. The "on" state name is taken from the widget's /AP /N keys (the non-Off one, e.g. /Yes), so the value matches whatever the document author defined.
Set a choice field (/Ch: combo box or list box) to value. Sets /V, sets /I (selected index) when the value is found in /Opt, and regenerates the widget appearance so the selection is visible.
Set document metadata (/Info). Only non-null fields are changed; any existing /Info entries (standard or custom) are preserved. Updates the existing /Info object in place if the trailer references one, otherwise creates a new /Info object and points the trailer at it. Returns the reference to the (possibly newly created) /Info dictionary.
Replace the document's page order with exactly orderedPageRefs. Rebuilds a single flat /Pages node (kids + /Count), re-parents every page to it, and keeps the catalog pointing at it. This is the engine behind delete, reorder, insert and merge: omit a ref to delete, permute to reorder, append a grafted ref to insert. Pages no longer referenced are dropped by saveRewritten.
Fill a text form field: set its value (/V) and regenerate the widget's normal appearance (/AP /N) so the value is visible in any viewer. The appearance honours the field's /DA (font, size, colour) and is clipped to the field rectangle. Also clears the form's /NeedAppearances flag (if set) so viewers use the appearance we just generated.
Set or replace a trailer entry (e.g. /Root, /Info) in the new section.
Overlay content onto an existing page (a stamp/watermark) drawn by block. The existing content is preserved (wrapped in q/Q so its graphics state can't leak into the overlay), the overlay is appended in its own q/Q, and any standard fonts the overlay uses are merged into the page's /Resources under fresh, non-colliding names.
Stage a replacement for an existing object (keeps ref's generation).