Skip to content

DocumentBuilder Fluent API

DocumentBuilder is a fluent API for constructing PDF documents page by page with full control over text placement, fonts, annotations, form fields, and content elements.

Binding coverage (v0.3.38). DocumentBuilder + FluentPageBuilder + EmbeddedFont ship in Rust, Python, Node/TypeScript, C#, Go, and WASM. Every binding exposes the same surface: multi-page construction, CJK / Cyrillic / Greek text via embedded fonts, 15 annotation methods, 5 AcroForm widget types, graphics primitives (rect, filled_rect, line), AES-256 encryption, and the HTML+CSS pipeline.

Quick Example

Rust

use pdf_oxide::writer::{DocumentBuilder, PageSize, DocumentMetadata};

let mut builder = DocumentBuilder::new()
    .metadata(DocumentMetadata::new().title("My Document"));

builder
    .page(PageSize::Letter)
        .at(72.0, 720.0)
        .heading(1, "Hello, World!")
        .paragraph("This is a PDF document created with DocumentBuilder.")
        .done();

let bytes = builder.build()?;
std::fs::write("output.pdf", bytes)?;

Python

from pdf_oxide import DocumentBuilder, EmbeddedFont

font = EmbeddedFont.from_file("DejaVuSans.ttf")
pdf = (DocumentBuilder()
    .register_embedded_font("DejaVu", font)
    .a4_page()
        .font("DejaVu", 12).at(72, 720).text("Hello, World!")
        .highlight((1.0, 1.0, 0.0))
    .done()
    .build())
open("output.pdf", "wb").write(pdf)

Node / TypeScript

import { DocumentBuilder, EmbeddedFont } from "pdf-oxide";

const font = await EmbeddedFont.fromFile("DejaVuSans.ttf");
const bytes = new DocumentBuilder()
  .registerEmbeddedFont("DejaVu", font)
  .a4Page()
    .font("DejaVu", 12).at(72, 720).text("Hello, World!")
    .highlight([1.0, 1.0, 0.0])
  .done()
  .build();

C#

using PdfOxide;

using var font = EmbeddedFont.FromFile("DejaVuSans.ttf");
var bytes = DocumentBuilder.Create()
    .RegisterEmbeddedFont("DejaVu", font)
    .A4Page()
        .Font("DejaVu", 12).At(72, 720).Text("Hello, World!")
        .Highlight(1.0, 1.0, 0.0)
    .Done()
    .Build();
File.WriteAllBytes("output.pdf", bytes);

Go (CGo path; requires CGO_ENABLED=1)

import pdfoxide "github.com/yfedoseev/pdf_oxide/go"

font, _ := pdfoxide.EmbeddedFontFromFile("DejaVuSans.ttf")
defer font.Close()

builder := pdfoxide.NewDocumentBuilder()
builder.RegisterEmbeddedFont("DejaVu", font)
builder.A4Page().
    Font("DejaVu", 12).At(72, 720).Text("Hello, World!").
    Highlight(1.0, 1.0, 0.0).
    Done()
bytes, _ := builder.Build()

WASM (browser / Node / bundler — same API)

import init, { DocumentBuilder, EmbeddedFont } from "pdf-oxide-wasm/web";
await init();

const font = await fetch("/DejaVuSans.ttf").then(r => r.arrayBuffer());
const bytes = new DocumentBuilder()
  .registerEmbeddedFont("DejaVu", EmbeddedFont.fromBytes(new Uint8Array(font), "DejaVu"))
  .a4Page()
    .font("DejaVu", 12).at(72, 720).text("Hello, World!")
  .done()
  .build();

Full API Reference

DocumentBuilder

DocumentBuilder::new() – Create Builder

let mut builder = DocumentBuilder::new();

.metadata(metadata) – Set Document Metadata

use pdf_oxide::writer::DocumentMetadata;

let mut builder = DocumentBuilder::new()
    .metadata(
        DocumentMetadata::new()
            .title("Report")
            .author("Jane Smith")
            .subject("Q4 Analysis")
            .keywords("finance, quarterly")
            .creator("MyApp")
    );

.page(size) – Add a Page

Returns a FluentPageBuilder for adding content to the page. Call .done() when finished.

use pdf_oxide::writer::PageSize;

builder.page(PageSize::A4)
    .at(72.0, 770.0)
    .text("Hello")
    .done();

.letter_page() / .a4_page() – Convenience Page Methods

builder.letter_page().text("US Letter page").done();
builder.a4_page().text("A4 page").done();

.build() – Generate PDF Bytes

let bytes: Vec<u8> = builder.build()?;

.save(path) – Build and Save to File

builder.save("output.pdf")?;

.save_encrypted(path, user_pw, owner_pw) – AES-256 Encryption

Added in v0.3.38. Available in every binding.

DocumentBuilder::new()
    .a4_page().text("secret").done()
    .save_encrypted("out.pdf", "user-pw", "owner-pw")?;
(DocumentBuilder()
    .a4_page().text("secret").done()
    .save_encrypted("out.pdf", "user-pw", "owner-pw"))
DocumentBuilder.Create()
    .A4Page().Text("secret").Done()
    .SaveEncrypted("out.pdf", "user-pw", "owner-pw");

Also available: .to_bytes_encrypted(user_pw, owner_pw) for in-memory output; .save_with_encryption(path, algorithm, permissions, user_pw, owner_pw) (Rust) for custom algorithm and per-permission flags.

DocumentMetadata

Builder for document-level metadata.

Method Description
.title(s) Set document title
.author(s) Set document author
.subject(s) Set document subject
.keywords(s) Set document keywords
.creator(s) Set creator application

FluentPageBuilder

Returned by builder.page(size). All methods return self for chaining (except .done()).

Text and Positioning

Method Description
.at(x, y) Set cursor position (points from bottom-left)
.text(s) Add text at current cursor position
.heading(level, s) Add heading (1-6, with appropriate font)
.paragraph(s) Add paragraph with automatic word wrapping
.font(name, size) Set font for subsequent text
.text_config(config) Set full text configuration
.space(points) Add vertical space
.horizontal_rule() Add a horizontal divider line
.element(elem) Add a raw ContentElement
.elements(vec) Add multiple raw content elements

Annotations

Method Description
.link_url(url) Link the last text element to a URL
.link_page(page_index) Link the last text to an internal page
.link_named(destination) Link to a named destination
.highlight(color) Highlight the last text (RGB tuple)
.underline(color) Underline the last text
.strikeout(color) Strikethrough the last text
.squiggly(color) Squiggly underline the last text
.sticky_note(text) Add sticky note at cursor position
.sticky_note_with_icon(text, icon) Add sticky note with specific icon
.sticky_note_at(x, y, text) Add sticky note at specific position
.stamp(stamp_type) Add stamp at cursor position
.stamp_at(rect, stamp_type) Add stamp at specific rectangle
.freetext(rect, text) Add free text annotation
.freetext_styled(rect, text, font, size) Add styled free text annotation
.watermark(text) Add diagonal watermark across page
.watermark_confidential() Add preset “CONFIDENTIAL” watermark
.watermark_draft() Add preset “DRAFT” watermark
.watermark_custom(watermark) Add custom watermark annotation
.add_annotation(annotation) Add any annotation type

AcroForm Widgets

Added across all bindings in v0.3.38. All positions are in PDF points from the page’s lower-left origin.

Method Description
.text_field(name, x, y, w, h, default_value=None) Single-line text input
.checkbox(name, x, y, w, h, checked) Checkbox widget
.combo_box(name, x, y, w, h, options, selected=None) Dropdown selector
.radio_group(name, buttons, selected=None) Radio group; buttons is a list of (export_value, x, y, w, h)
.push_button(name, x, y, w, h, caption) Clickable button with label
(DocumentBuilder()
    .a4_page()
        .text_field("name", 150, 680, 200, 20, "Jane Doe")
        .checkbox("subscribe", 72, 650, 15, 15, True)
        .combo_box("country", 150, 620, 200, 20, ["US", "UK", "DE"], "US")
        .radio_group("tier", [("free", 72, 590, 15, 15), ("pro", 120, 590, 15, 15)], "pro")
        .push_button("submit", 72, 540, 80, 25, "Submit")
    .done()
    .save("form.pdf"))

Graphics Primitives

Added across all bindings in v0.3.38: rect(x, y, w, h) (stroke-only), filled_rect(x, y, w, h, color) (filled with an RGB tuple), and line(x1, y1, x2, y2). These route through the same FluentPageBuilder chain and are sufficient for form backgrounds, separators, and simple table borders.

For full path / pattern / gradient / ExtGState control, use ContentStreamBuilder (Rust only — see Graphics, Patterns & Shadings).

.done() – Finish Page

Returns control to the DocumentBuilder.

builder.page(PageSize::Letter)
    .at(72.0, 720.0)
    .text("Content")
    .done();  // Back to builder

TextConfig

Configuration for text rendering.

use pdf_oxide::writer::TextConfig;

let config = TextConfig {
    font: "Times-Roman".to_string(),
    size: 14.0,
    align: TextAlign::Center,
    line_height: 1.5,
};
Field Type Default
font String "Helvetica"
size f32 12.0
align TextAlign Left
line_height f32 1.2

PageSize

Variant Width x Height (points)
Letter 612 x 792
A4 595 x 842
Legal 612 x 1008
A3 842 x 1190
Custom(w, h) Custom dimensions

Advanced Examples

Multi-Page Document with Annotations

use pdf_oxide::writer::{
    DocumentBuilder, DocumentMetadata, PageSize, StampType
};

let mut builder = DocumentBuilder::new()
    .metadata(
        DocumentMetadata::new()
            .title("Annotated Report")
            .author("Review Team")
    );

// Cover page
builder.page(PageSize::Letter)
    .at(72.0, 600.0)
    .font("Helvetica-Bold", 28.0)
    .text("Annual Review 2025")
    .font("Helvetica", 14.0)
    .space(20.0)
    .text("Prepared by the Review Team")
    .watermark_draft()
    .done();

// Content page with annotations
builder.page(PageSize::Letter)
    .at(72.0, 720.0)
    .heading(1, "Executive Summary")
    .paragraph(
        "Revenue increased 18% year-over-year, driven by expansion \
         into new markets and strong retention rates."
    )
    .text("See full financial details")
    .link_page(2)  // Link to page 3 (0-indexed)
    .space(12.0)
    .heading(2, "Key Findings")
    .text("Customer satisfaction reached an all-time high.")
    .highlight((1.0, 1.0, 0.0))  // Yellow highlight
    .sticky_note("Verify this claim with latest survey data")
    .paragraph(
        "Operating costs were reduced through automation initiatives, \
         achieving a 15% improvement in operational efficiency."
    )
    .stamp(StampType::ForComment)
    .done();

// Data page
builder.page(PageSize::Letter)
    .at(72.0, 720.0)
    .heading(1, "Financial Details")
    .paragraph("Detailed breakdown of revenue by segment...")
    .horizontal_rule()
    .paragraph("North America: $82M (+12%)")
    .paragraph("Europe: $41M (+28%)")
    .paragraph("Asia-Pacific: $19M (+35%)")
    .done();

builder.save("annotated_report.pdf")?;

Precise Text Positioning

use pdf_oxide::writer::{DocumentBuilder, PageSize};

let mut builder = DocumentBuilder::new();

builder.page(PageSize::Letter)
    // Title at top center area
    .at(200.0, 740.0)
    .font("Helvetica-Bold", 20.0)
    .text("Certificate of Completion")

    // Recipient name
    .at(200.0, 620.0)
    .font("Times-Roman", 16.0)
    .text("Awarded to: Jane Smith")

    // Details at specific positions
    .at(72.0, 500.0)
    .font("Helvetica", 12.0)
    .text("For successfully completing the Advanced Rust Programming course.")

    .at(72.0, 450.0)
    .text("Date: November 15, 2025")

    .at(350.0, 450.0)
    .text("Instructor: Dr. Alan Turing")

    .horizontal_rule()

    .at(72.0, 380.0)
    .font("Helvetica", 9.0)
    .text("Certificate ID: CERT-2025-00042")

    .done();

builder.save("certificate.pdf")?;