0004. PDF pages rasterized in the main process with pdf.js + @napi-rs/canvas
- Status: Accepted; the rendering now runs in the decoder process (ADR 0012)
- Date: recorded 2026-09-30 (the decision predates this record)
Context
The reader, the zoom and the continuous mode all work on page images returned by a ComicArchive. PDF pages are vector content, with no native resolution. Rendering them in Node needs a Canvas implementation, which Node doesn't have.
Decision
PdfArchive(src/main/services/pdf-archive.ts) implementsComicArchivelike CBZ/CBR, rasterizing each page on demand to PNG at a fixed ~200 DPI (RENDER_SCALE = 200 / 72).- It uses
pdfjs-dist'slegacybuild, with@napi-rs/canvasprovidingDOMMatrix,Path2D,ImageDataandImage(installed once onglobalThis) and the canvas itself.@napi-rs/canvasis pdf.js's own optional dependency for Node and ships prebuilt per-platform binaries (no compilation step). - Both packages are kept external in the main bundle and copied into the packaged app by the
packageAfterCopyhook offorge.config.ts;AutoUnpackNativesPluginunpacks the native binary out of the asar archive.
Consequences
- The rest of the reader doesn't distinguish a PDF page from an image page.
- ~200 DPI is high enough not to trigger the AI upscaling at normal zoom, without the memory/CPU cost of going higher.
- pdf.js's
standard_fontsandcmapsship with the package, with no separate copy step. - Only the
@napi-rs/canvas-<platform>-<arch>package matching the machine that rannpm installis present, so the app must be packaged on each target platform. - Packaging is more fragile: see the build gotchas.
Alternatives considered
- Bundling both packages with Vite: impossible for the native
.nodebinary, and unsafe for pdf.js'slegacybuild (itself a webpack bundle). - No other rendering approach (in the renderer, other libraries) was evaluated.