Skip to main content

Annotations in PDF Documents

  • 12 minutes to read

The PDF Document API supports the following annotation types:

Link Annotations
A hypertext link to a URI or a destination (a reference to a page with specific view parameters).
Markup Annotations

Annotations used to mark up document content. The following markups are available:

  • Text Markup (text highlight, underline, strikeout)
  • Sticky Note
  • Caret
  • Rubber Stamp
  • Shape (circle, square)
  • File Attachment
  • Free Text (text box, callout, typewriter)
  • Ink
  • Path (line, polyline, polygon)

You can create and delete annotations, edit their content, flatten, add related comments and reviews.

The PdfPageFacade.Annotations property retrieves all page annotation properties. Use the PdfDocumentFacade.Pages property to access the PdfPageFacade class.

Create Annotations

Call the PdfPageFacade.AddLinkAnnotation method to create a link annotation.

The code sample below creates an annotation linked to a URI string:

uri link

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a document
    processor.LoadDocument("..\\..\\Document.pdf");

    // Access the first page properties
    PdfPageFacade page = processor.DocumentFacade.Pages[0];

    // Find the target phrase in the document
    string linkText = "Evaluation";
    PdfTextSearchResults linkSearchResults = processor.FindText(linkText);

    if (linkSearchResults.Status == PdfTextSearchStatus.Found)
    {
        PdfRectangle linkRectangle = linkSearchResults.Rectangles[0].BoundingRectangle;
        string linkUri = "https://community.devexpress.com/blogs/";

        // Add a link annotation to the found text
        PdfLinkAnnotationFacade uriAnnotation = page.AddLinkAnnotation(linkRectangle, linkUri);
        uriAnnotation.Name = "link1";
        uriAnnotation.HighlightMode = PdfAnnotationHighlightingMode.Push;
    }
    processor.SaveDocument("..\\..\\Result.pdf");
}

A destination includes the following view parameters:

  • The displayed document page
  • The location of the document window on this page
  • The magnification (zoom factor)

Call one of the following methods to create a destination:

View Parameters Methods
Fit the page’s bounding box to the document window both horizontally and vertically. PdfPageFacade.CreateFitBBoxDestination
Fit the page’s bounding box to the document window horizontally. PdfPageFacade.CreateFitBBoxHorizontallyDestination
Fit the page’s bounding box to the document window vertically. PdfPageFacade.CreateFitBBoxVerticallyDestination
Fit the entire page to the document window both horizontally and vertically (Zoom to Page Level view). PdfPageFacade.CreateFitDestination
Fit the entire page to the document window horizontally. PdfPageFacade.CreateFitHorizontallyDestination
Fit the entire page to the document window vertically. PdfPageFacade.CreateFitVerticallyDestination
Display the specified page area in the document window. PdfPageFacade.CreateFitRectangleDestination
Position the specified page coordinate at the top left document window corner, and specify the zoom factor. PdfPageFacade.CreateXYZDestination

The code sample below creates a link annotation with a destination that displays the third page with the Zoom to Page Level view:

destination link

using (PdfDocumentProcessor pdfDocumentProcessor = new PdfDocumentProcessor())
{
    // Load a document
    pdfDocumentProcessor.LoadDocument("Demo.pdf");

    // Access third page properties
    PdfPageFacade pageFacade = pdfDocumentProcessor.DocumentFacade.Pages[2];

    // Create a Fit destination that refers to the third page
    PdfFitDestination destination = pageFacade.CreateFitDestination();

    // Find a specific phrase
    string linkText = "JBIG2 images";
    PdfTextSearchResults linkSearchResults = pdfDocumentProcessor.FindText(linkText);

    // If the phrase is found, obtain its bounding rectangle
    if (linkSearchResults.Status == PdfTextSearchStatus.Found)
    {
        PdfRectangle linkRectangle = linkSearchResults.Rectangles[0].BoundingRectangle;

        // Access first page properties
        PdfPageFacade linkPageFacade =
           pdfDocumentProcessor.DocumentFacade.Pages[linkSearchResults.PageNumber -1];

        // Create a link annotation associated with the bounding rectangle
        // and destination
        PdfLinkAnnotationFacade linkAnnotation =
            linkPageFacade.AddLinkAnnotation(linkRectangle, destination);
        linkAnnotation.HighlightMode = PdfAnnotationHighlightingMode.Push;
    }
    // Save the result
    pdfDocumentProcessor.SaveDocument("out.pdf");
}

Create Markup Annotations

The table below lists available markup annotation types and API used to create these annotations:

Annotation Class Method
Text Markup PdfTextMarkupAnnotationFacade PdfPageFacade.AddTextMarkupAnnotation
Sticky Note PdfTextAnnotationFacade PdfPageFacade.AddTextAnnotation
Caret PdfCaretAnnotationFacade PdfPageFacade.AddCaretAnnotation
Rubber Stamp PdfRubberStampAnnotationFacade PdfPageFacade.AddRubberStampAnnotation
Circle PdfCircleAnnotationFacade PdfPageFacade.AddCircleAnnotation
Square PdfSquareAnnotationFacade PdfPageFacade.AddSquareAnnotation
File Attachment PdfFileAttachmentAnnotationFacade PdfPageFacade.AddFileAttachmentAnnotation
Free Text PdfFreeTextAnnotationFacade PdfPageFacade.AddFreeTextAnnotation
Ink PdfInkAnnotationFacade PdfPageFacade.AddInkAnnotation
Line PdfLineAnnotationFacade PdfPageFacade.AddLineAnnotation
Polyline PdfPolyLineAnnotationFacade PdfPageFacade.AddPolyLineAnnotation
Polygon PdfPolygonAnnotationFacade PdfPageFacade.AddPolygonAnnotation

The code sample below creates a rubber stamp, file attachment, free text, and a circle annotation:

markup annotations

using DevExpress.Pdf;
using System;
using System.IO;

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a document
    processor.LoadDocument("..\\..\\Document.pdf");

    // Access the first page properties
    PdfPageFacade pageFacade = processor.DocumentFacade.Pages[0];

    // Define a rubber stamp rectangle
    PdfRectangle rubberStampRectangle = new PdfRectangle(663, 526, 763, 576);

    // Create a "Draft" rubber stamp annotation
    PdfRubberStampAnnotationFacade rubberStamp =
        pageFacade.AddRubberStampAnnotation(rubberStampRectangle,
        PdfRubberStampAnnotationIconName.Draft);
    rubberStamp.Author = "Jesse Faden";
    rubberStamp.Contents = "Made in PDF Document API";

    // Define a file attachment area
    PdfPoint attachmentPoint = new PdfPoint(52, 550);

    // Specify attachment data
    PdfFileAttachment attachment = new PdfFileAttachment()
    {
        CreationDate = DateTime.Now,
        Description = "This is my attached file",
        FileName = "MyAttach.txt",
        Data = File.ReadAllBytes("..\\..\\FileToAttach.txt")
    };

    // Create a file attachment annotation
    PdfFileAttachmentAnnotationFacade pdfFileAttachment =
        pageFacade.AddFileAttachmentAnnotation(attachmentPoint, attachment,
        PdfFileAttachmentAnnotationIconName.PaperClip);
    pdfFileAttachment.Author = "Nancy Skywalker";
    pdfFileAttachment.Contents = "Additional Content";

    // Specify a free text annotation area
    PdfRectangle freeTextRectangle = new PdfRectangle(14, 321, 145, 340);

    // Create a free text annotation in this area
    PdfFreeTextAnnotationFacade freeTextAnnotation =
       pageFacade.AddFreeTextAnnotation(freeTextRectangle, "Free Text Annotation");
    freeTextAnnotation.Author = "Rayn Anita W";

    // Add a callout line
    freeTextAnnotation.SetCallout(PdfAnnotationLineEndingStyle.OpenArrow, new PdfPoint(152,351));

    // Find the target phrase in the document
    string circleText = "dogfooded";
    PdfTextSearchResults searchResults = processor.FindText(circleText);

    if (searchResults.Status == PdfTextSearchStatus.Found)
    {
        // Define an area around the phrase to add an annotation
        PdfRectangle circleRectangle = searchResults.Rectangles[0].BoundingRectangle;

        // Create a circle annotation in this area
        PdfCircleAnnotationFacade circleAnnotation = pageFacade.AddCircleAnnotation(circleRectangle);
        circleAnnotation.Author = "Cardle Anita W";
        circleAnnotation.Contents = "It's better to say 'used' in this case";
    }

    // Save the result
    processor.SaveDocument("..\\..\\Result.pdf");
}

Edit Annotations

The PdfPageFacade.Annotations property returns all page annotation properties. You can filter annotation properties, cast them to the corresponding class, and use class properties to modify annotation parameters.

The code sample below changes annotations created in the previous example, so they appear as follows:

markup edited

using DevExpress.Pdf;
using System.Linq;

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a document
    processor.LoadDocument("..\\..\\Result.pdf");

    // Access the first page properties
    PdfPageFacade pageFacade = processor.DocumentFacade.Pages[0];

    // Obtain all free text annotations
    var freeTextAnnotations = pageFacade.Annotations.Where
        (annotation => annotation.Type == PdfAnnotationType.FreeText);
    foreach (PdfFreeTextAnnotationFacade freeText in freeTextAnnotations) 
    { 
        // Change border parameters and text justification
        freeText.InteriorColor = new PdfRGBColor(0.36, 0.54, 0.66);
        freeText.BorderWidth = 0.5;
        freeText.TextJustification = PdfTextJustification.Centered;
    }

    // Retrieve all circle annotations
    var circleAnnotations = pageFacade.Annotations.Where
        (annotation => annotation.Type == PdfAnnotationType.Circle);
    foreach (PdfCircleAnnotationFacade pdfCircle in circleAnnotations)
    { 
        // Change border style and color
        pdfCircle.BorderStyle = PdfBorderStyle.Dash; 
        pdfCircle.Color = new PdfRGBColor(0.52, 0.87, 0.01);
    }

    // Get all rubber stamps 
    var rubberStampAnnotations = pageFacade.Annotations.Where
        (annotation => annotation.Type == PdfAnnotationType.RubberStamp);
    foreach (PdfRubberStampAnnotationFacade pdfRubberStamp in rubberStampAnnotations)
    {
        // Generate a stamp from another document’s page
        pdfRubberStamp.SetCustomIcon("..\\..\\Demo.pdf", 4);
    }

    // Obtain all file attachments
    var fileAttachments = pageFacade.Annotations.Where
        (annotation => annotation.Type == PdfAnnotationType.FileAttachment);
    foreach (PdfFileAttachmentAnnotationFacade fileAttachment in fileAttachments) 
    {
        // Change the icon and its color
        fileAttachment.Color = new PdfRGBColor(0.83, 0.13, 0.18);
        fileAttachment.IconName = PdfFileAttachmentAnnotationIconName.Tag;
    }
        // Save the result
        processor.SaveDocument("..\\..\\Result_1.pdf");
}

Add Comments to Annotations

Use API from the table below to add comments to markup annotations:

API Description
PdfMarkupAnnotationFacade.AddReply Adds a comment to the annotation. This method returns the PdfMarkupAnnotationComment object. Use this class’ members to change the reply’s author, subject and text.
PdfMarkupAnnotationFacade.Replies Obtains all annotation comments.
PdfMarkupAnnotationComment.AddReply Creates a nested comment.
PdfMarkupAnnotationComment.Replies Gets all nested comments added to the comment.
PdfMarkupAnnotationComment.AddReview Add a review to the comment. Use the PdfMarkupAnnotationFacade.Reviews property to get all reviews.

The code sample below adds two nested comments to all sticky notes (the document in opened in WinForms PDF Viewer):

added comments

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a document
    processor.LoadDocument("..\\..\\Document.pdf");

    // Access the first page properties
    PdfPageFacade pageFacade = processor.DocumentFacade.Pages[0];

    // Retrieve all text annotations
    var stickyNotes = pageFacade.Annotations.Where
            (annotation => annotation.Type == PdfAnnotationType.Text);
    foreach (PdfTextAnnotationFacade stickyNote in stickyNotes)
    {
        // Add comments
        AddAnnotationComments(stickyNote);
    }

    // Save the result
    processor.SaveDocument("..\\..\\Result.pdf");
}

private static void AddAnnotationComments(PdfMarkupAnnotationFacade annotation)
{
    PdfMarkupAnnotationComment comment =
       annotation.AddReply("Reviewer", "Done");
    comment.Subject = "Proofread";

    PdfMarkupAnnotationComment nestedComment =
       comment.AddReply(annotation.Author, "Thanks");
    nestedComment.Subject = "Reviewed";
}

Add Reviews to Annotations

Call the PdfMarkupAnnotationFacade.AddReview method to add a review to the markup annotation. The PdfMarkupAnnotationFacade.Reviews property obtains all annotation reviews.

To remove all reviews, call the PdfMarkupAnnotationFacade.ClearReviews() method.

The code sample below adds a review to the annotations from a specific author (the document is opened in the WinForms PDF Viewer):

added reviews

using DevExpress.Pdf;

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a document
    processor.LoadDocument("..\\..\\Document.pdf");

    // Access the first page properties
    PdfPageFacade pageFacade = processor.DocumentFacade.Pages[0];

    foreach(PdfMarkupAnnotationFacade markupAnnotation in pageFacade.Annotations)
    {

        // Check the annotation author
        if (markupAnnotation.Author == "Brian Zetc") 
        {

          // Add a review to the annotation
            markupAnnotation.AddReview("Cardle Anita W", PdfAnnotationReviewStatus.Accepted);
        }
    }
    // Save the result
    processor.SaveDocument("..\\..\\Result.pdf");
}

Flatten Annotations

Call one of the following methods to flatten an annotation:

Method Description
PdfDocumentFacade.FlattenAnnotations Flattens document annotations.
PdfPageFacade.FlattenAnnotations Flattens annotations of a specific page.
PdfAnnotationFacade.Flatten() Flattens a specific annotation.

The code sample below flattens all text annotations in the document:

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
  // Load a document:
  processor.LoadDocument("..\\..\\Document.pdf");

  // Flatten all text annotations:
  PdfDocumentFacade documentFacade = processor.DocumentFacade;
  documentFacade.FlattenAnnotations(PdfAnnotationType.Text);

  // Save the result:
  processor.SaveDocument("..\\..\\Result.pdf");
}

Remove Annotations

Call the PdfAnnotationFacade.Remove() method to remove an annotation.

The code sample below removes all annotations from a specific author:

using DevExpress.Pdf;
using System.Linq;

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a document
    processor.LoadDocument("..\\..\\Document.pdf");

    // Access the first page properties
    PdfPageFacade pageFacade = processor.DocumentFacade.Pages[0];

    // Retrieve all markup annotations
    var markups = pageFacade.Annotations.Where
            (annotation => annotation.Type != PdfAnnotationType.Link).ToList();
    foreach(PdfMarkupAnnotationFacade markupAnnotation in markups)
    {
        // Check the annotation author
        if (markupAnnotation.Author == "Brian Zetc")
        {
            // Remove the annotation
            markupAnnotation.Remove();
        }
    }
    // Save the result
    processor.SaveDocument("..\\..\\Result.pdf");
}