e59c9a793e
Fix text editing layout and preserve source PDF font styles ( #36 )
...
* Comments: a text box's rectangle follows its edited text
Editing a text box (or typewriter or callout) rewrote /Contents but
kept the old /Rect: the appearance clipped the new text to the old box
and silently dropped lines that no longer fit, while shorter text left
an oversized box. set_contents now re-measures the text with the same
Helvetica widths as at creation and re-fits the box: the wrap width and
top edge stay, the height fits the wrapped lines. A callout's leader
line keeps its place and re-attaches to the moved box (that geometry
moved from set_rect into a shared apply_text_box). A locked box keeps
its text editable, so it re-fits too.
Covered by annot tests (grow and shrink with nothing clipped, callout
leader re-attach, locked box) and a comment_edit round trip through the
automation tools; parity entries cite them.
Co-Authored-By: GLM <noreply@z.ai >
* Polish edit text and images tool
* feat(edit-text): select source font style
* fix(edit-text): preserve detected PDF font styles
* feat(edit-text): support Japanese replacements
* fix(forms): escape non-ASCII format script strings
* Forms: unwrap_or instead of map_or with identity (clippy map_or_identity)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com >
Co-authored-by: GLM <noreply@z.ai >
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-05 07:48:23 -04:00
Brandon Thomas and Claude Opus 5.5
15f6fa7d4c
Never crash: forms scripts can't overflow the stack or the date arithmetic
...
Two crashes that a PDF can trigger, each with a regression test that failed before this change:
- Deeply nested arguments in a field's format script (`[[[[…` or `new Array(new Array(…`) and
deeply nested simplified field notation (`((((…` or `----…1`) recursed until the stack
overflowed, which aborts the whole app. Nesting is now capped at 64 levels; deeper input is
rejected like any other unparseable script.
- A date with a huge year (`1/1/2147483647`) overflowed `weekday`, and a `DateTime` with month 0
indexed before the month names. The weekday math is now done in i64, years beyond i32 don't
parse, and month and day names are looked up with `get`.
Also removes the crate's remaining `expect`/`unreachable!` calls and denies the panic lints.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-04 13:06:23 -04:00
Brandon Thomas and Claude Opus 5.5
aa194686f1
M6: Prepare a form detects fields (underscore blanks, rules, boxes, check squares) and names them from their labels; form.detect, form_detect_fields
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-03 05:21:01 -04:00
Brandon Thomas and Claude Opus 5.5
620ef4fcad
M6: Field Properties ▸ Actions tab (six triggers, JavaScript/link/reset/menu/page/show-hide/submit actions); form_actions, form_set_actions tools; signing UI tests get their own temp folders
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-03 05:08:28 -04:00
Brandon Thomas and Claude Opus 5.5
06f8d73ec7
M6: Acrobat JavaScript: sandboxed boa engine with the forms object model (printcraft-js); custom keystroke/validate/calculate/format scripts, button scripts, document JavaScripts, JavaScript console (⌘J), Preferences ▸ Enable JavaScript; js_run, js_document_scripts, js_set_document_script, form_set_script, js_enabled tools
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-03 04:41:47 -04:00
Brandon Thomas and Claude Opus 5.5
d5c659812c
M6: Image fields: Prepare a form ▸ Image field places an icon-only button that asks for a picture when clicked (buttonImportIcon recognised natively); form_set_image
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 05:16:42 -04:00
Brandon Thomas and Claude Opus 5.5
c0f9c73ae9
M6: Prepare a form ▸ Preview (fill the form as a reader would; Edit fields goes back) and Field Properties ▸ Locked (annotation Locked flag; properties greyed out until unlocked, values still fillable); form_set_props takes locked
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 04:28:19 -04:00
Brandon Thomas and Claude Opus 5.5
aac0db461d
M6: Duplicate a field across pages (right-click ▸ Duplicate…, all pages or a range): widgets of the same field share one value; a field that is its own widget is split into a field and a widget kid. Prepare mode gets a field context menu (Properties, Duplicate, Delete)
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 04:20:26 -04:00
Brandon Thomas and Claude Opus 5.5
d97711302c
M6: Order tabs manually: the Fields panel lists fields in tab order and, while preparing a form, moves a field earlier or later on its page (widgets reordered in /Annots, other annotations keep their places, page switches to annotation order); form_tab_order takes field + move
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 03:37:13 -04:00
Brandon Thomas and Claude Opus 5.5
dfae15ec67
M6: Field Properties ▸ Options for every field type: text alignment, default value, scroll long text, rich text, password, file selection, spell check, comb of characters (with its rules); choice defaults, sort items (the list is reordered), custom text, multiple selection, commit immediately; check box / radio checked by default and radios in unison. Reset form restores defaults. form_set_props takes align, default and flags
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 03:28:44 -04:00
Brandon Thomas and Claude Opus 5.5
92d37ca696
M6.6/M6.8: Field Properties Appearance tab (border/fill colour, thickness, solid/dashed/beveled/inset/underline, text colour, Helvetica/Times/Courier); tab order by rows/columns/structure (page /Tabs) honoured by Tab; push buttons run Reset form, Named (print, page navigation), URI, Go to and common one-line scripts (this.print, this.resetForm, app.alert, pageNum) without a JS engine; form_tab_order tool and appearance in form_set_props (67 tools)
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 01:15:02 -04:00
Brandon Thomas and Claude Opus 5.5
24f5768be4
M6.3/M6.6: Form formats, validation and calculation without a JavaScript engine: Acrobat's AF calls (AFNumber/AFPercent/AFDate/AFTime/AFSpecial format and keystroke, AFRange_Validate, AFSimple_Calculate, simplified field notation) recognised and run natively in Acrobat's event order (keystroke on commit, validate with Acrobat's messages, calculate in /CO order, format for display); Field Properties Format/Validate/Calculate tabs write the same scripts; form_set_props format/validate/calculate, form_fields reports them
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 01:07:37 -04:00
Brandon Thomas and Claude Opus 5.5
f8175fb97e
M8.5/M8.6/M8.7: Redact a PDF: new content crate (L2: content-stream operators with spans, inline images, serializer, matrices) and redact crate (L4): Redact annotations; apply removes glyphs (TJ displacement keeps the rest in place; simple, composite/CMap and Type 3 fonts), clears covered image pixels (or removes images it can't re-encode), removes or clips vectors and shadings, rewrites form XObjects copy-on-write, removes overlapping comments, links and fields, draws the boxes with overlay text, then verifies and fails closed; redacted documents save as a full rewrite. Search & Redact text and patterns (phone, e-mail, credit card, SSN, dates). UI: Redact tool (text or box), Redact pages, Find text and redact, Set properties, Clear all / Redact all with confirmation; redact_mark/redact_apply/redact_clear tools (57 tools). Fix: deleting a field when /AcroForm is a direct dictionary
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 00:24:29 -04:00
Brandon Thomas and Claude Opus 5.5
d8209fcbd2
M6.6: Prepare a form: add text, date, check box, radio (new group or join the selected one), drop-down, list box, button and signature fields with Acrobat's names (Text1, Check Box1, Group1…) by click or drag; fields shown with blue fill and name tags, select/move/resize/Delete; Field Properties (General, Appearance font size, Position, Options); engine AddField/SetFieldProps/DeleteField; form_add_field/form_set_props/form_delete_field tools (54 tools). Fix: check box appearance states were direct streams that read back as null after saving
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-02 00:04:25 -04:00
Brandon Thomas and Claude Opus 5.5
67ff9303c8
M6.1/M6.2: form filling: new fonts (L2) and forms (L3) crates; field tree with inheritance, widgets, options; set_value with validation and regenerated appearances (auto-size, comb, multiline, password, quadding, /MK, combo, list selection), check/radio states (own AP when missing), reset to /DV; engine SetFieldValue/ResetForm with fill-forms permission; UI in-place editor (Enter/click-away commit, Escape, Tab with select-all), check/radio toggle, choice popup, Clear form; tools form_fields/form_fill/form_reset. Perf: named destinations indexed once (190 MB manual opens in 1.8 s instead of 172 s); comment and form edits refresh view data from the object graph instead of a full re-inspection (6x faster per edit on large files; equivalence-tested). annot uses the shared fonts helpers. Docs, parity, roadmap.
...
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-01 22:37:35 -04:00