Як працювати з анотаціями PDF у C++

Як працювати з анотаціями PDF у C++

Aspose.PDF FOSS для C++ представляє кожну анотацію PDF як підклас загального базового класу Annotation і надає анотації на сторінці через AnnotationCollection, що повертається Page::Annotations(). У цьому посібнику додаються прості текстові нотатки та стилізована анотація до сторінки за допомогою TextAnnotation, документ зберігається, потім відкривається знову для читання анотацій та видалення однієї. Бібліотека інтегрована у проєкт CMake як залежність підкаталогу — крок встановлення через реєстр пакетів не потрібен.

Покроковий посібник

Крок 1: Встановити пакет

Додайте бібліотеку як підкаталог CMake та підключіть ціль статичної бібліотеки:

add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)

Перевірте, що інструментарій та крок лінкування правильно працюють у мінімальній програмі:

#include <aspose/pdf/document.hpp>
#include <iostream>

int main() {
    Aspose::Pdf::Document doc;
    std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}

Успішна збірка, яка виводить pages: 0, підтверджує, що бібліотеку підключено.


Крок 2: Імпорт необхідних класів

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/page_collection.hpp>
#include <aspose/pdf/rectangle.hpp>
#include <aspose/pdf/color.hpp>
#include <aspose/pdf/annotations/annotation.hpp>
#include <aspose/pdf/annotations/annotation_collection.hpp>
#include <aspose/pdf/annotations/annotation_type.hpp>
#include <aspose/pdf/annotations/annotation_flags.hpp>
#include <aspose/pdf/annotations/border.hpp>
#include <aspose/pdf/annotations/border_style.hpp>
#include <aspose/pdf/annotations/text_annotation.hpp>

using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Annotations;

Крок 3: Створити документ і додати сторінку

Створіть новий документ і додайте до нього сторінку. PageCollection::Add() повертає щойно доданий Page:

Document doc;
Page page = doc.Pages().Add();

Крок 4: Додати текстову анотацію до сторінки

TextAnnotation відображається як коментар у стилі липкої нотатки. Створіть його з власного Document, встановіть його позицію за допомогою Rect() і повідомлення за допомогою Contents(), потім додайте його до AnnotationCollection сторінки:

TextAnnotation note{doc};
note.Rect(Rectangle(100.0, 700.0, 200.0, 720.0, false));
note.Contents("Reviewed and approved.");

page.Annotations().Add(note);

Крок 5: Стилізувати другу анотацію за допомогою кольору, рамки та прапорців

Annotation також надає Color(), Border() та Flags(). Flags() приймає AnnotationFlags бітове поле — об’єднуйте значення за допомогою побітового OR, щоб встановити одночасно кілька прапорців:

TextAnnotation flagged{doc};
flagged.Rect(Rectangle(100.0, 600.0, 300.0, 650.0, false));
flagged.Contents("Needs follow-up");
flagged.Color(Color::FromRgb(220, 20, 20));
flagged.Flags(AnnotationFlags::Print | AnnotationFlags::ReadOnly);
flagged.Border().Width(2);
flagged.Border().Style(BorderStyle::Dashed);

page.Annotations().Add(flagged);

Крок 6: Зберегти документ

Нічого не записується на диск, доки не виконається Save():

doc.Save("annotated.pdf");

Крок 7: Відкрити PDF знову та прочитати його анотації

Відкрийте збережений файл знову і зчитайте назад AnnotationCollection першої сторінки. AnnotationCollection нумерується з нуля, а Count() повідомляє, скільки анотацій містить сторінка:

Document reopened("annotated.pdf");
auto& annots = reopened.Pages()[1].Annotations();

std::cout << "Annotation count: " << annots.Count() << "\n";

for (int i = 0; i < annots.Count(); ++i) {
    const auto& a = annots[i];
    if (a.AnnotationType() == AnnotationType::Text) {
        std::cout << "Text annotation: " << a.Contents() << "\n";
    }
}

Крок 8: Видалити анотацію та зберегти заново

AnnotationCollection::Delete(index) видаляє анотацію за її позицією, нумерація з нуля. Видаліть першу анотацію і збережіть результат у новий файл:

annots.Delete(0);
reopened.Save("annotated-cleaned.pdf");

Поширені проблеми та виправлення

Нічого не змінюється у збереженому PDF після виклику Annotations().Add()

Дві типові проблеми тут. По-перше, PageCollection — це індексація з 1 (doc.Pages()[1] — перша сторінка), тоді як AnnotationCollection — з 0 (annots[0] — перша анотація) — плутанина цих двох схем індексування призводить до роботи з неправильним об’єктом. По-друге, переконайтеся, що Document::Save() дійсно виконується після додавання анотації; до того часу нічого не записується на диск.

AnnotationCollection індексації або Delete(index) throws std::out_of_range

Допустимі індекси діапазону від 0 до Count() - 1. Передача від’ємного індексу або індексу, рівного чи більшого за Count(), за замовчуванням викликає std::out_of_range. Спочатку викличте Count(), щоб обмежити будь-який цикл або пошук.

Remove() returns false в другий раз, коли я викликаю його на тій самій анотації

Це не помилка. Remove() повідомляє, чи була анотація знайдена та видалена як bool; повторний виклик на анотації, яка вже відсутня, не робить нічого і повертає false. Перевіряйте повернене значення, а не припускайте, що Remove() завжди успішний.

Встановлення нового AnnotationFlags значення очищає прапорці, які я вже встановив

Flags(value) замінює весь набір прапорців — він не об’єднується з попереднім значенням. Щоб додати або очистити окремий прапорець, спочатку зчитайте поточні прапорці та об’єднайте їх за допомогою побітових операторів, наприклад a.Flags(a.Flags() | AnnotationFlags::Print) для додавання прапорця або a.Flags(a.Flags() & ~AnnotationFlags::Print) для очищення одного прапорця, залишаючи інші без змін.

Поширені запитання

Яке відношення між Annotation, TextAnnotation та іншими підтипами анотацій?

Annotation — це загальний базовий клас. TextAnnotation та інші конкретні типи анотацій кожен спеціалізує його для одного підтипу PDF-анотації, при цьому спільно використовують аксесори базового класу Rect(), Contents(), Color(), Flags() та Border().

Чи обмежуються анотації всім документом чи однією сторінкою?

Кожна сторінка має свій власний AnnotationCollection, який повертається методом Annotations() цієї сторінки. Анотації завжди обмежені сторінкою, до якої вони були додані, а не всім документом.

Як підрахувати кількість анотацій на сторінці?

Викличте Count() на AnnotationCollection, який повертає Page::Annotations().

Чи може анотація бути одночасно друкованою і лише для читання?

Так. AnnotationFlags — це бітове поле, тому значення комбінуйте за допомогою побітового OR, наприклад AnnotationFlags::Print | AnnotationFlags::ReadOnly.

Чи видалення анотації з AnnotationCollection видаляє її з PDF-файлу на диску?

Лише після виконання Document::Save(). Delete(), Remove() та Clear() лише змінюють колекцію в оперативній пам’яті — PDF на диску залишається незмінним, доки документ не буде збережений.

Дивіться також

 Українська