Skip to content

Создание аннотаций

PDF Oxide поддерживает создание всех стандартных типов аннотаций PDF. Аннотации можно добавлять через FluentPageBuilder (API DocumentBuilder) или PageBuilder (API PdfWriter).

Поддержка биндингов (v0.3.38). 15 методов аннотаций на DocumentBuilder / FluentPageBuilderlink_url / link_page / link_named, highlight, underline, strikeout, squiggly, стикеры, штампы (14 стандартных + произвольные), freetext и водяные знаки (custom / DRAFT / CONFIDENTIAL) — доступны в Rust, Python, Node/TypeScript, C#, Go и WASM. Низкоуровневый PdfWriter с отдельными методами для каждой фигуры (ink, polygon, polyline, caret, popup, file-attachment, redact) остаётся только в Rust; в остальных биндингах используйте DocumentBuilder либо правьте готовые PDF через Редактирование аннотаций.

Быстрый пример

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) — шорткаты для правки существующих PDF

Старые помощники addLink / addHighlight / addNote продолжают работать при редактировании уже готовых PDF:

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

Чтобы создавать аннотации сразу при генерации PDF из WASM, используйте DocumentBuilder (API совпадает с примером Node/TS выше).

Типы аннотаций

Текстовые аннотации (стикеры)

Всплывающие заметки с различными иконками.

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();
}

Доступные иконки: Note, Comment, Key, Help, NewParagraph, Paragraph, Insert

FluentPageBuilder equivalent:

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

Аннотации-ссылки

URL-ссылки и внутренняя навигация по страницам.

// 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();

Аннотации свободного текста

Текст, отображаемый непосредственно на поверхности страницы.

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

Выделение, подчёркивание, зачёркивание, волнистое подчёркивание

Текстовые аннотации разметки для рецензирования.

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

С явным указанием QuadPoints для точного позиционирования:

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

Аннотации-линии

Линии и стрелки между двумя точками.

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

Аннотации-фигуры (прямоугольник, круг)

Прямоугольники и эллипсы.

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

Аннотации-полигоны и полилинии

Замкнутые полигоны и незамкнутые полилинии.

// 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),
]);

Рукописные аннотации (рисование от руки)

Свободные штрихи и рисунки.

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

Аннотации-штампы

Стандартные аннотации резиновых штампов.

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)

Аннотации-водяные знаки

Водяные знаки на уровне страницы, отображаемые за содержимым.

// FluentPageBuilder API
builder.page(PageSize::Letter)
    .watermark("DRAFT")
    .done();

builder.page(PageSize::Letter)
    .watermark_confidential()
    .done();

builder.page(PageSize::Letter)
    .watermark_draft()
    .done();

Аннотации замазывания

Пометить области для замазывания.

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

Дополнительные типы аннотаций

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

Универсальный метод аннотаций

Добавить аннотацию любого типа с помощью общего метода 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);

Продвинутый пример

Полная демонстрация аннотаций

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

Связанные страницы