Skip to content

Render PDFs with odrcore, and hide the buttons a document cannot use - #159

Merged
andiwand merged 3 commits into
mainfrom
route-pdfs-through-core
Aug 16, 2026
Merged

Render PDFs with odrcore, and hide the buttons a document cannot use#159
andiwand merged 3 commits into
mainfrom
route-pdfs-through-core

Conversation

@andiwand

@andiwand andiwand commented Aug 16, 2026

Copy link
Copy Markdown
Member

PDFs were the one format pushed off odrcore on purpose: CoreWrapper.translate refused them and documentLoadingError handed the file to WKWebView, which drew it with the system viewer. Nothing in the app reached inside that — no search, no fit to the screen, and the tool bar sat above a page it knew nothing about. odrcore renders PDFs itself now, so the guard is gone and a pdf takes the same path as a document: isPdfFile joins the guard, and the branch with no Document behind it — the one a csv already took — translates the decoded file. .unknown keeps the combined view, which for a pdf is every page.

Images, media and fonts stay with the system. odrcore translates those too, but only into an <img> or a <video> the web view decodes anyway, and its own table says the page it writes for a psd or a wmf paints nothing.

Search

Not on yet, and not this repository's to switch on. odrcore writes the odr object into what it renders as a document or as text; pdf_file.cpp never calls write_document_script, so a pdf page has no odr.search to call. The button is therefore driven by the page rather than by the format — didFinish asks whether odr.search is there. A pdf picks the button up on its own the day odrcore writes the script for it, with no change here. testPdfPageCarriesItsText holds the other half: the text is already in the page, so there will be something to walk.

The buttons

The search button now leaves the bar rather than greying out, like the pencil beside it. Both are filtered out together with the 10pt gap behind them, or what stays drifts off the trailing edge — hence the two new spacer outlets. canEdit and canSearch replace showEditButton, and EXTENSION_WHITELIST becomes systemRenderedExtensions, which is what it always was: the other side of odrcore's format table rather than something derived from it.

Tests

test.pdf is a two page fixture the generator writes by hand, a few hundred bytes like the ODF ones. Three tests on it — that odrcore translates it into the one combined page, that it is not editable, and that its text reaches the page — plus one asserting a png is still refused, so the line between odrcore and the system is written down.

36 tests pass; both schemes build.

🤖 Generated with Claude Code

andiwand and others added 3 commits August 16, 2026 08:45
PDFs were the one format pushed off odrcore on purpose: `translate` refused
them and `documentLoadingError` handed the file to WKWebView, which drew it
with the system viewer. Nothing in the app reached inside that - no search,
no fit to the screen, and the tool bar sat above a page it knew nothing
about. odrcore has rendered PDFs itself since 6.2, so the guard is gone and a
pdf goes down the same path as a document: `isPdfFile` joins the guard, and
the branch that has no `Document` behind it - the one a csv already took -
translates the decoded file. `.unknown` keeps the combined view, which for a
pdf is every page.

Images, media and fonts stay with the system. odrcore translates them too,
but only into an `<img>` or a `<video>` the web view decodes anyway, and its
own table says the page it writes for a psd or a wmf paints nothing.

Search is not on yet: odrcore writes the `odr` object into what it renders as
a document or as text, and `pdf_file.cpp` does not call
`write_document_script`. So the button is now driven by the page rather than
by the format - `didFinish` asks whether `odr.search` is there. A pdf picks
the button up on its own the day odrcore writes the script for it, with no
change here. `testPdfPageCarriesItsText` holds the other half of that: the
text is in the page, so there will be something to walk.

The button goes rather than greys out, like the pencil beside it. Both are
filtered out of the bar together with the 10pt gap behind them, or what stays
drifts off the trailing edge - hence the two new spacer outlets. `canEdit`
and `canSearch` replace `showEditButton`, and `EXTENSION_WHITELIST` is now
`systemRenderedExtensions`, which is what it always was: the other side of
odrcore's format table, not something derived from it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UNugiHVRHVc1CGHgVGW7Dz
odrcore reads the standard security handler, so an encrypted pdf takes the
prompt the ODF formats already had - `isPasswordEncrypted` is true, and a
missing or wrong password comes back as `wrongPassword`, which is what
`Document.parse` turns into the alert rather than the error page. Verified
against AES-256 (`V 5`, `R 6`), what a pdf written today is locked with.

The fixture is qpdf's, because AES is not in the standard library and R6
derives its key with it. `make-fixtures.py` calls out to it and says so if it
is missing; everything else it writes is still by hand.

`copyFixture` takes a name now, since the fixtures are no longer all `test`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UNugiHVRHVc1CGHgVGW7Dz
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UNugiHVRHVc1CGHgVGW7Dz
@andiwand
andiwand merged commit 589f4f7 into main Aug 16, 2026
4 checks passed
@andiwand
andiwand deleted the route-pdfs-through-core branch August 16, 2026 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant