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:

Copy
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 = PSPDFStampAnnotation()
    stampAnnotation.boundingBox = CGRect(x: 200, y: 200, width: 50, height: 50)
    
    let appearanceStreamGenerator = PSPDFFileAppearanceStreamGenerator(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])
}