Files
pdfcraft/docs/file-format-parity.md
T
Max Abramowitz 3a117c3c0e M10: open Word, Excel and PowerPoint files through LibreOffice
## What this changes

**File ▸ Open opens Word, Excel, PowerPoint, OpenDocument and RTF files** as new, unsaved PDFs (`Report.docx` → `Report.pdf`), the "LibreOffice sidecar" that `docs/gaps.md` (gap 8) and `docs/file-format-parity.md` planned for `create.from-office`.

- **Conversion** (`crates/create/src/office.rs`): an installed LibreOffice runs headless as a separate process, in a private temporary folder (the input is always `document.<ext>`, so the user's file name never reaches its command line). It gets a fresh profile with `DisableMacrosExecution`, `MacroSecurityLevel` 3 and `BlockUntrustedRefererLinks` set, and Writer's and Calc's `Content/Update/Link` set to *Never* (2 for Writer and 1 for Calc: the two number their values differently), no console window on Windows (`CREATE_NO_WINDOW`), and is killed after 120 s. The output is size-capped (512 MB), must start `%PDF-`, and must open as a PDF before it is used. LibreOffice is found through `PDFCRAFT_SOFFICE`, the `PATH`, then the usual install folders per OS. Without it, the user is told it's needed rather than "not a readable PDF".
- **Off the frame thread:** File ▸ Open converts on the existing open worker (`ResultKind::Converted`); the frame thread only opens the result.
- **Detection:** `SourceKind::Office` requires an Office extension *and* an OLE, ZIP or RTF signature, so `photos.zip`, or a PDF saved with a `.docx` name, are not misread.
- **Open dialog:** PDF (still the default), Images, Office documents, Text, All files. All files is left out on macOS, where rfd merges every filter into one allowed-types list, and on the web; Office documents are left out on the web. The extension lists are now shared constants in `pdfcraft-create` (`IMAGE_EXTENSIONS`, `TEXT_EXTENSIONS`, `OFFICE_EXTENSIONS`), used by both detection and the picker. The duplicate filter list in `open_dialog` is gone. The two new labels are in all 22 catalogues, with their `ATTRIBUTION.toml` hashes updated.
- **Automation:** `doc_create_multiple`, `doc_combine` and batch `convert` go through `convert_to_pdf`, so they take Office documents too; their descriptions say so.

**Deliberately not in this PR:** Insert pages, Combine files and Create ▸ Multiple files convert on the frame thread, so they now refuse Office documents with a pointer to File ▸ Open (`convert_to_pdf_inline` / `as_pdf_inline`) rather than freezing the window for seconds. Moving them onto a worker is the follow-up. `create.from-office` goes planned → **partial**, with that and the rest listed in its notes.

## How you verified it

On Windows 11 Pro with LibreOffice 26.8.1 installed, per crate:

- [x] `cargo fmt --check`
- [x] `cargo clippy -p pdfcraft-create -p pdfcraft-engine -p pdfcraft-ui-egui -p pdfcraft-automation -j 2 --all-targets -- -D warnings`
- [x] `cargo test -p pdfcraft-create -p pdfcraft-engine --lib` (42 and 276 pass); `-p pdfcraft-automation --test automation` (the combine/create tests); `-p pdfcraft-ui-egui --lib open_worker` and `--test editing --test create`
- [x] `cargo xtask layers`, `cargo xtask assets`, `cargo xtask parity --partial`
- [ ] wasm check: the `wasm32-unknown-unknown` target isn't installed here, so I'm leaving it to CI. The web paths are `cfg`'d and were reviewed by eye.

**Tests seen failing before the fix**, by reverting each part:
- Detection off → `office_documents_are_their_own_kind`, `source_kind_tells_pdfs_images_and_text_apart`, and both engine Office tests fail.
- Worker conversion off → `file_open_converts_an_office_document_on_the_worker` fails with the old user-facing message, *"the file is not a readable PDF: no readable page tree or cross-reference data was found"*.

New tests also cover a converter that hangs (it's stopped; the test binary stands in for LibreOffice), one that writes no PDF, a missing converter, temp-folder cleanup, `file://` URL escaping (spaces, drive letters, UTF-8), and the search order.

**Real conversions, end to end:** `crates/automation/tests/it/office.rs` builds a minimal DOCX, an XLSX (with a formula, `=6*7`), a PPTX and an RTF inside the test, so no binary fixtures are committed. It runs them through `doc_create_multiple` in `separate` mode (each output reopened and its text checked, including `42`) and in `combine` mode (page order and bookmarks), and through `doc_combine` beside a PDF, with a page range on one file. These tests, `libreoffice_converts_a_document_when_installed` and the process-tree cleanup test (5 out of 5 reruns) pass with LibreOffice 26.8.1. The Office tests skip where LibreOffice isn't installed, which includes CI.

Three existing tests used a 4-byte `report.docx` as their "file that can't be converted" example. That's no longer true, so they now use `archive.zip`, which keeps what they test.

## Never-crash

- [x] No new `unwrap`/`expect`/`panic!`/`unreachable!`/`todo!` outside tests
- [x] No input-derived indexing or slicing (`rsplit_once` for the extension); the PDF read back is size-capped
- [x] No `unsafe`. The Windows flag uses `std::os::windows::process::CommandExt`
- [x] A crashing, hanging or misbehaving LibreOffice is an error, never a panic or a stuck app: the worker's `catch_unwind`, a 120 s kill, and output checks

## Provenance

- [x] No Adobe assets; no fonts; no copied code
- [x] LibreOffice (MPL-2.0) is only *run* as an external process, as the docs planned; nothing of it is linked or copied. Its command-line options and the profile keys come from LibreOffice's public documentation.
- [x] The translations are contributor-original, written from the plain meaning of "Office documents" and "All files" ("Office" kept as a product name); hashes updated, `cargo xtask assets` passes

## Security

- [x] `--root` confinement unchanged: automation still resolves and reads paths before converting; only the private temp folder is written outside it
- [x] MCP and the control channel untouched
- [ ] **No new outbound network: please decide.** PdfCraft itself opens no connection. The profile blocks untrusted referer links and sets Writer and Calc never to update linked content on load. I converted eight synthetic files that link to a listener on 127.0.0.1: RTF `INCLUDETEXT` and `INCLUDEPICTURE`, a DOCX external picture, an ODT linked section and linked picture, an ODS table source and an external cell reference, and an ODP linked picture. None made a connection, with or without the link settings. Two things remain open: Impress has no link-update setting, and the process's network access isn't sandboxed (documented in `crates/create/README.md` and `docs/gaps.md`).

## Parity and reach

- [x] `create.from-office` planned → partial, with the evidence tests and what's still missing
- [x] Reachable headlessly (`doc_create_multiple`, `doc_combine`, batch `convert`)
- [x] Docs: `docs/file-format-parity.md` (Word/Excel/PowerPoint and RTF rows), `docs/gaps.md` gap 8, `docs/target-app-parity.md` row J (numbers not re-measured), `docs/roadmap.md` M10, the `ROADMAP.md` log, and the `crates/create` README

## Anything a reviewer should look at first

1. **The network question** above. It's the owner's call.
2. **The frame-thread restraint:** Insert, Combine and Create Multiple refuse Office documents rather than block. Is a worker for those wanted in this PR, or as a follow-up?
2026-11-11 11:06:01 +01:00

10 KiB
Raw Blame History

File format parity

Last reviewed: 2026-10-12 · Last updated: 2026-10-22 · Change: minor (Word, Excel, PowerPoint, OpenDocument and RTF open through an installed LibreOffice; .p7b/.p7c bundles read for trust import) · Target: Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)

Every format Acrobat Pro reads or writes, and PdfCraft's support for it. Acrobat's list comes from its bundle's Info.plist CFBundleDocumentTypes (what it opens) and its public documentation (Create PDF and Export PDF). PdfCraft's support comes from the code and parity/acrobat-features.toml. Summary in target-app-parity.md; gaps in gaps.md.

Legend: R read/import, W write/export. Fidelity: high (tested against an external oracle or round-trips exactly), good (tested, known limits), basic (works, visibly lossy), none.

File formats and conversion ≈ 40% ready (estimated): PDF itself is strong except encrypted output interoperability; the conversion formats users reach for most (Word, Excel, PowerPoint, Office to PDF, OCR beyond English) are weak or missing. 120–220 h to parity (within the features total).

PDF

Format Acrobat PdfCraft Fidelity Tests and evidence
PDF 1.0–1.7, ISO 32000-1 R W R W high for reading and unencrypted writing 958-file pdf.js corpus open/edit/save; qpdf --check on saved outputs; xtask check baselines
PDF 2.0 (ISO 32000-2) R W R W (2.0-only features ignored but preserved) good No UTF-8 strings, /AF, DPart, namespaces (pdf-spec-parity.md)
Encrypted PDF (standard security R2–R6) R W R W reading high; writing opens in Acrobat DC since #836 (#774; AES-256 and RC4-128 checked by hand, no automated interop suite) crates/crypt, crates/cos tests (the_catalog_of_an_encrypted_document_stays_outside_object_streams); all 7 corpus encrypted files open
Certificate-encrypted PDF (public-key handler) R W none (clear message) none core.unsupported-handlers
Linearized PDF (Fast Web View) R W R (as normal PDF); no W none for W core.linearization planned
Damaged PDF R (repair) R (repair, logged) high core.repair-broken-files, nightly fuzzing
PDF/A-1, 2, 3, 4 R W, verify R; verify/convert 2b and 3b (partial) basic optimize.pdfa-*; veraPDF not yet used as oracle
PDF/X, PDF/UA, PDF/E, PDF/VT R W, verify R only none pdf-spec-parity.md
PDF Portfolio (collection) R W R as a PDF with attachments; no portfolio view none organize.portfolio-* planned
XFA forms (in PDF) R W (fill) R, lay out dynamic forms, fill, save datasets (partial) basic form.xfa-* partial; crates/xfa tests

Data and interchange formats

Format Acrobat PdfCraft Fidelity Tests and evidence
FDF (.fdf) comments and form data R W R W good crates/xfdf; comment-exchange fixes for popups, polygon vertices and callouts (#807, #809, #819)
XFDF (.xfdf, ISO 19444-1) R W R W good as above
XML form data R W R W good form.data-xml-csv-txt
XDP data (.xdp) for XFA forms R W R W: Export Data writes the whole datasets as an XDP; Import Data takes an XDP, datasets or data XML good form.xfa-data (data_exports_as_datasets_xml_or_an_xdp_and_imports_from_any_of_them, xfa_data_files_export_and_import_through_tools)
XDP opened as a document R none none Acrobat opens .xdp as a document type
CSV / tab-delimited form data W (merge to spreadsheet) R W; merge to spreadsheet good form.merge-to-spreadsheet
Comment summary (PDF) W W (comments only layout) basic comment.summarize partial
Measurement CSV W W good comment.measure-export
Compare report (PDF) W W good misc.compare-report
Action Wizard sequences (.sequ) R W own JSON actions; no .sequ none for .sequ misc.action-wizard-*
Security settings (.acrobatsecuritysettings), .apf profiles, .secstore R W none none out of scope unless asked
Search index (.pdx) R W none none view.search-index planned
JDF / MJD job definitions R none none print.jdf planned (P3)
Preflight profiles (.kfp) and reports R W none none gap 9
PDF Optimizer settings (.optimize) R W none (dialog settings not saved as presets) none optimize.optimizer-presets planned

Certificates and keys

Format Acrobat PdfCraft Fidelity Tests and evidence
PKCS #12 digital IDs (.p12, .pfx) R W R W (self-signed IDs) high OpenSSL-made fixtures (crates/sign/tests/data/README.md)
Certificates (.cer, .der, .pem, .p7c, .p7b) R W R (.cer/.pem/.der/.p7b/.p7c/.p12 trust import); W public certificate good; .p7c/.p7b bundles read (DER or PEM), not written sign.trust-import partial, sign.export-certificate
CMS / PKCS #7 signatures, RFC 3161 tokens, OCSP, CRL R W R W high pdfsig and OpenSSL oracles

Create PDF from

Source Acrobat PdfCraft Fidelity Tests and evidence
JPEG, PNG, TIFF (multipage, and BigTIFF), GIF, BMP, JPEG 2000 yes yes (ICC profiles kept; DPI choices) good create.from-images, create.from-multipage-tiff, bigtiff_images_become_pages
PCX yes no none in Acrobat's document types
Plain text yes yes good create.from-text
Clipboard (image or text) yes yes good create.from-clipboard
Screenshot yes no none create.from-screenshot planned
Word, Excel, PowerPoint (and Visio, Publisher on Windows) yes yes, desktop only, through an installed LibreOffice (File ▸ Open); not Visio or Publisher good where LibreOffice is (its layout, not measured against Acrobat) create.from-office partial
HTML file, web page URL yes no none create.from-html, create.from-web-page planned
RTF yes yes, through LibreOffice (as Office documents) good where LibreOffice is create.from-office partial
PostScript / EPS (Distiller) yes no none create.distiller planned (P3)
Markdown no no none create.from-markdown planned (P2; not an Acrobat feature)
Scanner yes no none ocr.scanner-acquire planned
Several files at once yes yes: combine PDFs, images and text into one document, or create a separate PDF for each non-PDF source (GUI and doc_create_multiple mode=separate); existing outputs get numbered names good for supported source types create.create-multiple, separate_batch_creates_one_pdf_per_source_without_replacing_existing_files

Export PDF to

Target Acrobat PdfCraft Fidelity Tests and evidence
Word (.docx) yes, layout-preserving flowing paragraphs and inferred tables (bordered only along the grid lines the page draws); positioned text/artwork only for pages with rotated text or text overlapping an image/watermark, with per-page sizes basic (#773 synthetic invoice regression covered; exact fonts, vector rules and general layout fidelity remain incomplete) create.export-docx partial
Word 97–2003 (.doc) yes no none
Excel (.xlsx), XML Spreadsheet 2003 yes no none create.export-xlsx planned
PowerPoint (.pptx) yes slides per page: title from largest text, body text, images, tables (no slide overflow reflow / normAutofit; first page sets presentation dimensions) basic create.export-pptx partial
RTF yes yes basic create.export-rtf
HTML (single page, multiple pages) yes single file with headings, paragraphs, images, tables basic create.export-html partial
Plain text yes yes (reading order) good (word-F1 0.98 vs pdftotext; reading order is scored separately, because F1 cannot see it) create.export-text, xtask text-oracle
Accessible text (from tags) yes no none create.export-accessible-text planned
PNG, JPEG, TIFF yes yes good create.export-png, create.export-jpeg-tiff
JPEG 2000 yes no none create.export-jpeg2000 planned
All embedded images yes yes good create.export-all-images
XML 1.0 yes no none create.export-xml planned
SVG no (dropped by Adobe) no none create.export-svg planned
PostScript, EPS yes no none create.export-ps, create.export-eps planned

OCR (scans to searchable PDF)

Capability Acrobat PdfCraft Fidelity
Searchable image (invisible text layer) yes yes (Tr 3 text fitted to word boxes) good for English
Editable text and images output yes no none
Languages dozens (Latin with accents, Cyrillic, Greek, CJK, Arabic, Hebrew, Indic) Latin without accents only (ocrs models) basic (#744)
Deskew, rotation, despeckle, background and halo removal, descreen yes no none
Camera images (edges, perspective, whiteboard, card) yes no none
MRC (adaptive) compression, PDF/A output of scans yes no none

Revision history

Date Change Summary
2026-10-22 minor Office documents (Word, Excel, PowerPoint, OpenDocument, RTF) open from File ▸ Open as new PDFs, converted by an installed LibreOffice; create.from-office partial.
2026-10-19 patch Certificates row: .p7b/.p7c bundles (DER or PEM PKCS7/CMS) are read for trust import.
2026-10-12 minor XDP split into data (read and write for XFA forms, already shipped under form.xfa-data) and opening .xdp as a document (none). Create PDF reads BigTIFF; malformed GIF headers are no longer detected as images.
2026-10-11 minor #773: inferred tables have no invented borders; rotated or overlapping invoice pages use floating shapes and page sections. Full Office layout fidelity remains partial.
2026-10-11 minor Encrypted PDF row: written files open in Acrobat DC (#774, fixed by #836). FDF row: #807, #809 and #819 fixed
2026-10-10 major Created from Acrobat 26.002.21931's CFBundleDocumentTypes, Acrobat's public Create/Export documentation, and PdfCraft's code and checklist