Changelog
All notable changes to this project are documented here. The format follows Keep a Changelog and this project adheres to Semantic Versioning.
2.0.0 - 2026-07-23
Added
- Custom font embedding â
FontFamily.Register(...)embeds a TrueType font (regular, bold, italic, bold-italic) as aType0/CIDFontType2composite font withIdentity-Hencoding, giving full Unicode text support beyond the standard-14 fonts'WinAnsiEncodingrange (brand typefaces, Cyrillic, Greek, and beyond). Fonts are embedded once per document regardless of how many times they're used, and requesting an unregistered style falls back to the closest registered variant instead of throwing. - Devanagari-aware rendering (pure C#, no native dependency, none planned):
- Matra reordering â the vowel sign ā¤ŋ (
U+093F) is moved to its correct pre-consonant visual position. - Conjunct ligatures â the font's own
half/akhn/cjctGSUB features are substituted so ⤏āĨā¤ĩ, ⤏āĨā¤Ĩ, ā¤āĨ⤎, ā¤āĨ⤠etc. render as proper joined forms. - Reph â cluster-initial ⤰āĨ (⤧⤰āĨā¤Ž, ā¤ĩ⤰āĨā¤¤ā¤Žā¤žā¤¨, ā¤ĻāĨ⤰āĨā¤Ŧā¤˛ā¤¤ā¤ž) is reordered and substituted via
the font's
rphffeature. - Below-base/post-base 'ra' â ā¤āĨ⤰, ⤤āĨ⤰, ā¤ĒāĨ⤰, ⤎āĨā¤āĨ⤰ substituted via the font's
rkrffeature.
- Matra reordering â the vowel sign ā¤ŋ (
- New
docs/custom-fonts.mdguide. - New sample:
15_child_nutrition_india_report.pdfâ a full multi-page Hindi-language report exercising the new Devanagari shaping corrections.
Fixed
- Word-wrap: a single word/token wider than the line now breaks at character boundaries instead of overflowing the container.
Changed
- Breaking (none): version bumped
1.5.1â2.0.0to reflect the scope of the new font subsystem, not a breaking API change. - CI (
ci.yml): added a nuget.org connectivity canary as the last step of every run. - Publish workflow (
publish.yml): added pre-publish connectivity andNUGET_API_KEYauthentication checks, so a dead network path or a stale key is caught beforePack/Pushâ previously such a failure could only be recovered by bumping the version, since nuget.org rejects re-pushing the same version.
1.5.1 - 2026-07-10
Added
- .NET 10 target â the library now multi-targets
net8.0,net9.0andnet10.0(the current LTS). No API or behaviour changes; existing .NET 8/9 consumers are unaffected.
Changed
- Test suite now runs once per supported runtime (
net8.0,net9.0,net10.0); the sample app moved tonet10.0. - CI workflows install the .NET 8/9/10 SDKs;
global.jsonnow requires the .NET 10 SDK (withrollForward: latestMajor). - Consolidated the two overlapping CI workflows into a single
ci.yml. - Migrated the solution to the XML-based
.slnxformat (TerraPDF.slnx).
1.5.0 - 2026-07-06
Added (barcodes & QR codes)
container.Barcode(data, ...)â Code128 (Subset B) barcode generation, encoding printable ASCII (0x20-0x7E). Supports an explicit or auto-fill width, custom module/background colour, an optional human-readable caption rendered below the bars, and a configurable quiet zone.container.QrCode(data, ...)â from-scratch ISO/IEC 18004 QR code generator: byte-mode encoding, automatic version selection (1-40), all four error correction levels (QrErrorCorrectionLevel.L/M/Q/H), Reed-Solomon error correction, and full mask-pattern penalty scoring. Supports an explicit or auto-fill size, custom module/background colour, and a configurable quiet zone.- Both render as vector-filled rectangles (one rect per bar / per contiguous run of dark QR modules), matching the existing
VectorCanvasrendering style â crisp at any zoom, no raster image pipeline, and placeable anywhere anIContaineris exposed (Column,Row,Tablecell, header, footer). - New
PdfPage.AddFilledRectsbatch primitive: emits one colour operator followed by manyreops and a single trailing fill, avoiding a redundant colour-set/fill pair per module on symbols with thousands of modules.
1.4.0 - 2026-07-04
Added
- AES-256 PDF encryption by default (Standard Security Handler Revision 6, SHA-2 key derivation, PDF 2.0 output).
EncryptionOptions.Algorithmlets you opt back into AES-128 (EncryptionAlgorithm.Aes128) for legacy viewers. - Images from bytes and streams â
container.Image(byte[])andcontainer.Image(Stream)overloads (with optional width), for images from databases, embedded resources, or generated data. Format is now detected from magic bytes rather than the file extension. - PNG transparency â RGBA PNGs keep their alpha channel via a
/SMasksoft mask; indexed-transparency (tRNS) PNGs still render opaque. - Image deduplication â identical image data reused across pages is embedded once and shared document-wide.
- Anchor-based bookmarks â
container.Bookmark("Title"[, parentTitle])marks its content as an outline destination; the page number and position are resolved automatically at render time. The page-number-basedBookmark(title, pageNumber)API remains available. - Paragraphs split across pages â a text block taller than the remaining page now flows onto the next page instead of overflowing.
FontFamily(string)onTextDescriptor,SpanDescriptor, andTextStylenow actually works â supports Helvetica, Times, and Courier (plus common aliases like "Arial"), withBold()/Italic()staying within the selected family.
Fixed
- Bookmark destinations now use zoom-retaining
/XYZcoordinates instead of/Fit//FitH, and land at the correct position. - Height-constrained images preserve aspect ratio instead of being squashed.
- Table of Contents heading scan now traverses decorators, hyperlinks, and bookmark anchors.
- Encrypted documents no longer leak metadata, bookmark titles, or hyperlink URIs in plaintext â everything is encrypted with the owning object's key.
- Document metadata is now referenced from the PDF trailer, so viewers display it correctly.
- Pagination now works through all decorators (
Margin,RoundedBorder,RoundedBox, per-edge borders). - Negative-value validation added to the single-side
Padding*/Margin*overloads.
Changed
- Breaking:
TextDescriptor.Span(string, Action<TextStyle>)is nowSpan(string, Func<TextStyle, TextStyle>).TextStyleis immutable, so the callback must return the configured style:t.Span("hi", s => s.Bold()). - Content streams are now Flate-compressed, and serialization is streamed instead of buffered in memory â smaller files, lower peak memory.
- Fragment-based layout engine â page counting and rendering now always agree.
1.3.0 - 2026-05-19
Added
- AES-128 PDF Encryption using the PDF Standard Security Handler.
EncryptionOptionswithUserPassword,OwnerPassword, andPermissions.PdfPermissionsflags forPrint,CopyText,ModifyContents,ModifyAnnotations,FillForms,ExtractForAccessibility,AssembleDocument,PrintLowResolution,All, andNone.- Per-object AES-128 CBC encryption of content streams and image XObjects.
- Encrypted documents are emitted as PDF 1.6, the minimum version required for AES encryption.
- Encryption tests covering password combinations, permission flags, multi-page documents, metadata, null guards, and output-size sanity.
Fixed
- Encrypted PDFs now write the random
/IDarray to the trailer so viewers can reproduce the file encryption key. - Removed invalid
/Filter /Cryptentries from content streams and JPEG image dictionaries. - AES encryption now uses the correct padding behavior for decrypted content.
- Sample output folders are created automatically before sample PDFs are written.
- Encryption showcase badges use WinAnsi-safe ASCII symbols.
1.2.3
Added
- Vector Graphics / Canvas API via
container.Canvas(height, draw). VectorCanvasprimitives for lines, rectangles, rounded rectangles, circles, ellipses, arbitrary Bezier paths, polygons, and grids.PathDescriptorhelpers forMoveTo,LineTo,CurveTo,Close,Rect,Ellipse,Circle,Polyline,Polygon,Fill,Stroke, and even-odd fill.- Vector graphics sample demonstrating primitives, custom paths, charts, progress bars, callouts, and icon-grid patterns.
- Unicode and WinAnsiEncoding showcase sample covering Windows-1252 specials, Latin-1 characters, full byte-to-glyph reference grids, font comparison, and glyph metrics.
- Documentation guides for vector graphics and Unicode / character encoding.
Fixed
- Several language sample sentences now avoid characters outside WinAnsiEncoding so output PDFs do not show replacement
?glyphs. - Win-1252 showcase tables now use proportional column definitions to avoid page overflow.
1.2.2 - 2026-05-04
Added
- Table of Contents generation â
container.TableOfContents()creates a TOC page populated with headings collected from.H1()â.H6(), with hierarchical numbering (e.g. 1, 1.1, 1.1.1) and clickable internal links. - Internal links (GoTo) â
container.InternalLink(pageNumber, top?)creates intra-document navigation that preserves current zoom level and scrolls to the target heading. - Section headings â
.H1()through.H6()methods with sensible default styles (size + weight), each returningTextDescriptorfor further customisation.
Fixed
- Internal link zoom issue â
/FitHreplaced with/XYZso clicking TOC entries no longer resets zoom. - Page number display in TOC now excludes TOC page count (TOC treated as page zero), while links still point to correct physical pages.
HeadingRecorderpropagation throughDrawingContext.Atfixed so TOC entries are correctly collected.
1.2.1 - 2026-05-03
Documentation
- Corrected all
GeneratePdf()âPublishPdf()method references throughout README and all documentation files - Fixed
Color.Bluehex values: Darken2 (#1976D2), added missing Darken3 (#1565C0) and Darken4 (#0D47A1) - Added
PageBreak()toColumnDescriptorAPI table in layout guide - Documented
HeaderOnFirstPageOnly()page method for first-page-only headers - Clarified
RelativeItem()default weight = 1 in row-and-column layout guide - Added
FontFamily(string)toTextDescriptormethods table in text-and-spans guide
1.2.0 - 2025-07-14
Added
Underline()style method onTextDescriptorandSpanDescriptor. Draws an underline beneath the text. Can be combined withStrikethrough().LineHeight(double)style method onTextDescriptor. Sets a line-height multiplier (e.g.1.0= tight,1.4= default,2.0= double-spaced). Also accepted byDefaultTextStylefor page-wide control.TextStyle.LineHeightMultiplierproperty exposed for custom render logic.RoundedBorder(radius, lineWidth, hexColor)decorator â draws a rounded-corner stroke border around child content. Corner radius is automatically clamped to half the shorter dimension.RoundedBox(radius, fillHexColor, borderHexColor, lineWidth)decorator â fills the area withfillHexColorand draws a rounded-corner border in one call. Equivalent toBackground + RoundedBorderbut rendered as a single path.BorderTop(lineWidth, hexColor),BorderBottom,BorderLeft,BorderRightper-edge border decorators. Each side is independently configurable with its own width and colour. ThehexColorparameter defaults to"#000000".PageBreak()container extension â inserts an explicit page-break marker inside aColumn. Silently skipped when it falls at the very start of a page.Hyperlink(url)container extension â wraps child content in a clickable PDF URI annotation (/Annotswith/URIaction). Clicking the area in a conforming PDF viewer navigates to the given URL.HighPriorityFeatureTests.csâ 20 new tests covering all five features above (underline, hyperlink, per-edge borders, line height, and their combinations).RoundedBorderTests.csâ dedicated tests forRoundedBorderandRoundedBoxgeometry, clamping behaviour, and validation.PageBreakTests.csâ tests for explicit page-break positioning.HeaderFirstPageOnlyTests.csâ tests verifying that the header slot can be conditionally rendered only on the first page usingShowIf.
Fixed
- Breaking (behaviour):
TextDescriptor.Span().Bold()/.Italic()/.Strikethrough()etc. previously mutated the whole block'sSpanStyleinstead of the individual span's style. Now correctly isolated.
Changed
- Folder
Fluentrenamed toCore(TerraPDF.Corenamespace). - Folder
Infrastructurerenamed toInfra(TerraPDF.Infranamespace).
1.1.0 - 2025-06-01
Added
Margin,MarginVertical,MarginHorizontal,MarginTop,MarginBottom,MarginLeft,MarginRightdecorator methods with fullUnitoverloads. Margin is outer spacing â the margin region stays transparent, background and border start after the gap.SpanDescriptorâ per-span fluent builder returned byTextDescriptor.Span(),CurrentPageNumber(), andTotalPages(). Style methods chained after.Span(...)now apply only to that span, not the wholeTextBlock.- Complete documentation suite under
docs/:getting-started.md,text-and-spans.md,layout.md,decorators.md,images.md,colors.md,page-sizes-and-units.md,components-and-templates.md,row-and-column-layout.md. CHANGELOG.md,CONTRIBUTING.md,SECURITY.md.- Input validation (using
ArgumentNullException.ThrowIfNull,ArgumentException.ThrowIfNullOrWhiteSpace,ArgumentOutOfRangeException.ThrowIfNegative/ThrowIfNegativeOrZero) on every public API entry point. - 62 new tests across
ValidationTestsandBehaviourTests(92 total).
Fixed
- Breaking (behaviour):
TextDescriptor.Span().Bold()/.Italic()/.Strikethrough()etc. previously mutated the whole block'sSpanStyleinstead of the individual span's style. Now correctly isolated.
Changed
- Folder
Fluentrenamed toCore(TerraPDF.Corenamespace). - Folder
Infrastructurerenamed toInfra(TerraPDF.Infranamespace).
1.0.0 - 2025-01-01
Added
- Initial release.
- PDF 1.7 generation with zero native dependencies.
- Text styling: bold, italic, bold-italic, strikethrough, underline, font size, colour.
- Multi-span text blocks with mixed styles.
Column(vertical stacking) andRow(horizontal layout) withRelativeItem,AutoItem, andConstantItemsizing.Tablewith relative and constant columns,HeaderRow(repeats on continuation pages), alternating-row support.Paddingwith all side variants andUnitoverloads.Background,Border,Alignment(horizontal + vertical),ShowIf.- Horizontal and vertical rule lines.
- PNG and JPEG image embedding.
IComponentreusable content blocks.IDocumentreusable document templates.- Headers, footers, page numbers (
CurrentPageNumber,TotalPages). - Multi-page documents with automatic table pagination.
- Full Material Design colour palette (
Color.*). - Standard page sizes including ISO A-series, Letter, Legal, Tabloid,
Executive, and
Landscape()helper. Unitsystem: Point, Millimetre, Centimetre, Inch.- Targets .NET 8 and .NET 9.
- CI workflow (GitHub Actions): build, test, coverage.
- Publish workflow (GitHub Actions): NuGet + symbols on release tag.