Crear anotaciones
PDF Oxide admite la creación de todos los tipos estándar de anotación PDF. Las anotaciones se añaden a través de FluentPageBuilder (API de DocumentBuilder) o PageBuilder (API de PdfWriter).
Cobertura por binding (v0.3.38). Los 15 métodos de anotación de
DocumentBuilder/FluentPageBuilder—link_url/link_page/link_named,highlight,underline,strikeout,squiggly, nota adhesiva, sello (14 estándar + personalizado), texto libre y marca de agua (custom / DRAFT / CONFIDENTIAL) — están disponibles en Rust, Python, Node/TypeScript, C#, Go y WASM. La superficie de bajo nivel dePdfWritercon formas por método (ink,polygon,polyline,caret,popup, adjuntos,redact) sigue siendo solo Rust; desde otros bindings usaDocumentBuildero edita PDFs existentes vía Edición de anotaciones.
Ejemplo rápido
Rust (DocumentBuilder)
use pdf_oxide::writer::{DocumentBuilder, PageSize, StampType};
let mut builder = DocumentBuilder::new();
builder.page(PageSize::Letter)
.at(72.0, 720.0)
.text("Click here for details")
.link_url("https://example.com")
.text("Important finding")
.highlight((1.0, 1.0, 0.0)) // Yellow highlight
.sticky_note("Review this section carefully")
.stamp(StampType::Approved)
.done();
builder.save("annotated.pdf")?;
Rust (PdfWriter)
use pdf_oxide::writer::PdfWriter;
use pdf_oxide::geometry::Rect;
let mut writer = PdfWriter::new();
{
let mut page = writer.add_letter_page();
page.add_text("Document text", 72.0, 720.0, "Helvetica", 12.0);
page.link(Rect::new(72.0, 720.0, 100.0, 12.0), "https://example.com");
page.highlight_rect(Rect::new(72.0, 700.0, 200.0, 12.0));
page.sticky_note(Rect::new(300.0, 720.0, 24.0, 24.0), "A note");
page.finish();
}
writer.save("annotated.pdf")?;
Python
from pdf_oxide import DocumentBuilder, StampType
pdf = (DocumentBuilder()
.letter_page()
.at(72, 720).text("Click here for details")
.link_url("https://example.com")
.text("Important finding")
.highlight((1.0, 1.0, 0.0))
.sticky_note("Review this section carefully")
.stamp(StampType.APPROVED)
.done()
.save("annotated.pdf"))
Node / TypeScript
import { DocumentBuilder, StampType } from "pdf-oxide";
await new DocumentBuilder()
.letterPage()
.at(72, 720).text("Click here for details")
.linkUrl("https://example.com")
.text("Important finding")
.highlight([1.0, 1.0, 0.0])
.stickyNote("Review this section carefully")
.stamp(StampType.Approved)
.done()
.save("annotated.pdf");
C#
using PdfOxide;
DocumentBuilder.Create()
.LetterPage()
.At(72, 720).Text("Click here for details")
.LinkUrl("https://example.com")
.Text("Important finding")
.Highlight(1.0, 1.0, 0.0)
.StickyNote("Review this section carefully")
.Stamp(StampType.Approved)
.Done()
.Save("annotated.pdf");
Go
builder := pdfoxide.NewDocumentBuilder()
builder.LetterPage().
At(72, 720).Text("Click here for details").
LinkUrl("https://example.com").
Text("Important finding").
Highlight(1.0, 1.0, 0.0).
StickyNote("Review this section carefully").
Stamp(pdfoxide.StampApproved).
Done()
_ = builder.Save("annotated.pdf")
JavaScript (WASM) — atajos para PDFs existentes
Los helpers clásicos addLink / addHighlight / addNote siguen funcionando para editar PDFs ya creados:
import init, { WasmPdfDocument } from "pdf-oxide-wasm/web";
await init();
const doc = new WasmPdfDocument(bytes);
doc.addLink(0, 100, 200, 300, 50, "https://oxide.fyi");
doc.addHighlight(0, 100, 700, 400, 20);
doc.addNote(0, 50, 750, "Review this section");
const saved = doc.save();
doc.free();
Para anotaciones en tiempo de creación desde WASM, usa DocumentBuilder (misma API que el ejemplo de Node/TS anterior).
Tipos de anotaciones
Anotaciones de texto (notas adhesivas)
Notas emergentes con varios íconos.
use pdf_oxide::writer::PdfWriter;
use pdf_oxide::annotation_types::TextAnnotationIcon;
use pdf_oxide::geometry::Rect;
let mut writer = PdfWriter::new();
{
let mut page = writer.add_letter_page();
// Default note icon
page.sticky_note(Rect::new(72.0, 720.0, 24.0, 24.0), "Review this section");
// Comment icon
page.comment(Rect::new(72.0, 690.0, 24.0, 24.0), "Needs clarification");
// Custom icon
page.text_note_with_icon(
Rect::new(72.0, 660.0, 24.0, 24.0),
"Important",
TextAnnotationIcon::Key,
);
page.finish();
}
Íconos disponibles: Note, Comment, Key, Help, NewParagraph, Paragraph, Insert
Equivalente de FluentPageBuilder:
builder.page(PageSize::Letter)
.at(72.0, 720.0)
.sticky_note("Review this")
.sticky_note_with_icon("Important", TextAnnotationIcon::Key)
.sticky_note_at(300.0, 720.0, "Positioned note")
.done();
Anotaciones de enlace
Enlaces URL y navegación interna de páginas.
// URL link
page.link(Rect::new(72.0, 720.0, 150.0, 12.0), "https://example.com");
// Internal page link (0-indexed page number)
page.internal_link(Rect::new(72.0, 700.0, 100.0, 12.0), 2);
FluentPageBuilder:
builder.page(PageSize::Letter)
.at(72.0, 720.0)
.text("Visit website")
.link_url("https://example.com")
.text("Go to appendix")
.link_page(5)
.text("Jump to glossary")
.link_named("glossary")
.done();
Anotaciones FreeText
Texto mostrado directamente en la superficie de la página.
use pdf_oxide::geometry::Rect;
// Basic text box
page.textbox(Rect::new(72.0, 650.0, 200.0, 50.0), "Annotation text");
// Styled text box
page.textbox_styled(
Rect::new(72.0, 580.0, 200.0, 50.0),
"Styled text",
"Courier",
14.0,
);
// Centered text
page.textbox_centered(Rect::new(72.0, 520.0, 200.0, 30.0), "Centered");
// Callout with leader line
page.callout(
Rect::new(200.0, 450.0, 150.0, 50.0),
"Callout text",
vec![150.0, 430.0, 200.0, 475.0],
);
// Typewriter (borderless text)
page.typewriter(Rect::new(72.0, 400.0, 300.0, 20.0), "Typewriter text");
FluentPageBuilder:
builder.page(PageSize::Letter)
.freetext(Rect::new(100.0, 600.0, 200.0, 50.0), "Comment text")
.freetext_styled(Rect::new(100.0, 530.0, 200.0, 50.0), "Styled", "Courier", 14.0)
.done();
Resaltado, subrayado, tachado, ondulado
Anotaciones de marcado de texto para revisión.
use pdf_oxide::geometry::Rect;
page.highlight_rect(Rect::new(72.0, 720.0, 200.0, 12.0));
page.underline_rect(Rect::new(72.0, 700.0, 200.0, 12.0));
page.strikeout_rect(Rect::new(72.0, 680.0, 200.0, 12.0));
page.squiggly_rect(Rect::new(72.0, 660.0, 200.0, 12.0));
Con QuadPoints explícitos para posicionamiento preciso:
page.highlight(
Rect::new(72.0, 720.0, 200.0, 12.0),
vec![[72.0, 732.0, 272.0, 732.0, 72.0, 720.0, 272.0, 720.0]],
);
FluentPageBuilder (color is RGB 0.0-1.0):
builder.page(PageSize::Letter)
.at(72.0, 720.0)
.text("Highlighted text")
.highlight((1.0, 1.0, 0.0)) // Yellow
.text("Underlined text")
.underline((0.0, 0.0, 1.0)) // Blue
.text("Deleted text")
.strikeout((1.0, 0.0, 0.0)) // Red
.text("Questionable text")
.squiggly((1.0, 0.5, 0.0)) // Orange
.done();
Anotaciones de línea
Líneas y flechas entre dos puntos.
// Simple line
page.line((100.0, 500.0), (300.0, 500.0));
// Arrow
page.arrow((100.0, 470.0), (300.0, 470.0));
// Double-headed arrow
page.double_arrow((100.0, 440.0), (300.0, 440.0));
Anotaciones de forma (cuadrado, círculo)
Rectángulos y elipses.
use pdf_oxide::geometry::Rect;
// Rectangle outline
page.rectangle(Rect::new(72.0, 400.0, 150.0, 80.0));
// Filled rectangle
page.rectangle_filled(
Rect::new(250.0, 400.0, 150.0, 80.0),
(0.0, 0.0, 1.0), // Blue stroke
(0.8, 0.8, 1.0), // Light blue fill
);
// Circle outline
page.circle(Rect::new(72.0, 300.0, 80.0, 80.0));
// Filled circle
page.circle_filled(
Rect::new(180.0, 300.0, 80.0, 80.0),
(1.0, 0.0, 0.0), // Red stroke
(1.0, 0.9, 0.9), // Light red fill
);
Anotaciones de polígono y polilínea
Polígonos cerrados y polilíneas abiertas.
// Closed triangle
page.polygon(vec![(200.0, 250.0), (250.0, 300.0), (150.0, 300.0)]);
// Filled polygon
page.polygon_filled(
vec![(300.0, 250.0), (350.0, 300.0), (250.0, 300.0)],
(0.0, 0.5, 0.0), // Green stroke
(0.8, 1.0, 0.8), // Light green fill
);
// Open polyline (zigzag)
page.polyline(vec![
(72.0, 200.0), (150.0, 230.0), (220.0, 200.0), (300.0, 230.0),
]);
Anotaciones de tinta (dibujo a mano alzada)
Trazos y dibujos a mano alzada.
// Single stroke
page.ink(vec![(100.0, 150.0), (120.0, 170.0), (140.0, 150.0), (160.0, 170.0)]);
// Multiple strokes
page.freehand(vec![
vec![(100.0, 100.0), (200.0, 100.0)], // Horizontal line
vec![(150.0, 50.0), (150.0, 150.0)], // Vertical line
]);
// Styled ink
page.ink_styled(
vec![(200.0, 150.0), (250.0, 180.0), (300.0, 150.0)],
(1.0, 0.0, 0.0), // Red
3.0, // 3pt line width
);
Anotaciones de sello
Anotaciones de sello de goma estándar.
use pdf_oxide::writer::StampType;
use pdf_oxide::geometry::Rect;
page.stamp(Rect::new(400.0, 700.0, 150.0, 50.0), StampType::Approved);
page.stamp_approved(Rect::new(400.0, 640.0, 150.0, 50.0));
page.stamp_draft(Rect::new(400.0, 580.0, 120.0, 40.0));
page.stamp_confidential(Rect::new(400.0, 520.0, 150.0, 50.0));
page.stamp_final(Rect::new(400.0, 460.0, 100.0, 40.0));
page.stamp_not_approved(Rect::new(400.0, 400.0, 150.0, 50.0));
page.stamp_for_comment(Rect::new(400.0, 340.0, 150.0, 50.0));
page.stamp_custom(Rect::new(400.0, 280.0, 150.0, 50.0), "ReviewPending");
StampType variants: Approved, Experimental, NotApproved, AsIs, Expired, NotForPublicRelease, Confidential, Final, Sold, Departmental, ForComment, TopSecret, Draft, ForPublicRelease, Custom(String)
Anotaciones de marca de agua
Marcas de agua a nivel de página que aparecen detrás del contenido.
// FluentPageBuilder API
builder.page(PageSize::Letter)
.watermark("DRAFT")
.done();
builder.page(PageSize::Letter)
.watermark_confidential()
.done();
builder.page(PageSize::Letter)
.watermark_draft()
.done();
Anotaciones de redacción
Marcar regiones para redacción.
use pdf_oxide::geometry::Rect;
page.redact(Rect::new(72.0, 600.0, 200.0, 20.0));
page.redact_with_text(Rect::new(72.0, 570.0, 200.0, 20.0), "REDACTED");
Tipos de anotaciones adicionales
use pdf_oxide::geometry::Rect;
// Popup window
page.popup(Rect::new(200.0, 500.0, 200.0, 100.0), true);
// Caret (text insertion marker)
page.caret(Rect::new(72.0, 450.0, 20.0, 20.0));
page.caret_paragraph(Rect::new(72.0, 420.0, 20.0, 20.0));
page.caret_with_comment(Rect::new(72.0, 390.0, 20.0, 20.0), "Insert paragraph here");
// File attachment
page.file_attachment(Rect::new(72.0, 350.0, 24.0, 24.0), "report.xlsx");
page.file_attachment_paperclip(Rect::new(72.0, 320.0, 24.0, 24.0), "notes.txt");
Método genérico de anotación
Agregue cualquier tipo de anotación usando el método genérico add_annotation():
use pdf_oxide::writer::{LinkAnnotation, Annotation};
use pdf_oxide::geometry::Rect;
let link = LinkAnnotation::uri(
Rect::new(72.0, 720.0, 100.0, 12.0),
"https://example.com",
);
page.add_annotation(link);
Ejemplo avanzado
Demostración completa de anotaciones
use pdf_oxide::writer::{PdfWriter, StampType};
use pdf_oxide::geometry::Rect;
let mut writer = PdfWriter::new();
{
let mut page = writer.add_letter_page();
// Links
page.add_text("Visit Rust", 72.0, 750.0, "Helvetica", 12.0);
page.link(Rect::new(72.0, 750.0, 70.0, 12.0), "https://rust-lang.org");
// Text markup
page.highlight_rect(Rect::new(72.0, 720.0, 150.0, 12.0));
page.underline_rect(Rect::new(72.0, 700.0, 150.0, 12.0));
page.strikeout_rect(Rect::new(72.0, 680.0, 150.0, 12.0));
page.squiggly_rect(Rect::new(72.0, 660.0, 150.0, 12.0));
// Notes
page.sticky_note(Rect::new(300.0, 720.0, 24.0, 24.0), "Important");
page.comment(Rect::new(340.0, 720.0, 24.0, 24.0), "Review needed");
// Shapes
page.line((72.0, 620.0), (250.0, 620.0));
page.arrow((72.0, 600.0), (250.0, 600.0));
page.rectangle(Rect::new(72.0, 540.0, 100.0, 50.0));
page.circle(Rect::new(200.0, 540.0, 50.0, 50.0));
// Ink
page.ink(vec![(72.0, 500.0), (120.0, 520.0), (170.0, 500.0)]);
// Stamp
page.stamp_approved(Rect::new(400.0, 720.0, 150.0, 50.0));
// Redact
page.redact(Rect::new(72.0, 450.0, 200.0, 15.0));
page.finish();
}
writer.save("annotation_showcase.pdf")?;
Páginas relacionadas
- API de bajo nivel DocumentBuilder – Construcción fluida de páginas con anotaciones
- Creación de campos de formulario – Campos de formulario interactivos
- Gráficos, patrones y sombreados – Primitivas de dibujo de bajo nivel