What JetsonPDF actually supports, grouped by area. Everything below ships in the current source.
Pick your level. JetsonPDF ships three layered authoring APIs:
Writer — Document + Page.DrawText/DrawImage/DrawPath. Direct control of every byte. Good for templated forms, fixed layouts, programmatic content.
Fluent — FluentDocument.Create(d => d.Page(...)). QuestPDF-style layout DSL: rows, columns, tables, headers/footers, page numbers. Good for invoices, dashboards, anything paginating.
Flow — FlowDocument with mutable Section/Paragraph/Table tree. Word-like retained-mode DOM with named styles, footnotes, hyphenation, TOC. Good for reports, books, long-form prose.
Writer
A drawing-model API. Build a Document, append Pages, paint onto each page, save the bytes.
Document model — Document.AddPage(PageSize), doc.Save(path | Stream), info dictionary, viewer prefs, page layout / mode, open action, named destinations, outlines, page labels.
Fonts — the standard 14 (FontFamily.Helvetica et al.); EmbeddedFontFace.FromFile for TrueType / OpenType with TTF subsetting and CFF1 subset on write; Type3Font for procedural glyphs with auto /ToUnicode.
Vector graphics — DrawRectangle, DrawLine, DrawPath with full path operators, line cap/join, dash patterns, even-odd fill, transforms, clipping.
Colour spaces — DeviceGray / RGB / CMYK, plus CalGray, CalRGB, Lab, Separation, DeviceN, NChannel, ICC profiles. Real CIE math, not pass-through stubs.
Per-page — ReadPage with content items (text, vector paths, images, inline images, form-XObject invocations) and annotations.
Filters — FlateDecode (with PNG predictors 10-15), DCTDecode, LZWDecode, ASCII85Decode, ASCIIHexDecode, RunLengthDecode, CCITTFaxDecode (G3 1D, G3 2D mixed mode, G4), JBIG2Decode (MQ arithmetic, all four templates with AT pixels and TPGD; symbol dicts; text regions; halftones; refinement; Huffman; MMR), JPXDecode (passthrough with JP2 ihdr).
Fonts — standard 14, embedded TrueType, Type 0 / CID, Type 1 (with /Differences via Adobe Glyph List), Type 3 (now prefers /ToUnicode over AGL).
Colour spaces — everything the writer can produce, parsed back: device, calibrated, indexed, separation, DeviceN, NChannel, Lab, ICC, pattern.
Shadings — Type 1, 2, 3 (axial, radial, function-based) and mesh decoding for types 4-7 to triangle soup / patch lists.
Structure tree — ReadStructureTree, ReadStructureElement, ReadStructureAttributes, OBJR child refs.
Layers, signatures, conformance — ReadOptionalContentGroup, ReadSignature, ReadDocumentSecurityStore, ReadVri, ReadOutputIntent, plus PDF/A and PDF/UA flag detection from XMP.
Forms (editing) — edit existing AcroForms
The JetsonPDF.Forms assembly turns "open this PDF, fill in the fields, save it" into a one-line operation. Sits on top of the Reader and Writer; saves are emitted as single-layer incremental updates (§7.5.6) so digital signatures keep working.
Entry point — Form.Open(path | byte[] | Stream, password?) → Form with a Fields collection.
Discovery — every /Tx, /Btn, /Ch, /Sig widget across every page. Multi-widget fields (radio groups) collapse to a single FormField with a member list.
Type-safe mutations — SetText, SetImage, SetChecked, Toggle, SelectRadio, SetChoice, SetChoices, Clear — each gated to the matching FormFieldType; wrong-type calls throw InvalidOperationException with the field name in the message.
Image stamping — SetImage(image, alignment, padding, markReadOnly) bakes a Form XObject /AP /N at the widget's rect. Aspect-preserved, centred by default (six alignments + Stretch). Valid on text fields, push buttons, and unsigned /FT /Sig widgets.
ReadOnly on stamp — defaults to true for text fields so Acrobat renders the appearance immediately (Acrobat otherwise treats an empty-/V text widget's /AP /N as a stale cache). Opt out with markReadOnly: false. Never applied to signature fields — the user must remain able to invoke Sign.
Signature awareness — FormField.IsSigned distinguishes signed from unsigned /FT /Sig widgets; signed widgets are discoverable but reject every mutation (the cryptographic byte range covers /AP).
Choice options — FormField.Options exposes the /Opt array as (Export, Display) pairs.
Encryption parity — encrypted source files round-trip: incremental update encrypts new objects under the file's existing key, no re-keying.
Single-layer save — repeated Save() calls within one Form instance produce byte-identical output. Mutations are re-applied against the original source bytes, not stacked on previous saves. Eliminates the stale-appearance and file-bloat failure modes that naive incremental editors fall into.
Per-field clear & form.Clear() — reset one field or every value-bearing field at once; push buttons and signature fields are skipped automatically.
Composition — extract & merge pages
The JetsonPDF.Composition assembly does page-level assembly: PageExtractor pulls a chosen subset of pages out of a PDF into a new file, and Merger concatenates whole PDFs into one. Both are a lossless COS object-graph copy (§7.3) — content, resources, fonts, images, and annotations are copied in their original encoded form, never re-rendered.
Extract — PageExtractor.Extract(source, 1, 3, 5) with 1-based page numbers; order is preserved, so the same call reorders and duplicates pages. ExtractRange(source, 5, 12) for an inclusive range; a password overload decrypts encrypted sources.
Merge — Merger.Merge(a, b, c) concatenates in order. byte[], file-path, and Stream overloads for both operations.
Navigation carries over — outlines/bookmarks are appended under one root with destinations remapped and dead bookmarks pruned; the modern /Names /Dests tree and legacy /Dests dict merge into one name tree.
AcroForm fields merge — a combined /AcroForm with unified /Fields, merged /DR, OR'd /NeedAppearances / /SigFlags. Cross-document name collisions are suffixed (signature → signature_2) and referring /DA font tokens are rewritten so each field stays independent.
Reader-only — depends on Common + Reader (not the Writer); targets net8.0 / netstandard2.0 / net462.
The JetsonPDF.Fluent namespace exposes a QuestPDF-style fluent DSL on top of the Writer. Write FluentDocument.Create(...), compose Pages out of Header/Footer/Background/Foreground/Content slots, and let the engine paginate.
Slot model — p.Header(), p.Footer(), p.Background(), p.Foreground(), p.Content(). Header / footer / background / foreground render on every paginated page; content overflows.
Two-pass renderer — total page count is resolved after layout, so {TotalPages} and IDynamicComponent.Compose see the final number without a second layout pass.
Navigation — .Section("anchor") registers a named destination; .SectionLink("anchor") emits an internal link; .Link("https://...") emits a URI link.
Form widgets — .AsTextField(name), .AsCheckBox, .AsComboBox(name, options), .AsListBox, .AsPushButton(name, caption). Acrobat draws the chrome at the arranged bounds.
The JetsonPDF.Flow namespace is a Word-like retained-mode DOM. Build a FlowDocument tree of Section → Paragraph / Table / BlockImage / PageBreak, mutate it freely, then call Save. The renderer paginates over the Fluent engine.
Sections — FlowDocument.AddSection with per-section PageSize, PageMargins, StartsOnNewPage, ColumnCount / ColumnGap, FootnoteAreaHeight, and Header / Footer / Body blocks.
Paragraphs — built-in ParagraphStyle.Heading1..3 / Quote / Caption, plus user-defined NamedStyle with a BasedOn chain. Alignment, line spacing, indents, SpaceBefore/SpaceAfter, KeepWithNext, KeepLinesTogether, PageBreakBefore.
Inline runs — p => p.AddText("...").Bold().Italic().Underline().Strikethrough(); hyperlinks via .Link(url); track changes via .AsInsertion(author) / .AsDeletion(author); review markers via .Comment(author, text).
Lists — ListMarker with bullets / numbers / lower-roman / upper-roman / letter at level; hanging indent.
Tables — Table with relative Columns weights, Header/Body rows, RepeatHeader, CellBorderWidth, CellPadding; cells take a string or a Paragraph.
Drop caps + floating images — DropCap { LineSpan = 3 } at the start of a paragraph; FloatImage = new AnchoredImage(image, w, h) { Side = AnchorSide.Right } for wrapped images.
Declare it, then verify it. JetsonPDF separates "the file says it's PDF/A" from "the file is actually PDF/A," and gives you tooling for both.
PDF 2.0 baseline — PDF 2.0 header, UseObjectStreams flag, xref streams, modern security handlers.
Tagged PDF — doc.MarkAsTagged, nested page.BeginTag("H1") / BeginTag("P"), role map & class map, /Lang at document and element level, /Alt, /E, /ID, /ActualText (writer + reader marked-content stack).
Conformance flags — Conformance.PdfA1b / PdfA2b / PdfA3b / PdfUA1 / PdfUA2 emit the right XMP packet, /OutputIntents, and catalog entries (DisplayDocTitle, /Lang).
Validator — ConformanceValidator.Validate(doc) returns IReadOnlyList<ConformanceIssue>; doc.Validate() shorthand. 7 PDF/A-1b rules + 5 PDF/UA-1 rules, plus the PDF/A-2/3 + PDF/UA-2 variants with prefixed codes (PDFA2x, PDFA3x, PDFUA2x).
Strict mode — doc.ThrowOnConformanceError = true aborts Save with a ConformanceException if any error issue is found.
Linearization — Linearizer emits ISO Annex F with linearization dict, two xref tables, and bit-packed Page Offset + Shared Object hint tables.
PKCS#7 signatures — Signer.Sign(byte[], SignatureOptions) for invisible detached signatures with the standard sub-filter adbe.pkcs7.detached; multiple signatures via incremental update.
DocTimeStamp — Timestamper.AddDocumentTimestamp with caller-supplied or default PdfTimestampClient (RFC 3161 over HTTP) emits /Type /DocTimeStamp /SubFilter /ETSI.RFC3161.
DocMDP & FieldMDP — certify documents with permission level (NoChanges / FormFilling / FormFillingAndAnnotations); restrict per-field modifications via FieldMdpRestriction.
DSS / VRI catalog — Dss.AddSecurityStore writes the catalog /DSS with cert / CRL / OCSP streams plus per-signature VRI entries — the missing piece for PAdES B-LTA.
WPF integration
The JetsonPDF.Wpf assembly turns JetsonPDF into a first-class WPF citizen: XamlToPdfConverter parses authoring-XAML, lets WPF run Measure / Arrange, and walks the visual tree to emit a PDF; PdfToXamlConverter turns any ReadDocument back into a XAML tree you can drop into a ContentControl. Multi-page authoring, AcroForm widgets via jetsonpdf:Form.*, PaginatedTable, and a round-trip editor sample — the WPF page has the full surface.
The JetsonPDF.OpenSilver package is the second walker for the same xmlns:jetsonpdf authoring dialect — running in WebAssembly via OpenSilver instead of WPF. Same Document/Page tree, same annotations, same AcroForm widgets, same {jetsonpdf:PageNumber} / {jetsonpdf:Base64Image} markup extensions; ships as netstandard2.0, runs in a Wasm browser app, a WebView2 simulator, or a Playwright-driven Chromium CLI — no WPF, no STA thread, no Windows.
PDFML is JetsonPDF's declarative XML language for PDFs: clean, prefix-free markup (<Document> / <Page> / <TextBlock> / <Grid>) that renders deterministically to ISO 32000-2, with WPF-style {Binding} data binding built in.
The language — https://schemas.jetsonpdf.com/pdfml/1.0; PascalCase throughout, WPF layout panels, native cmyk() color, layers, page labels, named destinations, AcroForm fields, PDF/A · PDF/UA. A normative XSD ships in spec/pdfml/.
Dialects — Dialect="WPF" (layout, default), "PDF" (raw imaging-model operators), or "Mixed" (WPF and PDF islands embedded in each other).
Data binding — Text="{Binding Customer.Name}", <ItemsControl> + <DataTemplate> for collections, StringFormat / FallbackValue / TargetNullValue; resolved at render time against a data object, emitting a static PDF.
Runtime-independent renderer — new PdfmlRenderer().Render(pdfml, data) → byte[]. No WPF, browser, or STA; runs on desktop, server, Blazor, and CI. Targets net8.0 / netstandard2.0 / net462.
Live control — <PdfmlView Markup="..." Model="..."/> hosts a data-bound PDFML document in WPF or OpenSilver and re-renders on INotifyPropertyChanged.
Visual Studio — the PDFML Language Support extension adds schema IntelliSense and a live, type-as-you-go PDF preview for .pdfml files.
The JetsonPDF.PdfToTiffConverter package rasterizes any PDF into a multipage TIFF. It drives the same PdfToXamlConverter render pipeline the WPF viewer uses — each page becomes a XAML tree, WPF runs Measure / Arrange, a RenderTargetBitmap captures it, and the managed JetsonPDF.Tiff writer encodes the frames. No GDI+, no System.Drawing.
Entry points — PdfToTiffConverter.ConvertToFile(pdfPath, tiffPath, options?) and its ...Async form; a stream-based ConvertAsync(ReadDocument, Stream, options?); and RenderPageAsync(ReadPage) → BitmapSource for feeding a different encoder.
Page subset — Pages takes 1-based page numbers; PdfToTiffOptions.ParsePageRange("1-3,5,7-9") builds the list from a spec string.
Multipage strategy — one multi-frame TIFF, or one file per page (OneTiffPerPage) with a {0} / -p001 naming pattern.
Progress — an IProgress<TiffConversionProgress> sink reports each TiffConversionStage with a weighted Fraction and a ready-to-bind Description.
Browser-side — JetsonPDF.OpenSilver ships PdfToTiffBrowserConverter, which captures each page with html2canvas entirely in WebAssembly — no server round-trip.
Standalone TIFF codec — JetsonPDF.Tiff is a managed (netstandard2.0) TIFF reader and writer: decodes 1/4/8-bit, CCITT G3/G4, LZW, Deflate, PackBits, multi-page; writes Deflate / PackBits. Browsers can't display TIFF natively, so it also emits a data:image/png URI per frame.
The desktop converter is Windows-only and must run on an STA thread (it drives the WPF render path). See the WPF guide and the OpenSilver guide for the full surface.