Введение
PDF-аннотации охватывают широкий спектр интерактивных и визуальных элементов, наложенных поверх содержимого страницы: липкие текстовые заметки, гиперссылки, выделенный или зачернённый текст, геометрические фигуры, штрихи чернилами, вложения файлов и штампы одобрения. Aspose.PDF FOSS для C++ представляет каждый из них как конкретный подкласс Annotation, поэтому код, проходящий по аннотациям страницы, может работать обобщённо с базовым классом, но при этом иметь доступ к членам, специфичным для подтипа — например Icon() у TextAnnotation или Action() у LinkAnnotation — при необходимости.
Перечисление Annotations::AnnotationType в библиотеке перечисляет подтипы, которые она распознаёт: Text, Link, FreeText, Line, Square, Circle, Polygon, PolyLine, Highlight, Underline, Squiggly, StrikeOut, Stamp, Caret, Ink, Popup, FileAttachment, Sound, Movie, Widget, Screen, PrinterMark, Watermark, Redaction, RichMedia и несколько других. Каждое значение сопоставляется с конкретным классом — CircleAnnotation, SquareAnnotation, PolygonAnnotation, PolylineAnnotation и LineAnnotation для разметки фигур; FreeTextAnnotation и InkAnnotation для свободного текста и нарисованных штрихов; FileAttachmentAnnotation, SoundAnnotation, MovieAnnotation, ScreenAnnotation и RichMediaAnnotation для встроенного контента; а WidgetAnnotation — для отображения полей AcroForm.
В этой статье рассматриваются базовые API Annotation и AnnotationCollection, добавление текстовых заметок и ссылок, определение типов аннотаций при загрузке существующего документа, а также чтение и обновление метаданных разметки и штампов. Aspose.PDF FOSS для C++ — это библиотека C++20 без зависимостей во время выполнения, кроме стандартной библиотеки; заголовочные файлы включаются напрямую из каталога aspose/pdf/annotations/, а библиотека собирается как цель CMake.
Что включено
Annotation и AnnotationCollection
Annotation — базовый класс для каждого подптипа аннотации. Он предоставляет общие свойства: Rect() / Rect(value) — ограничивающий прямоугольник аннотации, Contents() — связанный текст, Name(), Color(), Flags() (битовая маска AnnotationFlags — Print, Hidden, Invisible, NoZoom, ReadOnly и другие), Border(), Width() / Height(), AnnotationType() и PageIndex(). AnnotationCollection хранит аннотации на одной странице и доступна через Page.Annotations().
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/annotation_collection.hpp>
#include <iostream>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Annotations;
Document doc("reviewed.pdf");
AnnotationCollection& annots = doc.Pages()[1].Annotations();
std::cout << "Annotation count: " << annots.Count() << "\n";
for (int i = 0; i < annots.Count(); ++i) {
Annotation& a = annots[i];
std::cout << " " << a.Name() << ": " << a.Contents() << "\n";
}
AnnotationCollection также предоставляет методы Add(annotation), Add(annotation, considerRotation), Delete(index), Delete(annotation), Clear(), Remove(annotation), Contains(annotation) и IsReadOnly().
Текстовые заметки с TextAnnotation
TextAnnotation представляет знакомый комментарий-липкая заметка. Помимо базовых членов Annotation, он добавляет Open() / Open(value) для управления тем, будет ли заметка отображаться раскрытой, и Icon() / Icon(value) (значение TextIcon, например Note, Comment, Key, Help или Check) для выбора значка.
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/text_annotation.hpp>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Annotations;
Document doc("input.pdf");
TextAnnotation note{doc};
note.Rect(Rectangle{100.0, 700.0, 200.0, 720.0, false});
note.Contents("Reviewed by QA");
note.Icon(TextIcon::Comment);
note.Open(true);
doc.Pages()[1].Annotations().Add(note);
doc.Save("annotated.pdf");
Ссылки и действия с LinkAnnotation
LinkAnnotation прикрепляет кликабельный регион к странице. Он создаётся из принадлежащей Page и Rectangle, а его поведение задаётся с помощью Action(value) — любого подкласса PdfAction, включая NamedAction (предопределённая навигация, например PredefinedAction::LastPage), GoToAction, GoToURIAction или JavascriptAction. Destination() читает цель ссылки IAppointment, а Highlighting() / Highlighting(value) задаёт HighlightingMode (None, Invert, Outline, Push, Toggle), применяемый при активации ссылки.
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/link_annotation.hpp>
#include <aspose/pdf/annotations/named_action.hpp>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Annotations;
Document doc;
Page page = doc.Pages().Add();
LinkAnnotation link{page, Rectangle{0.0, 0.0, 100.0, 20.0, false}};
link.Action(NamedAction{PredefinedAction::LastPage});
link.Highlighting(HighlightingMode::Push);
page.Annotations().Add(link);
Определение типов аннотаций при загрузке
При открытии документа существующие аннотации уже заполнены в AnnotationCollection каждой страницы, а AnnotationType() определяет, какой конкретный подтип представляет каждая запись. Это позволяет вызывающему коду ветвиться по значению перечисления, не зная заранее, какие типы аннотаций содержатся в данном PDF.
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/annotation_type.hpp>
#include <iostream>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Annotations;
Document doc("mixed-annotations.pdf");
auto& annots = doc.Pages()[1].Annotations();
for (int i = 0; i < annots.Count(); ++i) {
switch (annots[i].AnnotationType()) {
case AnnotationType::Text: std::cout << "Text note\n"; break;
case AnnotationType::Link: std::cout << "Link\n"; break;
case AnnotationType::Circle: std::cout << "Circle shape\n"; break;
case AnnotationType::Square: std::cout << "Square shape\n"; break;
case AnnotationType::Highlight: std::cout << "Highlight\n"; break;
case AnnotationType::Stamp: std::cout << "Stamp\n"; break;
default: break;
}
}
Метаданные разметки аннотаций
MarkupAnnotation является базой для аннотаций, содержащих метаданные рецензента: Title() (автор), Subject(), RichText() для форматированного текста комментария и Opacity() для наложения на содержимое страницы. InReplyTo() и Popup() связывают разметочную аннотацию с веткой комментариев, к которой она относится, а ClearState() / SetReviewState(state, userName) управляют её статусом рецензирования. HighlightAnnotation, UnderlineAnnotation, StrikeOutAnnotation и SquigglyAnnotation — подтипы разметки, располагающиеся над текстом; их общий базовый класс TextMarkupAnnotation добавляет QuadPoints() для определения покрываемых четырехугольных областей и GetMarkedText() для получения текста под ними.
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/markup_annotation.hpp>
using namespace Aspose::Pdf::Annotations;
for (int i = 0; i < annots.Count(); ++i) {
if (auto* markup = dynamic_cast<MarkupAnnotation*>(&annots[i])) {
markup->Title("QA Reviewer");
markup->Subject("Layout issue");
markup->Opacity(0.6);
}
}
Аннотации-штампы с помощью StampAnnotation
StampAnnotation размещает предопределённую или пользовательскую печать на странице. Icon() / Icon(value) выбирает значение StampIcon — Approved, Draft, Confidential, Final, Expired, NotApproved, ForComment, TopSecret и другие — а Image() / Image(value) предоставляет необработанные байты изображения для пользовательского вида печати вместо встроенного значка.
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/stamp_annotation.hpp>
using namespace Aspose::Pdf::Annotations;
for (int i = 0; i < annots.Count(); ++i) {
if (auto* stamp = dynamic_cast<StampAnnotation*>(&annots[i])) {
stamp->Icon(StampIcon::Approved);
}
}
Быстрый старт
Добавьте библиотеку как подкаталог CMake и выполните привязку к цели aspose_pdf_foss:
add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)
Откройте документ, добавьте текстовое примечание и прочитайте количество аннотаций:
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/text_annotation.hpp>
#include <iostream>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Annotations;
int main() {
Document doc("input.pdf");
TextAnnotation note{doc};
note.Rect(Rectangle{100.0, 700.0, 200.0, 720.0, false});
note.Contents("Reviewed by QA");
note.Icon(TextIcon::Comment);
doc.Pages()[1].Annotations().Add(note);
doc.Save("annotated.pdf");
std::cout << "Annotations on page 1: "
<< doc.Pages()[1].Annotations().Count() << "\n";
}
Поддерживаемые форматы
| Формат | Расширение | Чтение | Записать |
|---|---|---|---|
| BMP | .bmp | — | ✓ |
| JPEG | .jpg | — | ✓ |
| TIFF | .tiff | — | ✓ |
| Text | .txt | — | ✓ |
| SVG | .svg | ✓ | — |
Поддержка форматов применяется к рендерингу страниц и параметрам загрузки на уровне документа; эти записи отражают подтверждённые пути экспорта (BmpDevice, JpegDevice, TiffDevice, TextDevice) и импорта (SvgLoadOptions), а не сериализацию, специфичную для аннотаций.
Открытый исходный код и лицензирование
Aspose.PDF FOSS для C++ выпускается под лицензией MIT. Исходный код доступен по адресу https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-Cpp, и библиотеку можно использовать в коммерческих и open-source проектах без лицензионных сборов.