Skip to content

API Fluida de DocumentBuilder

DocumentBuilder es una API fluida para construir documentos PDF página por página, con control total sobre la colocación del texto, las fuentes, las anotaciones, los campos de formulario y los elementos de contenido.

Cobertura en los bindings (v0.3.38). DocumentBuilder + FluentPageBuilder + EmbeddedFont están disponibles en Rust, Python, Node/TypeScript, C#, Go y WASM. Todos los bindings exponen el mismo conjunto de funciones: construcción de varias páginas, texto en CJK / cirílico / griego mediante fuentes incrustadas, 15 métodos de anotación, 5 tipos de widget de AcroForm, primitivas gráficas (rect, filled_rect, line), cifrado AES-256 y la canalización HTML+CSS.

Ejemplo Rápido

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 (ruta CGo; requiere 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 (navegador / Node / bundler — la misma 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)

Referencia Completa de la API

DocumentBuilder

DocumentBuilder::new() – Crear el Builder

let mut builder = DocumentBuilder::new();

.metadata(metadata) – Establecer los Metadatos del Documento

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) – Añadir una Página

Devuelve un FluentPageBuilder para añadir contenido a la página. Llama a .done() cuando termines.

use pdf_oxide::writer::PageSize;

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

.letter_page() / .a4_page() – Métodos de Página de Conveniencia

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

.build() – Generar los Bytes del PDF

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

.save(path) – Construir y Guardar en un Archivo

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

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

Añadido en la v0.3.38. Disponible en todos los bindings.

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

También disponibles: .to_bytes_encrypted(user_pw, owner_pw) para la salida en memoria; .save_with_encryption(path, algorithm, permissions, user_pw, owner_pw) (Rust) para algoritmo personalizado e indicadores por permiso.

DocumentMetadata

Builder para los metadatos a nivel de documento.

Método Descripción
.title(s) Establece el título del documento
.author(s) Establece el autor del documento
.subject(s) Establece el asunto del documento
.keywords(s) Establece las palabras clave del documento
.creator(s) Establece la aplicación creadora

FluentPageBuilder

Devuelto por builder.page(size). Todos los métodos devuelven self para el encadenamiento (excepto .done()).

Texto y Posicionamiento

Método Descripción
.at(x, y) Establece la posición del cursor (puntos desde la esquina inferior izquierda)
.text(s) Añade texto en la posición actual del cursor
.heading(level, s) Añade un encabezado (1–6, con la fuente adecuada)
.paragraph(s) Añade un párrafo con ajuste de línea automático
.font(name, size) Establece la fuente para el texto siguiente
.text_config(config) Establece la configuración completa de texto
.space(points) Añade espacio vertical
.horizontal_rule() Añade una línea divisoria horizontal
.element(elem) Añade un ContentElement sin procesar
.elements(vec) Añade varios elementos de contenido sin procesar

Anotaciones

Método Descripción
.link_url(url) Enlaza el último elemento de texto a una URL
.link_page(page_index) Enlaza el último texto a una página interna
.link_named(destination) Enlaza a un destino con nombre
.highlight(color) Resalta el último texto (tupla RGB)
.underline(color) Subraya el último texto
.strikeout(color) Tacha el último texto
.squiggly(color) Subrayado ondulado en el último texto
.sticky_note(text) Añade una nota adhesiva en la posición del cursor
.sticky_note_with_icon(text, icon) Añade una nota adhesiva con un icono específico
.sticky_note_at(x, y, text) Añade una nota adhesiva en una posición específica
.stamp(stamp_type) Añade un sello en la posición del cursor
.stamp_at(rect, stamp_type) Añade un sello en un rectángulo específico
.freetext(rect, text) Añade una anotación de texto libre
.freetext_styled(rect, text, font, size) Añade una anotación de texto libre con estilo
.watermark(text) Añade una marca de agua diagonal en la página
.watermark_confidential() Añade la marca de agua predefinida “CONFIDENTIAL”
.watermark_draft() Añade la marca de agua predefinida “DRAFT”
.watermark_custom(watermark) Añade una anotación de marca de agua personalizada
.add_annotation(annotation) Añade cualquier tipo de anotación

Widgets de AcroForm

Añadidos en todos los bindings en la v0.3.38. Todas las posiciones se expresan en puntos PDF desde el origen en la esquina inferior izquierda de la página.

Método Descripción
.text_field(name, x, y, w, h, default_value=None) Entrada de texto de una sola línea
.checkbox(name, x, y, w, h, checked) Widget de casilla de verificación
.combo_box(name, x, y, w, h, options, selected=None) Selector desplegable
.radio_group(name, buttons, selected=None) Grupo de botones de opción; buttons es una lista de (export_value, x, y, w, h)
.push_button(name, x, y, w, h, caption) Botón en el que se puede hacer clic, con etiqueta
(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"))

Primitivas Gráficas

Añadidas en todos los bindings en la v0.3.38: rect(x, y, w, h) (solo contorno), filled_rect(x, y, w, h, color) (relleno con una tupla RGB) y line(x1, y1, x2, y2). Estas pasan por la misma cadena de FluentPageBuilder y son suficientes para fondos de formularios, separadores y bordes simples de tablas.

Para el control completo de trazados / patrones / degradados / ExtGState, usa ContentStreamBuilder (solo Rust — consulta Gráficos, Patrones y Sombreados).

.done() – Finalizar la Página

Devuelve el control al DocumentBuilder.

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

TextConfig

Configuración para el renderizado del texto.

use pdf_oxide::writer::TextConfig;

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

PageSize

Variante Ancho x Alto (puntos)
Letter 612 x 792
A4 595 x 842
Legal 612 x 1008
A3 842 x 1190
Custom(w, h) Dimensiones personalizadas

Ejemplos Avanzados

Documento de Varias Páginas con Anotaciones

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

Posicionamiento Preciso del Texto

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

Páginas Relacionadas