freepdfeditor/docs/adr/0001-render-what-you-will-s...

2.9 KiB

ADR-0001 — Render what you will save

  • Status: Accepted
  • Date: 2025-07-25
  • Plan reference: §2.5

Context

The single biggest failure mode for WYSIWYG PDF editors is divergence between the preview and the saved file: the user edits one thing, the file contains another. Overlay-style editors avoid this by not really editing — they cover old text with a white rectangle and draw new text on top, producing files that look right and are broken for search, copy-paste, accessibility, and redaction. We chose full content editing (§1.1), so we own an interpreter and an emitter, and divergence is a structural risk.

The decision must be made before any rendering or editing code lands because it shapes the whole pipeline: every edit's effect on the saved bytes must be computable, and the rasterizer must render the saved bytes, not a model projection.

Decision

The preview is, by construction, a render of the exact bytes that saving would produce. Concretely:

  1. Every edit mutates the semantic model (L5).
  2. The dirty page's content stream is re-emitted immediately into an in-memory buffer (§4.4).
  3. The rasterizer renders that buffer, not the model.

To keep keystroke latency bounded under this rule, a two-tier scheme applies during an active edit gesture:

  • Predictive tier (every keystroke, < 8 ms): render only the dirty text frame's damage rectangle from the L3 display list via Skia, composited over the cached page raster.
  • Authoritative tier (on 120 ms idle, on gesture end, and always before save): re-emit and re-render through PDFium, then diff against the predictive tier. A mismatch above threshold repaints and logs a fidelity event.

Nothing is ever saved that has not been rendered from its own bytes.

Consequences

Positive. The preview and the saved file cannot diverge by construction. The predictive-vs-authoritative diff gives a continuous, free, in-production consistency check between our interpreter and PDFium's — exactly the divergence we are most exposed to (§11).

Negative. Re-emission must be fast (< 5 ms for a typical page) which drives the surgical (not full-rebuild) design of ADR-0002. The predictive tier requires a first-class Skia display-list renderer, which is real ongoing cost — it is a tracked metric with a budget, not a debugging toy.

Neutral. Fidelity events (§2.5, §4.3, §4.4) are recorded locally and visible in the fidelity panel; they are only transmitted if the user explicitly submits a diagnostic bundle.

Alternatives considered

  • Overlay editing — rejected; produces files that are broken for search, copy-paste, accessibility, and redaction (§1.1).
  • Model-driven rendering (render the L5 model directly, save separately) — rejected; reintroduces divergence as the model and the emitter can drift.
  • Re-render through PDFium on every keystroke — rejected for latency on dense pages; kept as the authoritative tier only.