Sluggish Rendering

By default, all annotations (except notes) are rendered as part of a page image, which makes annotations cheap in terms of memory usage. However, this means that whenever they are updated, the entire page needs to be rerendered. This also poses a problem when selecting an annotation, as the annotation needs to be extracted from the page. The page then needs to be rerendered without the extracted annotation, and the annotation needs to be drawn in its own separate view that supports dragging and resizing. This entire process could take a noticeable amount of time, leading to a non-optimal user experience.

To deal with this, PSPDFKit can be configured to not render annotations as part of the page image and instead show each one in a separate View in Android’s view hierarchy. We call this mode overlay mode.

Overlay Mode

If you frequently change annotations, rendering them in overlay mode is more performant. Using overlay mode makes annotation selection almost instantaneous — there’s no need to rerender a page when selecting/deselecting annotations. Updates to annotations in overlay mode are also propagated to the UI much faster.

That said, there are a few points you should keep in mind before enabling overlay mode in your app:

  • Rendering annotations in overlay mode increases memory usage because each annotation needs to be drawn in a separate view instead of being part of an existing page image. This means you should never enable overlay mode for too many annotations on low-end devices. We recommend only enabling overlay mode for all annotations when using high-end devices.

  • Overlay mode could increase CPU usage and slightly increase page loading time because each annotation view needs to be laid out in the view hierarchy.

Overlay Mode Configuration

You can configure which annotation types should be rendered in overlay mode via setOverlaidAnnotationTypes(). You can also configure specific annotations to be rendered in overlay mode on top of these overlaid annotation types via setOverlaidAnnotations(). Both methods are defined in PdfFragment.

⚠️ Warning: Make sure you call these methods on PdfFragment after the document has been loaded — for example, in onDocumentLoaded() or later. Otherwise, the defaults will override the set values once the document is loaded into the fragment.

For example, if you wish to enable overlay mode for all supported annotation types, do the following:

// Passing all annotation types enables overlay mode for all types that support overlay.
// Passing all annotation types enables overlay mode for all types that support overlay.

Or, if you just want to enable some annotation types, do this:

pdfFragment.setOverlaidAnnotationTypes(EnumSet.of(AnnotationType.INK, AnnotationType.CIRCLE))
getPdfFragment().setOverlaidAnnotationTypes(EnumSet.of(AnnotationType.INK, AnnotationType.CIRCLE));

There are some annotation types — such as note, file, and sound annotations — that always need to be rendered in the overlay. If you set custom types as mentioned, the default ones will be added as well.

💡 Tip: For a complete example, take a look at AnnotationOverlayActivity inside the Catalog app.

Supported Annotation Types

The following annotation types are supported in overlay mode:

ℹ️ Note: Note annotations are always rendered in overlay mode.

Control the Annotation Appearance Stream Rendering

An annotation contains properties that define how the annotation should look. However, these don’t describe the appearance of an annotation in enough detail to make it render the same in different PDF viewers. To solve this issue, annotations in a PDF can specify an optional appearance stream (or AP stream for short), which describes how to render the annotation.

PSPDFKit generates AP streams for all created annotations. It also regenerates existing AP streams when the annotation is edited. This is the reason why annotation rendering sometimes changes when editing annotations created in third-party PDF tools. This is an expected behavior, since PSPDFKit can’t reproduce annotation rendering of third-party tools after modifying an annotation’s properties.

Annotation overlays are optimized for speed, and one of these optimizations is that they do not render annotation AP streams for annotation types that can be drawn faster using Android’s platform rendering (using the Canvas API). This can lead to issues where annotations created with third-party tools could be drawn differently than what was expected.

ℹ️ Note: Platform drawing is used for notes, files, free text annotations, and all shape annotations (ink, line circle, square, polygon, and polyline).

Annotation Overlay Render Strategy

It’s possible to control whether this optimized platform rendering or (slower) AP stream is preferable in an annotation overlay by setting AnnotationOverlayRenderStrategy via PdfFragment#setAnnotationOverlayRenderStrategy():

fragment.setAnnotationOverlayRenderStrategy { AnnotationOverlayRenderStrategy.Strategy.AP_STREAM_RENDERING }
fragment.setAnnotationOverlayRenderStrategy(annotation -> Strategy.AP_STREAM_RENDERING);

This callback is called for each Annotation when the annotation overlay creates the corresponding view for the annotation. You can use different render strategies for different annotations, depending on your requirements.

There are two supported render strategies at the moment:

  • AP_STREAM_RENDERING displays the annotation AP stream in the overlay. The annotation will be displayed exactly as defined in the PDF. Since documents can store arbitrary AP streams for annotations, PSPDFKit has to switch to non-AP stream rendering upon editing an annotation. This can lead to slightly slower annotation selection speeds than when using the PLATFORM_RENDERING strategy.

  • PLATFORM_RENDERING displays annotations in platform view. Note that certain annotation types are always displayed as though the AP_STREAM_RENDERING strategy was set, because there’s no platform view to display them. These include text markup annotations, redaction annotations, and image/stamp annotations.

ℹ️ Note: AP_STREAM_RENDERING is not supported for sound annotations.