using Elwig.Documents; using iText.IO.Font.Constants; using iText.Kernel.Font; using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Action; using iText.Kernel.Pdf.Canvas; using iText.Kernel.Pdf.Event; using iText.Kernel.Pdf.Xobject; using iText.Layout; using iText.Layout.Borders; using iText.Layout.Element; using iText.Layout.Properties; using System; using System.Collections.Generic; namespace Elwig.Helpers.Printing { public class FooterEventHandler : AbstractPdfDocumentEventHandler { private const float _fontSize = 10; private const float _ptInMm = 2.8346456693f; private const float _placeholderWidth = 50 * _ptInMm; private readonly string _date; private readonly string? _center; private readonly bool _doublePaged; private readonly bool _isPreview; private readonly bool _isBusiness; private readonly bool _showFoldMarks; private readonly PdfFont _font; private readonly PdfFont _fontBold; private readonly PdfFont _fontItalic; private readonly List _pageNumPlaceholders; public int NumberOfPages { get; private set; } public FooterEventHandler(Documents.Document? doc = null) { _date = $"{doc?.Date ?? DateOnly.FromDateTime(Utils.Today):dddd, d. MMMM yyyy}"; _center = doc?.DocumentId; _doublePaged = doc?.IsDoublePaged ?? false; _isPreview = doc?.IsPreview ?? false; _isBusiness = doc is BusinessDocument; _showFoldMarks = doc?.ShowFoldMarks ?? false; _font = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN); _fontBold = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLD); _fontItalic = PdfFontFactory.CreateFont(StandardFonts.TIMES_ITALIC); _pageNumPlaceholders = []; } protected override void OnAcceptedEvent(AbstractPdfDocumentEvent evt) { if (evt.GetType() == PdfDocumentEvent.END_PAGE) { OnPageEnd((PdfDocumentEvent)evt); } else if (evt.GetType() == PdfDocumentEvent.START_DOCUMENT_CLOSING) { OnDocumentClose((PdfDocumentEvent)evt); } } private void OnPageEnd(PdfDocumentEvent evt) { var pdf = evt.GetDocument(); var page = evt.GetPage(); var pageNum = pdf.GetPageNumber(page); var pageSize = page.GetPageSize(); float leftX1 = pageSize.GetLeft() + 25 * _ptInMm; float leftX2 = pageSize.GetLeft() + 20 * _ptInMm; float rightX1 = pageSize.GetRight() - 20 * _ptInMm; float rightX2 = pageSize.GetRight() - 25 * _ptInMm; float footerY = pageSize.GetBottom() + 25 * _ptInMm; float y = footerY + _fontSize; float footerWidth = 165 * _ptInMm; float footerHeight = 25 * _ptInMm; var pdfCanvas = new PdfCanvas(page.NewContentStreamAfter(), page.GetResources(), pdf); using var canvas = new Canvas(pdfCanvas, pageSize); var placeholder = new PdfFormXObject(new Rectangle(0, 0, _placeholderWidth, _fontSize)); _pageNumPlaceholders.Add(placeholder); var c = App.Client; var dateP = new Paragraph(_date).SetFont(_font).SetFontSize(_fontSize); var centerP = new Paragraph(_center ?? "").SetFont(_fontItalic).SetFontSize(_fontSize); var pageNumP = new Paragraph().Add(new Image(placeholder)).SetFont(_font).SetFontSize(_fontSize); if (pageNum == 1) { // First page canvas.ShowTextAligned(dateP, leftX1, y, TextAlignment.LEFT); canvas.ShowTextAligned(centerP, (leftX1 + rightX1) / 2, y, TextAlignment.CENTER); canvas.ShowTextAligned(pageNumP, rightX1, y, TextAlignment.RIGHT); var footerP = new Paragraph().SetFont(_font).SetFontSize(_fontSize) .SetTextAlignment(TextAlignment.CENTER).SetVerticalAlignment(VerticalAlignment.TOP) .SetMargin(0).SetMultipliedLeading(1) .SetWidth(footerWidth).SetHeight(footerHeight).SetPaddingTop(1 * _ptInMm).SetBorderTop(new SolidBorder(0.5f)) .Add(c.NameFull); if (_isBusiness) { footerP.Add("\n"); footerP.AddAll(Utils.GenerateFooter("\n", " \u00b7 ") .Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine() .Item(c.EmailAddress != null ? new Link(c.EmailAddress, PdfAction.CreateURI($"mailto:{Uri.EscapeDataString(c.Name)}%20<{c.EmailAddress}>")) : null) .Item(c.Website != null ? new Link(c.Website, PdfAction.CreateURI($"http://{c.Website}/")) : null) .Item("Betriebs-Nr.", c.LfbisNr).Item("Bio-KSt.", c.OrganicAuthority).NextLine() .Item("UID", c.UstIdNr).Item("BIC", c.Bic).Item("IBAN", c.Iban) .ToLeafElements()); } // FIXME links are drawn on next page - move footer into "normal" document creation canvas.ShowTextAligned(footerP, (leftX1 + rightX1) / 2, footerY, TextAlignment.CENTER, VerticalAlignment.TOP); } else if (_doublePaged && (pageNum % 2 == 0)) { // Swap side canvas.ShowTextAligned(pageNumP, leftX2, footerY, TextAlignment.LEFT, VerticalAlignment.TOP); canvas.ShowTextAligned(centerP, (leftX2 + rightX2) / 2, footerY, TextAlignment.CENTER, VerticalAlignment.TOP); canvas.ShowTextAligned(dateP, rightX2, footerY, TextAlignment.RIGHT, VerticalAlignment.TOP); } else { canvas.ShowTextAligned(dateP, leftX1, footerY, TextAlignment.LEFT, VerticalAlignment.TOP); canvas.ShowTextAligned(centerP, (leftX1 + rightX1) / 2, footerY, TextAlignment.CENTER, VerticalAlignment.TOP); canvas.ShowTextAligned(pageNumP, rightX1, footerY, TextAlignment.RIGHT, VerticalAlignment.TOP); } if (_showFoldMarks) { var m1 = pageSize.GetTop() - 105 * _ptInMm; var m2 = pageSize.GetTop() - 148.5 * _ptInMm; var m3 = pageSize.GetTop() - 210 * _ptInMm; pdfCanvas.SetLineWidth(0.5f); pdfCanvas.MoveTo(0, m1); pdfCanvas.LineTo(10 * _ptInMm, m1); pdfCanvas.MoveTo(pageSize.GetRight(), m1); pdfCanvas.LineTo(pageSize.GetRight() - 10 * _ptInMm, m1); pdfCanvas.MoveTo(0, m2); pdfCanvas.LineTo(7 * _ptInMm, m2); pdfCanvas.MoveTo(pageSize.GetRight(), m2); pdfCanvas.LineTo(pageSize.GetRight() - 7 * _ptInMm, m2); pdfCanvas.MoveTo(0, m3); pdfCanvas.LineTo(10 * _ptInMm, m3); pdfCanvas.MoveTo(pageSize.GetRight(), m3); pdfCanvas.LineTo(pageSize.GetRight() - 10 * _ptInMm, m3); pdfCanvas.ClosePathStroke(); } if (NumberOfPages > 0) { // FillPlaceholders() was already called FillPlaceholder(pdf, pageNum); } } private void OnDocumentClose(PdfDocumentEvent evt) { FillPlaceholders(evt.GetDocument()); } private void FillPlaceholders(PdfDocument pdf) { NumberOfPages = pdf.GetNumberOfPages(); for (int i = 0; i < _pageNumPlaceholders.Count; i++) FillPlaceholder(pdf, i + 1); } private void FillPlaceholder(PdfDocument pdf, int pageNum) { var placeholder = _pageNumPlaceholders[pageNum - 1]; using var canvas = new Canvas(placeholder, pdf); if (_doublePaged && (pageNum % 2 == 0)) { // swap var p = new Paragraph().SetFont(_font).SetFontSize(_fontSize); if (_isPreview) p.Add(new Text("(vorläufig) ").SetFont(_fontBold)); p.Add($"Seite {pageNum:N0} von {NumberOfPages:N0} "); canvas.ShowTextAligned(p, 0, 0, TextAlignment.LEFT); } else { var p = new Paragraph().SetFont(_font).SetFontSize(_fontSize) .Add($"Seite {pageNum:N0} von {NumberOfPages:N0}"); if (_isPreview) p.Add(new Text(" (vorläufig)").SetFont(_fontBold)); canvas.ShowTextAligned(p, _placeholderWidth, 0, TextAlignment.RIGHT); } } } }