Drawing an upright stamp annotation on a rotated page
Q: When using a custom appearance stream generator, how do I draw an upright stamp annotation even on a rotated page?
A: When using a custom appearance stream generator to draw a stamp annotation, we will have to take care of the rotation offset of the page when drawing the image.
To always have the stamp annotation displayed upright regardless of the page rotation, we will need to rotate the context for the appearance stream generator’s drawing block in the opposite direction of the page rotation before drawing the image on to the context.
Here is sample code which demonstrates the counter-rotation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | func addUprightStampAnnotation () { // We need to fetch the pageInfo for the page in which the stamp annotation needs to be drawn. let pageInfo = document.pageInfoForPage(at: 0) // Here, we get the rotation of the page and convert it to radians. let rotation = CGFloat((pageInfo!.rotationOffset.rawValue + pageInfo!.savedRotation.rawValue) % 360) * CGFloat.pi / 180 let image: UIImage = UIImage.init(named: "stamp-image")! let stampAnnotation = StampAnnotation() stampAnnotation.boundingBox = CGRect(x: 200, y: 200, width: 50, height: 50) let appearanceStreamGenerator = FileAppearanceStreamGenerator(fileURL: URL(fileURLWithPath: "")) appearanceStreamGenerator.drawingBlock = { context in var transform = CGAffineTransform.identity // First translate and go to the center of the stamp annotation transform = transform.translatedBy(x: stampAnnotation.boundingBox.origin.x + (stampAnnotation.boundingBox.size.width / 2), y: stampAnnotation.boundingBox.origin.y + (stampAnnotation.boundingBox.size.height / 2)) // Now rotate the context in the opposite direction of the page rotation transform = transform.rotated(by: -1 * rotation) // Translate back to origin transform = transform.translatedBy(x: -1 * (stampAnnotation.boundingBox.origin.x + (stampAnnotation.boundingBox.size.width / 2)), y: -1 * (stampAnnotation.boundingBox.origin.y + (stampAnnotation.boundingBox.size.height / 2))) context.concatenate(transform) // Draw the image now context.draw(image.cgImage!, in: stampAnnotation.boundingBox) } stampAnnotation.appearanceStreamGenerator = appearanceStreamGenerator document.add(annotations: [stampAnnotation]) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | - (void)addUprightStampAnnotation { PSPDFDocument *document; // We need to fetch the pageInfo for the page in which the stamp annotation needs to be drawn. PSPDFPageInfo *pageInfo = [document pageInfoForPageAtIndex:0]; // Here, we get the rotation of the page and convert it to radians. CGFloat rotationInDegrees = (CGFloat)pageInfo.rotationOffset + (CGFloat)pageInfo.savedRotation; CGFloat rotation = rotationInDegrees * M_PI / 180; UIImage *image = [UIImage imageNamed:@"stamp-image"]; PSPDFStampAnnotation *stampAnnotation = [[PSPDFStampAnnotation alloc] init]; stampAnnotation.boundingBox = CGRectMake(200, 200, 50, 50); PSPDFFileAppearanceStreamGenerator *appearanceStreamGenerator = [[PSPDFFileAppearanceStreamGenerator alloc] initWithFileURL:[NSURL new]]; [appearanceStreamGenerator setDrawingBlock:^(CGContextRef context) { CGAffineTransform transform = CGAffineTransformIdentity; // First translate and go to the center of the stamp annotation transform = CGAffineTransformTranslate(transform, stampAnnotation.boundingBox.origin.x + (stampAnnotation.boundingBox.size.width / 2), stampAnnotation.boundingBox.origin.y + (stampAnnotation.boundingBox.size.height / 2)); // Now rotate the context in the opposite direction of the page rotation transform = CGAffineTransformRotate(transform, -1 * rotation); // Translate back to origin transform = CGAffineTransformTranslate(transform, -1 * (stampAnnotation.boundingBox.origin.x + (stampAnnotation.boundingBox.size.width / 2)), -1 * (stampAnnotation.boundingBox.origin.y + (stampAnnotation.boundingBox.size.height / 2))); CGContextConcatCTM(context, transform); // Draw the image now CGContextDrawImage(context, stampAnnotation.boundingBox, image.CGImage); }]; stampAnnotation.appearanceStreamGenerator = appearanceStreamGenerator; [document addAnnotations:@[stampAnnotation] options:nil]; } |