From 44a9dd348b4e587a221d1dbf3f84b5231c44395c Mon Sep 17 00:00:00 2001 From: Julien R Date: Fri, 13 Oct 2023 17:24:44 +0200 Subject: [PATCH 1/3] implement PdfFileAttachmentAnnotation --- .../src/PdfSharp-gdi/PdfSharp-gdi.csproj | 2 + .../src/PdfSharp-wpf/PdfSharp-wpf.csproj | 2 + .../PdfFileAttachmentAnnotation.cs | 109 ++++++++++++++++++ .../enums/PdfFileAttachmentAnnotationIcon.cs | 36 ++++++ .../src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs | 34 ++++++ 5 files changed, 183 insertions(+) create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/enums/PdfFileAttachmentAnnotationIcon.cs diff --git a/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj b/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj index e0431f99..cff5a9ff 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj @@ -241,6 +241,8 @@ + + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj b/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj index f2bab080..44eb1211 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj @@ -240,6 +240,8 @@ + + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs new file mode 100644 index 00000000..8675beb7 --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs @@ -0,0 +1,109 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Pdf.Advanced; + +namespace PdfSharp.Pdf.Annotations +{ + /// + /// Represents a file attachment annotation. + /// + public sealed class PdfFileAttachmentAnnotation : PdfAnnotation + { + /// + /// Initializes a new instance of the class. + /// + public PdfFileAttachmentAnnotation() + { + Initialize(); + } + + /// + /// Initializes a new instance of the class. + /// + public PdfFileAttachmentAnnotation(PdfDocument document) + : base(document) + { + Initialize(); + } + + void Initialize() + { + Elements.SetName(Keys.Subtype, "/FileAttachment"); + Icon = PdfFileAttachmentAnnotationIcon.PushPin; + Flags = PdfAnnotationFlags.Locked; + } + + /// + /// Creates a file attachment annotation. + /// + public static PdfFileAttachmentAnnotation CreateFileAttachmentAnnotation(PdfRectangle rect, PdfFileSpecification fileSpecification) + { + var annot = new PdfFileAttachmentAnnotation + { + Rectangle = rect, + }; + return annot; + } + + /// + /// Gets or sets an icon to be used in displaying the annotation. + /// + public PdfFileAttachmentAnnotationIcon Icon + { + get + { + string value = Elements.GetName(Keys.Name); + if (value == "") + return PdfFileAttachmentAnnotationIcon.NoIcon; + value = value.Substring(1); + if (!Enum.IsDefined(typeof(PdfFileAttachmentAnnotationIcon), value)) + return PdfFileAttachmentAnnotationIcon.NoIcon; + return (PdfFileAttachmentAnnotationIcon)Enum.Parse(typeof(PdfFileAttachmentAnnotationIcon), value, false); + } + set + { + if (Enum.IsDefined(typeof(PdfFileAttachmentAnnotationIcon), value) && + PdfFileAttachmentAnnotationIcon.NoIcon != value) + { + Elements.SetName(Keys.Name, "/" + value.ToString()); + } + else + Elements.Remove(Keys.Name); + } + } + + + /// + /// Predefined keys of this dictionary. + /// + internal new class Keys : PdfAnnotation.Keys + { + /// + /// (Required) The file associated with this annotation. + /// + [KeyInfo(KeyType.FileSpecification | KeyType.Required)] + public const string FS = "/FS"; + + /// + /// (Optional) The name of an icon that shall be used in displaying the annotation. + /// Conforming readers shall provide predefined icon appearances for at least the following names: + /// Graph + /// PushPin + /// Paperclip + /// Tag + /// + [KeyInfo(KeyType.Name | KeyType.Optional)] + public const string Name = "/Name"; + + public static DictionaryMeta Meta => _meta ??= CreateMeta(typeof(Keys)); + + static DictionaryMeta? _meta; + } + + /// + /// Gets the KeysMeta of this dictionary type. + /// + internal override DictionaryMeta Meta => Keys.Meta; + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/enums/PdfFileAttachmentAnnotationIcon.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/enums/PdfFileAttachmentAnnotationIcon.cs new file mode 100644 index 00000000..b9b78042 --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/enums/PdfFileAttachmentAnnotationIcon.cs @@ -0,0 +1,36 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +namespace PdfSharp.Pdf.Annotations +{ + /// + /// Specifies the pre-defined icon names of file attachment annotations. + /// + public enum PdfFileAttachmentAnnotationIcon + { + /// + /// A pre-defined annotation icon. + /// + NoIcon, + + /// + /// A pre-defined annotation icon. + /// + Graph, + + /// + /// A pre-defined annotation icon. + /// + PushPin, + + /// + /// A pre-defined annotation icon. + /// + Paperclip, + + /// + /// A pre-defined annotation icon. + /// + Tag, + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs index 29724160..00b66bc3 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs @@ -6,6 +6,7 @@ using PdfSharp.Drawing; using PdfSharp.Pdf.Advanced; using PdfSharp.Pdf.Annotations; +using System.IO; namespace PdfSharp.Pdf { @@ -498,6 +499,39 @@ public PdfLinkAnnotation AddFileLink(PdfRectangle rect, string fileName) return annotation; } + /// + /// Adds a file attachment annotation. + /// + /// The rect. + /// The file specification + public PdfFileAttachmentAnnotation AddFileAttachmentAnnotation(PdfRectangle rect, PdfFileSpecification fileSpecification) + { + if (fileSpecification.Reference == null) + Owner.Internals.AddObject(fileSpecification); + + var annotation = PdfFileAttachmentAnnotation.CreateFileAttachmentAnnotation(rect, fileSpecification); + Annotations.Add(annotation); + annotation.Elements.SetReference(PdfFileAttachmentAnnotation.Keys.FS, fileSpecification.ReferenceNotNull); + return annotation; + } + + /// + /// Adds a file attachment annotation. + /// + /// The rect. + /// The file stream + /// The file name + public PdfFileAttachmentAnnotation AddFileAttachmentAnnotation(PdfRectangle rect, PdfEmbeddedFileStream fileStream, string fileName) + { + var fileSpecification = new PdfFileSpecification(Owner, fileStream, fileName); + Owner.Internals.AddObject(fileSpecification); + + var annotation = PdfFileAttachmentAnnotation.CreateFileAttachmentAnnotation(rect, fileSpecification); + Annotations.Add(annotation); + annotation.Elements.SetReference(PdfFileAttachmentAnnotation.Keys.FS, fileSpecification.ReferenceNotNull); + return annotation; + } + #endregion /// From b854215f186d47c8ddcac6d735cc7d307023a097 Mon Sep 17 00:00:00 2001 From: Julien R Date: Fri, 20 Oct 2023 17:22:14 +0200 Subject: [PATCH 2/3] enable display of custom appearance for file attachment annotations --- .../src/PdfSharp-gdi/PdfSharp-gdi.csproj | 3 +- .../src/PdfSharp-wpf/PdfSharp-wpf.csproj | 3 +- .../IAnnotationAppearanceHandler.cs | 12 ++++++ .../PdfFileAttachmentAnnotation.cs | 37 +++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/IAnnotationAppearanceHandler.cs diff --git a/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj b/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj index cff5a9ff..128152d4 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj @@ -1,4 +1,4 @@ - + library @@ -234,6 +234,7 @@ + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj b/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj index 44eb1211..789408bc 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj @@ -1,4 +1,4 @@ - + library @@ -233,6 +233,7 @@ + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/IAnnotationAppearanceHandler.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/IAnnotationAppearanceHandler.cs new file mode 100644 index 00000000..e686b05f --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/IAnnotationAppearanceHandler.cs @@ -0,0 +1,12 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Drawing; + +namespace PdfSharp.Pdf.Annotations +{ + public interface IAnnotationAppearanceHandler + { + void DrawAppearance(XGraphics gfx, XRect rect); + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs index 8675beb7..734e2a9c 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs @@ -1,6 +1,7 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. +using PdfSharp.Drawing; using PdfSharp.Pdf.Advanced; namespace PdfSharp.Pdf.Annotations @@ -73,6 +74,42 @@ public PdfFileAttachmentAnnotationIcon Icon } } + public IAnnotationAppearanceHandler CustomAppearanceHandler { get; set; } + + /// + /// Creates the custom appearance form X object for this annotation + /// + public void RenderCustomAppearance() + { + var visible = !(Rectangle.X1 + Rectangle.X2 + Rectangle.Y1 + Rectangle.Y2 == 0); + + if (!visible) + return; + + if (CustomAppearanceHandler == null) + throw new Exception("AppearanceHandler is null"); + + XForm form = new XForm(_document, Rectangle.Size); + XGraphics gfx = XGraphics.FromForm(form); + + CustomAppearanceHandler.DrawAppearance(gfx, Rectangle.ToXRect()); + + form.DrawingFinished(); + + // Get existing or create new appearance dictionary + if (Elements[PdfAnnotation.Keys.AP] is not PdfDictionary ap) + { + ap = new PdfDictionary(_document); + Elements[PdfAnnotation.Keys.AP] = ap; + } + + // Set XRef to normal state + ap.Elements["/N"] = form.PdfForm.Reference; + + form.PdfRenderer.Close(); + + Icon = PdfFileAttachmentAnnotationIcon.NoIcon; + } /// /// Predefined keys of this dictionary. From fe0bdf2fd13e1801484f77da8eb517459601923c Mon Sep 17 00:00:00 2001 From: Edouard Paumier Date: Fri, 3 Nov 2023 10:49:51 +0100 Subject: [PATCH 3/3] Improving slightly the syntax --- .../PdfFileAttachmentAnnotation.cs | 18 ++++++++++-------- .../src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs index 734e2a9c..96d33fd5 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/PdfFileAttachmentAnnotation.cs @@ -1,4 +1,4 @@ -// PDFsharp - A .NET library for processing PDF +// PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. using PdfSharp.Drawing; @@ -38,11 +38,11 @@ void Initialize() /// /// Creates a file attachment annotation. /// - public static PdfFileAttachmentAnnotation CreateFileAttachmentAnnotation(PdfRectangle rect, PdfFileSpecification fileSpecification) + public static PdfFileAttachmentAnnotation CreateFileAttachmentAnnotation(PdfRectangle rectangle) { var annot = new PdfFileAttachmentAnnotation { - Rectangle = rect, + Rectangle = rectangle, }; return annot; } @@ -57,15 +57,17 @@ public PdfFileAttachmentAnnotationIcon Icon string value = Elements.GetName(Keys.Name); if (value == "") return PdfFileAttachmentAnnotationIcon.NoIcon; + value = value.Substring(1); if (!Enum.IsDefined(typeof(PdfFileAttachmentAnnotationIcon), value)) return PdfFileAttachmentAnnotationIcon.NoIcon; + return (PdfFileAttachmentAnnotationIcon)Enum.Parse(typeof(PdfFileAttachmentAnnotationIcon), value, false); } set { - if (Enum.IsDefined(typeof(PdfFileAttachmentAnnotationIcon), value) && - PdfFileAttachmentAnnotationIcon.NoIcon != value) + if (value != PdfFileAttachmentAnnotationIcon.NoIcon && + Enum.IsDefined(typeof(PdfFileAttachmentAnnotationIcon), value)) { Elements.SetName(Keys.Name, "/" + value.ToString()); } @@ -74,14 +76,14 @@ public PdfFileAttachmentAnnotationIcon Icon } } - public IAnnotationAppearanceHandler CustomAppearanceHandler { get; set; } + public IAnnotationAppearanceHandler? CustomAppearanceHandler { get; set; } /// /// Creates the custom appearance form X object for this annotation /// public void RenderCustomAppearance() { - var visible = !(Rectangle.X1 + Rectangle.X2 + Rectangle.Y1 + Rectangle.Y2 == 0); + var visible = (Rectangle.X1 + Rectangle.X2 + Rectangle.Y1 + Rectangle.Y2) != 0; if (!visible) return; @@ -89,7 +91,7 @@ public void RenderCustomAppearance() if (CustomAppearanceHandler == null) throw new Exception("AppearanceHandler is null"); - XForm form = new XForm(_document, Rectangle.Size); + XForm form = new(_document, Rectangle.Size); XGraphics gfx = XGraphics.FromForm(form); CustomAppearanceHandler.DrawAppearance(gfx, Rectangle.ToXRect()); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs index 00b66bc3..98443e37 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs @@ -509,7 +509,7 @@ public PdfFileAttachmentAnnotation AddFileAttachmentAnnotation(PdfRectangle rect if (fileSpecification.Reference == null) Owner.Internals.AddObject(fileSpecification); - var annotation = PdfFileAttachmentAnnotation.CreateFileAttachmentAnnotation(rect, fileSpecification); + var annotation = PdfFileAttachmentAnnotation.CreateFileAttachmentAnnotation(rect); Annotations.Add(annotation); annotation.Elements.SetReference(PdfFileAttachmentAnnotation.Keys.FS, fileSpecification.ReferenceNotNull); return annotation; @@ -526,7 +526,7 @@ public PdfFileAttachmentAnnotation AddFileAttachmentAnnotation(PdfRectangle rect var fileSpecification = new PdfFileSpecification(Owner, fileStream, fileName); Owner.Internals.AddObject(fileSpecification); - var annotation = PdfFileAttachmentAnnotation.CreateFileAttachmentAnnotation(rect, fileSpecification); + var annotation = PdfFileAttachmentAnnotation.CreateFileAttachmentAnnotation(rect); Annotations.Add(annotation); annotation.Elements.SetReference(PdfFileAttachmentAnnotation.Keys.FS, fileSpecification.ReferenceNotNull); return annotation;