Generating a PDF invoice or report in .NET usually means a heavy dependency. Here's
how to do it with Matios.Pdf — a PDF engine that writes
the format (ISO 32000) itself, on the BCL alone. Zero dependencies, MIT.
Install
dotnet add package Matios.Pdf
A report with a header, footer and a paginating table
The high-level PdfFlow stacks blocks and paginates on its own — repeating the
header/footer and the table's header row across pages:
using Matios.Pdf;
using var doc = new PdfDocument();
var flow = new PdfFlow(doc, PdfPageSize.A4, margin: 56);
flow.Header(40, a => a.Graphics.DrawString("Report", PdfFont.HelveticaBold, 13, a.X, a.Y + 14));
flow.Footer(28, a => a.Graphics.DrawString(
$"Page {a.PageNumber} of {a.TotalPages}", PdfFont.Helvetica, 9, a.X + a.Width, a.Y + 14, PdfTextAlign.Right));
flow.Paragraph("A justified paragraph that wraps to the column width and paginates "
+ "on its own.", PdfFont.Helvetica, 12, leading: 16, align: PdfTextAlign.Justify, spacingAfter: 10);
flow.Table(t =>
{
t.ProportionalColumns(6, 1, 2, 2);
t.Align(PdfTextAlign.Left, PdfTextAlign.Right, PdfTextAlign.Right, PdfTextAlign.Right);
t.HeaderRow("Description", "Qty", "Unit", "Total");
for (int i = 1; i <= 40; i++) // enough rows to span pages
t.Row($"Line item {i}", "1", "12.50", (i * 12.5).ToString("F2"));
});
flow.Save("report.pdf");
Need pixel control instead? Drop to doc.Pages.Add(size).Graphics and draw text,
lines, rectangles, curves and images directly.
Full Unicode, embedded and subsetted
Embed a TrueType font and it's subsetted to just the glyphs you used — a ~1 MB
Arial becomes ~17 KB in the file, self-contained:
var font = PdfFont.FromFile(@"C:\Windows\Fonts\arial.ttf");
g.DrawString("Canción · €50 · ñandú · Ελληνικά · Русский", font, 14, 72, 160);
Read and encrypt too
using var doc = PdfDocument.Load("in.pdf"); // parse an existing PDF
int pages = doc.Pages.Count;
using var secured = new PdfDocument();
secured.Encrypt("pass"); // AES-256
secured.Pages.Add(PdfPageSize.A4).Graphics
.DrawString("Confidential", PdfFont.HelveticaBold, 18, 72, 100);
secured.Save("secured.pdf");
Every feature is verified by opening the output in real readers (pypdf, PIL,
FreeType), not just unit tests.
Docs, examples and benchmarks → pdf.matios.cl. Part of
a family of zero-dependency, MIT packages for .NET — matios.cl.
If you try it, I'd love your feedback — issues and stars welcome. 🙌

Top comments (0)