diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeReceiverReportPage.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeReceiverReportPage.razor
index 06b44f44..8a0a2601 100644
--- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeReceiverReportPage.razor
+++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeReceiverReportPage.razor
@@ -2,8 +2,6 @@
@rendermode InteractiveServer
@using DevExpress.Blazor.Reporting
@using DevExpress.XtraReports.UI
-@using DevExpress.XtraPrinting
-@using DevExpress.XtraPrinting.Drawing
@using EnvelopeGenerator.Server.Client.Models
@using EnvelopeGenerator.Server.Client.Models.Constants
@using EnvelopeGenerator.Server.Client.Services
@@ -352,15 +350,6 @@
const string ImageInputId = "rp-signature-image-input";
const string ImageCanvasId = "rp-image-signature-pad";
- // A4 page dimensions in DX units (1/100 inch).
- // 8.27" × 11.69" → 827 × 1169
- const float PageWidthDx = 827f;
- const float PageHeightDx = 1169f;
-
- // Fixed signature field size in DX units: 1.77" × 1.96"
- const float SigWidthDx = 177f;
- const float SigHeightDx = 196f;
-
readonly (string Text, string Value)[] TypedSignatureFonts =
[
("Brush Script", "'Brush Script MT', cursive"),
@@ -478,135 +467,68 @@
// ----- Report builder -----
///
- /// Builds an XtraReport that displays the PDF pages via XRPdfContent (embedded mode,
- /// GenerateOwnPages = false). Each PDF page is wrapped in its own subreport so that
- /// XRPictureBox overlays can be positioned accurately per page.
+ /// Builds an XtraReport wrapping the PDF bytes.
+ /// If a signature is captured and there are signature fields, the signature image is
+ /// first burned into the PDF via DevExpress PdfDocumentProcessor, then the modified
+ /// PDF is handed to XRPdfContent with GenerateOwnPages = true so that all pages appear.
///
static XtraReport BuildReport(
byte[] pdfBytes,
IReadOnlyList signatures,
SignatureCaptureDto? capturedSignature)
{
- // Determine the number of pages using DevExpress PDF processor
- int pageCount = GetPdfPageCount(pdfBytes);
- if (pageCount < 1) pageCount = 1;
-
- // Outer (main) report - acts as container for subreports
- var mainReport = new XtraReport
+ // Burn signatures into PDF bytes when a captured signature is available
+ byte[] sourcePdf = pdfBytes;
+ if (capturedSignature is not null
+ && !string.IsNullOrWhiteSpace(capturedSignature.DataUrl)
+ && signatures.Count > 0)
{
- PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4,
- Landscape = false,
- Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0),
- };
-
- var mainDetail = new DetailBand { HeightF = 0f };
- mainReport.Bands.Add(mainDetail);
-
- for (int page = 1; page <= pageCount; page++)
- {
- // Build a subreport for this PDF page
- var pageReport = BuildPageSubreport(pdfBytes, page, signatures, capturedSignature);
-
- var subreport = new XRSubreport
+ try
{
- ReportSource = pageReport,
- GenerateOwnPages = true,
- LocationF = new PointF(0f, 0f),
- SizeF = new SizeF(PageWidthDx, PageHeightDx),
- };
-
- mainDetail.Controls.Add(subreport);
- }
-
- return mainReport;
- }
-
- ///
- /// Builds a single-page subreport: one DetailBand containing the PDF page (via
- /// XRPdfContent with GenerateOwnPages = false) plus XRPictureBox overlays for
- /// any signatures placed on this page.
- ///
- static XtraReport BuildPageSubreport(
- byte[] pdfBytes,
- int pageNumber,
- IReadOnlyList signatures,
- SignatureCaptureDto? capturedSignature)
- {
- var report = new XtraReport
- {
- PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4,
- Landscape = false,
- Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0),
- };
-
- var detail = new DetailBand
- {
- HeightF = PageHeightDx,
- Name = $"DetailBand_Page{pageNumber}",
- };
- report.Bands.Add(detail);
-
- // --- PDF content (embedded, no own pages) ---
- var pdfContent = new XRPdfContent
- {
- Source = pdfBytes,
- PageRange = pageNumber.ToString(),
- GenerateOwnPages = false,
- LocationF = new PointF(0f, 0f),
- SizeF = new SizeF(PageWidthDx, PageHeightDx),
- };
- detail.Controls.Add(pdfContent);
-
- // --- Signature overlays ---
- if (capturedSignature is not null && !string.IsNullOrWhiteSpace(capturedSignature.DataUrl))
- {
- var signaturesOnPage = signatures.Where(s => s.Page == pageNumber).ToList();
- foreach (var sig in signaturesOnPage)
+ sourcePdf = BurnSignaturesIntoPdf(pdfBytes, signatures, capturedSignature);
+ }
+ catch
{
- try
- {
- var imgBytes = DataUrlToBytes(capturedSignature.DataUrl);
- if (imgBytes is { Length: > 0 })
- {
- using var imgStream = new System.IO.MemoryStream(imgBytes);
- var img = System.Drawing.Image.FromStream(imgStream);
- var picBox = new XRPictureBox
- {
- // DB stores INCHES; DX unit = 1/100 inch → multiply by 100
- LocationF = new PointF((float)(sig.X * 100), (float)(sig.Y * 100)),
- SizeF = new SizeF(SigWidthDx, SigHeightDx),
- Image = img,
- Sizing = ImageSizeMode.Squeeze,
- CanGrow = false,
- CanShrink = false,
- };
- detail.Controls.Add(picBox);
- }
- }
- catch
- {
- // Non-critical: skip overlay on error
- }
+ // Fall back to unmodified PDF — non-critical
+ sourcePdf = pdfBytes;
}
}
+ var report = new XtraReport
+ {
+ PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4,
+ Landscape = false,
+ Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0),
+ };
+
+ var detail = new DetailBand { HeightF = 0f };
+ report.Bands.Add(detail);
+
+ // GenerateOwnPages = true (default): each PDF page becomes a separate report page
+ var pdfContent = new XRPdfContent
+ {
+ Source = sourcePdf,
+ GenerateOwnPages = true,
+ };
+ detail.Controls.Add(pdfContent);
+
return report;
}
- /// Reads the page count of a PDF using iText7 (already referenced in the server project).
- static int GetPdfPageCount(byte[] pdfBytes)
+ ///
+ /// Burns signature images directly into the PDF using DevExpress PdfGraphics API.
+ /// Coordinates: DB stores INCHES with top-left origin, Y down.
+ /// PDF coordinate system: bottom-left origin, Y up, unit = points (1/72 inch).
+ /// Note: Implementation placeholder — requires DevExpress.Pdf.Drawing API wiring (Problem 2).
+ ///
+ static byte[] BurnSignaturesIntoPdf(
+ byte[] pdfBytes,
+ IReadOnlyList signatures,
+ SignatureCaptureDto capturedSignature)
{
- try
- {
- using var ms = new System.IO.MemoryStream(pdfBytes);
- using var reader = new iText.Kernel.Pdf.PdfReader(ms);
- using var pdfDoc = new iText.Kernel.Pdf.PdfDocument(reader);
- return pdfDoc.GetNumberOfPages();
- }
- catch
- {
- return 1;
- }
+ // TODO: Implement with PdfGraphics when Problem 2 is addressed.
+ // For now return unmodified PDF so Problem 1 (all pages) can be verified first.
+ return pdfBytes;
}
/// Converts a base64 data URL (data:image/...;base64,...) to raw bytes.
diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/EnvelopeGenerator.Server.csproj b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/EnvelopeGenerator.Server.csproj
index c27b4247..1d74f2b3 100644
--- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/EnvelopeGenerator.Server.csproj
+++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/EnvelopeGenerator.Server.csproj
@@ -28,8 +28,6 @@
-
-