From a47729ebcaa734a2bb5321abbc07aecd4719ccab Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 6 Nov 2025 21:49:24 +0100 Subject: [PATCH] feat(pdf): implement annotation burning logic in BurnPdfCommandHandler - Added full implementation of BurnElementAnnotsToPDF method - Integrated PdfEditor for background rendering - Added annotation handling for form fields, images, and ink types - Included error handling for PDF loading and saving - Removed unused DigitalData.Core.Abstractions namespace --- .../EnvelopeGenerator.Application.csproj | 5 + .../Pdf/BurnPdfCommand.cs | 91 ++++++++++++++++++- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj index 8b5c5416..9decce7d 100644 --- a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj +++ b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj @@ -46,6 +46,7 @@ + @@ -165,4 +166,8 @@ + + + + diff --git a/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs b/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs index 97e1d783..d741166f 100644 --- a/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs +++ b/EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs @@ -1,7 +1,7 @@ using DigitalData.Core.Abstraction.Application.Repository; -using DigitalData.Core.Abstractions; using EnvelopeGenerator.Application.Common.Configurations; using EnvelopeGenerator.Domain.Entities; +using EnvelopeGenerator.PdfEditor; using GdPicture14; using MediatR; using Microsoft.EntityFrameworkCore; @@ -63,7 +63,94 @@ public class BurnPdfCommandHandler : IRequestHandler /// public byte[] BurnElementAnnotsToPDF(byte[] pSourceBuffer, List elements) { - return Enumerable.Empty().ToArray(); + // Add background + using (var doc = PdfEditor.Pdf.FromMemory(pSourceBuffer)) + { + // TODO: take the length from the largest y + pSourceBuffer = doc.Background(elements, 1.9500000000000002 * 0.93, 2.52 * 0.67) + .ExportStream() + .ToArray(); + + GdPictureStatus oResult; + using (var oSourceStream = new MemoryStream(pSourceBuffer)) + { + // Open PDF + oResult = _manager.InitFromStream(oSourceStream); + if (oResult != GdPictureStatus.OK) + throw new BurnAnnotationException($"Could not open document for burning: [{oResult}]"); + + // Imported from background (add to configuration) + double margin = 0.2; + double inchFactor = 72; + + // Y offset of form fields + var keys = new[] { "position", "city", "date" }; // add to configuration + double unitYOffsets = 0.2; + + var yOffsetsOfFF = keys + .Select((k, i) => new { Key = k, Value = unitYOffsets * i + 1 }) + .ToDictionary(x => x.Key, x => x.Value); + + // Add annotations + foreach (var element in elements) + { + double frameX = element.Left - 0.7 - margin; + + var frame = element.Annotations?.FirstOrDefault(a => a.Name == "frame"); + double frameY = element.Top - 0.5 - margin; + double frameYShift = frame.Y - frameY * inchFactor; + double frameXShift = frame.X - frameX * inchFactor; + + foreach (var annot in element.Annotations) + { + double yOffsetofFF; + if (!yOffsetsOfFF.TryGetValue(annot.Name, out yOffsetofFF)) + yOffsetofFF = 0; + + double y = frameY + yOffsetofFF; + + if (annot.Type == AnnotationType.FormField) + { + AddFormFieldValue( + annot.X / inchFactor, + y, + annot.Width / inchFactor, + annot.Height / inchFactor, + element.Page, + annot.Value + ); + } + else if (annot.Type == AnnotationType.Image) + { + AddImageAnnotation( + annot.X / inchFactor, + annot.Name == "signature" ? (annot.Y - frameYShift) / inchFactor : y, + annot.Width / inchFactor, + annot.Height / inchFactor, + element.Page, + annot.Value + ); + } + else if (annot.Type == AnnotationType.Ink) + { + AddInkAnnotation(element.Page, annot.Value); + } + } + } + + // Save PDF + using (var oNewStream = new MemoryStream()) + { + oResult = _manager.SaveDocumentToPDF(oNewStream); + if (oResult != GdPictureStatus.OK) + throw new BurnAnnotationException($"Could not save document to stream: [{oResult}]"); + + _manager.Close(); + + return oNewStream.ToArray(); + } + } + } } ///