Charta 1.14.0
dotnet add package Charta --version 1.14.0
NuGet\Install-Package Charta -Version 1.14.0
<PackageReference Include="Charta" Version="1.14.0" />
<PackageVersion Include="Charta" Version="1.14.0" />
<PackageReference Include="Charta" />
paket add Charta --version 1.14.0
#r "nuget: Charta, 1.14.0"
#:package Charta@1.14.0
#addin nuget:?package=Charta&version=1.14.0
#tool nuget:?package=Charta&version=1.14.0
Charta
A permanently-MIT PDF generation library for .NET — fluent layout API, zero native dependencies, streaming output, NativeAOT-ready.
Why Charta? Every free .NET PDF option forces a trade-off: the modern fluent engine is revenue-gated, the permissive veteran has no layout engine or text shaping, the feature king is AGPL. Charta is MIT forever — no revenue thresholds, no dual-license switch — with a 166KB package that depends on nothing but the BCL.
Quick start
using Charta;
var result = Document.Create(doc =>
{
doc.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimeter);
page.Header().Text("Invoice #1042").FontSize(20).Bold();
page.Content().Column(col =>
{
col.Spacing(10);
col.Item().Text("Thanks for your purchase! Line breaking, kerning, and pagination are automatic.");
col.Item().LineHorizontal(1);
col.Item().Row(row =>
{
row.RelativeItem().Text("Total");
row.ConstantItem(120).AlignRight().Text("€ 1.250,00").Bold();
});
});
page.Footer().AlignCenter().Text("Page footer").FontSize(9);
});
}).GeneratePdf("invoice.pdf");
// result.Diagnostics tells you if anything didn't fit — Charta clips and reports, it never throws.
Fonts resolve against explicitly registered files first (FontManager.RegisterFont(...) — the reproducible path for servers and containers), then against the operating system's installed fonts. Registered TrueType fonts are always subset and embedded.
Script support today
| Scripts | Status |
|---|---|
| Latin (incl. Turkish, Polish, Vietnamese), Cyrillic, Greek | ✅ Full: correct rendering, kerning, and text extraction |
| CJK | ✅ Rendering, UAX#14 line breaking, and extraction (no vertical text yet) |
| Hebrew and mixed-direction text | ✅ Built-in UAX#9 bidi (100% conformant): correct reading order, mirrored brackets, correct extraction |
| Arabic, Indic, and other joining scripts | ✅ with the Charta.Shaping.HarfBuzz add-on — cursive joining, contextual forms, and marks. Without it, reading order is correct but letters render unjoined and a LayoutDiagnostic says so. |
// Enable full shaping for Arabic/Indic (optional add-on, one line at startup):
Charta.Shaping.HarfBuzz.ChartaHarfBuzz.Register();
Why another PDF library?
Every free .NET PDF option forces a trade-off: a modern fluent layout engine is revenue-gated, the permissively-licensed veteran has no modern layout engine or text shaping, and the most feature-complete library is AGPL. Charta aims to close that gap: a document generation engine that is MIT forever, has no revenue thresholds, no native binary payload in the core package, and treats digital signatures, complex-script text, and PDF/A + PDF/UA compliance as first-class free features.
Cookbook
Tables
page.Content().Table(table =>
{
table.ColumnsDefinition(cols =>
{
cols.RelativeColumn(3);
cols.ConstantColumn(80);
cols.RelativeColumn();
});
table.Header(header => // repeats at the top of every page
{
header.Cell().Background(Color.FromHex(0x1E5AA8)).Padding(6)
.Text("Product").FontColor(Color.White).Bold();
// ...
});
foreach (var row in rows)
{
table.Cell().Padding(6).Text(row.Name);
table.Cell().Padding(6).AlignRight().Text($"{row.Qty}");
table.Cell().Padding(6).AlignRight().Text($"{row.Total:N2}");
}
});
Cells are ordinary containers (Padding, Background, Border, … all work) and support
ColumnSpan/RowSpan. Rows joined by a rowspan paginate as one unbreakable band.
Page numbers and rich text
page.Footer().Text(t =>
{
t.AlignCenter();
t.Span("Page ").FontSize(9);
t.CurrentPageNumber().FontSize(9).Bold();
t.Span(" of ").FontSize(9);
t.TotalPages().FontSize(9); // triggers an automatic counting pass
});
Vector graphics and SVG
Draw vectors directly, or drop in an SVG (both managed, no extra dependency):
page.Content().Width(150).Svg(File.ReadAllText("logo.svg"));
page.Content().Canvas(300, 120, canvas =>
{
canvas.Rectangle(10, 10, 80, 100).Fill(Color.FromHex(0x1E5AA8));
canvas.Circle(200, 60, 40).FillAndStroke(Color.White, Color.Black, 2);
});
PDF/A archival compliance
Target PDF/A-2b for long-term archival — embedded sRGB output intent, pdfaid metadata, embedded fonts, validated by the official veraPDF validator in CI:
Document.Create(doc =>
{
doc.Metadata(m => m.Title("Archived report"));
doc.Page(page => page.Content().Text("..."));
}).GeneratePdf("archive.pdf", new PdfSaveOptions { Conformance = PdfConformance.PdfA2b });
Use a font that covers every character you render — PDF/A forbids showing the .notdef glyph, and
Charta raises a layout diagnostic naming the page if any text would render as .notdef under a
conformance level.
PDF/UA accessible (tagged) documents
Target PDF/UA-1 for accessibility — a full structure tree derived from the layout, marked content,
/Lang, DisplayDocTitle, and decorations tagged as artifacts, validated by veraPDF in CI. A title
is required; tag headings with .Heading(1..6) and give figures alternate text:
Document.Create(doc =>
{
doc.Metadata(m => m.Title("Accessible report"));
doc.Page(page => page.Content().Column(col =>
{
col.Item().Text("Quarterly results").FontSize(20).Heading(1);
col.Item().Text("...");
col.Item().Image("chart.png", altText: "Bar chart of revenue by quarter.");
}));
}).GeneratePdf("accessible.pdf", new PdfSaveOptions
{
Conformance = PdfConformance.PdfUA1,
Language = "en-US",
});
Digital signatures
The optional Charta.Signing add-on signs a
document with an X.509 certificate — a PAdES B-B signature, built on the .NET crypto stack (no
BouncyCastle, no native dependencies):
using Charta.Signing;
var signer = PdfSigners.FromCertificate(certificate);
Document.Create(doc => /* ... */)
.GenerateSignedPdf("signed.pdf", signer, new SignatureInfo { Reason = "Approval" });
Add a trusted RFC 3161 timestamp (PAdES B-T) by passing a timestamp authority — the signing time is then asserted by a third party, not the signer:
var tsa = TimestampAuthorities.Http(new Uri("https://freetsa.org/tsr"));
var signer = PdfSigners.FromCertificate(certificate, timestampAuthority: tsa);
Encryption
Protect a document with a password — AES-256 (the PDF 2.0 security handler, V5/R6), on the BCL crypto stack, no dependencies. Set a separate owner password to enforce permissions against readers who only have the user password:
Document.Create(doc => /* ... */)
.GeneratePdf("protected.pdf", new PdfSaveOptions
{
Encryption = new PdfEncryption
{
UserPassword = "open-me",
OwnerPassword = "full-control",
Permissions = PdfPermissions.Print | PdfPermissions.Copy,
},
});
Encryption cannot be combined with a signature or a PDF/A / PDF/UA level (those forbid it), and encrypted output is not byte-reproducible — fresh random salts and keys are generated each time.
HTML to PDF
The optional Charta.Html add-on renders a subset of
HTML/CSS. AngleSharp parses the markup; the cascade and layout are Charta's own — no browser, no
native code. Unsupported features are reported, never thrown:
using Charta.Html;
Document.Create(doc => doc.Page(page => page.Content().Html("""
<style>h1 { color: #003366 } .lead { color: #555 }</style>
<h1>Report</h1>
<p class="lead">A <b>bold</b> word and a <a href="https://example.com">link</a>.</p>
<ul><li>first</li><li>second</li></ul>
"""))).GeneratePdf("page.pdf");
Covers block flow, inline styling, lists, tables (with colspan/rowspan), rules, and images, with
type/.class/#id selectors. See the package readme for the full
support matrix.
Fonts on servers and in Docker
Register fonts explicitly — output becomes reproducible and independent of what the host has installed. Registered fonts are always subset and embedded:
FontManager.RegisterFontFile("fonts/Inter-Regular.ttf");
FontManager.RegisterFontFile("fonts/Inter-SemiBold.ttf");
FontManager.RegisterFontFile("fonts/Inter-Bold.ttf");
// The first registered family is also the default when no FontFamily(...) is set.
.Bold(), .SemiBold(), and .Italic() select a face by weight and style. Resolution matches
the nearest registered weight on the OS/2 axis (SemiBold is 600, Bold is 700), so register the face
you want to use — Charta never synthesizes a heavier weight from a lighter one.
Without registration Charta falls back to OS fonts (Windows font directory, fontconfig on Linux, macOS font folders — no native calls).
When something doesn't fit
Charta never throws for layout problems. Content that cannot fit even a full page is clipped and
reported in result.Diagnostics with what/where/why; treat a non-empty list as a warning in
development and log it in production. Prefer exceptions in CI? Opt in with
new PdfSaveOptions { Overflow = OverflowBehavior.Throw }. To see where content was clipped, turn
on new PdfSaveOptions { DebugLayout = true } — clipped regions get a red overlay in the output.
Text supports letter-spacing (.LetterSpacing(2)), and rich-text spans support .Superscript() /
.Subscript(), underline, and strikethrough.
Design principles
- MIT forever. No dual-license switch, no revenue gates. The trademark is the only reserved right.
- Zero dependencies in the core. The
Chartapackage references nothing but the BCL. Optional capabilities (HarfBuzz shaping, HTML rendering) live in opt-in add-on packages. - Never throw on overflow. Content that does not fit is clipped, shrunk, or expanded according to policy — and reported through layout diagnostics. Exceptions are opt-in, for CI strictness.
- Streaming by default. Pages are serialized and flushed as they finish. Memory stays flat whether the document has 5 pages or 5,000.
- NativeAOT and trimming clean. No reflection, no runtime code generation. Verified by a publish-and-run gate in CI.
Roadmap
| Milestone | Scope |
|---|---|
| M0 | Walking skeleton: streaming COS writer, valid "Hello PDF" |
| M1 | Real text: font parsing, subsetting, embedding; images |
| M2 | Layout engine: measure/arrange, pagination, overflow policy |
| M3 | Fluent API, first NuGet release |
| M4 | Tables with correct rowspan pagination |
| M5 | Digital signatures (PAdES B-B/B-T) |
| M6 | RTL and complex-script shaping (optional add-on) |
| M7 | PDF/A-2b/3b and PDF/UA |
| M8 | HTML/CSS subset rendering |
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Charta:
| Package | Downloads |
|---|---|
|
Charta.Html
HTML/CSS subset rendering for Charta: turn a fragment of HTML — headings, paragraphs, lists, tables, inline styling, images and links — into a laid-out PDF. Parses with AngleSharp; the cascade and layout are Charta's own. Unsupported features are reported as diagnostics, never thrown. |
|
|
Charta.Shaping.HarfBuzz
HarfBuzz text shaping for Charta: correct cursive joining and mark positioning for Arabic, Indic, and other complex scripts. Reference this package and call ChartaHarfBuzz.Register(). |
|
|
Charta.Signing
PAdES digital signatures for Charta: sign generated PDFs with an X.509 certificate. Uses only the .NET cryptography stack — no BouncyCastle, no native dependencies. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.14.0 | 131 | 7/20/2026 |
| 1.13.0 | 119 | 7/10/2026 |
| 1.12.0 | 122 | 7/10/2026 |
| 1.11.0 | 126 | 7/10/2026 |
| 1.10.1 | 111 | 7/10/2026 |
| 1.10.0 | 103 | 7/10/2026 |
| 1.9.0 | 104 | 7/10/2026 |
| 1.8.0 | 127 | 7/10/2026 |
| 1.7.0 | 122 | 7/10/2026 |
| 1.6.0 | 105 | 7/10/2026 |
| 1.5.0 | 122 | 7/10/2026 |
| 1.4.0 | 101 | 7/9/2026 |
| 1.3.0 | 104 | 7/9/2026 |
| 1.2.0 | 126 | 7/9/2026 |
| 1.1.0 | 126 | 7/9/2026 |
| 1.0.0 | 114 | 7/9/2026 |
See CHANGELOG.md in the repository.