Commit Graph
4844 Commits
Author SHA1 Message Date
oracola91 687425fa7f ATTRIBUTION.toml: new SHA-256 for the es, lt and vi catalogs
The catalogs this PR changes are tracked assets, so their recorded
hashes follow the edits (cargo xtask assets).
2026-10-18 21:52:37 +03:00
Marco Arnulfo 9e0937c3f7 M12: the Visual filter only hides shading, since visual differences are never listed: say so 2026-10-18 20:38:18 +02:00
Marco Arnulfo 947f0f2994 XFA: turn TIFF pictures by their Orientation tag 2026-10-18 20:37:33 +02:00
jonathanwxh-cell 9b0aeb0f69 M11: integrate main b0e5c6eb into PR #3227 and fix version parser lifetime 2026-10-19 02:35:26 +08:00
oracola91 262ae579f8 i18n: Lithuanian and Vietnamese for the new signature messages
The Lithuanian and Vietnamese catalogs came to main after this branch.
Their tests require every key the other catalogs have, so the four new
signature messages need a line in each.
2026-10-18 21:32:13 +03:00
oracola91 954c5142e7 fix(ui): the message bar shows a signature problem before "Certified by"
With a valid certification signature, the message bar said "Certified
by ..." whatever the other signatures said, so an approval signature
added later that is invalid, or whose validity is unknown, did not show
in the bar. The Signatures panel listed it correctly.

The bar now says "Certified by ..." only when every signature is valid.
Otherwise it shows "At least one signature is invalid." or "At least one
signature has problems.", as it already did for documents without a
certification.
2026-10-18 21:30:52 +03:00
PerchAnton 2448074def M4: assert redo survives destination-budget refusal 2026-10-18 21:25:45 +03:00
oracola91 343f1b05cc fix(sign): signed attributes must carry the message digest and the data content type
With signed attributes, the signature value is made over the attributes,
and their messageDigest is what ties it to the document. The digest was
compared only when the attribute was present, and the content-type
attribute was never checked. RFC 5652 section 5.3 requires both.

A signature whose signed attributes have no messageDigest, or name a
content type other than id-data, is now invalid. A missing content type
is reported and the signature is read anyway. A signature that still
validates with an RSA key under 2048 bits now gets a note, as SHA-1 and
RIPEMD-160 do. The four new sentences are in WORDINGS and in Spanish.
2026-10-18 21:19:46 +03:00
PerchAnton 031532b8a5 M4: bound named-destination pruning during page deletion (#3309) 2026-10-18 21:01:43 +03:00
NetterSilverandClaude Haiku 5.5 57c6e476db Keep text rows in other layers, gs states or Tz out of a paragraph
Fixes #3115

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 18:00:00 +00:00
mtlcl410andClaude Opus 5.5 ecb990c8ce M10: glyph names: a uni part with a surrogate group maps to nothing; numbered names read under a suffix (#3170)
Review follow-ups on #3239.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv2WwdgjmBz33GWkwgNn3Q
2026-10-19 01:57:14 +08:00
Marco Arnulfo d7f8ba8b57 fix(forms): Tab and Space reach check boxes and radio buttons, and a click focuses them (fixes #2223) 2026-10-18 19:55:32 +02:00
mtlcl410andClaude Opus 5.5 36cfc8566e M10: dynamicRender is read only from markup whose closing tags match (#3180)
Review follow-up on #3192.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv2WwdgjmBz33GWkwgNn3Q
2026-10-19 01:53:12 +08:00
Marco Arnulfo 1a12b0094d Preferences: always use my default zoom and page layout (fixes #1618) 2026-10-18 19:34:04 +02:00
mtlcl410andClaude Opus 5.5 f62bf71a77 M8: tag cleanup keeps inherited pages, fails closed over replaced streams and in-place elements (#3302)
Review follow-ups on #3285: walk /K before the parent and ID trees and look up
an element's inherited /Pg through /P; drop the structure tree when a cut-short
walk could leave MCRs naming a replaced stream; drop it when an element written
in place tags a removed annotation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv2WwdgjmBz33GWkwgNn3Q
2026-10-19 01:33:42 +08:00
Marco Arnulfo a4cdbb6235 XFA: decode BMP and TIFF pictures (fixes #1644)
Pictures in templates and data that are BMP or TIFF were left out with a
warning. They are now recognised by their signature, sized from their
headers, and decoded through the same bounded reader as GIF (first page
of a TIFF). A BMP needs a valid info-header size after "BM", so text
starting with those two letters is still not taken for one.

A BMP or TIFF chosen for an XFA image field is kept in the data as
image/bmp or image/tiff, since the layout can now show it.
2026-10-18 19:21:49 +02:00
alehel 9b6e74928f Merge remote-tracking branch 'origin/main' into fix/background-hidden-by-page-backdrop
# Conflicts:
#	ROADMAP.md
2026-10-18 19:17:34 +02:00
Mawfyy 932bf9c6bf M4: Ctrl-drag copies pages in the Organize grid (#2997) (#3092)
* M4: Ctrl-drag copies pages in the Organize grid (#2997)

Dragging thumbnails in the Organize page grid with Ctrl held (Option on
macOS) drops copies at the gap instead of moving the pages: a "+" badge
by the pointer, the copies land at the gap selected, and one undo step
takes them out. The insertion point joins the engine edit
(Edit::DuplicatePages { at }) so the copy is one undo step rather than a
duplicate plus a move.

page_duplicate takes a 1-based "at" (the first copy becomes page "at"),
so agents can drive the same thing, and the UI control channel's
ui.drag modifiers now reach the input state -- which gestures that read
it (this copy-drag, and Alt-drag column select) need.

Closes #2997.

* fix(ui): take the grid's copy modifier from the runtime OS (#3092 review)

Option-drag in the Organize grid moved the pages instead of copying them in a Mac
browser: `cfg!(target_os = "macos")` is false in the wasm build, and eframe sets the
context's OS from the browser. `copy_modifier` now takes the context and asks
`commands::mac_shortcuts`, as the shortcut labels do.

The drag helpers in `tests/editing.rs` and `tests/control.rs` picked the modifier the
same compile-time way, so they would have sent Ctrl on a Mac host; both read the
context's OS now. The new regression test
`option_copies_and_ctrl_moves_when_the_context_reports_macos` drives a Mac context —
Ctrl moves, Option copies — and fails without this change.
2026-10-18 11:13:22 -06:00
jonathanwxh-cell bec4e807b7 M2: integrate current main into PR #2960 2026-10-19 01:02:08 +08:00
Marco Arnulfo 9f536c9efd M12: Compare panel filters text changes and visual differences (gap 21) 2026-10-18 18:59:13 +02:00
Marco Arnulfo fcdf2a2146 Layers panel: Reset to Initial Visibility
Layer options in the Layers panel header resets every layer to the state the
file's default configuration (/OCProperties /D) gives it, as Acrobat does.
Visibility is view state, so the reset doesn't mark the document changed and
doesn't enter Undo. doc_info now reports each layer's initial state.
2026-10-18 18:56:40 +02:00
Marco Arnulfo 3468c8543f fix(print): disable Print on documents whose security forbids printing (part of #2669) 2026-10-18 18:56:08 +02:00
PerchAnton 4119359c7d M12: retain accepted whitespace when structured XFA data cannot sync 2026-10-18 19:54:41 +03:00
mtlcl410andClaude Opus 5.5 ce3c0e46c9 M8: redaction clears tag text of elements reached only through the parent or ID tree, and fails closed past the walk limit (#3302)
tags::clean, which drops /Alt, /ActualText and /E that repeat redacted
text, walked the structure tree from the root's /K only, so an element
listed only in /ParentTree or /IDTree kept the redacted words. It now
starts from both trees too, as drop_object_refs does since 3f543ca1.

Past its 2,000,000-reference cap the walk used to skip the rest and
report success. It now fails closed: every structure element in the
document, found by reading each object rather than through the tree,
loses its alternate and actual text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv2WwdgjmBz33GWkwgNn3Q
2026-10-19 00:52:18 +08:00
mtlcl410andClaude Opus 5.5 e6de108972 M8: note that structure elements written in place keep their references (#2447)
Review note from Losminek on #3285.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv2WwdgjmBz33GWkwgNn3Q
2026-10-19 00:44:58 +08:00
enes yıldızandClaude Opus 5.5 882b5a33bc M1: merge upstream main into claude/fix/2670-cli-owner-password
Merges #2813 (dynamic-XFA layout in the CLI) into the owner-password branch. In
info, text and render the engine Session and the cos document keep the typed
password, while anything handed to `inspect` or `PageRenderer` gets the render
password (the user password recovered from an R2-R4 owner password), including
the dynamic-XFA detection in render and the original-bytes check in text.

Checked: cargo fmt --check; clippy -p pdfcraft-cli -p pdfcraft-engine --all-targets
-D warnings; cargo test -p pdfcraft-cli (75 passed) and -p pdfcraft-engine (283 lib
+ integration passed); cargo xtask layers, assets, parity; a throwaway RC4-40,
RC4-128 and AES-128 dynamic-XFA check with the owner and user passwords through
info, text and render (not committed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 19:44:21 +03:00
PerchAnton 12210a350d M12: retain product notes while integrating current main 2026-10-18 19:42:01 +03:00
PerchAnton b7b4ab0c8d M12: retain product notes while integrating current main 2026-10-18 19:39:17 +03:00
mtlcl410andClaude Opus 5.5 9194ec457f M7: the paragraph editor draws on its page only (#3061)
A paragraph running past its page's bottom edge, as HTML-to-PDF converters
write when they rely on the page clip, opened in an editor that covered the
next page with its box and text, and paragraph outlines crossed the gap
between pages. The editor is clipped to its page within the document area
(it also covered the tool bars when scrolled up), and outlines to their page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-19 00:38:46 +08:00
MarekSpodBiedry 853851075f Mark the alpha changes as PdfCraft patches 2026-10-18 18:37:46 +02:00
PerchAnton c3df50e8dd M12: retain product notes while integrating current main 2026-10-18 19:36:34 +03:00
PerchAnton d39de3d31c M12: retain product notes while integrating current main 2026-10-18 19:33:52 +03:00
Oliver HagmannandClaude Fable 5.1 fe7169c8eb Renderer: sample a mesh shading over its triangles alone, not the whole path
A BricsCAD plan page (3370 × 1524 pt, 251,000 single-segment strokes and 310
one-triangle type 4 shadings painted with `sh` at 50% alpha) took 2 s per
1024 px tile at every zoom, and 7.9 s for a fit-to-width render; on a busy
machine the 20 s watchdog gave the page up ("page 57 took longer than 20 s and
was skipped"). A 16 px tile of the same page took 65 ms, so neither parsing nor
the strokes were the cost: `sh` fills the whole canvas with the shading, and
`set_paint` sampled the mesh texture over the whole path, one hash lookup and
one texel per canvas pixel, 310 times per tile.

hayro-interpret patch (35): `EncodedShadingPattern::extent`, the device-space
pixels a mesh's triangles touched when it was encoded (`None` for shadings that
paint everywhere, and for a mesh with a `/Background`). hayro patch (19):
`set_paint` returns `PaintSetup::Nothing` for a mesh with no triangle on the
canvas (an empty extent, tested before it is intersected: `Rect::ZERO` sits at
the canvas origin), which the fill, stroke, rect and stencil callers skip, and
otherwise intersects the texture with the extent and pads instead of repeating it.

Measured with `page_timing` on the page: fit 7864 → 880 ms, a 1024 px tile
2030 → 85 ms at 100% and 2030 → 70 ms at 400% (the 16 px tile's 65 ms is the
page's re-interpretation, paid per tile), with byte-identical output hashes.
The three `mesh_extent_tests` pin what the texture must and must not cover.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-18 18:32:33 +02:00
NetterSilverandClaude Haiku 5.5 31373819f2 Zero-pad required integer digits in FormCalc Format()
Found while testing crates/js/src/formcalc.rs:2240-2276 ("format" builtin, number branch)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 16:20:32 +00:00
PerchAnton 28e6d4e773 M7: retain product notes while integrating current main 2026-10-18 19:18:04 +03:00
PerchAnton 613503f5a0 M7: preserve rotation and index regressions on current main 2026-10-18 19:10:36 +03:00
mtlcl410andClaude Opus 5.5 3f543ca17f M8: redaction drops OBJRs of elements reached only through the parent or ID tree (#2447)
Follow-up to #2532 (review by aiongg): the structure-tree walk started
only at the root's /K, so an element listed only in /ParentTree or
/IDTree kept its object reference to a removed link or comment, and the
root kept that annotation reachable in a full rewrite. The walk now
also starts from both trees and follows their nodes (/Nums, /Names,
/Kids), written in place or as their own objects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv2WwdgjmBz33GWkwgNn3Q
2026-10-19 00:09:17 +08:00
wstock a2bc0d3570 lopdf: a rebuilt trailer's /Root must match its generation (#2365 review)
usable() and is_catalog() checked the object number only, so a later stream
with /Root 1 1 R outranked the trailer naming 1 0 R; get_offset then found no
such object and Document Properties lost the catalog. cos resolves by number
alone, so its rank needs no change.

Test: inspect::tests::rebuilt_file_prefers_a_trailer_whose_root_is_the_catalog
2026-10-18 16:05:33 +00:00
PerchAnton e75551ce62 M1: reject partial resource-fork copies and integrate current main 2026-10-18 19:03:07 +03:00
NetterSilverandClaude Haiku 5.5 61632e4899 Treat CRLF as a single line break in fonts::wrap
Found while testing crates/fonts/src/lib.rs:79 (wrap_with: `text.split(['\n', '\r'])`)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 16:01:48 +00:00
Lucas Dias d6f872b665 M12: avoid white flashes while reading pages render 2026-10-18 12:49:00 -03:00
alehel dc27841010 Merge remote-tracking branch 'origin/main' into fix/background-hidden-by-page-backdrop
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/tests/ui_group/marks.rs
2026-10-18 17:34:42 +02:00
Dylan M. Taylor 98cbd38a8e Merge pull request #3161 from dylanmtaylor/chore/drop-competitor-references
docs: drop references to competing commercial software
2026-10-18 11:31:27 -04:00
aiongg b0e5c6eba2 Merge pull request #3041 from aiongg/next
Integration batch: 38 PRs on main
2026-10-18 11:25:56 -04:00
wstock d75d440ad9 lopdf: a rebuild prefers a trailer whose /Root is the catalog (#2365 review)
The mirror of the cos change for render::inspect: a later cross-reference
stream whose /Root points at /Info replaced the earlier trailer, and Document
Properties lost the catalog. A candidate whose /Root is /Type /Catalog or has
/Pages now wins; another dictionary is still taken when nothing better is
there (FDF).

Test: inspect::tests::rebuilt_file_prefers_a_trailer_whose_root_is_the_catalog
2026-10-18 15:23:38 +00:00
PerchAnton 778c561d76 M12: retain product notes while integrating current main 2026-10-18 18:14:25 +03:00
PerchAnton 8a786ab2d9 M12: retain product notes while integrating current main 2026-10-18 18:11:02 +03:00
jonathanwxh-cell d76516219d M2: keep hidden ActualText fixture outside CropBox (#2838) 2026-10-18 23:09:40 +08:00
jonathanwxh-cell 2714f9e54f automation: report effective validated PDF version in doc_optimize (#3090) 2026-10-18 23:09:09 +08:00
sanches 2b445950df Merge remote-tracking branch 'origin/main' into i18n-id-vi 2026-10-18 18:08:27 +03:00