Rotate Annotations on iOS

PSPDFKit supports rotating certain types of annotations. This guide discusses the user interface (UI) PSPDFKit provides for annotation rotation, the API that can be used to read and set rotation, and the compatibility that can be expected with other PDF readers.

User Interface

When an annotation is selected, PSPDFKit shows a ResizableView, which allows a user to move and resize the annotation. ResizableView will automatically show the rotation knob for supported annotation types. At an angle of zero degrees, the rotation knob appears below the annotation. The knob rotates as the annotation is rotated.

Disabling Annotation Rotation

You can disable rotation with the resizable view’s allowRotating property. This can be done either by overriding updateAnnotationSelectionView in a subclass of PDFPageView, or by subclassing ResizableView directly and overriding the allowRotating getter.

Here’s an example that shows using a page view subclass to completely disable rotation:

let pdfViewController = PDFViewController(document: document) {
    // Register our custom subclass of `PDFPageView`.
    $0.overrideClass(PDFPageView.self, with: NoAnnotationRotationPageView.self)
}

class NoAnnotationRotationPageView: PDFPageView {
    override func updateAnnotationSelectionView() {
        self.annotationSelectionView?.allowRotating = false
    }
}

Here’s an example that shows using a resizable view subclass to disable rotation only for FreeTextAnnotation:

let pdfViewController = PDFViewController(document: document) {
    // Register our custom subclass of `ResizableView`.
    $0.overrideClass(ResizableView.self, with: NoTextRotationResizableView.self)
}

class NoTextRotationResizableView: ResizableView {
    override var allowRotating: Bool {
        get { (self.trackedAnnotations.first is FreeTextAnnotation) == false }
        set {}
    }
}

Rotating Annotations Programmatically

This section explains how to rotate annotations programmatically.

Conventions

Annotation rotation is the counterclockwise angle of the annotation relative to the page, in degrees. Rotation values are integers, which means the highest precision possible is 1 degree. Rotation angles should be between 0 and 359. Setting a value outside this range will result in the value being wrapped around to lie within that range.

While PDF pages can be rotated in an underlying PDF, PSPDFKit exposes a normalized (non-rotated) coordinate space for each page. This means if an annotation appears the right way up, it will have a rotation of 0, even if the content on the page may appear sideways or upside-down. See our Coordinate Space Conversion guide to learn more.

Rotatable Annotation Types

Annotation types support rotation by conforming to the Rotatable protocol. Currently, this is implemented by FreeTextAnnotation and StampAnnotation.

Getting Rotation

The angle of an annotation can be read from the read-only rotation property.

Setting Rotation

The bounding box of an annotation is the rectangle that encloses the annotation’s contents. The edges of the bounding box are parallel to the edge of the page. If an annotation has a rotation that isn’t a multiple of 90 degrees, the bounding box will be larger than the actual size of the annotation contents.

To change an annotation’s rotation, use setRotation(_:updateBoundingBox:). You must specify whether the bounding box should be updated to preserve the apparent content size after the rotation change. If the annotation is already visible, you should pass true to update the bounding box. In some cases, it may be useful to set the rotation without updating the bounding box — for example, if you already know the correct final bounding box when deserializing an annotation.

Compatibility

The PDF specification (version 2.0) doesn’t define behavior for annotation rotation.

Rotation compatibility between PDF readers is mostly achieved using appearance streams. An appearance stream is a series of PDF drawing commands that can be attached to an annotation.

As an example, consider annotations are added to a document in a PDF reader (A). If that document is opened in another PDF reader (B), until the annotations are edited, they’ll appear in B exactly the same as they appeared in A. This is achieved by rendering the appearance stream. However, if the second reader app edits an annotation, then the appearance stream usually needs to be regenerated. If the second reader app doesn’t understand all the annotation properties used by the first app, this regenerated appearance may not match the original.

Text Annotations

Text annotations are represented as FreeTextAnnotations in PSPDFKit.

Apple Preview doesn’t support rotated text annotations. The appearance will be regenerated without rotation if the annotation is edited.

Adobe Acrobat has limited support for text annotation rotation. It appears to mainly support rotation in steps of 90 degrees to counteract page rotation. Page rotation isn’t something you typically have to worry about when using PSPDFKit because of our normalized page coordinate spaces.

Text annotations rotated to angles that aren’t multiples of 90 degrees shouldn’t be considered compatible with Adobe Acrobat. Acrobat is expected to show rotated text annotations correctly. However, it displays strange behavior when trying to edit such an annotation, and it doesn’t show a rotation knob to adjust the angle.

Stamp Annotations

Apple Preview doesn’t allow stamps to be rotated or edited in any way. This is good for compatibility because it ensures the existing rotated appearance of any stamp will be preserved.

Stamp compatibility with Adobe Acrobat varies by stamp type.

ℹ️ Note: PSPDFKit supports rotating two kinds of stamps — standard stamps and vector image annotations (vector image stamps) — in a limited configuration. You can read more about the stamp kind and configuration combination in our Rotatable API documentation.

Image Annotations

An image annotation is a StampAnnotation with a bitmap image set. However, PSPDFKit doesn’t support rotating image annotations.

Standard Stamps

A standard stamp is a StampAnnotation that displays text or an image that’s predefined by the PDF software. Standard stamps include those displaying text such as Approved and Confidential, as well as those showing a green checkmark or red cross image.

Adobe Acrobat has good support for rotating standard stamps.

While the exact appearance generated for these stamps differs slightly between PSPDFKit and Adobe Acrobat, both sides understand the standard types, so if a stamp created with one of these is edited by the other, the appearance will change slightly, but the text, color, and rotation will be preserved. The size may be altered when applying rotation with Acrobat, but the user is able to adjust the size again to restore the original size.

Custom Text Stamps and Vector Image Annotations

PSPDFKit can create custom text stamps by setting the title and subtitle of a StampAnnotation. These properties aren’t part of the PDF specification. As such, other PDF readers have no ability to regenerate the appearance of such an annotation if one is edited. Rotating these custom text stamps — i.e. the ones containing a title and subtitle — is also not supported by the PSPDFKit SDK.

A vector image annotation, also known as a vector stamp, is purely a container for an appearance stream. You create a vector image annotation by creating a StampAnnotation with no stamp type or title and then setting its appearanceStreamGenerator. If the appearance stream of a vector image was regenerated, there would be nothing left except an empty box. If PSPDFKit detects an annotation is a vector image and that the annotation is resized or rotated, PSPDFKit will preserve the appearance stream by applying a transform to the annotation.

Since the title and subtitle properties are “off spec,” as far as Adobe Acrobat is concerned, there’s no difference between a custom text stamp and a vector image annotation.

Adobe Acrobat will correctly show and resize custom text stamp annotations that were created and rotated by PSPDFKit. Acrobat will show a rotation knob, but if that knob is used to adjust the angle, then Acrobat will discard the original appearance and replace it with a black cross in a white box.

Instant JSON and XFDF

Instant JSON doesn’t store appearance streams at all, while XFDF does store appearance streams for stamp annotations but not for text annotations. As such, storing annotations with rotation is generally not recommended when using these data formats, although the rotated appearance will be correctly replicated if the document is always opened by PSPDFKit.