Files
pdfcraft/crates/annot
42bc4f117d M5: copy and paste comments between documents, select several, finish connected lines from the menu (#3484)
Comments copy and paste, within and between documents. ⌘C with comments selected (and no text
selected) copies them, each with its replies, as XFDF: into the app's clipboard (every tab and
window) and as text onto the system clipboard. ⌘V, Edit ▸ Paste comments or the page's context
menu pastes them onto the current page at their own positions, as new comments under names of
their own, so nothing is replaced and pasting twice gives two sets; the copies are selected.
XFDF with comments from the system clipboard pastes too, so comments travel between processes.

pdfcraft_xfdf::export_xfdf_comments writes a selection with its replies; import_comments takes
a target page and a name prefix and imports copies (the usual import still replaces same names).
Engine: Edit::PasteComments { xfdf, page } (one undo step, comment permission) and
Session::export_comments. Tools: comments_copy (read-only) and comments_paste.

Several comments select at once: ⌘-click (Ctrl on Windows and Linux) or ⇧-click adds one or
takes it out, on the page and in the Comments panel; the one clicked last has the handles.
Delete removes them all as one step, a drag moves them together, the context menu copies them.

Connected lines, polygons and clouds finish from the right-click menu's Complete (with Undo last
point and Cancel drawing), as other editors do, besides Enter and a double-click.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-05 16:41:45 +01:00
..

pdfcraft-annot

Comments (annotations), ISO 32000-2 §12.5. Layer L3, depends on pdfcraft-cos, pdfcraft-fonts and pdfcraft-model.

What it does

  • Builders for the comment types Acrobat's commenting tools create: sticky note (Text + Popup), highlight, underline, strikethrough, squiggly, rectangle (Square), oval (Circle), line and arrow (Line with /LE), freehand drawing (Ink) and text box (FreeText).
  • Appearance streams (appearance::build) generated from the annotation dictionary, so new and restyled comments look the same in every viewer. Highlights multiply (/BM /Multiply). A line's leader lines (/LL, /LLE, /LLO) and caption (/Cap, /CP, /CO) are drawn as ISO 32000-2 Table 178 places them, the caption in black Helvetica 10. Note icons are PdfCraft's own drawings. Text boxes use standard Helvetica (WinAnsi), with line breaking by approximate Helvetica proportions (no font program is bundled). Text it can't draw (in a text box, callout, Fill & Sign text, line caption, measurement label or dynamic stamp's by-line; appearance::undrawable_text) is kept as typed and drawn as ?, and the comment is marked with the first such character (pdfcraft_fonts::UNDRAWN_MARK) so the engine reports the edit and flattening refuses to make it permanent. Two refusals (AnnotError::Undrawable): a redaction mark's overlay text, which becomes page content when applied; and a restyle or resize of a comment another program drew with a font that has those characters, whose appearance is kept rather than redrawn with ? (new text for it is taken).
  • Edits: reply (/IRT), set review status (a /State reply, as Acrobat's "Set status" does), change text, move, resize, restyle, delete (with pop-up and replies).

API sketch

let index = add_annotation(&mut doc, &NewAnnotation { page, shape, style, contents, author }, &meta)?;
add_reply(&mut doc, page, index, "Agreed", "Ada", &meta)?;
set_review_state(&mut doc, page, index, ReviewState::Accepted, "Ada", &meta)?;
move_annotation(&mut doc, page, index, dx, dy, &meta)?;
set_style(&mut doc, page, index, StyleChange::new(Some(rgb), Some(0.5), Some(2.0), None), &meta)?;
delete_annotation(&mut doc, page, index)?;
signature_image(&doc, page, index)?; // embedded image XObject of Fill & Sign signature/initials

A comment is addressed by (page, index in /Annots), the same pair pdfcraft_render::Annotation reports. Meta carries the date and the /NM id so edits stay deterministic; the engine supplies them.

Fidelity rules

  • Unknown keys are kept. Inline annotation dictionaries are promoted to indirect objects only when an edit needs a reference to them.
  • set_style refuses (and changes nothing) when it cannot redraw the comment, e.g. stamps, cloudy borders or callouts, instead of leaving a stale appearance.
  • Replies get the parent's /Rect and an empty appearance: they appear in comment lists but never paint a second icon.
  • Resizing a stamp changes its /Rect and preserves its original appearance and resources; viewers scale that appearance into the new rectangle. Locked stamps refuse the edit.
  • Picture stamps (a natural-size or explicit-rectangle image, a PDF page, or an image signature) and PdfCraft's rubber stamps counterrotate their appearance on rotated pages, so the picture or label reads upright as the page is displayed. Restyling a picture stamp keeps that appearance matrix. The rotation is the page's /Rotate at placement.
  • Sticky notes and file attachments are not counterrotated: they carry the NoRotate flag and their icon is drawn in an unturned 20 × 20 box. A viewer keeps them upright on a turned page, about the upper-left corner of /Rect (ISO 32000-2 §12.5.3). PdfCraft's renderer does so (vendored hayro-interpret patch 37), and Summary::no_rotate tells the UI where the icon is drawn.

Not yet

Callouts, polygons and polylines, clouds, carets (insert/replace text), stamps, file attachments, rich text (/RC, /DS), and the shared named-appearance cache Acrobat writes.