Skip to content
Guides

Add Annotations to PDF

This sample shows how to print the annotation list information, set the annotations (including markup, note, ink, freetext, circle, square, line, stamp, and sound annotations), and delete the annotations.

objective-c
// Init Methods
- (instancetype)initWithDocument:(CPDFDocument *)document {
  CPDFDocument *myDocument = document;
  [self createTestAnnots:myDocument];
}

// Create all type annotation using API
- (void)createTestAnnots:(CPDFDocument *)oldDocument {
  NSString *commandLineStr = @"" 
  
  // Get Sandbox path for saving the PDFFile
  NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
  NSString *writeDirectoryPath = [NSString stringWithFormat:@"%@/%@", path, @"Annoation"];

  if (![[NSFileManager defaultManager] fileExistsAtPath:writeDirectoryPath])
      [[NSFileManager defaultManager] createDirectoryAtURL:[NSURL fileURLWithPath:writeDirectoryPath] withIntermediateDirectories:YES attributes:nil error:nil];
  NSString *writeFilePath = [NSString stringWithFormat:@"%@/%@.pdf",writeDirectoryPath,@"CreateAnnotationTest"];

  // Save the document in the test PDF file
  NSURL *anntationURL = [NSURL fileURLWithPath:writeFilePath];
  [oldDocument writeToURL:anntationURL];

  // Create a new document for test PDF file
  CPDFDocument *document = [[CPDFDocument alloc] initWithURL:anntationURL];

  //-----------------------------------------------------------------------------------------
  // Test of a free text annotation and ink annotation.
  CPDFPage *page1 = [document pageAtIndex:0];

  {
      //  Create a freetext annotation
      CPDFFreeTextAnnotation *freeText1 = [[CPDFFreeTextAnnotation alloc] initWithDocument:document];
      freeText1.contents = @"\n\nSome swift brown fox snatched a gray hare out of the air by freezing it with an angry glare."
      "\n\nAha!\n\nAnd there was much rejoicing!";
      freeText1.bounds = CGRectMake(10, 200, 160, 570);
      freeText1.font = [UIFont fontWithName:@"Helvetica" size:12];
      freeText1.fontColor = [UIColor redColor];
      freeText1.alignment = NSTextAlignmentLeft;
      //  add a freetext annotation for page
      [page1 addAnnotation:freeText1];
  }

  {
      // Create a ink annotation
      CPDFInkAnnotation *ink = [[CPDFInkAnnotation alloc] initWithDocument:document];
      CGPoint startPoint = CGPointMake(220, 505);
      CGPoint point1 = CGPointMake(100, 490);
      CGPoint point2 = CGPointMake(120, 410);
      CGPoint point3 = CGPointMake(100, 400);
      CGPoint point4 = CGPointMake(180, 490);
      CGPoint endPoint = CGPointMake(140, 440);
      ink.color = [UIColor redColor];
      ink.opacity = 0.5;
      ink.borderWidth = 2.0;
      ink.paths = @[@[[NSValue valueWithCGPoint:startPoint],[NSValue valueWithCGPoint:point1],[NSValue valueWithCGPoint:point2],[NSValue valueWithCGPoint:point3],[NSValue valueWithCGPoint:point4],[NSValue valueWithCGPoint:endPoint]]];
      [page1 addAnnotation:ink];
  }

  //-----------------------------------------------------------------------------------------
  // Test of line annotaiton
  // Set line with and Dotted line
  CPDFBorder *border1 = [[CPDFBorder alloc] initWithStyle:CPDFBorderStyleDashed
                                                  lineWidth:1
                                                dashPattern:@[@(2), @(1)]];
  CPDFBorder *border2 = [[CPDFBorder alloc] initWithStyle:CPDFBorderStyleDashed
                                                  lineWidth:1
                                                dashPattern:@[@(2), @(0)]];
  CPDFPage *page2 = [document pageAtIndex:1];
  {
      // Create a Line annotations.
      CPDFLineAnnotation *line1 = [[CPDFLineAnnotation alloc] initWithDocument:document];
      line1.startPoint = CGPointMake(350, 270);
      line1.endPoint = CGPointMake(260, 370);
      line1.startLineStyle = CPDFLineStyleSquare;
      line1.endLineStyle = CPDFLineStyleCircle;
      line1.color = [UIColor redColor];
      line1.interiorColor = [UIColor yellowColor];
      line1.opacity = 0.5;
      line1.interiorOpacity = 0.5;
      line1.border = border1;
      [line1 setContents:@"Dashed Captioned"];
      [page2 addAnnotation:line1];
  }

  {
      CPDFLineAnnotation *line2 = [[CPDFLineAnnotation alloc] initWithDocument:document];
      line2.startPoint = CGPointMake(385, 480);
      line2.endPoint = CGPointMake(540, 555);
      line2.startLineStyle = CPDFLineStyleCircle;
      line2.endLineStyle = CPDFLineStyleOpenArrow;
      line2.color = [UIColor redColor];
      line2.interiorColor = [UIColor yellowColor];
      line2.opacity = 0.5;
      line2.interiorOpacity = 0.5;
      line2.border = border2;
      [line2 setContents:@"Inline Caption"];
      [page2 addAnnotation:line2];
  }

  {
      CPDFLineAnnotation *line3 = [[CPDFLineAnnotation alloc] initWithDocument:document];
      line3.startPoint = CGPointMake(25, 426);
      line3.endPoint = CGPointMake(180, 555);
      line3.startLineStyle = CPDFLineStyleCircle;
      line3.endLineStyle = CPDFLineStyleSquare;
      line3.color = [UIColor greenColor];
      line3.interiorColor = [UIColor yellowColor];
      line3.opacity = 0.5;
      line3.interiorOpacity = 0.5;
      line3.border = border2;
      [line3 setContents:@"Offset Caption"];
      [page2 addAnnotation:line3];
  }

  //-----------------------------------------------------------------------------------------
  // Test of circle and square annotation
  CPDFPage *page3 = [document pageAtIndex:2];
  {
      // Create a circle annotations.
      CPDFCircleAnnotation *circle1 = [[CPDFCircleAnnotation alloc] initWithDocument:document];
      circle1.bounds = CGRectMake(300, 300, 100, 100);
      circle1.color = [UIColor redColor];
      circle1.interiorColor = [UIColor yellowColor];
      circle1.opacity = 0.5;
      circle1.interiorOpacity = 0.5;
      circle1.border = border1;
      [page3 addAnnotation:circle1];
  }

  {
      CPDFCircleAnnotation *circle2 = [[CPDFCircleAnnotation alloc] initWithDocument:document];
      circle2.bounds = CGRectMake(100, 100, 200, 200);
      circle2.color = [UIColor greenColor];
      circle2.interiorColor = [UIColor purpleColor];
      circle2.opacity = 1.0;
      circle2.interiorOpacity = 1.0;
      circle2.border = border2;
      [page3 addAnnotation:circle2];
  }

  {
      // Create a sqaure annotations.
      CPDFSquareAnnotation *square1 = [[CPDFSquareAnnotation alloc] initWithDocument:document];
      square1.bounds = CGRectMake(10, 200, 80, 150);
      square1.color = [UIColor redColor];
      square1.interiorColor = [UIColor yellowColor];
      square1.opacity = 0.5;
      square1.interiorOpacity = 0.5;
      square1.border = border1;
      [page3 addAnnotation:square1];
  }

  {
      CPDFSquareAnnotation *square2 = [[CPDFSquareAnnotation alloc] initWithDocument:document];
      square2.bounds = CGRectMake(400, 200, 80, 300);
      square2.color = [UIColor greenColor];
      square2.interiorColor = [UIColor purpleColor];
      square2.opacity = 1.0;
      square2.interiorOpacity = 1.0;
      square2.border = border2;
      [page3 addAnnotation:square2];
  }

  //-----------------------------------------------------------------------------------------
  // Test of markup, note, link and sound anntation
  CPDFPage *page4 = [document pageAtIndex:3];
  {
      // Get array of search result
      NSArray *resultArray = [document findString:@"Page" withOptions:CPDFSearchCaseInsensitive];

      // Get the first page of search resultsGet the first page of search results
      NSArray *selections = [resultArray objectAtIndex:3];

      // Get the first search result on the first page
      CPDFSelection *selection = [selections objectAtIndex:0];

      NSMutableArray *quadrilateralPoints = [NSMutableArray array];

      CGRect bounds = selection.bounds;
      [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))]];
      [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))]];
      [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))]];
      [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))]];


      // Create a highlight annotations.
      CPDFMarkupAnnotation *highlight = [[CPDFMarkupAnnotation alloc] initWithDocument:document markupType:CPDFMarkupTypeHighlight];
      highlight.color = [UIColor yellowColor];
      highlight.quadrilateralPoints = quadrilateralPoints;
      [page4 addAnnotation:highlight];
  }

  {
      // Create a note annotation
      CPDFTextAnnotation *text = [[CPDFTextAnnotation alloc] initWithDocument:document];
      text.contents = @"test";
      text.bounds = CGRectMake(50, 200, 50, 50);
      text.color = [UIColor yellowColor];
      [page4 addAnnotation:text];
  }

  {
      // Create a link annotation
      CPDFDestination *dest = [[CPDFDestination alloc] initWithDocument:document pageIndex:1];
      CPDFLinkAnnotation *link = [[CPDFLinkAnnotation alloc] initWithDocument:document];
      link.bounds = CGRectMake(50, 100, 50, 50);
      link.destination = dest; //    link.URL = @"https://www.";
      [page4 addAnnotation:link];
  }

  {
      // Create a sound annotation
      // need import a recording file
      NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Bird" ofType:@"wav"];
      CPDFSoundAnnotation *soundAnnotation = [[CPDFSoundAnnotation alloc] initWithDocument:document];
      if ([soundAnnotation setMediaPath:filePath]) {
          soundAnnotation.bounds = CGRectMake(100, 200, 50, 50);
          [page4 addAnnotation:soundAnnotation];
      }
  }

  //-----------------------------------------------------------------------------------------
  // Test of stamp annotation
  CPDFPage *page5 = [document pageAtIndex:4];
  CGSize size5 = [document pageSizeAtIndex:4];
  CGFloat height5 = size5.height;

  {
      // Create a all standard annotation
      for (int i = 1; i <= 23; i++) {
          CPDFStampAnnotation *standard = [[CPDFStampAnnotation alloc] initWithDocument:document type:i];
          standard.bounds = CGRectMake(50, height5 - i*30, 50, 30);
          [page5 addAnnotation:standard];
      }
  }

  {
      // Create a text stamp annotation
      NSTimeZone* timename = [NSTimeZone systemTimeZone];
      NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init ];
      [outputFormatter setTimeZone:timename ];

      // Get date
      NSString *tDate = nil;
      [outputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:SS"];

      tDate = [outputFormatter stringFromDate:[NSDate date]];
      CPDFStampAnnotation *text = [[CPDFStampAnnotation alloc] initWithDocument:document text:@"ComPDFKit" detailText:tDate style:CPDFStampStyleRed shape:CPDFStampShapeArrowLeft];
      text.bounds = CGRectMake(150, height5-50, 80, 50);
      [page5 addAnnotation:text];
  }

  {
      // Create a text stamp annotation
      CPDFStampAnnotation *image = [[CPDFStampAnnotation alloc] initWithDocument:document image:[UIImage imageNamed:@"Logo"]];
      image.bounds = CGRectMake(150, height5-120, 50, 50);
      [page5 addAnnotation:image];
  }

  // Save the create annotation action in document
  [document writeToURL:anntationURL];
  commandLineStr = [commandLineStr stringByAppendingString:@"Done.\n"];
  commandLineStr = [commandLineStr stringByAppendingString:@"Done. Results saved in CreateAnnotationTest.pdf\n"];

  // Dele the first annotation
  [self deleteTestAnnot:document];
  
  // Print annotation list information
  [self printAnnotationList:document];
}

// Dele the first annotation
- (void)deleteTestAnnot:(CPDFDocument *)oldDocument {
  NSString *commandLineStr = @"" 
  
  // Get Sandbox path for saving the PDFFile
  NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
  NSString *writeDirectoryPath = [NSString stringWithFormat:@"%@/%@", path, @"Annoation"];

  if (![[NSFileManager defaultManager] fileExistsAtPath:writeDirectoryPath])
      [[NSFileManager defaultManager] createDirectoryAtURL:[NSURL fileURLWithPath:writeDirectoryPath] withIntermediateDirectories:YES attributes:nil error:nil];
  NSString *writeFilePath = [NSString stringWithFormat:@"%@/%@.pdf",writeDirectoryPath,@"DeleteAnnotationTest"];

  // Save the document in the PDF file
  NSURL *deleteAnntationURL = [NSURL fileURLWithPath:writeFilePath];
  [oldDocument writeToURL:deleteAnntationURL];

  // Create a new document for test PDF file
  CPDFDocument *document = [[CPDFDocument alloc] initWithURL:deleteAnntationURL];

  // Remove the fisrt annotation from document
  CPDFPage *page = [document pageAtIndex:0];

  CPDFAnnotation *annotation = [[page annotations] objectAtIndex:0];
  [page removeAnnotation:annotation];

  // Save the remove the fisrt annotation action in document
  [document writeToURL:deleteAnntationURL];
  commandLineStr = [commandLineStr stringByAppendingString:@"Done.\n"];
  commandLineStr = [commandLineStr stringByAppendingString:@"Done. Results saved in DeleteAnnotationTest.pdf\n"];
}

// Print annotation list information
- (void)printAnnotationList:(CPDFDocument *)document {
  NSString *commandLineStr = @"" 
  
  NSMutableArray *annotations = [NSMutableArray array];
    for (int i=0; i<document.pageCount; i++) {
        // Loop through all anntation
        CPDFPage *page = [document pageAtIndex:i];
        [annotations addObjectsFromArray:[page annotations]];
        for (CPDFAnnotation *annotation in annotations) {
            commandLineStr = [commandLineStr stringByAppendingString:@"-------------------------------------\n"];
            commandLineStr = [commandLineStr stringByAppendingFormat:@"Page: %d\n", i+1];
            commandLineStr = [commandLineStr stringByAppendingFormat:@"Annot Type: %@\n", annotation.type];
            commandLineStr = [commandLineStr stringByAppendingFormat:@"\tPosition: %d, %d, %d, %d\n\n", (int)annotation.bounds.origin.x,(int)annotation.bounds.origin.y, (int)annotation.bounds.size.width, (int)annotation.bounds.size.height];
        }
  }
}