Examples

Self-contained snippets you can paste into a fresh project. Each one runs against the current JetsonPDF API.

Reference PDFs. Every public namespace has a generated, paginated reference document: Writer · Reader · Fluent · Flow.
Sample outputs. Rendered PDFs from the in-tree samples — open them to see what the code below actually produces: FluentInvoice.pdf · FluentMeetingNotes.pdf · FluentShowcase.pdf · FlowReport.pdf.

1Hello world

The minimum: one page, one line of text, one file on disk.

using JetsonPDF;

var doc = new PdfDocument { Title = "Hello" };
var page = doc.AddPage(PageSize.Letter);

page.DrawText("Hello, PDF!",
    new PdfFont(FontFamily.Helvetica, 24),
    x: 72, y: 700);

doc.Save("hello.pdf");

PDF coordinates start at the bottom-left, in points (1 point = 1/72 inch). A US Letter page is 612×792 points; y: 700 is near the top.

3Embedded TrueType + Unicode

Embed a font file once and use it like any standard font. Subsetting happens automatically on save.

using JetsonPDF;

var doc = new PdfDocument
{
    Title = "Unicode demo",
    PdfVersion = "2.0",
};

var calibri = EmbeddedFontFace.FromFile(@"C:\Windows\Fonts\calibri.ttf");
var font = new PdfFont(calibri, 14);

var page = doc.AddPage(PageSize.Letter);
page.DrawText("English  —  Français  —  Español",
    font, x: 72, y: 720);
page.DrawText("中文  —  日本語  —  한국어",
    font, x: 72, y: 690);

doc.Save("unicode.pdf");

For CJK content, JetsonPDF emits a Type 0 / CIDFontType2 font with a /ToUnicode CMap so text is still selectable and copyable.

4Vector graphics + transparency

Paths, fills, gradients, and a translucent overlay.

using JetsonPDF;

var doc = new PdfDocument();
var page = doc.AddPage(PageSize.Letter);

// Solid fill + stroke.
page.DrawRectangle(72, 600, 200, 120,
    fill: PdfColor.Rgb(0.13, 0.31, 0.52),
    stroke: PdfColor.Black,
    strokeWidth: 1.5);

// A 2-stop axial gradient.
var shading = new PdfAxialShading(
    x0: 72,  y0: 480, x1: 272, y1: 480,
    PdfColor.Rgb(1.0, 0.85, 0.20),
    PdfColor.Rgb(0.90, 0.30, 0.30));
page.DrawShading(shading, clipX: 72, clipY: 460, clipW: 200, clipH: 80);

// Transparent overlay.
using (page.BeginTransparencyGroup(opacity: 0.4))
{
    page.DrawRectangle(140, 540, 200, 100,
        fill: PdfColor.Rgb(0.0, 0.6, 0.3));
}

doc.Save("vectors.pdf");

5AcroForm widgets

Add an interactive form — text fields, a checkbox, and a Print button — from C#.

using JetsonPDF;
using JetsonPDF.Forms;

var doc = new PdfDocument { Title = "Signup" };
var page = doc.AddPage(PageSize.Letter);
var label = new PdfFont(FontFamily.Helvetica, 11);

page.DrawText("Name:",  label, x: 72, y: 720);
page.AddTextField("name",  x: 130, y: 712, width: 280, height: 20, label);

page.DrawText("Email:", label, x: 72, y: 690);
var email = page.AddTextField("email", x: 130, y: 682, width: 280, height: 20, label);
email.MaxLength = 120;

var subscribe = page.AddCheckBox("subscribe", x: 130, y: 650, width: 14, height: 14);
subscribe.IsChecked = true;
page.DrawText("Send me occasional updates", label, x: 152, y: 651);

var print = page.AddPushButton("printBtn",
    x: 130, y: 600, width: 90, height: 24, label, caption: "Print");
print.Action = PdfWidgetAction.NamedAction("Print");

doc.Save("signup.pdf");

6AES-256 encryption with permissions

Encrypt the document and limit what viewers can do without the owner password.

using JetsonPDF;

var doc = new PdfDocument
{
    Title = "Confidential",
    PdfVersion = "2.0",
    Encryption = new PdfEncryptionOptions
    {
        Algorithm     = PdfEncryptionAlgorithm.Aes256,
        UserPassword  = "open-me",
        OwnerPassword = "owner-only",
        Permissions   = PdfPermissions.Print | PdfPermissions.CopyContent,
    },
};

doc.AddPage(PageSize.Letter)
   .DrawText("Confidential.",
       new PdfFont(FontFamily.Helvetica, 24),
       x: 72, y: 700);

doc.Save("encrypted.pdf");

AES-256 uses Standard Security Handler V5 (algorithms 2.B / 8 / 9 / 10 in PDF 2.0). Acrobat X+ and every modern viewer read it; for older viewers, drop down to Aes128.

7Detached PKCS#7 signature

Sign the rendered bytes with a certificate that has a private key. Multi-signing works via incremental update.

using System.Security.Cryptography.X509Certificates;
using JetsonPDF;

// 1. Build the document as usual.
var doc = new PdfDocument { Title = "Signed report" };
doc.AddPage(PageSize.Letter)
   .DrawText("Signed.", new PdfFont(FontFamily.Helvetica, 24), 72, 700);

byte[] unsigned = doc.SaveToBytes();

// 2. Sign in-memory with a PFX certificate.
var cert = new X509Certificate2("signer.pfx", "pfx-password",
    X509KeyStorageFlags.Exportable);

var signed = PdfSigner.Sign(unsigned, new PdfSignatureOptions(cert)
{
    Reason   = "Approved",
    Location = "HQ",
    FieldName = "Signature1",
});

File.WriteAllBytes("signed.pdf", signed);

For PAdES B-LT/B-LTA, follow up with PdfTimestamper.AddDocumentTimestamp and PdfDss.AddSecurityStore to embed the validation material.

8Fluent invoice with header, footer, and table

The JetsonPDF.Fluent namespace exposes a QuestPDF-style layout DSL. Header, footer, and content slots; rows; tables; per-run rich text; live page numbers.

using JetsonPDF;
using JetsonPDF.Fluent;

var doc = Document.Create(d =>
{
    d.Page(p =>
    {
        p.Size(PageSize.Letter);
        p.Margin(50);
        p.DefaultTextStyle(s => s.FontSize = 10);

        // Header — repeats on every page.
        p.Header().Row(row =>
        {
            row.RelativeItem().Text("INVOICE", s =>
            {
                s.FontSize = 24;
                s.FontStyle = FontStyle.Bold;
                s.FontColor = Colors.IndigoDark;
            });
            row.ConstantItem(120).AlignRight().Text(t =>
            {
                t.AlignRight();
                t.Span("Page ");
                t.CurrentPageNumber().Bold();
                t.Span(" / ");
                t.TotalPages().Bold();
            });
        });

        // Footer — repeats on every page.
        p.Footer().AlignCenter().Text("https://jetsonpdf.net");

        // Content — auto-paginates on overflow.
        p.Content().PaddingVertical(12).Column(col =>
        {
            col.Spacing(14);

            col.Item().Text("Bill to: Acme Corporation",
                s => s.FontStyle = FontStyle.Bold);

            col.Item().Table(t =>
            {
                t.ColumnsDefinition(c =>
                {
                    c.RelativeColumn(3);    // Description
                    c.ConstantColumn(50);   // Qty
                    c.ConstantColumn(70);   // Price
                    c.ConstantColumn(80);   // Amount
                });

                // Header row — repeats per page.
                t.Header(h =>
                {
                    h.Cell().Padding(6).Background(Colors.IndigoDark)
                        .Text("Description", s => s.FontColor = Colors.White);
                    h.Cell().Padding(6).Background(Colors.IndigoDark).AlignRight()
                        .Text("Qty",    s => s.FontColor = Colors.White);
                    h.Cell().Padding(6).Background(Colors.IndigoDark).AlignRight()
                        .Text("Price",  s => s.FontColor = Colors.White);
                    h.Cell().Padding(6).Background(Colors.IndigoDark).AlignRight()
                        .Text("Amount", s => s.FontColor = Colors.White);
                });

                foreach (var (name, qty, price) in lineItems)
                {
                    t.Cell().Padding(6).Text(name);
                    t.Cell().Padding(6).AlignRight().Text(qty.ToString());
                    t.Cell().Padding(6).AlignRight().Text($"${price:F2}");
                    t.Cell().Padding(6).AlignRight().Text($"${qty * price:F2}");
                }

                // Footer row — only on the last page; spans columns.
                t.Footer(f =>
                {
                    f.Cell(columnSpan: 3).Padding(6).AlignRight()
                        .Text("Total", s => s.FontStyle = FontStyle.Bold);
                    f.Cell().Padding(6).Background(Colors.IndigoDark).AlignRight()
                        .Text($"${total:F2}", s =>
                        { s.FontStyle = FontStyle.Bold; s.FontColor = Colors.White; });
                });
            });
        });
    });
}).WithMetadata(title: "Invoice #INV-2026-001", author: "Acme");

doc.GeneratePdf("invoice.pdf");

The full source for this sample (with stripes, callout box, and form widgets) lives at samples/FluentInvoice/Program.csdownload the rendered PDF. See the Fluent API reference for every container method.

9Form widgets and internal nav with Fluent

Any leaf slot becomes an AcroForm widget. .Section(anchor) registers a named destination; .SectionLink(anchor) links to it.

using JetsonPDF;
using JetsonPDF.Fluent;

var doc = Document.Create(d => d.Page(p =>
{
    p.Size(PageSize.Letter);
    p.Margin(50);

    p.Content().Column(col =>
    {
        col.Spacing(12);

        // A named destination.
        col.Item().Section("top").Text("Customer acknowledgement",
            s => s.FontStyle = FontStyle.Bold);

        // Text field — Acrobat draws the chrome at the arranged bounds.
        col.Item().Row(row =>
        {
            row.ConstantItem(100).AlignMiddle().Text("Signed name:");
            row.RelativeItem().Height(18).AsTextField("ack.name");
        });

        // Check box.
        col.Item().Row(row =>
        {
            row.ConstantItem(15).Height(15).AsCheckBox("ack.agreed");
            row.RelativeItem().PaddingLeft(6).AlignMiddle()
                .Text("I agree to the payment terms above.");
        });

        // Combo box with options.
        col.Item().Row(row =>
        {
            row.ConstantItem(100).AlignMiddle().Text("Region:");
            row.ConstantItem(160).Height(18).AsComboBox("ack.region",
                new[] { "North America", "EMEA", "APAC", "LATAM" });
        });

        // Push button — combine .Link(uri) with .AsPushButton.
        col.Item().Width(120).Height(22)
            .Link("https://jetsonpdf.net/pay")
            .AsPushButton("ack.pay", "Pay now");

        // Internal-link button to the named destination above.
        col.Item().SectionLink("top").Width(60).Height(14)
            .Background(Colors.Blue).AlignCenter().AlignMiddle()
            .Text("Top", s => s.FontColor = Colors.White);
    });
}));

doc.GeneratePdf("acknowledgement.pdf");

10Word-style report with Flow

JetsonPDF.Flow is a Word-like retained-mode DOM. Build a tree of Section/Paragraph/Table, mutate it freely, then Save. Auto-paginates over the Fluent renderer.

using JetsonPDF;
using JetsonPDF.Flow;

var doc = new FlowDocument
{
    Title  = "Q3 Quarterly Report",
    Author = "Acme Corp",
    DefaultRunProperties = new RunProperties
    {
        FontFamily = "Helvetica",
        FontSize   = 11,
        Color      = PdfColor.Black,
    },
    Hyphenator = JetsonPDF.Flow.Hyphenation.Hyphenator.EnglishDefault(),
};

// Named style with a basedOn graph.
doc.AddStyle("Callout", configure: s =>
{
    s.RunProperties.Italic = true;
    s.RunProperties.FontSize = 10;
    s.ParagraphProperties.LeftIndent  = 24;
    s.ParagraphProperties.RightIndent = 24;
});

var section = doc.AddSection();
section.PageSize    = PageSize.Letter;
section.PageMargins = new Margins(72);

// Footer with live page numbers.
section.Footer.Body.Add(new Paragraph(p =>
{
    p.AddText("Page ");
    p.AddPageNumber();
    p.AddText(" of ");
    p.AddPageCount();
}) { Alignment = TextAlign.Center });

// Headings auto-bookmark — TableOfContents picks them up.
section.Body.Add(new Paragraph("Q3 Quarterly Report")
    { Style = ParagraphStyle.Heading1, Alignment = TextAlign.Center });

section.Body.Add(new Paragraph("Contents") { Style = ParagraphStyle.Heading2 });
section.Body.Add(new TableOfContents());

section.Body.Add(new Paragraph("Introduction")
    { Style = ParagraphStyle.Heading1, PageBreakBefore = true });

// Rich inline runs: bold, italic, link, footnote, drop cap, justified.
section.Body.Add(new Paragraph(p =>
{
    p.AddText("This report describes ");
    p.AddText("quarterly performance").Bold();
    p.AddText(" across our three primary business lines. ");
    p.AddText("All comparisons reference the prior fiscal quarter");
    p.AddFootnote("Constant-currency rates are locked at the start of FY25.");
    p.AddText(". For methodology see ");
    p.AddText("our public docs").Link("https://www.example.com/methodology");
    p.AddText(".");
})
{
    DropCap    = new DropCap { LineSpan = 3 },
    Alignment  = TextAlign.Justify,
});

// Numbered list — auto-counter, hanging indent.
section.Body.Add(new Paragraph("Total revenue grew 12% year over year.")
    { ListMarker = new ListMarker(ListKind.Number) });
section.Body.Add(new Paragraph("Hardware margin expanded by 180 bps.")
    { ListMarker = new ListMarker(ListKind.Number) });

// Named-style callout.
section.Body.Add(new Paragraph("Forward-looking statements may change.")
    { StyleName = "Callout" });

// Table with repeating header.
var table = new Table
{
    Columns         = { 2.0, 1.0, 1.0 },
    RepeatHeader    = true,
    CellBorderWidth = 0.5,
    CellPadding     = 5,
};
var hdr = new TableRow();
hdr.Cells.Add(new TableCell(new Paragraph("Region")
    { Style = ParagraphStyle.Heading3 }));
hdr.Cells.Add(new TableCell(new Paragraph("Q3")
    { Style = ParagraphStyle.Heading3, Alignment = TextAlign.Right }));
hdr.Cells.Add(new TableCell(new Paragraph("Δ")
    { Style = ParagraphStyle.Heading3, Alignment = TextAlign.Right }));
table.Header.Add(hdr);
foreach (var (region, q3, delta) in new[]
{
    ("North America", "$53.6M", "+11.2%"),
    ("EMEA",          "$34.0M", "+9.3%"),
    ("APAC",          "$25.9M", "+14.1%"),
})
{
    var row = new TableRow();
    row.Cells.Add(new TableCell(region));
    row.Cells.Add(new TableCell(new Paragraph(q3)
        { Alignment = TextAlign.Right }));
    row.Cells.Add(new TableCell(new Paragraph(delta)
        { Alignment = TextAlign.Right }));
    table.Body.Add(row);
}
section.Body.Add(table);

// Endnote list — auto-collected from the body.
section.Body.Add(new Paragraph("Notes")
    { Style = ParagraphStyle.Heading2, PageBreakBefore = true });
section.Body.Add(new EndnoteList());

doc.Save("FlowReport.pdf");

The full FlowReport sample (cover, footnotes, two-column section, track changes, anchored images, comments, segment table) lives at samples/FlowReport/Program.csdownload the rendered PDF. See the Flow API reference for the complete tree.

11Author a PDF in XAML

Compose with the WPF layout engine you already know — Grid, StackPanel, Border, data-bound text. JetsonPDF runs Measure/Arrange and walks the resulting visual tree.

<jetsonpdf:Document
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:jetsonpdf="http://schemas.jetsonpdf.org/authoring/2025"
    PageSize="Letter" Title="Invoice #123" Author="Acme">
  <jetsonpdf:Document.Pages>
    <jetsonpdf:Page>
      <Grid Margin="48">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="*"/>
          <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Border Grid.Row="0" Background="#213F85" Padding="20,12">
          <TextBlock Text="Invoice #123"
                     FontSize="28" FontWeight="Bold"
                     Foreground="White"/>
        </Border>

        <StackPanel Grid.Row="1" Margin="0,24,0,0">
          <TextBlock FontSize="14" Text="Bill to: Wile E. Coyote"/>
          <TextBlock FontSize="14" Text="123 Desert Rd."/>
        </StackPanel>

        <TextBlock Grid.Row="2" HorizontalAlignment="Right" FontSize="11">
          <Run Text="Page "/><Run Text="{jetsonpdf:PageNumber}"/>
          <Run Text=" of "/><Run Text="{jetsonpdf:PageCount}"/>
        </TextBlock>
      </Grid>
    </jetsonpdf:Page>
  </jetsonpdf:Document.Pages>
</jetsonpdf:Document>

Then in C# — on an STA thread, since WPF requires it:

using JetsonPDF.Wpf.Authoring;

string xaml = File.ReadAllText("invoice.xaml");
byte[] pdfBytes = XamlToPdfConverter.Convert(xaml);
File.WriteAllBytes("invoice.pdf", pdfBytes);

Add jetsonpdf:Form.FieldName="email" to a TextBox and that XAML control becomes a real AcroForm widget at the arranged bounds.

12Read a PDF and walk its content

Open a file, list its outlines, and dump the text of every page.

using JetsonPDF.Reading;

var doc = PdfReader.Load("input.pdf");

Console.WriteLine($"Title: {doc.Info.Title}");
Console.WriteLine($"Pages: {doc.Pages.Count}");
Console.WriteLine($"Encrypted: {doc.IsEncrypted}");

foreach (var item in doc.Outlines)
    Console.WriteLine($" * {item.Title}");

foreach (var page in doc.Pages)
{
    Console.WriteLine($"--- page {page.PageNumber} ---");
    foreach (var content in page.Items.OfType<PageTextItem>())
        Console.WriteLine(content.Text);
}

Need to read an encrypted file? Pass the password as the second argument to Load: PdfReader.Load("input.pdf", "open-me").

13Render any PDF as a WPF view

Convert ReadPdfDocument straight into XAML and host it in a WPF window. No filesystem access; images come back as base64 inline.

using JetsonPDF.Reading;
using JetsonPDF.Wpf;
using System.Windows.Markup;

var read = PdfReader.Load("input.pdf");
string xaml = PdfToXamlConverter.Convert(read);

// Parse the XAML and bind it into the host control.
var visual = (FrameworkElement)XamlReader.Parse(xaml);
PdfHost.Content = visual;

The output is a StackPanel — one Canvas per page — with absolute-positioned TextBlock, Image, Path, and Glyphs elements. Wrap it in a ScrollViewer for paging.