PdfDocument 1.0.0

dotnet add package PdfDocument --version 1.0.0
                    
NuGet\Install-Package PdfDocument -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PdfDocument" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PdfDocument" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="PdfDocument" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PdfDocument --version 1.0.0
                    
#r "nuget: PdfDocument, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PdfDocument@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PdfDocument&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=PdfDocument&version=1.0.0
                    
Install as a Cake Tool

๐Ÿ“„ PDF Generation with DANFE, DACTE and Barcode Support

.NET 10 library for generating PDF documents from code.
Render text, shapes, tables, JPEG images and barcodes (Code 39 / EAN-13 / Code 128).
Plugin-based architecture with NFe/DANFE and CTe/DACTE support โ€” parse Brazilian fiscal XMLs and render their auxiliary documents.

.NET Build Tests License NuGet c6g.large .NET


๐Ÿ“‹ Table of Contents


๐ŸŽฏ Why PdfDocument?

Generate PDFs without heavy dependencies. PdfDocument is a lightweight library that writes PDFs directly โ€” no JNI, no C++ wrappers, no commercial licensing.

Feature PdfDocument
Size ~30 KB
Dependencies 1 (CodePages)
License MIT โญ
Native DANFE / DACTE โœ… NFe + CTe
Native Barcode โœ… Code39 + EAN13 + Code128
.NET 10 native โœ…
Crossโ€‘platform โœ… ARM64 / x64
Memory Diagnostic โœ… BenchmarkDotNet
CWE/Security verified โœ… 10+ classes

๐Ÿ“ฆ Installation

NuGet

dotnet add package PdfDocument --version 1.0.0
git clone https://github.com/valdomirogalo/PdfDocument.git
cd PdfDocument
dotnet restore
dotnet build

Dependencies

The library requires only one NuGet package:

Package Version Reason
System.Text.Encoding.CodePages 10.0.10 WinAnsi (1252) encoding for PDF compatibility on Linux/ARM64

Note: The playground, tests and benchmark projects are excluded from the NuGet package (<IsPackable>false</IsPackable>).


โšก Quick Start

1. Create a document with text and shapes

using PdfDocument;

using var pdf = new PdfBuilder();
var page = pdf.AddPage();
var canvas = page.Canvas;

canvas.DrawText("Hello, PDF!", 50, 700, 16);
canvas.DrawLine(50, 680, 400, 680);
canvas.DrawRectangle(50, 600, 200, 80);
canvas.FillRectangle(300, 600, 200, 80);

pdf.Save("example.pdf");

2. Add a table

var data = new string[,]
{
    { "Product", "Qty", "Price" },
    { "Item A", "10", "$50.00" },
    { "Item B", "5", "$25.00" },
};

canvas.DrawTable(data, 50, 500, new[] { 120.0, 80, 100 }, 24);

3. Generate a barcode

var bars = Code39.Generate("ABC-123");
canvas.DrawBarcode(bars, 50, 400, 1.5, 40);

4. Generate a DANFE/DACTE from fiscal XML (NFe or CTe)

using PdfDocument;
using PdfDocument.NFe;   // or PdfDocument.CTe

var factory = new PdfPluginFactory();

// One-step convenience method
factory.RegisterParser(new NFeParser());
factory.RegisterRenderer(new NFeRenderer());
factory.Generate("nfe.xml", "danfe.pdf");

// Or explicit two-step pipeline with decorators
factory.RegisterParser(new LoggingDataParser<NFeData>(new NFeParser(), Console.WriteLine));
factory.RegisterRenderer(new LoggingLayoutRenderer<NFeData>(new NFeRenderer(), Console.WriteLine));
var data = factory.Parse<NFeData>("nfe.xml");
factory.Render(data, "danfe.pdf");

๐Ÿ—๏ธ Architecture

PdfPluginFactory (Plugin Registry + Routing)
โ”œโ”€โ”€ IDataParser<T>          โ† Parsers: XML โ†’ IPdfData
โ”‚   โ”œโ”€โ”€ NFeParser            (PdfDocument.NFe)
โ”‚   โ””โ”€โ”€ CTeParser            (PdfDocument.CTe)
โ”œโ”€โ”€ ILayoutRenderer<T>      โ† Renderers: IPdfData โ†’ PDF
โ”‚   โ”œโ”€โ”€ NFeRenderer          (PdfDocument.NFe)
โ”‚   โ””โ”€โ”€ CTeRenderer          (PdfDocument.CTe)
โ””โ”€โ”€ Decorators (cross-cutting)
    โ”œโ”€โ”€ LoggingDataParser<T>
    โ””โ”€โ”€ LoggingLayoutRenderer<T>

PdfBuilder (Document)
โ”œโ”€โ”€ PdfPage (Page)
โ”‚   โ””โ”€โ”€ PdfCanvas (Drawing area)
โ”‚       โ”œโ”€โ”€ DrawLine / DrawRectangle / FillRectangle
โ”‚       โ”œโ”€โ”€ DrawText / DrawTextAligned / DrawCell
โ”‚       โ”œโ”€โ”€ DrawGrid / DrawTable
โ”‚       โ”œโ”€โ”€ DrawImage (JPEG)
โ”‚       โ””โ”€โ”€ DrawBarcode
โ”œโ”€โ”€ Code39 (Barcode generator)
โ”œโ”€โ”€ EAN13 (Barcode generator)
โ””โ”€โ”€ Code128 (Barcode generator)

Plugin Pipeline

                     PdfPluginFactory
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  input.xml โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚ parser.CanParse? โ”‚
                    โ”‚        โ”‚         โ”‚
                    โ”‚   parser.Parse() โ”‚โ”€โ”€โ–ถ IPdfData (CTeData / NFeData)
                    โ”‚        โ”‚         โ”‚
                    โ”‚ renderer.Render()โ”‚โ”€โ”€โ–ถ output.pdf (DACTE / DANFE)
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

  Explicit two-step:
  var data = factory.Parse<CTeData>("cte.xml");   // typed intermediate
  factory.Render(data, "dacte.pdf");               // separate render step

PDF Generation Flow

C# Code     โ†’  PdfCanvas (PDF command StringBuilder)
                    โ†“
              PdfBuilder.Save()
                    โ†“
           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
           โ”‚  PDF Objects    โ”‚
           โ”‚  (Font, Images, โ”‚
           โ”‚   Pages, Catalog)โ”‚
           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                    โ†“
           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
           โ”‚  xref table     โ”‚
           โ”‚  trailer        โ”‚
           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                    โ†“
              .pdf File

Memory Management

  • Streaming: PdfBuilder.Save() writes directly to FileStream โ€” no buffering of the entire PDF in memory
  • Pre-allocated StringBuilder: PdfCanvas._cmds pre-allocated with 4096 capacity โ€” fewer resizes
  • ArrayPool buffers: EscapePdfString rents byte/char buffers from System.Buffers.ArrayPool โ€” zero intermediate allocations per DrawText call
  • No content duplication: Removed unused _objects dictionary that was storing every PDF object's content in memory (written but never read)
  • No LOH allocations: All drawing operations use StringBuilder.AppendLine โ€” no large temporary arrays
  • ReadOnlySpan: EAN13 uses spans for digit validation โ€” no Substring allocations
  • c6g.large optimized: 2 vCPUs, 4 GB RAM โ€” single-threaded, no parallel overhead, 512 KB image limit, 32K text limit

๐Ÿ“š API Reference

PdfBuilder โ€” Main class

public sealed class PdfBuilder : IDisposable
Method Description Security
AddPage(width, height) Adds a page (default: 612ร—792 pts = Letter) โ€”
AddImage(name, data) Registers JPEG image (max 512 KB) CWE-79: name validated
AddImage(name, path) Loads and registers JPEG from file CWE-79: name validated
Save(path) Saves PDF to the specified path โ€”

PdfPage

Property Description
Width Width in points
Height Height in points
Canvas Drawing surface (PdfCanvas)

PdfCanvas โ€” Drawing surface

Method Description
DrawLine(x1, y1, x2, y2) Straight line
DrawRectangle(x, y, w, h) Rectangle (outline)
FillRectangle(x, y, w, h) Rectangle (filled)
DrawGrid(x, y, w, h, cols, rows) Grid of lines
DrawText(text, x, y, size) Simple text
DrawTextAligned(text, x, y, w, h, align, fontSize) Aligned text (Left/Center/Right)
DrawCell(text, x, y, w, h, align, fontSize, border) Cell with optional border
DrawTable(data, x, y, colWidths, rowHeight, ...) Complete table
DrawImage(name, x, y, w, h) Registered image (CWE-79 validated)
DrawBarcode(bars, x, y, moduleWidth, height) Barcode
GetContent() Returns accumulated PDF commands

Coordinate system: The coordinate system is top-down (origin at top-left). y decreases as you go down the page.


๐Ÿ”ข Barcodes

Code 39

Full alphanumeric support (A-Z, 0-9, -.$/+%):

var bars = Code39.Generate("ABC-123");
canvas.DrawBarcode(bars, x, y, moduleWidth: 1.5, height: 40);

Features:

  • Auto uppercase conversion
  • Automatic * start/stop
  • Inter-character gaps inserted automatically
  • Bar widths: black = 3 modules, white = 1 module

EAN-13

// 12 digits โ†’ check digit auto-calculated
var bars = EAN13.Generate("789123456789");

// 13 digits โ†’ validation
var bars = EAN13.Generate("7891234567895");

Features:

  • Accepts 12 digits (auto-calculation) or 13 digits (validation)
  • Accepts hyphens and spaces as separators
  • Automatic left (101), center (01010) and right (101) guards
  • Uses ReadOnlySpan<char> for validation โ€” zero extra allocations

๐Ÿงพ DANFE / NFe ยท DACTE / CTe

Plugin Factory โ€” Unified API

var factory = new PdfPluginFactory();

// Register plugins (programmatic or assembly scanning)
factory.RegisterParser(new NFeParser());
factory.RegisterRenderer(new NFeRenderer());
factory.RegisterParser(new CTeParser());
factory.RegisterRenderer(new CTeRenderer());

// Auto-routing: the factory discovers which parser to use via CanParse()
factory.Generate("nfe.xml", "danfe.pdf");   // โ†’ NFeParser + NFeRenderer
factory.Generate("cte.xml", "dacte.pdf");   // โ†’ CTeParser + CTeRenderer

// Explicit pipeline with decorators
factory.RegisterParser(new LoggingDataParser<CTeData>(new CTeParser(), Console.WriteLine));
var data = factory.Parse<CTeData>("cte.xml");   // typed CTeData
factory.Render(data, "dacte.pdf");               // separate render

NFeParser (NFe 4.00 XML)

var parser = new NFeParser();
if (parser.CanParse("nfe.xml"))
{
    NFeData data = parser.Parse("nfe.xml");
    // Returns NFeData with all fields:
    // - Identification (cUF, natOp, mod, serie, nNF, dhEmi...)
    // - Issuer (CNPJ, name, address, IE, CRT...)
    // - Recipient (CNPJ, name, address...)
    // - Product (code, description, NCM, CFOP, qty, price...)
    // - Totals (vBC, vICMS, vProd, vNF...)
    // - Carrier (CNPJ, name, IE, address...)
    // - Payment (method, amount)
}

CTeParser (CTe 3.00 XML)

var parser = new CTeParser();
if (parser.CanParse("cte.xml"))
{
    CTeData data = parser.Parse("cte.xml");
    // Returns CTeData with all fields:
    // - Identification (cUF, nCT, dhEmi, modal, tpServ...)
    // - Route (origin/destination municipalities)
    // - Issuer โ€” transport company (CNPJ, IE, name, address)
    // - Sender (CPF/CNPJ, name, address)
    // - Recipient (CNPJ, IE, name, address)
    // - Cargo (product, quantity, value)
    // - Tax documents (type, number, date, value)
    // - Service values (total, received)
    // - ICMS tax (CST, Simples Nacional)
    // - Road transport (RNTRC)
}

NFeRenderer / CTeRenderer

var renderer = new CTeRenderer();
renderer.Render(data, "dacte.pdf");

Generates a complete DACTE/DANFE with:

  • Header with document data
  • Issuer, sender and recipient information
  • Route (origin โ†’ destination) for CTe
  • Cargo/document details
  • Tax calculations
  • Road transport info
  • Additional observations

Enhanced DANFE (Playground)

The playground includes an enhanced layout that replicates the official DANFE format, including:

  • Issuer logo in the header
  • 44-digit access key
  • Authorization protocol
  • Complete product table
  • Side-by-side tax layout
  • Carrier section with volumes
  • Additional data and complementary information

๐ŸŽฎ Playground

The samples/Playground project contains complete usage examples:

cd samples/Playground
dotnet run

Generates 6 sample PDFs: | File | Content | |------|---------| | exemplo_basico.pdf | Geometric shapes, grid, aligned cells | | exemplo_tabela.pdf | 4ร—4 table with header | | exemplo_barcode39.pdf | Code39 barcodes | | exemplo_ean13.pdf | EAN-13 barcodes | | exemplo_danfe.pdf | Simplified DANFE via NFeRenderer | | exemplo_danfe_enhanced.pdf | Official DANFE layout with logo |


โšก Benchmarks

Measured with BenchmarkDotNet 0.14.0 ยท .NET 10.0.10 ยท AMD Ryzen 7 5700U ยท GC Workstation

PdfCanvas โ€” Drawing operation throughput

Operation Scale Mean Allocated
DrawLine 1,000 calls 829 ฮผs 230 KB
DrawLine 10,000 calls 709 ns/op 235 B
DrawRectangle 1,000 calls 746 ฮผs 208 KB
FillRectangle 1,000 calls 768 ฮผs 208 KB
DrawText (ASCII) 1,000 calls 1,325 ฮผs 290 KB
DrawText (Unicode/WinAnsi) 1,000 calls 1,747 ฮผs 386 KB
DrawTextAligned 1,000 calls 1,059 ฮผs 255 KB
DrawCell (with border) 1,000 calls 1,725 ฮผs 435 KB
DrawGrid 10ร—10 1 grid 17 ฮผs โ€”
DrawGrid 50ร—50 1 grid 67 ฮผs 16 KB
DrawBarcode (Code39) 10 chars 36 ฮผs โ€”
DrawTable 5ร—4 1 table 44 ฮผs โ€”
GetContent (1k draws) buffer read 842 ฮผs 298 KB

PdfBuilder โ€” Complete document generation

Scenario Mean Allocated
1 empty page 85 ฮผs 18 KB
1 page, 100 text lines 413 ฮผs 120 KB
1 page, 500 rectangles 464 ฮผs 171 KB
1 table 50ร—6 510 ฮผs 167 KB
5 Code39 barcodes 277 ฮผs 82 KB
Complete DANFE (NFeRenderer) 159 ฮผs 35 KB
10 pages, 50 lines each 1,321 ฮผs 506 KB

How to run

# Specific benchmark
dotnet run -c Release --project benchmarks/PdfDocument.Benchmarks -- 1

# All benchmarks
dotnet run -c Release --project benchmarks/PdfDocument.Benchmarks -- 6

Results saved to benchmarks/PdfDocument.Benchmarks/BenchmarkDotNet.Artifacts/results/.


๐Ÿ”ง Performance Optimizations

Based on dotnet-dump analysis (core dump from Playground sample on 2026-07-18), the following optimizations were implemented to reduce memory and prevent OOM in batch/high-throughput scenarios.

Improvements Applied

Area Before After Improvement
EscapePdfString allocs per DrawText byte[] + StringBuilder + char[] + string ArrayPool byte buffer + ArrayPool char buffer + final string ~37% fewer allocations per DrawText call
PNP/Encoding init first DrawText call NotSupportedException thrown and caught CodePagesEncodingProvider registered upfront in static initializer Zero exceptions
_objects dictionary in PdfBuilder Every PDF object content stored in both stream AND dictionary Dictionary removed (completely unused) ~50% less content memory
_usedImages lookup List<string>.Contains() O(n) HashSet<string>.Add() O(1) Faster with many images
NFeParser XML parsing XmlDocument (DOM) + XPath per field XDocument (LINQ to XML) with streaming reader Lower memory + 1-pass read
_cmds initial capacity Default (16 chars) 4096 chars pre-allocated Fewer buffer resizes
Dispose() cleanup GC.SuppressFinalize() only Clears _pages, _images, _offsets GC reclaims memory immediately

Memory Comparison: Before vs After (DrawText ASCII 1k)

Before:  458 KB allocated (byte[] + StringBuilder + char[] + string)
After:   290 KB allocated (string only + pooled buffers)
         โ””โ”€โ”€ 37% reduction in managed allocations

๐Ÿงช Tests

150 tests ยท xUnit ยท All passing โœ…

Suite Tests Coverage
PdfCanvasTests 25 Lines, rectangles, text, grid, tables, barcode, alignment, image validation, edge cases
Code39Tests 9 Generation, validation, invalid chars, gaps, case
EAN13Tests 12 12/13 digits, check digit, hyphens, spaces, guards
Code128Tests 13 Code128C generation, check digit, bar pattern, input validation
PdfDocumentTests 18 AddPage, AddImage, Save, multiple pages, JPEG parsing, dispose
PdfConstantsTests 12 IsValidPdfName with null/empty, valid names, invalid chars
NFeParserTests 19 Full parse, missing fields, protocol, adicional, transport, volumes
NFeRendererTests 5 RenderToFile, null validation, PDF structure
DanfeValidationTests 37 Full DANFE layout validation, field verification, edge cases
dotnet test

Highlighted tests

  • PDF character escaping: Verifies parentheses, backslashes and non-ASCII chars are properly escaped
  • EAN-13 check digit: Cross-validation of check digit calculation with 13 provided digits
  • Grid with invalid dimensions: Ensures DrawGrid with 0 columns/rows draws nothing
  • Save with image: Verifies the saved PDF is valid with all expected components
  • PDF injection prevention: Validates image names are rejected when containing dangerous characters
  • Parse XML with missing fields: Parser resilience when XML lacks expected nodes
  • Code128C barcode: Validates check digit, bar alternation, and digit filtering from mixed input

๐Ÿ”’ Security

CWE Coverage

CWE Name Risk Status
CWE-125 Out-of-bounds Read High โœ… Fixed โ€” bounds check in GetJpegDimensions
CWE-611 XXE (XML External Entities) High โœ… Fixed โ€” DtdProcessing.Prohibit in NFeParser
CWE-79 PDF Injection Medium โœ… Fixed โ€” IsValidPdfName() in AddImage/DrawImage
CWE-20 Improper Input Validation Medium โœ… OK โ€” all public APIs validate inputs
CWE-502 Deserialization Critical โœ… N/A โ€” no deserialization
CWE-117 Log Injection Low โœ… N/A โ€” library has zero logging
CWE-770 Resource Exhaustion Medium โœ… OK โ€” 512 KB image limit, 32K text limit
CWE-400 Uncontrolled Resource Medium โœ… OK โ€” all loops bounded by known data
CWE-754 Unusual Condition Check Medium โœ… OK โ€” ArgumentNullException.ThrowIfNull everywhere
CWE-22 Path Traversal Medium โœ… OK โ€” caller's responsibility

Secure by Design

  • โœ… No deserialization: Zero System.Text.Json or unsafe deserialization
  • โœ… No logging: Library has zero ILogger, Console, or log statements (CWE-117 mitigated)
  • โœ… XXE prevention: XmlReaderSettings.DtdProcessing = Prohibit in NFeParser (CWE-611 mitigated)
  • โœ… PDF injection prevention: Image names validated [a-zA-Z0-9_-]+ (CWE-79 mitigated)
  • โœ… OOB read prevention: JPEG SOF0 bounds check before dimension extraction (CWE-125 mitigated)
  • โœ… Encoding control: Explicit WinAnsi (1252), no dependency on system default
  • โœ… No string interpolation in exceptions: Static labels, user data as parameters
  • โœ… No thread pool starvation: 100% synchronous execution (ideal for 2 vCPU c6g.large)

๐Ÿ“ Code Quality

Clean Code Practices

  • โœ… No magic numbers: PdfConstants.cs centralizes all named constants (40+ constants)
  • โœ… DRY: WriteIndirectObject eliminates repetition of offset recording
  • โœ… DRY: IsValidPdfName shared between PdfBuilder.AddImage and PdfCanvas.DrawImage
  • โœ… DRY: DrawInfoLine, DrawSection eliminate repetition in DANFE renderer
  • โœ… Single Responsibility: Each class has a clear responsibility
  • โœ… Null Safety: Nullable enabled, ArgumentNullException.ThrowIfNull on all public APIs
  • โœ… XML Documentation: All public classes and methods documented with <summary>
  • โœ… Primary constructors: PdfPage uses primary constructor syntax (IDE0290)
  • โœ… Early Return: Early exit pattern with no nested else blocks
  • โœ… ReadOnlySpan: EAN13 uses spans to avoid Substring allocations

Error Handling

Scenario Behavior
Image > 512 KB ArgumentException
Image name invalid ArgumentException (CWE-79)
Duplicate image ArgumentException
Invalid JPEG (no SOF0 / truncated) InvalidDataException
JPEG truncated after SOF0 InvalidDataException (CWE-125)
Code 39 invalid character ArgumentException
EAN-13 invalid check digit ArgumentException
Text exceeds 32K chars ArgumentException
NFe XML not found FileNotFoundException
Missing infNFe node InvalidOperationException
Null in public parameters ArgumentNullException
ColumnWidths mismatch in table ArgumentException

๐Ÿ“ Project Structure

PdfDocument/
โ”œโ”€โ”€ PdfDocument.slnx                          # .NET 10 Solution
โ”œโ”€โ”€ README.md                                 # This file
โ”œโ”€โ”€ LICENSE                                   # MIT License
โ”‚
โ”œโ”€โ”€ src/PdfDocument/                          # ๐Ÿ“š Core library (NuGet 1.0.0)
โ”‚   โ”œโ”€โ”€ PdfDocument.csproj                    #   Target: net10.0
โ”‚   โ”œโ”€โ”€ PdfDocument.cs                        #   PdfBuilder โ€” PDF construction
โ”‚   โ”œโ”€โ”€ PdfPage.cs                            #   Individual page
โ”‚   โ”œโ”€โ”€ PdfCanvas.cs                          #   Drawing canvas (shapes, text, tables, barcode)
โ”‚   โ”œโ”€โ”€ PdfConstants.cs                       #   Named constants + IsValidPdfName
โ”‚   โ”œโ”€โ”€ PdfPluginFactory.cs                   #   Plugin registry: Parse<T>() + Render<T>() + Generate()
โ”‚   โ”œโ”€โ”€ IDataParser.cs                        #   Interface: XML โ†’ IPdfData
โ”‚   โ”œโ”€โ”€ ILayoutRenderer.cs                    #   Interface: IPdfData โ†’ PDF
โ”‚   โ”œโ”€โ”€ IPdfData.cs                           #   Marker interface for data models
โ”‚   โ”œโ”€โ”€ Bar.cs                                #   Barcode bar struct
โ”‚   โ”œโ”€โ”€ Code39.cs                             #   Code 39 generator
โ”‚   โ”œโ”€โ”€ EAN13.cs                              #   EAN-13 generator
โ”‚   โ”œโ”€โ”€ Code128.cs                            #   Code 128 generator
โ”‚   โ””โ”€โ”€ Decorators/                           #   Cross-cutting concerns
โ”‚       โ”œโ”€โ”€ LoggingDataParser.cs              #   Logging decorator for IDataParser<T>
โ”‚       โ””โ”€โ”€ LoggingLayoutRenderer.cs          #   Logging decorator for ILayoutRenderer<T>
โ”‚
โ”œโ”€โ”€ src/PdfDocument.NFe/                      # ๐Ÿงพ NFe plugin (NuGet PdfDocument.NFe)
โ”‚   โ”œโ”€โ”€ PdfDocument.NFe.csproj                #   Target: net10.0
โ”‚   โ”œโ”€โ”€ NFeConstants.cs                       #   DANFE layout constants
โ”‚   โ”œโ”€โ”€ NFeData.cs                            #   Data model (record, implements IPdfData)
โ”‚   โ”œโ”€โ”€ NFeParser.cs                          #   XML NFe 4.00 parser (XXE-safe, XDocument)
โ”‚   โ””โ”€โ”€ NFeRenderer.cs                        #   DANFE PDF renderer
โ”‚
โ”œโ”€โ”€ src/PdfDocument.CTe/                      # ๐Ÿš› CTe plugin (NuGet PdfDocument.CTe)
โ”‚   โ”œโ”€โ”€ PdfDocument.CTe.csproj                #   Target: net10.0
โ”‚   โ”œโ”€โ”€ CTeConstants.cs                       #   DACTE layout constants
โ”‚   โ”œโ”€โ”€ CTeData.cs                            #   Data model (record, implements IPdfData)
โ”‚   โ”œโ”€โ”€ CTeParser.cs                          #   XML CTe 3.00 parser (XXE-safe, XDocument)
โ”‚   โ”œโ”€โ”€ CTeRenderer.cs                        #   DACTE PDF renderer
โ”‚   โ””โ”€โ”€ Sample/                               #   Sample CTe XML and reference PDF
โ”‚
โ”œโ”€โ”€ samples/Playground/                       # ๐ŸŽฎ Usage examples (IsPackable=false)
โ”‚   โ”œโ”€โ”€ Playground.csproj
โ”‚   โ””โ”€โ”€ Program.cs                            #   6 complete demos
โ”‚
โ”œโ”€โ”€ tests/PdfDocument.Tests/                  # ๐Ÿงช Unit tests (150) (IsPackable=false)
โ”‚   โ”œโ”€โ”€ PdfDocument.Tests.csproj              #   xUnit + coverlet
โ”‚   โ”œโ”€โ”€ PdfCanvasTests.cs                     #   25 tests
โ”‚   โ”œโ”€โ”€ Code39Tests.cs                        #   9 tests
โ”‚   โ”œโ”€โ”€ EAN13Tests.cs                         #   12 tests
โ”‚   โ”œโ”€โ”€ Code128Tests.cs                       #   13 tests
โ”‚   โ”œโ”€โ”€ PdfDocumentTests.cs                   #   18 tests
โ”‚   โ”œโ”€โ”€ PdfConstantsTests.cs                  #   12 tests
โ”‚   โ”œโ”€โ”€ NFeParserTests.cs                     #   19 tests
โ”‚   โ”œโ”€โ”€ NFeRendererTests.cs                   #   5 tests
โ”‚   โ””โ”€โ”€ DanfeValidationTests.cs               #   37 tests
โ”‚
โ””โ”€โ”€ benchmarks/PdfDocument.Benchmarks/        # โšก Performance benchmarks (IsPackable=false)
    โ”œโ”€โ”€ PdfDocument.Benchmarks.csproj         #   BenchmarkDotNet 0.14.0
    โ”œโ”€โ”€ Program.cs                            #   Interactive CLI (1-6)
    โ”œโ”€โ”€ BenchConstants.cs
    โ”œโ”€โ”€ PdfCanvasBenchmarks.cs                #   13 drawing benchmarks
    โ”œโ”€โ”€ Code39Benchmarks.cs                   #   Params: 1 to 50 chars
    โ”œโ”€โ”€ EAN13Benchmarks.cs                    #   6 scenarios
    โ”œโ”€โ”€ NFeParserBenchmarks.cs                #   Full parse + missing fields
    โ””โ”€โ”€ PdfBuilderBenchmarks.cs               #   7 full document scenarios

๐Ÿ”„ Roadmap

  • Basic drawing operations (lines, rectangles, text)
  • Tables with header and data
  • Code 39 and EAN-13 barcodes
  • Code 128 barcodes
  • JPEG image insertion
  • Plugin architecture (IDataParser<T> + ILayoutRenderer<T> + PdfPluginFactory)
  • NFe XML parser (4.00) + DANFE rendering
  • CTe XML parser (3.00) + DACTE rendering
  • Logging decorators for parser and renderer pipelines
  • Unit tests (150)
  • Performance benchmarks
  • Official DANFE layout with logo
  • NuGet packaging (v1.0.0)
  • Security audit (CWE-125, CWE-611, CWE-79, CWE-117, CWE-770)
  • CodePages encoding fix (eliminated exception on first DrawText call)
  • Memory optimizations (ArrayPool, removed _objects leak, XDocument, HashSet)
  • TrueType font (TTF) support
  • Page rotation support
  • PDF/A support
  • Async API for large documents

โš–๏ธ License

MIT License โ€” Free to use, modify, distribute, and incorporate into any project (commercial or not).

MIT License

Copyright ยฉ 2026 Valdomiro Galo

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

<div align="center"> <sub>Made with ๐Ÿ’œ by <a href="https://github.com/valdomirogalo">Valdomiro Galo</a></sub> </div>

Product Compatible and additional computed target framework versions.
.NET 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 90 7/31/2026