Question:
I converted a docx file to a PDF but need to add a watermark to the footer of the page without overlapping any content.
Answer:
The following C# code shows how you can calculate the used area of a page, and determine the size of a stamp. Using this information, you can calculate whether or not a stamp will fit in within the footer without overlapping any content. This uses the first page to calculate the usable area, but can easily be expanded as needed.
string stampText = "IMPORTANT INFORMATION\nthis is a test stamp";
using (PDFDoc doc = new PDFDoc())
using (Stamper s = new Stamper(Stamper.SizeType.e_font_size, 12, 12))
{
//////////////////////////////////////////////////////////////////////////////////////////////
// NOTE: following code will only work with PDFs generated with OfficeToPDF API
// code below will not necessarily work with ANY PDF file, due to page rotation complications.
//Convert office document
pdftron.PDF.Convert.OfficeToPDF(doc, "../../input.docx", null);
//////////////////////////////////////////////////////////////////////////////////////////////
//Get the size of the visible content on the first page
Page firstPage = doc.GetPage(1);
Rect firstPageCropBox = firstPage.GetCropBox();
Rect pageContentSize = firstPage.GetVisibleContentBox();
//Setup stamp settings for a centered, and at the foot stamp
s.SetSize(Stamper.SizeType.e_font_size, 12, 0); // aim for 12pt font size
s.SetAlignment(Stamper.HorizontalAlignment.e_horizontal_center, Stamper.VerticalAlignment.e_vertical_bottom);
s.SetTextAlignment(Stamper.TextAlignment.e_align_center);
s.SetFontColor(new ColorPt(1, 0, 0)); // set text color to red
s.SetFont(Font.Create(doc, "Arial", stampText));
//Create empty doc and blank page to place a test stamp
PDFDoc testDoc = new PDFDoc();
Page stampedPage = testDoc.PageCreate(new Rect(0, 0, 1200, 1200)); // make a large page so we know the true size.
testDoc.PagePushBack(stampedPage);
//Place the test stamp on the first empty page of the test document
s.StampText(testDoc, stampText, new PageSet(1, 1));
//Grab the visible size of the newly stamped page to get the size of the stamp
Rect stampSize = stampedPage.GetVisibleContentBox();
stampedPage.SetCropBox(stampSize);
double requiredWidth = Math.Ceiling(stampSize.Width());
double requiredHeight = Math.Ceiling(stampSize.Height());
Console.WriteLine($"{requiredWidth} x {requiredHeight}");
Rect targetPageContentBBox = firstPage.GetVisibleContentBox();
double footerSpaceAvailable = targetPageContentBBox.y1 - firstPageCropBox.y1;
double widthAvailable = targetPageContentBBox.Width() - requiredWidth;
if (footerSpaceAvailable < 0.0 || widthAvailable < 0.0)
{
throw new Exception("Not enough space for footer watermark");
// TODO switch Stamper to relative, rather than fixed size.
}
double yTop = targetPageContentBBox.y1;
double yBottom = firstPage.GetCropBox().y1;
double footerSpace = yTop - yBottom;
// Centre in the footer. You may want to do a different placement, e.g. minimum height from the bottom edge.
// Assuming space is available.
double y = yTop - (footerSpaceAvailable / 2.0) - (requiredHeight / 2.0);
s.SetSize(Stamper.SizeType.e_absolute_size, requiredWidth, requiredHeight);
s.SetPosition(0.0, y);
s.StampPage(doc, stampedPage, new PageSet(1, doc.GetPageCount()));
doc.Save("../../output_01.pdf", SDFDoc.SaveOptions.e_linearized);
}