PDF output

edit

The Meziantou.Framework.WebPlatform.PdfRendering package prints a document to PDF with Meziantou.Framework.Pdf. The document is laid out for printing, as for Printing pages, and each page becomes a PDF page of vector graphics and text:

dotnet package add Meziantou.Framework.WebPlatform.PdfRendering
// The rendering backend keeps and decodes the images, and rasterizes what PDF cannot draw
using var context = new BrowsingContext(new BrowsingContextOptions { RenderingBackend = new ImagingRenderingBackend() });
context.Navigate("https://example.com/", _ => """
    <!DOCTYPE html>
    <html lang="en">
    <title>Monthly report</title>
    <style>@page { size: A4; margin: 2cm }</style>
    <h1>Monthly report</h1>
    <p>See the <a href="https://example.com/details">details</a>.</p>
    """);
context.EventLoop.RunUntilIdle();

// A tagged PDF document (PDF/UA-1): text, links, bookmarks and the structure of the document
var pdf = context.PrintToPdf(options: new PdfPrintOptions { PdfUAConformance = PdfUAConformance.PdfUA1 });
var bytes = pdf.ToByteArray();

PrintToPdf returns a PdfDocument, or writes the PDF to a stream. It takes the PrintOptions of the printing (the size of the pages, the margins, the header and the footer) and the PdfPrintOptions of the PDF:

using var context = new BrowsingContext(new BrowsingContextOptions { RenderingBackend = new ImagingRenderingBackend() });
context.Navigate("https://example.com/invoices/42", _ => """
    <!DOCTYPE html>
    <title>Invoice 42</title>
    <h1>Invoice 42</h1>
    <p>Thank you for your order.</p>
    """);
context.EventLoop.RunUntilIdle();

using var stream = new MemoryStream(); // or a FileStream
context.PrintToPdf(stream, new PrintOptions
{
    PageWidth = 794,    // A4 at 96 dpi, in CSS px, for the pages without @page size
    PageHeight = 1123,
    MarginTop = 48,
    MarginBottom = 48,
    DisplayHeaderFooter = true,
    FooterTemplate = """<div style="width: 100%; font-size: 10px; text-align: center"><span class="pageNumber"></span> / <span class="totalPages"></span></div>""",
});

What the PDF contains

  • Text that can be selected, searched and extracted: the glyphs of the fonts the layout used, embedded as subsets, at the positions the layout computed.
  • Images, embedded once each. A JPEG image is embedded as it is. The browsing context needs a RenderingBackend (ImagingRenderingBackend) to keep the bytes of the images.
  • Links: the a elements are link annotations; a link to a fragment of the document goes to its place in the PDF.
  • Bookmarks: the headings are the outline of the document.
  • Metadata: the title, the language, the author, the description and the keywords of the document.
  • Structure: the PDF is tagged. Its structure tree is made from the elements (headings, paragraphs, lists, tables, figures with their alternate text, links), and the decorations are artifacts.

PDF options

PdfPrintOptionsDefaultEffect
TaggedtrueWrites the structure tree
IncludeLinkstrueWrites the link annotations
IncludeOutlinestrueWrites the bookmarks
PdfUAConformancenoneWrites a PDF/UA-1 document (accessible PDF)
PdfAConformancenoneWrites a PDF/A document (archiving)
Titlethe title elementThe title of the PDF
RasterizationScale2The pixels per CSS pixel of what PDF cannot draw

What is drawn as an image

PDF cannot draw everything that CSS can: the blurred shadows, the filters, the masks, the compositing operators other than the default one (source-over), the 3D transforms, the conic gradients and the color glyphs are drawn as images, at RasterizationScale pixels per CSS pixel, in place.