support looking up in reply to value for annotation #362

This commit is contained in:
Eliot Jones
2023-05-27 13:40:01 +01:00
parent fba1cbc13c
commit 211b27062d
5 changed files with 97 additions and 8 deletions

View File

@@ -0,0 +1,43 @@
namespace UglyToad.PdfPig.Tests.Integration;
using Annotations;
using System.Linq;
using Xunit;
public class AnnotationReplyToTests
{
private static string GetFilename()
{
return IntegrationHelpers.GetDocumentPath("annotation-comments.pdf");
}
[Fact]
public void HasCorrectNumberOfAnnotations()
{
using var document = PdfDocument.Open(GetFilename());
var page = document.GetPage(1);
var annotations = page.ExperimentalAccess.GetAnnotations().ToList();
Assert.Equal(4, annotations.Count);
Assert.Equal(AnnotationType.Text, annotations[0].Type);
Assert.Equal(AnnotationType.Popup, annotations[1].Type);
Assert.Equal(AnnotationType.Text, annotations[2].Type);
Assert.Equal(AnnotationType.Popup, annotations[3].Type);
}
[Fact]
public void SecondTextReplyToFirst()
{
using var document = PdfDocument.Open(GetFilename());
var page = document.GetPage(1);
var annotations = page.ExperimentalAccess.GetAnnotations().ToList();
Assert.Equal(annotations[0], annotations[2].InReplyTo);
}
}

View File

@@ -290,6 +290,7 @@
public static readonly NameToken Inklist = new NameToken("InkList");
public static readonly NameToken Intent = new NameToken("Intent");
public static readonly NameToken Interpolate = new NameToken("Interpolate");
public static readonly NameToken Irt = new NameToken("IRT");
public static readonly NameToken It = new NameToken("IT");
public static readonly NameToken ItalicAngle = new NameToken("ItalicAngle");
// J

View File

@@ -88,15 +88,30 @@
/// </summary>
public bool HasDownAppearance => downAppearanceStream != null;
/// <summary>
/// The <see cref="Annotation"/> this annotation was in reply to. Can be <see langword="null" />
/// </summary>
public Annotation InReplyTo { get; }
/// <summary>
/// Create a new <see cref="Annotation"/>.
/// </summary>
public Annotation(DictionaryToken annotationDictionary, AnnotationType type, PdfRectangle rectangle,
string content, string name, string modifiedDate,
AnnotationFlags flags, AnnotationBorder border, IReadOnlyList<QuadPointsQuadrilateral> quadPoints,
public Annotation(
DictionaryToken annotationDictionary,
AnnotationType type,
PdfRectangle rectangle,
string content,
string name,
string modifiedDate,
AnnotationFlags flags,
AnnotationBorder border,
IReadOnlyList<QuadPointsQuadrilateral> quadPoints,
PdfAction action,
AppearanceStream normalAppearanceStream, AppearanceStream rollOverAppearanceStream,
AppearanceStream downAppearanceStream, string appearanceState)
AppearanceStream normalAppearanceStream,
AppearanceStream rollOverAppearanceStream,
AppearanceStream downAppearanceStream,
string appearanceState,
Annotation inReplyTo)
{
AnnotationDictionary = annotationDictionary ?? throw new ArgumentNullException(nameof(annotationDictionary));
Type = type;
@@ -112,6 +127,7 @@
this.rollOverAppearanceStream = rollOverAppearanceStream;
this.downAppearanceStream = downAppearanceStream;
this.appearanceState = appearanceState;
InReplyTo = inReplyTo;
}
/// <inheritdoc />

View File

@@ -33,6 +33,8 @@
public IEnumerable<Annotation> GetAnnotations()
{
var lookupAnnotations = new Dictionary<IndirectReference, Annotation>();
if (!pageDictionary.TryGet(NameToken.Annots, tokenScanner, out ArrayToken annotationsArray))
{
yield break;
@@ -45,6 +47,13 @@
continue;
}
Annotation replyTo = null;
if (annotationDictionary.TryGet(NameToken.Irt, out IndirectReferenceToken referencedAnnotation)
&& lookupAnnotations.TryGetValue(referencedAnnotation.Data, out var linkedAnnotation))
{
replyTo = linkedAnnotation;
}
var type = annotationDictionary.Get<NameToken>(NameToken.Subtype, tokenScanner);
var annotationType = type.ToAnnotationType();
var action = GetAction(annotationDictionary);
@@ -136,9 +145,29 @@
appearanceState = appearanceStateToken.Data;
}
yield return new Annotation(annotationDictionary, annotationType, rectangle,
contents, name, modifiedDate, flags, border, quadPointRectangles, action,
normalAppearanceStream, rollOverAppearanceStream, downAppearanceStream, appearanceState);
var annotation = new Annotation(
annotationDictionary,
annotationType,
rectangle,
contents,
name,
modifiedDate,
flags,
border,
quadPointRectangles,
action,
normalAppearanceStream,
rollOverAppearanceStream,
downAppearanceStream,
appearanceState,
replyTo);
if (token is IndirectReferenceToken indirectReference)
{
lookupAnnotations[indirectReference.Data] = annotation;
}
yield return annotation;
}
}