Introduction

PDF annotations cover a wide range of interactive and visual elements layered on top of page content: sticky text notes, hyperlinks, highlighted or struck-through text, geometric shapes, ink strokes, file attachments, and approval stamps. Aspose.PDF FOSS for C++ represents every one of these as a concrete subclass of Annotation, so code that walks a page’s annotations can work generically against the base class while still reaching subtype-specific members — such as Icon() on a TextAnnotation or Action() on a LinkAnnotation — when needed.

The library’s Annotations::AnnotationType enum enumerates the subtypes it recognizes: 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, and several others. Each value maps to a concrete class — CircleAnnotation, SquareAnnotation, PolygonAnnotation, PolylineAnnotation, and LineAnnotation for shape markup; FreeTextAnnotation and InkAnnotation for free-form text and drawn strokes; FileAttachmentAnnotation, SoundAnnotation, MovieAnnotation, ScreenAnnotation, and RichMediaAnnotation for embedded content; and WidgetAnnotation for AcroForm field appearances.

This post covers the Annotation and AnnotationCollection base API, adding text notes and links, detecting annotation types when loading an existing document, and reading or updating markup metadata and stamps. Aspose.PDF FOSS for C++ is a C++20 library with no runtime dependencies beyond the standard library; headers are included directly from the aspose/pdf/annotations/ directory and the library builds as a CMake target.


What’s Included

Annotation and AnnotationCollection

Annotation is the base class for every annotation subtype. It exposes shared properties: Rect() / Rect(value) for the annotation’s bounding rectangle, Contents() for the associated text, Name(), Color(), Flags() (an AnnotationFlags bitmask — Print, Hidden, Invisible, NoZoom, ReadOnly, and others), Border(), Width() / Height(), AnnotationType(), and PageIndex(). AnnotationCollection holds the annotations on a single page and is reached through 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 also exposes Add(annotation), Add(annotation, considerRotation), Delete(index), Delete(annotation), Clear(), Remove(annotation), Contains(annotation), and IsReadOnly().

Text Notes with TextAnnotation

TextAnnotation represents the familiar sticky-note comment. Beyond the base Annotation members, it adds Open() / Open(value) to control whether the note appears expanded, and Icon() / Icon(value) (a TextIcon value such as Note, Comment, Key, Help, or Check) to choose the icon glyph.

#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 attaches a clickable region to a page. It is constructed from the owning Page and a Rectangle, and its behavior is set with Action(value) — any PdfAction subclass, including NamedAction (predefined navigation such as PredefinedAction::LastPage), GoToAction, GoToURIAction, or JavascriptAction. Destination() reads the link’s IAppointment target, and Highlighting() / Highlighting(value) sets the HighlightingMode (None, Invert, Outline, Push, Toggle) applied when the link is activated.

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

Detecting Annotation Types on Load

When a document is opened, existing annotations are already populated in each page’s AnnotationCollection, and AnnotationType() identifies which concrete subtype each entry represents. This lets calling code branch on the enum value without knowing in advance which annotation types a given PDF contains.

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

Markup Annotation Metadata

MarkupAnnotation is the base for annotations that carry reviewer metadata: Title() (the author), Subject(), RichText() for formatted comment text, and Opacity() for blending against page content. InReplyTo() and Popup() connect a markup annotation to the comment thread it belongs to, and ClearState() / SetReviewState(state, userName) manage its review status. HighlightAnnotation, UnderlineAnnotation, StrikeOutAnnotation, and SquigglyAnnotation are markup subtypes positioned over text; their shared TextMarkupAnnotation base adds QuadPoints() to define the quadrilateral regions covered and GetMarkedText() to read back the text underneath.

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

Stamp Annotations with StampAnnotation

StampAnnotation places a predefined or custom stamp on a page. Icon() / Icon(value) selects a StampIcon value — Approved, Draft, Confidential, Final, Expired, NotApproved, ForComment, TopSecret, and others — and Image() / Image(value) supplies raw image bytes for a custom stamp appearance instead of a built-in icon.

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

Quick Start

Add the library as a CMake subdirectory and link against the aspose_pdf_foss target:

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

Open a document, add a text note, and read the annotation count back:

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

Supported Formats

FormatExtensionReadWrite
BMP.bmp
JPEG.jpg
TIFF.tiff
Text.txt
SVG.svg

Format support applies to page rendering and load options at the document level; these entries reflect confirmed export (BmpDevice, JpegDevice, TiffDevice, TextDevice) and import (SvgLoadOptions) paths rather than annotation-specific serialization.


Open Source & Licensing

Aspose.PDF FOSS for C++ is released under the MIT license. Source code is available at https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-Cpp, and the library can be used in commercial and open-source projects without licensing fees.


Getting Started