mirror of
https://github.com/UglyToad/PdfPig.git
synced 2026-03-10 00:23:29 +08:00
add support for quadpoints to annotations
highlight, link, strikeout, squiggly and underline annotation types may define a set of quadrilaterals using the quadpoints entry. this defines the regions to show/activate the annotation. the order of points in the quadpoints array does not match the specification so we provide a convenience class to access the point data rather than interpreting it as a rectangle: https://stackoverflow.com/questions/9855814/pdf-spec-vs-acrobat-creation-quadpoints.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
namespace UglyToad.PdfPig.Tests.Integration
|
namespace UglyToad.PdfPig.Tests.Integration
|
||||||
{
|
{
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Annotations;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
public class CatGeneticsTests
|
public class CatGeneticsTests
|
||||||
@@ -31,6 +32,13 @@
|
|||||||
var annotations = page.ExperimentalAccess.GetAnnotations().ToList();
|
var annotations = page.ExperimentalAccess.GetAnnotations().ToList();
|
||||||
|
|
||||||
Assert.NotEmpty(annotations);
|
Assert.NotEmpty(annotations);
|
||||||
|
|
||||||
|
var highlights = annotations.Where(x => x.Type == AnnotationType.Highlight);
|
||||||
|
|
||||||
|
foreach (var highlight in highlights)
|
||||||
|
{
|
||||||
|
Assert.NotEmpty(highlight.QuadPoints);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
"UglyToad.PdfPig.Annotations.AnnotationBorder",
|
"UglyToad.PdfPig.Annotations.AnnotationBorder",
|
||||||
"UglyToad.PdfPig.Annotations.AnnotationFlags",
|
"UglyToad.PdfPig.Annotations.AnnotationFlags",
|
||||||
"UglyToad.PdfPig.Annotations.AnnotationType",
|
"UglyToad.PdfPig.Annotations.AnnotationType",
|
||||||
|
"UglyToad.PdfPig.Annotations.QuadPointsQuadrilateral",
|
||||||
"UglyToad.PdfPig.Content.Catalog",
|
"UglyToad.PdfPig.Content.Catalog",
|
||||||
"UglyToad.PdfPig.Content.CropBox",
|
"UglyToad.PdfPig.Content.CropBox",
|
||||||
"UglyToad.PdfPig.Content.DocumentInformation",
|
"UglyToad.PdfPig.Content.DocumentInformation",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace UglyToad.PdfPig.Annotations
|
namespace UglyToad.PdfPig.Annotations
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Core;
|
using Core;
|
||||||
using Tokens;
|
using Tokens;
|
||||||
using Util.JetBrains.Annotations;
|
using Util.JetBrains.Annotations;
|
||||||
@@ -54,11 +55,18 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public AnnotationBorder Border { get; }
|
public AnnotationBorder Border { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rectangles defined using QuadPoints, for <see cref="AnnotationType.Link"/> these are the regions used to activate the link,
|
||||||
|
/// for text markup annotations these are the text regions to apply the markup to.
|
||||||
|
/// See <see cref="QuadPointsQuadrilateral.Points"/> for more information regarding the order of the points.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<QuadPointsQuadrilateral> QuadPoints { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="Annotation"/>.
|
/// Create a new <see cref="Annotation"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Annotation(DictionaryToken annotationDictionary, AnnotationType type, PdfRectangle rectangle, string content, string name, string modifiedDate,
|
public Annotation(DictionaryToken annotationDictionary, AnnotationType type, PdfRectangle rectangle, string content, string name, string modifiedDate,
|
||||||
AnnotationFlags flags, AnnotationBorder border)
|
AnnotationFlags flags, AnnotationBorder border, IReadOnlyList<QuadPointsQuadrilateral> quadPoints)
|
||||||
{
|
{
|
||||||
AnnotationDictionary = annotationDictionary ?? throw new ArgumentNullException(nameof(annotationDictionary));
|
AnnotationDictionary = annotationDictionary ?? throw new ArgumentNullException(nameof(annotationDictionary));
|
||||||
Type = type;
|
Type = type;
|
||||||
@@ -68,6 +76,7 @@
|
|||||||
ModifiedDate = modifiedDate;
|
ModifiedDate = modifiedDate;
|
||||||
Flags = flags;
|
Flags = flags;
|
||||||
Border = border;
|
Border = border;
|
||||||
|
QuadPoints = quadPoints ?? EmptyArray<QuadPointsQuadrilateral>.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -82,7 +82,36 @@
|
|||||||
border = new AnnotationBorder(horizontal, vertical, width, dashes);
|
border = new AnnotationBorder(horizontal, vertical, width, dashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return new Annotation(annotationDictionary, annotationType, rectangle, contents, name, modifiedDate, flags, border);
|
var quadPointRectangles = new List<QuadPointsQuadrilateral>();
|
||||||
|
if (annotationDictionary.TryGet(NameToken.Quadpoints, tokenScanner, out ArrayToken quadPointsArray))
|
||||||
|
{
|
||||||
|
var values = new List<decimal>();
|
||||||
|
for (var i = 0; i < quadPointsArray.Length; i++)
|
||||||
|
{
|
||||||
|
if (!(quadPointsArray[i] is NumericToken value))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
values.Add(value.Data);
|
||||||
|
|
||||||
|
if (values.Count == 8)
|
||||||
|
{
|
||||||
|
quadPointRectangles.Add(new QuadPointsQuadrilateral(new[]
|
||||||
|
{
|
||||||
|
new PdfPoint(values[0], values[1]),
|
||||||
|
new PdfPoint(values[2], values[3]),
|
||||||
|
new PdfPoint(values[4], values[5]),
|
||||||
|
new PdfPoint(values[6], values[7])
|
||||||
|
}));
|
||||||
|
|
||||||
|
values.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return new Annotation(annotationDictionary, annotationType, rectangle, contents, name, modifiedDate, flags, border,
|
||||||
|
quadPointRectangles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
namespace UglyToad.PdfPig.Annotations
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A QuadPoints quadrilateral is four points defining the region for an annotation to use.
|
||||||
|
/// An annotation may cover multiple quadrilaterals.
|
||||||
|
/// </summary>
|
||||||
|
public class QuadPointsQuadrilateral
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The 4 points defining this quadrilateral.
|
||||||
|
/// The PDF specification defines these as being in anti-clockwise order starting from the lower-left corner, however
|
||||||
|
/// Adobe's implementation doesn't obey the specification and points seem to go in the order: top-left, top-right,
|
||||||
|
/// bottom-left, bottom-right. See: https://stackoverflow.com/questions/9855814/pdf-spec-vs-acrobat-creation-quadpoints.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<PdfPoint> Points { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="QuadPointsQuadrilateral"/>.
|
||||||
|
/// </summary>
|
||||||
|
public QuadPointsQuadrilateral(IReadOnlyList<PdfPoint> points)
|
||||||
|
{
|
||||||
|
if (points == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(points));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (points.Count != 4)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Quadpoints quadrilateral should only contain 4 points, instead got {points.Count} points.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Points = points;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"[ {Points[0]}, {Points[1]}, {Points[2]}, {Points[3]} ]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user