Skip to content

DocumentBuilder フルエント API

DocumentBuilder は、テキストの配置、フォント、注釈、フォームフィールド、コンテンツ要素を完全に制御しながら、PDF ドキュメントをページ単位で構築するためのフルエント API です。

バインディング対応状況(v0.3.38)。 DocumentBuilder + FluentPageBuilder + EmbeddedFontRust、Python、Node/TypeScript、C#、Go、WASM で提供されています。すべてのバインディングが同一の機能を公開しています。複数ページ構築、埋め込みフォントによる CJK/キリル文字/ギリシャ文字テキスト、15 種類の注釈メソッド、5 種類の AcroForm ウィジェット、グラフィックスプリミティブ(rectfilled_rectline)、AES-256 暗号化、そして HTML+CSS パイプラインです。

クイック例

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 経由。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(ブラウザ/Node/バンドラー — 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();

C++

#include <pdf_oxide/pdf_oxide.hpp>

auto font = pdf_oxide::EmbeddedFont::from_file("DejaVuSans.ttf");
auto builder = pdf_oxide::DocumentBuilder::create();
builder.register_embedded_font("DejaVu", font);
builder.a4_page()
    .font("DejaVu", 12).at(72, 720).text("Hello, World!")
    .highlight(1.0, 1.0, 0.0)
    .done();
std::vector<std::uint8_t> bytes = builder.build();

Swift

import PdfOxide

let font = try EmbeddedFont.fromFile("DejaVuSans.ttf")
let builder = try DocumentBuilder.create()
try builder.registerEmbeddedFont("DejaVu", font)
let page = try builder.a4Page()
try page.font("DejaVu", 12).at(72, 720).text("Hello, World!")
    .highlight(1.0, 1.0, 0.0)
    .done()
let bytes = try builder.build()

Dart

import 'package:pdf_oxide/pdf_oxide.dart';

final font = EmbeddedFont.fromFile('DejaVuSans.ttf');
final builder = DocumentBuilder.create();
builder.registerEmbeddedFont('DejaVu', font);
builder.a4Page()
    .font('DejaVu', 12.0).at(72.0, 720.0).text('Hello, World!')
    .highlight(1.0, 1.0, 0.0)
    .done();
final bytes = builder.build();

R

library(pdfoxide)

font <- pdf_embedded_font_from_file("DejaVuSans.ttf")
b    <- pdf_builder_create()
pdf_builder_register_embedded_font(b, "DejaVu", font)
pg <- pdf_builder_a4_page(b)
pdf_page_font(pg, "DejaVu", 12)
pdf_page_at(pg, 72, 720)
pdf_page_builder_text(pg, "Hello, World!")
pdf_page_highlight(pg, 1.0, 1.0, 0.0)
pdf_page_done(pg)
bytes <- pdf_builder_build(b)

Julia

using PdfOxide

emb = embedded_font_from_file("DejaVuSans.ttf")
b   = DocumentBuilder()
register_embedded_font(b, "DejaVu", emb)
pg = a4_page(b)
font(pg, "DejaVu", 12)
at(pg, 72, 720)
text(pg, "Hello, World!")
highlight(pg, 1.0, 1.0, 0.0)
done(pg)
bytes = build(b)

Zig

const pdf_oxide = @import("pdf_oxide");
const a = std.heap.page_allocator;

var font = try pdf_oxide.EmbeddedFont.fromFile("DejaVuSans.ttf");
var builder = try pdf_oxide.DocumentBuilder.create();
try builder.registerEmbeddedFont("DejaVu", &font);
var page = try builder.a4Page();
try page.font("DejaVu", 12);
try page.at(72, 720);
try page.text("Hello, World!");
try page.highlight(1.0, 1.0, 0.0);
try page.done();
const bytes = try builder.build(a);

Objective-C

#import "POXPdfOxide.h"
NSError *err = nil;

POXEmbeddedFont *font = [POXEmbeddedFont fromPath:@"DejaVuSans.ttf" error:&err];
POXDocumentBuilder *builder = [POXDocumentBuilder createWithError:&err];
[builder registerEmbeddedFont:@"DejaVu" font:font error:&err];
POXPageBuilder *page = [builder a4PageWithError:&err];
[page font:@"DejaVu" size:12 error:&err];
[page at:72 y:720 error:&err];
[page text:@"Hello, World!" error:&err];
[page highlightR:1.0 g:1.0 b:0.0 error:&err];
[page done:&err];
NSData *bytes = [builder buildWithError:&err];

Elixir

{:ok, font} = PdfOxide.font_from_file("DejaVuSans.ttf")
{:ok, db}   = PdfOxide.builder()
:ok = PdfOxide.builder_register_embedded_font(db, "DejaVu", font)
{:ok, page} = PdfOxide.builder_a4_page(db)
:ok = PdfOxide.page_font(page, "DejaVu", 12)
:ok = PdfOxide.page_at(page, 72, 720)
:ok = PdfOxide.page_text(page, "Hello, World!")
:ok = PdfOxide.page_highlight(page, 1.0, 1.0, 0.0)
:ok = PdfOxide.page_done(page)
{:ok, bytes} = PdfOxide.builder_build(db)

完全な API リファレンス

DocumentBuilder

DocumentBuilder::new() – ビルダーの作成

let mut builder = DocumentBuilder::new();

.metadata(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) – ページの追加

ページにコンテンツを追加するための FluentPageBuilder を返します。完了したら .done() を呼び出します。

use pdf_oxide::writer::PageSize;

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

.letter_page() / .a4_page() – 便利なページメソッド

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

.build() – PDF バイト列の生成

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

.save(path) – ビルドしてファイルに保存

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

.save_encrypted(path, user_pw, owner_pw) – AES-256 暗号化

v0.3.38 で追加。すべてのバインディングで利用可能です。

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");

その他に次も利用できます。メモリ内出力用の .to_bytes_encrypted(user_pw, owner_pw)、カスタムアルゴリズムと権限ごとのフラグを指定する .save_with_encryption(path, algorithm, permissions, user_pw, owner_pw)(Rust)。

DocumentMetadata

ドキュメントレベルのメタデータ用ビルダーです。

メソッド 説明
.title(s) ドキュメントのタイトルを設定
.author(s) ドキュメントの作成者を設定
.subject(s) ドキュメントの件名を設定
.keywords(s) ドキュメントのキーワードを設定
.creator(s) 作成アプリケーションを設定

FluentPageBuilder

builder.page(size) から返されます。すべてのメソッドはチェーン用に self を返します(.done() を除く)。

テキストと配置

メソッド 説明
.at(x, y) カーソル位置を設定(左下からのポイント数)
.text(s) 現在のカーソル位置にテキストを追加
.heading(level, s) 見出しを追加(1〜6、適切なフォントで)
.paragraph(s) 自動ワードラップ付きの段落を追加
.font(name, size) 後続のテキストのフォントを設定
.text_config(config) テキスト設定全体を指定
.space(points) 垂直方向の余白を追加
.horizontal_rule() 水平方向の区切り線を追加
.element(elem) 生の ContentElement を追加
.elements(vec) 複数の生コンテンツ要素を追加

注釈

メソッド 説明
.link_url(url) 直前のテキスト要素を URL にリンク
.link_page(page_index) 直前のテキストを内部ページにリンク
.link_named(destination) 名前付き送り先にリンク
.highlight(color) 直前のテキストをハイライト(RGB タプル)
.underline(color) 直前のテキストに下線
.strikeout(color) 直前のテキストに取り消し線
.squiggly(color) 直前のテキストに波線下線
.sticky_note(text) カーソル位置に付箋を追加
.sticky_note_with_icon(text, icon) 特定のアイコン付きで付箋を追加
.sticky_note_at(x, y, text) 特定の位置に付箋を追加
.stamp(stamp_type) カーソル位置にスタンプを追加
.stamp_at(rect, stamp_type) 特定の矩形にスタンプを追加
.freetext(rect, text) フリーテキスト注釈を追加
.freetext_styled(rect, text, font, size) スタイル付きフリーテキスト注釈を追加
.watermark(text) ページ全体に斜めの透かしを追加
.watermark_confidential() プリセットの「CONFIDENTIAL」透かしを追加
.watermark_draft() プリセットの「DRAFT」透かしを追加
.watermark_custom(watermark) カスタム透かし注釈を追加
.add_annotation(annotation) 任意の注釈タイプを追加

AcroForm ウィジェット

v0.3.38 ですべてのバインディングに追加されました。すべての位置はページの左下原点からの PDF ポイント単位です。

メソッド 説明
.text_field(name, x, y, w, h, default_value=None) 単一行テキスト入力
.checkbox(name, x, y, w, h, checked) チェックボックスウィジェット
.combo_box(name, x, y, w, h, options, selected=None) ドロップダウンセレクター
.radio_group(name, buttons, selected=None) ラジオグループ。buttons(export_value, x, y, w, h) のリスト
.push_button(name, x, y, w, h, caption) ラベル付きのクリック可能なボタン
(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"))

グラフィックスプリミティブ

v0.3.38 ですべてのバインディングに追加されました。rect(x, y, w, h)(線のみ)、filled_rect(x, y, w, h, color)(RGB タプルで塗りつぶし)、line(x1, y1, x2, y2) です。これらは同じ FluentPageBuilder チェーンを経由し、フォームの背景、区切り線、シンプルな表の罫線には十分です。

パス/パターン/グラデーション/ExtGState を完全に制御するには、ContentStreamBuilder(Rust のみ — グラフィックス、パターン、シェーディング を参照)を使用してください。

.done() – ページの完了

制御を DocumentBuilder に戻します。

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

TextConfig

テキストレンダリングの設定です。

use pdf_oxide::writer::TextConfig;

let config = TextConfig {
    font: "Times-Roman".to_string(),
    size: 14.0,
    align: TextAlign::Center,
    line_height: 1.5,
};
フィールド デフォルト
font String "Helvetica"
size f32 12.0
align TextAlign Left
line_height f32 1.2

PageSize

バリアント 幅 x 高さ(ポイント)
Letter 612 x 792
A4 595 x 842
Legal 612 x 1008
A3 842 x 1190
Custom(w, h) カスタム寸法

応用例

注釈付きの複数ページドキュメント

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")?;

精密なテキスト配置

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")?;

関連ページ