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+EmbeddedFontestá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
- API Fluida de PdfBuilder – Creación de alto nivel con PdfBuilder
- Creación de Anotaciones – Todos los tipos de anotación en detalle
- Creación de Campos de Formulario – Añadir campos de formulario interactivos
- Renderizado de Tablas – Crear tablas