PdfDocument Class

Definition

Render caches with byte budgets (issue #103, spec #33 viewer capability 13 and story 8).

public sealed class PdfDocument : IDisposable

Remarks

ISO 32000-2 §7.5 (file structure) and §7.7.2 (document catalog). Opening reads the header, the cross-reference information, the trailer and the catalog; every other object, the page tree included, loads on first use. The document is a live view over its COS objects (Catalog, Trailer, Resolve(CosObject?)), so a change made through the COS layer is visible through the document model.

Reading is lenient by default: deviations are repaired and recorded in Diagnostics. In strict mode the first deviation throws a DiagnosticException; deviations in objects loaded after open (the page tree, for instance) throw from the member that loads them, so strict validation at open is not exhaustive.

Repairs (ISO 32000-2 §7.5 describes the structure but not its repair): a wrong startxref or Prev offset reads the nearest cross-reference section; an entry whose offset does not hold its object is looked up near that offset, then anywhere in the file; a missing or unusable cross-reference table or trailer is rebuilt by scanning the file for object headers, object streams and trailers, and the catalog is found by its type when no trailer leads to it; a wrong stream Length is recovered from endstream (or endobj), without changing the Length entry; a missing endobj ends the object at the next keyword.

Objects load lazily through the cross-reference table (§7.5.4: it "permits random access to indirect objects ... so that the entire PDF file need not be read"), are parsed once, and are kept: every reference to an object resolves to the same instance. A file opened from a path is memory-mapped and a seekable stream is read in place, so memory grows with the objects used, not with the file: stream data stays in the file and is read each time it is asked for (EncodedData). A 2 GiB file opens and reads its last page in a few megabytes of managed memory. A non-seekable stream is copied when opened.

Concurrency contract. While nobody mutates the document, any number of threads may read it at the same time: resolve objects, walk pages, decode streams, read diagnostics, render. Each object is still parsed once, and every thread sees the same instance. Mutation (changing a COS object reachable from the document) is single-threaded and the caller's responsibility to synchronize: no read may run while a mutation runs, and reading concurrently with a mutation is undefined. Disposing the document while another thread reads it is a caller error too; reads after Dispose() throw .

Tip: use kind:method, kind:property, kind:ctor. Press Esc to clear.

Properties (41)

Methods (130)