Como trabalhar com anotações PDF em C++

Como trabalhar com anotações PDF em C++

Aspose.PDF FOSS para C++ representa cada anotação PDF como uma subclasse da classe base comum Annotation, e expõe as anotações em uma página através do AnnotationCollection retornado por Page::Annotations(). Este guia adiciona uma anotação de nota de texto simples e uma anotação estilizada a uma página com TextAnnotation, salva o documento e, em seguida, reabre-o para ler as anotações de volta e remover uma. A biblioteca está integrada a um projeto CMake como dependência de subdiretório — não há etapa de instalação via registro de pacotes.

Guia passo a passo

Passo 1: Instalar o pacote

Adicione a biblioteca como um subdiretório CMake e vincule o alvo da biblioteca estática:

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

Verifique se a cadeia de ferramentas e a etapa de linkagem são resolvidas corretamente com um programa mínimo:

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

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

Uma compilação bem-sucedida que imprime pages: 0 confirma que a biblioteca está vinculada.


Etapa 2: Importar classes necessárias

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

Etapa 3: Criar um documento e adicionar uma página

Crie um novo documento e adicione uma página a ele. PageCollection::Add() retorna o Page recém-adicionado:

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

Etapa 4: Adicionar uma anotação de texto à página

TextAnnotation é renderizado como um comentário no estilo de nota adesiva. Construa-o a partir do Document proprietário, defina sua posição com Rect() e sua mensagem com Contents(), então adicione-o ao AnnotationCollection da página:

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

page.Annotations().Add(note);

Etapa 5: Estilizar uma segunda anotação com cor, borda e flags

Annotation também expõe Color(), Border() e Flags(). Flags() aceita um campo de bits AnnotationFlags — combine valores com OR bit a bit para definir mais de um flag ao mesmo tempo:

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

Etapa 6: Salvar o documento

Nada é gravado no disco até que Save() seja executado:

doc.Save("annotated.pdf");

Etapa 7: Reabrir o PDF e Ler suas Anotações

Reabra o arquivo salvo e leia novamente o AnnotationCollection da primeira página. AnnotationCollection é baseado em zero, e Count() informa quantas anotações a página contém:

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

Etapa 8: Remover uma Anotação e Regravar

AnnotationCollection::Delete(index) remove uma anotação pela sua posição baseada em zero. Exclua a primeira anotação e salve o resultado em um novo arquivo:

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

Problemas Comuns e Soluções

Nada muda no PDF salvo após chamar Annotations().Add()

Duas coisas costumam dar errado aqui. Primeiro, PageCollection é baseado em 1 (doc.Pages()[1] é a primeira página) enquanto AnnotationCollection é baseado em 0 (annots[0] é a primeira anotação) — confundir os dois esquemas de indexação leva a operar no objeto errado. Segundo, confirme se Document::Save() realmente executa após a anotação ser adicionada; nada é gravado no disco até então.

AnnotationCollection indexação ou Delete(index) throws std::out_of_range

Índices válidos vão de 0 a Count() - 1. Passar um índice negativo ou um índice igual ou maior que Count() lança std::out_of_range por design. Chame Count() primeiro para limitar qualquer loop ou busca.

Remove() returns false na segunda vez que a chamo na mesma anotação

Isso não é um erro. Remove() indica se a anotação foi encontrada e removida como um bool; chamá-lo novamente em uma anotação que já foi removida é uma operação nula que retorna false. Verifique o valor de retorno em vez de assumir que Remove() sempre tem sucesso.

Definindo um novo AnnotationFlags valor limpa as flags que eu já havia definido

Flags(value) substitui todo o conjunto de flags — não mescla com o valor anterior. Para adicionar ou limpar uma única flag, leia primeiro as flags atuais e combine-as com operadores bit a bit, por exemplo a.Flags(a.Flags() | AnnotationFlags::Print) para adicionar uma flag, ou a.Flags(a.Flags() & ~AnnotationFlags::Print) para limpar uma flag enquanto deixa as demais intactas.

Perguntas Frequentes

Qual é a relação entre Annotation, TextAnnotation e os outros subtipos de anotação?

Annotation é a classe base comum. TextAnnotation e os outros tipos concretos de anotação especializam-na para um subtipo de anotação PDF, ao mesmo tempo em que compartilham os acessores Rect(), Contents(), Color(), Flags() e Border() da classe base.

As anotações têm escopo para todo o documento ou para uma única página?

Cada página tem seu próprio AnnotationCollection, retornado pelo método Annotations() dessa página. As anotações sempre têm escopo na página em que foram adicionadas, não no documento como um todo.

Como contar quantas anotações existem em uma página?

Chame Count() no AnnotationCollection retornado por Page::Annotations().

Uma anotação pode ser tanto imprimível quanto somente leitura ao mesmo tempo?

Sim. AnnotationFlags é um campo de bits, portanto combine valores com OR bit a bit, por exemplo AnnotationFlags::Print | AnnotationFlags::ReadOnly.

Excluir uma anotação de AnnotationCollection a remove do arquivo PDF no disco?

Só depois que Document::Save() for executado. Delete(), Remove() e Clear() apenas modificam a coleção em memória — o PDF no disco permanece inalterado até que o documento seja salvo.

Ver também

 Português