Annotations named destinations (#579)

* Add Named Destinations to Catalog so that bookmarks and links can access
them.

The named destinations require access to page nodes, so created Pages object
that is made using PagesFactory (which contains the page-related code from
Catalog).

* Further implementation of destinations:
- Implement NamedDestinations in AnnotationProvider, so that we can look
  up named destinations for annotations and turn them into explicit destinations.
  Reused existing code inside BookmarksProvider to get destinations/actions.
- Added GoToE action
- According to the PDF reference, destinations are also required for
  external destinations and hence for ExternalBookmarkNode. This allows us
  to push up DocumentBookmarkNode.Destination to BookmarkNode.

* Implemented stateful appearance streams and integration test

* Added AppearanceStream to public API because it is used in the (public)
Annotation constructor

* After #552, must push down ExplicitDestination do DocumentBookmarkNode since it
does not apply to UriBookmarkNode.

* Added actions, which fits the PDF model better and works well with the
new bookmarks code (after PR #552)

* Rename Action to PdfAction + removed unused using in ActionProvider.cs

---------

Co-authored-by: mvantzet <mark@radialsg.com>
This commit is contained in:
mvantzet
2023-04-10 18:14:14 +02:00
committed by GitHub
parent 2e0622b652
commit 0e39bc0b76
37 changed files with 1263 additions and 625 deletions

View File

@@ -14,6 +14,8 @@
using Tokenization.Scanner;
using Tokens;
using Outline;
using Outline.Destinations;
using System.Linq;
using Util.JetBrains.Annotations;
/// <inheritdoc />
@@ -42,6 +44,7 @@
[NotNull]
private readonly Pages pages;
private readonly NamedDestinations namedDestinations;
/// <summary>
/// The metadata associated with this document.
@@ -75,13 +78,12 @@
/// </summary>
public bool IsEncrypted => encryptionDictionary != null;
internal PdfDocument(
IInputBytes inputBytes,
HeaderVersion version,
internal PdfDocument(IInputBytes inputBytes,
HeaderVersion version,
CrossReferenceTable crossReferenceTable,
IPageFactory pageFactory,
Catalog catalog,
DocumentInformation information,
DocumentInformation information,
EncryptionDictionary encryptionDictionary,
IPdfTokenScanner pdfScanner,
ILookupFilterProvider filterProvider,
@@ -98,7 +100,8 @@
this.parsingOptions = parsingOptions;
Information = information ?? throw new ArgumentNullException(nameof(information));
pages = new Pages(catalog, pageFactory, pdfScanner);
pages = catalog.Pages;
namedDestinations = catalog.NamedDestinations;
Structure = new Structure(catalog, crossReferenceTable, pdfScanner);
Advanced = new AdvancedPdfDocumentAccess(pdfScanner, filterProvider, catalog);
documentForm = new Lazy<AcroForm>(() => acroFormFactory.GetAcroForm(catalog));
@@ -148,7 +151,7 @@
try
{
return pages.GetPage(pageNumber, parsingOptions);
return pages.GetPage(pageNumber, namedDestinations, parsingOptions);
}
catch (Exception ex)
{