PDF output
editThe 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
aelements 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
| PdfPrintOptions | Default | Effect |
|---|---|---|
| Tagged | true | Writes the structure tree |
| IncludeLinks | true | Writes the link annotations |
| IncludeOutlines | true | Writes the bookmarks |
| PdfUAConformance | none | Writes a PDF/UA-1 document (accessible PDF) |
| PdfAConformance | none | Writes a PDF/A document (archiving) |
| Title | the title element | The title of the PDF |
| RasterizationScale | 2 | The 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.