Search code examples
c#htmlpdffontsitext7

C# - iText7 - Watermarking (stamping) HTML over PDF


This proved to be pretty difficult, as I cannot wrap my head around this being a newbie in C#.

I have this function:

...

var font = PdfFontFactory.CreateFont("assets/fonts/default.ttf", PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED); // always not null
font.SetSubset(false);

doc.AddFont(font);

var fs = new iText.Layout.Font.FontProvider();
fs.AddFont("assets/fonts/default.ttf");
fs.AddStandardPdfFonts();

var elements = HtmlConverter.ConvertToElements(new MemoryStream(watermark.Content), new ConverterProperties().SetFontProvider(fs));

Table table = new Table(UnitValue.CreatePercentArray(new float[] { 4, 1, 3 })).UseAllAvailableWidth(); // subject to change, taken from official docs

var cell = new Cell();

cell.SetFont(font).Add((IBlockElement)elements[0]);

table.AddCell(cell);

var page = doc!.GetFirstPage(); // always not null

PdfCanvas canvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), doc.Document);
new Canvas(canvas, page.GetPageSize()).Add(cell)
    .Close();

return doc;

Closing the documents before converting it to bytes returns the following error: All the fonts must be embedded. This one is not: {0}, although I try my best to use and embed it everywhere. What might be the problem?

Some points:

  1. This function is supposed to get an HTML and watermark it over the PDF/A-3. It does not care about specific HTML tags, fonts and other things included - just like stamping a picture of a rendered HTML on the first page of the PDF.
  2. I cannot regulate nor control the HTML that I get from requests. I cannot change or set the fonts myself programmaticaly and by hand. I do not know which fonts I'm gonna receive. I wish HtmlConverter allowed to set a predefined font for a whole document, but oh well.
  3. Converting HTML to elements and using table with canvas is the best bet. Another way might be to convert HTML to PNG, which makes life happier and easier, but afaik it is not possible in C# without rendering the whole page internally, which is stupid for such a task imo.

Solution

  • Turns out registering a font with PdfFontFactory.Register(path) before this function and using PdfFontFactory.CreateRegisteredFont without other changes solves the issue.