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
This commit is contained in:
Developer 02 2025-11-06 21:49:24 +01:00
parent fcfed963b7
commit a47729ebca
2 changed files with 94 additions and 2 deletions

View File

@ -46,6 +46,7 @@
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
<ProjectReference Include="..\EnvelopeGenerator.PdfEditor\EnvelopeGenerator.PdfEditor.csproj" />
</ItemGroup>
<ItemGroup>
@ -165,4 +166,8 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Exceptions\" />
</ItemGroup>
</Project>

View File

@ -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<BurnPdfCommand>
/// <returns></returns>
public byte[] BurnElementAnnotsToPDF(byte[] pSourceBuffer, List<Signature> elements)
{
return Enumerable.Empty<byte>().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();
}
}
}
}
/// <summary>