Move Paths, GetAnnotations() and GetOptionalContents() outside of ExperimentalAccess and mark Experimental class and reference as obsolete

This commit is contained in:
BobLd 2024-10-30 19:00:15 +00:00
parent 40af401364
commit d3bf63fdbf
18 changed files with 99 additions and 73 deletions

View File

@ -184,7 +184,7 @@
if (includePaths) if (includePaths)
{ {
altoPage.PrintSpace.GraphicalElements = page.ExperimentalAccess.Paths altoPage.PrintSpace.GraphicalElements = page.Paths
.Select(p => ToAltoGraphicalElement(p, page.Height)) .Select(p => ToAltoGraphicalElement(p, page.Height))
.ToArray(); .ToArray();
} }

View File

@ -193,7 +193,7 @@
if (includePaths) if (includePaths)
{ {
foreach (var path in page.ExperimentalAccess.Paths) foreach (var path in page.Paths)
{ {
hocr += "\n" + GetCode(path, page.Height, true, level + 1); hocr += "\n" + GetCode(path, page.Height, true, level + 1);
} }

View File

@ -240,7 +240,7 @@
if (includePaths) if (includePaths)
{ {
foreach (var path in page.ExperimentalAccess.Paths) foreach (var path in page.Paths)
{ {
var graphicalElement = ToPageXmlLineDrawingRegion(path, data, page.Width, page.Height); var graphicalElement = ToPageXmlLineDrawingRegion(path, data, page.Width, page.Height);

View File

@ -69,7 +69,7 @@
{ {
var builder = new StringBuilder($"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width='{Math.Round(page.Width, Rounding)}' height='{Math.Round(page.Height, Rounding)}'>\n<g transform=\"scale(1, 1) translate(0, 0)\">\n"); var builder = new StringBuilder($"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width='{Math.Round(page.Width, Rounding)}' height='{Math.Round(page.Height, Rounding)}'>\n<g transform=\"scale(1, 1) translate(0, 0)\">\n");
foreach (var path in page.ExperimentalAccess.Paths) foreach (var path in page.Paths)
{ {
if (!path.IsClipping) if (!path.IsClipping)
{ {

View File

@ -11,7 +11,7 @@ namespace UglyToad.PdfPig.Tests.Geometry
new ParsingOptions { ClipPaths = true })) new ParsingOptions { ClipPaths = true }))
{ {
var page = document.GetPage(45); var page = document.GetPage(45);
Assert.Equal(28, page.ExperimentalAccess.Paths.Count); Assert.Equal(28, page.Paths.Count);
} }
} }
} }

View File

@ -15,7 +15,7 @@
var page = document.GetPage(1); var page = document.GetPage(1);
var words = page.GetWords().ToList(); var words = page.GetWords().ToList();
foreach (var path in page.ExperimentalAccess.Paths) foreach (var path in page.Paths)
{ {
Assert.NotEqual(FillingRule.NonZeroWinding, path.FillingRule); // allow none and even-odd Assert.NotEqual(FillingRule.NonZeroWinding, path.FillingRule); // allow none and even-odd

View File

@ -16,9 +16,9 @@ public class AnnotationReplyToTests
var page = document.GetPage(1); var page = document.GetPage(1);
var annotations = page.ExperimentalAccess.GetAnnotations().ToList(); var annotations = page.GetAnnotations().ToArray();
Assert.Equal(4, annotations.Count); Assert.Equal(4, annotations.Length);
Assert.Equal(AnnotationType.Text, annotations[0].Type); Assert.Equal(AnnotationType.Text, annotations[0].Type);
Assert.Equal(AnnotationType.Popup, annotations[1].Type); Assert.Equal(AnnotationType.Popup, annotations[1].Type);
@ -33,7 +33,7 @@ public class AnnotationReplyToTests
var page = document.GetPage(1); var page = document.GetPage(1);
var annotations = page.ExperimentalAccess.GetAnnotations().ToList(); var annotations = page.GetAnnotations().ToArray();
Assert.Equal(annotations[0], annotations[2].InReplyTo); Assert.Equal(annotations[0], annotations[2].InReplyTo);
} }

View File

@ -11,7 +11,7 @@
using (var doc = PdfDocument.Open(pdf)) using (var doc = PdfDocument.Open(pdf))
{ {
var annots = doc.GetPage(1).ExperimentalAccess.GetAnnotations().ToArray(); var annots = doc.GetPage(1).GetAnnotations().ToArray();
Assert.Equal(5, annots.Length); Assert.Equal(5, annots.Length);
Assert.All(annots, a => Assert.NotNull(a.Action)); Assert.All(annots, a => Assert.NotNull(a.Action));
Assert.All(annots, a => Assert.IsType<GoToAction>(a.Action)); Assert.All(annots, a => Assert.IsType<GoToAction>(a.Action));
@ -25,7 +25,7 @@
var pdf = IntegrationHelpers.GetSpecificTestDocumentPath("appearances"); var pdf = IntegrationHelpers.GetSpecificTestDocumentPath("appearances");
using (var doc = PdfDocument.Open(pdf)) using (var doc = PdfDocument.Open(pdf))
{ {
var annotations = doc.GetPage(1).ExperimentalAccess.GetAnnotations().ToArray(); var annotations = doc.GetPage(1).GetAnnotations().ToArray();
var annotation = Assert.Single(annotations); var annotation = Assert.Single(annotations);
Assert.True(annotation.HasDownAppearance); Assert.True(annotation.HasDownAppearance);

View File

@ -28,7 +28,7 @@
{ {
var page = document.GetPage(1); var page = document.GetPage(1);
var annotations = page.ExperimentalAccess.GetAnnotations().ToList(); var annotations = page.GetAnnotations().ToArray();
Assert.NotEmpty(annotations); Assert.NotEmpty(annotations);

View File

@ -285,7 +285,7 @@
{ {
var page1 = document.GetPage(1); var page1 = document.GetPage(1);
var background = page1.ExperimentalAccess.Paths[0]; var background = page1.Paths[0];
Assert.True(background.IsFilled); Assert.True(background.IsFilled);
var (r, g, b) = background.FillColor.ToRGBValues(); var (r, g, b) = background.FillColor.ToRGBValues();
@ -327,7 +327,7 @@
using (var document = PdfDocument.Open(path)) using (var document = PdfDocument.Open(path))
{ {
Page page1 = document.GetPage(1); Page page1 = document.GetPage(1);
var paths1 = page1.ExperimentalAccess.Paths.Where(p => p.IsFilled).ToArray(); var paths1 = page1.Paths.Where(p => p.IsFilled).ToArray();
var reflexRed = paths1[0].FillColor.ToRGBValues(); // 'Reflex Red' Separation color space var reflexRed = paths1[0].FillColor.ToRGBValues(); // 'Reflex Red' Separation color space
Assert.Equal(0.930496, reflexRed.r, 6); Assert.Equal(0.930496, reflexRed.r, 6);
Assert.Equal(0.111542, reflexRed.g, 6); Assert.Equal(0.111542, reflexRed.g, 6);
@ -341,7 +341,7 @@
Assert.Equal("w", firstLetter.Value); Assert.Equal("w", firstLetter.Value);
Assert.Equal((0, 0, 1), firstLetter.Color.ToRGBValues()); // Blue Assert.Equal((0, 0, 1), firstLetter.Color.ToRGBValues()); // Blue
var paths2 = page2.ExperimentalAccess.Paths; var paths2 = page2.Paths;
var filledPath = paths2.Where(p => p.IsFilled).ToArray(); var filledPath = paths2.Where(p => p.IsFilled).ToArray();
var filledRects = filledPath.Where(p => p.Count == 1 && p[0].IsDrawnAsRectangle).ToArray(); var filledRects = filledPath.Where(p => p.Count == 1 && p[0].IsDrawnAsRectangle).ToArray();

View File

@ -24,7 +24,7 @@
{ {
var page = document.GetPage(i + 1); var page = document.GetPage(i + 1);
Assert.NotNull(page.ExperimentalAccess.GetAnnotations().ToList()); Assert.NotNull(page.GetAnnotations().ToArray());
} }
} }
} }
@ -45,7 +45,7 @@
{ {
var page = document.GetPage(i + 1); var page = document.GetPage(i + 1);
Assert.NotNull(page.ExperimentalAccess.GetAnnotations().ToList()); Assert.NotNull(page.GetAnnotations().ToArray());
} }
} }
} }

View File

@ -8,7 +8,7 @@
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("AcroFormsBasicFields.pdf"))) using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("AcroFormsBasicFields.pdf")))
{ {
var page = document.GetPage(1); var page = document.GetPage(1);
var oc = page.ExperimentalAccess.GetOptionalContents(); var oc = page.GetOptionalContents();
Assert.Empty(oc); Assert.Empty(oc);
} }
@ -20,7 +20,7 @@
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("odwriteex.pdf"))) using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("odwriteex.pdf")))
{ {
var page = document.GetPage(1); var page = document.GetPage(1);
var oc = page.ExperimentalAccess.GetOptionalContents(); var oc = page.GetOptionalContents();
Assert.Equal(3, oc.Count); Assert.Equal(3, oc.Count);
@ -40,19 +40,19 @@
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("Layer pdf - 322_High_Holborn_building_Brochure.pdf"))) using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("Layer pdf - 322_High_Holborn_building_Brochure.pdf")))
{ {
var page1 = document.GetPage(1); var page1 = document.GetPage(1);
var oc1 = page1.ExperimentalAccess.GetOptionalContents(); var oc1 = page1.GetOptionalContents();
Assert.Equal(16, oc1.Count); Assert.Equal(16, oc1.Count);
Assert.Contains("NEW ARRANGEMENT", oc1); Assert.Contains("NEW ARRANGEMENT", oc1);
var page2 = document.GetPage(2); var page2 = document.GetPage(2);
var oc2 = page2.ExperimentalAccess.GetOptionalContents(); var oc2 = page2.GetOptionalContents();
Assert.Equal(15, oc2.Count); Assert.Equal(15, oc2.Count);
Assert.DoesNotContain("NEW ARRANGEMENT", oc2); Assert.DoesNotContain("NEW ARRANGEMENT", oc2);
Assert.Contains("WDL Shell text", oc2); Assert.Contains("WDL Shell text", oc2);
Assert.Equal(2, oc2["WDL Shell text"].Count); Assert.Equal(2, oc2["WDL Shell text"].Count);
var page3 = document.GetPage(3); var page3 = document.GetPage(3);
var oc3 = page3.ExperimentalAccess.GetOptionalContents(); var oc3 = page3.GetOptionalContents();
Assert.Equal(15, oc3.Count); Assert.Equal(15, oc3.Count);
Assert.Contains("WDL Shell text", oc3); Assert.Contains("WDL Shell text", oc3);
Assert.Equal(2, oc3["WDL Shell text"].Count); Assert.Equal(2, oc3["WDL Shell text"].Count);

View File

@ -12,7 +12,7 @@
{ {
var page = document.GetPage(1); var page = document.GetPage(1);
var annotationStamp = page.ExperimentalAccess.GetAnnotations().ElementAt(14); var annotationStamp = page.GetAnnotations().ElementAt(14);
Assert.Equal(Annotations.AnnotationType.Stamp, annotationStamp.Type); Assert.Equal(Annotations.AnnotationType.Stamp, annotationStamp.Type);
Assert.True(annotationStamp.HasNormalAppearance); Assert.True(annotationStamp.HasNormalAppearance);
@ -28,7 +28,7 @@
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("output_w3c_csswg_drafts_issues2023.pdf"))) using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("output_w3c_csswg_drafts_issues2023.pdf")))
{ {
var page = document.GetPage(1); var page = document.GetPage(1);
var path = page.ExperimentalAccess.Paths.Single(); var path = page.Paths.Single();
var color = path.FillColor; var color = path.FillColor;
Assert.Equal(ColorSpace.Pattern, color.ColorSpace); Assert.Equal(ColorSpace.Pattern, color.ColorSpace);
@ -55,7 +55,7 @@
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("22060_A1_01_Plans-1.pdf"))) using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("22060_A1_01_Plans-1.pdf")))
{ {
var page = document.GetPage(1); var page = document.GetPage(1);
var filledPath = page.ExperimentalAccess.Paths.Where(p => p.IsFilled).ToArray(); var filledPath = page.Paths.Where(p => p.IsFilled).ToArray();
var pattern = filledPath[0].FillColor; var pattern = filledPath[0].FillColor;
Assert.Equal(ColorSpace.Pattern, pattern.ColorSpace); Assert.Equal(ColorSpace.Pattern, pattern.ColorSpace);
@ -100,7 +100,7 @@
{ {
// page 53 // page 53
var page = document.GetPage(53); var page = document.GetPage(53);
var strokedPath = page.ExperimentalAccess.Paths.Where(p => p.StrokeColor?.ColorSpace == ColorSpace.Pattern).ToArray(); var strokedPath = page.Paths.Where(p => p.StrokeColor?.ColorSpace == ColorSpace.Pattern).ToArray();
Assert.Equal(5, strokedPath.Length); Assert.Equal(5, strokedPath.Length);
foreach (var p in strokedPath) foreach (var p in strokedPath)
{ {
@ -114,7 +114,7 @@
// page 307 // page 307
page = document.GetPage(307); page = document.GetPage(307);
strokedPath = page.ExperimentalAccess.Paths.Where(p => p.StrokeColor?.ColorSpace == ColorSpace.Pattern).ToArray(); strokedPath = page.Paths.Where(p => p.StrokeColor?.ColorSpace == ColorSpace.Pattern).ToArray();
Assert.Equal(2, strokedPath.Length); Assert.Equal(2, strokedPath.Length);
foreach (var p in strokedPath) foreach (var p in strokedPath)
{ {

View File

@ -32,7 +32,7 @@
{ {
var page = document.GetPage(1); var page = document.GetPage(1);
Assert.Equal(612, page.Height); Assert.Equal(612, page.Height);
Assert.Equal(224, page.ExperimentalAccess.Paths.Count); Assert.Equal(224, page.Paths.Count);
} }
} }

View File

@ -171,7 +171,7 @@
DrawRectangle(letter.GlyphRectangle, graphics, violetPen, imageHeight, scale); DrawRectangle(letter.GlyphRectangle, graphics, violetPen, imageHeight, scale);
} }
foreach (var annotation in page.ExperimentalAccess.GetAnnotations()) foreach (var annotation in page.GetAnnotations())
{ {
DrawRectangle(annotation.Rectangle, graphics, bluePen, imageHeight, scale); DrawRectangle(annotation.Rectangle, graphics, bluePen, imageHeight, scale);
} }

View File

@ -115,16 +115,16 @@
output.AddPage(existing, 1); output.AddPage(existing, 1);
results = output.Build(); results = output.Build();
var pg = existing.GetPage(1); var pg = existing.GetPage(1);
var annots = pg.ExperimentalAccess.GetAnnotations().ToList(); var annots = pg.GetAnnotations().ToArray();
annotCount = annots.Count; annotCount = annots.Length;
Assert.Contains(annots, x => x.Type == Annotations.AnnotationType.Link); Assert.Contains(annots, x => x.Type == Annotations.AnnotationType.Link);
} }
using (var rewritten = PdfDocument.Open(results, ParsingOptions.LenientParsingOff)) using (var rewritten = PdfDocument.Open(results, ParsingOptions.LenientParsingOff))
{ {
var pg = rewritten.GetPage(1); var pg = rewritten.GetPage(1);
var annots = pg.ExperimentalAccess.GetAnnotations().ToList(); var annots = pg.GetAnnotations().ToArray();
Assert.Equal(annotCount - 1, annots.Count); Assert.Equal(annotCount - 1, annots.Length);
Assert.DoesNotContain(annots, x => x.Type == Annotations.AnnotationType.Link); Assert.DoesNotContain(annots, x => x.Type == Annotations.AnnotationType.Link);
} }
} }

View File

@ -194,7 +194,7 @@
using (var document = PdfDocument.Open(result, ParsingOptions.LenientParsingOff)) using (var document = PdfDocument.Open(result, ParsingOptions.LenientParsingOff))
{ {
Assert.Equal(2, document.GetPages().Sum( Assert.Equal(2, document.GetPages().Sum(
page => page.ExperimentalAccess.GetAnnotations().Count(x => x.Type == Annotations.AnnotationType.Link))); page => page.GetAnnotations().Count(x => x.Type == Annotations.AnnotationType.Link)));
} }
} }
@ -209,7 +209,7 @@
using (var document = PdfDocument.Open(result, ParsingOptions.LenientParsingOff)) using (var document = PdfDocument.Open(result, ParsingOptions.LenientParsingOff))
{ {
Assert.Equal(1, document.GetPages().Sum( Assert.Equal(1, document.GetPages().Sum(
page => page.ExperimentalAccess.GetAnnotations().Count(x => x.Type == Annotations.AnnotationType.Link))); page => page.GetAnnotations().Count(x => x.Type == Annotations.AnnotationType.Link)));
} }
} }

View File

@ -83,9 +83,15 @@
/// </summary> /// </summary>
public IReadOnlyList<IGraphicsStateOperation> Operations => Content.GraphicsStateOperations; public IReadOnlyList<IGraphicsStateOperation> Operations => Content.GraphicsStateOperations;
/// <summary>
/// The set of <see cref="PdfPath"/>s drawn by the PDF content.
/// </summary>
public IReadOnlyList<PdfPath> Paths => Content?.Paths ?? Array.Empty<PdfPath>();
/// <summary> /// <summary>
/// Access to members whose future locations within the API will change without warning. /// Access to members whose future locations within the API will change without warning.
/// </summary> /// </summary>
[Obsolete("Use methods and properties directly at Page level.")]
public Experimental ExperimentalAccess { get; } public Experimental ExperimentalAccess { get; }
internal Page(int number, DictionaryToken dictionary, MediaBox mediaBox, CropBox cropBox, PageRotationDegrees rotation, internal Page(int number, DictionaryToken dictionary, MediaBox mediaBox, CropBox cropBox, PageRotationDegrees rotation,
@ -119,7 +125,7 @@
Height = viewBox.Height; Height = viewBox.Height;
Size = viewBox.GetPageSize(); Size = viewBox.GetPageSize();
ExperimentalAccess = new Experimental(this, annotationProvider); ExperimentalAccess = new Experimental(this);
this.annotationProvider = annotationProvider; this.annotationProvider = annotationProvider;
this.pdfScanner = pdfScanner ?? throw new ArgumentNullException(nameof(pdfScanner)); this.pdfScanner = pdfScanner ?? throw new ArgumentNullException(nameof(pdfScanner));
} }
@ -197,72 +203,92 @@
/// </summary> /// </summary>
public IReadOnlyList<MarkedContentElement> GetMarkedContents() => Content.GetMarkedContents(); public IReadOnlyList<MarkedContentElement> GetMarkedContents() => Content.GetMarkedContents();
/// <summary>
/// Get the annotation objects from the page.
/// </summary>
/// <returns>The lazily evaluated set of annotations on this page.</returns>
public IEnumerable<Annotation> GetAnnotations()
{
return annotationProvider.GetAnnotations();
}
/// <summary>
/// Gets any optional content on the page.
/// <para>Does not handle XObjects and annotations for the time being.</para>
/// </summary>
public IReadOnlyDictionary<string, IReadOnlyList<OptionalContentGroupElement>> GetOptionalContents()
{
List<OptionalContentGroupElement> mcesOptional = new List<OptionalContentGroupElement>();
// 4.10.2
// Optional content in content stream
GetOptionalContentsRecursively(Content?.GetMarkedContents(), ref mcesOptional);
// Optional content in XObjects and annotations
// TO DO
//var annots = GetAnnotations().ToList();
return mcesOptional.GroupBy(oc => oc.Name).ToDictionary(g => g.Key!, g => (IReadOnlyList<OptionalContentGroupElement>)g.ToList());
}
private void GetOptionalContentsRecursively(IReadOnlyList<MarkedContentElement>? markedContentElements, ref List<OptionalContentGroupElement> mcesOptional)
{
if (markedContentElements is null || markedContentElements.Count == 0)
{
return;
}
foreach (var mce in markedContentElements)
{
if (mce.Tag == "OC")
{
mcesOptional.Add(new OptionalContentGroupElement(mce, pdfScanner));
// we don't recurse
}
else if (mce.Children?.Count > 0)
{
GetOptionalContentsRecursively(mce.Children, ref mcesOptional);
}
}
}
/// <summary> /// <summary>
/// Provides access to useful members which will change in future releases. /// Provides access to useful members which will change in future releases.
/// </summary> /// </summary>
[Obsolete("Use methods and properties directly at Page level.")]
public class Experimental public class Experimental
{ {
private readonly Page page; private readonly Page page;
private readonly AnnotationProvider annotationProvider;
/// <summary> /// <summary>
/// The set of <see cref="PdfPath"/>s drawn by the PDF content. /// The set of <see cref="PdfPath"/>s drawn by the PDF content.
/// </summary> /// </summary>
public IReadOnlyList<PdfPath> Paths => page.Content?.Paths ?? new List<PdfPath>(); [Obsolete("Use Page.Paths instead.")]
public IReadOnlyList<PdfPath> Paths => page.Paths;
internal Experimental(Page page, AnnotationProvider annotationProvider) internal Experimental(Page page)
{ {
this.page = page; this.page = page;
this.annotationProvider = annotationProvider;
} }
/// <summary> /// <summary>
/// Get the annotation objects from the page. /// Get the annotation objects from the page.
/// </summary> /// </summary>
/// <returns>The lazily evaluated set of annotations on this page.</returns> /// <returns>The lazily evaluated set of annotations on this page.</returns>
[Obsolete("Use Page.GetAnnotations() instead.")]
public IEnumerable<Annotation> GetAnnotations() public IEnumerable<Annotation> GetAnnotations()
{ {
return annotationProvider.GetAnnotations(); return page.GetAnnotations();
} }
/// <summary> /// <summary>
/// Gets any optional content on the page. /// Gets any optional content on the page.
/// <para>Does not handle XObjects and annotations for the time being.</para> /// <para>Does not handle XObjects and annotations for the time being.</para>
/// </summary> /// </summary>
[Obsolete("Use Page.GetOptionalContents() instead.")]
public IReadOnlyDictionary<string, IReadOnlyList<OptionalContentGroupElement>> GetOptionalContents() public IReadOnlyDictionary<string, IReadOnlyList<OptionalContentGroupElement>> GetOptionalContents()
{ {
List<OptionalContentGroupElement> mcesOptional = new List<OptionalContentGroupElement>(); return page.GetOptionalContents();
// 4.10.2
// Optional content in content stream
GetOptionalContentsRecursively(page.Content?.GetMarkedContents(), ref mcesOptional);
// Optional content in XObjects and annotations
// TO DO
//var annots = GetAnnotations().ToList();
return mcesOptional.GroupBy(oc => oc.Name).ToDictionary(g => g.Key!, g => (IReadOnlyList<OptionalContentGroupElement>)g.ToList());
}
private void GetOptionalContentsRecursively(IReadOnlyList<MarkedContentElement>? markedContentElements, ref List<OptionalContentGroupElement> mcesOptional)
{
if (markedContentElements is null || markedContentElements.Count == 0)
{
return;
}
foreach (var mce in markedContentElements)
{
if (mce.Tag == "OC")
{
mcesOptional.Add(new OptionalContentGroupElement(mce, page.pdfScanner));
// we don't recurse
}
else if (mce.Children?.Count > 0)
{
GetOptionalContentsRecursively(mce.Children, ref mcesOptional);
}
}
} }
} }
} }