PdfDocument 1.0.0
dotnet add package PdfDocument --version 1.0.0
NuGet\Install-Package PdfDocument -Version 1.0.0
<PackageReference Include="PdfDocument" Version="1.0.0" />
<PackageVersion Include="PdfDocument" Version="1.0.0" />
<PackageReference Include="PdfDocument" />
paket add PdfDocument --version 1.0.0
#r "nuget: PdfDocument, 1.0.0"
#:package PdfDocument@1.0.0
#addin nuget:?package=PdfDocument&version=1.0.0
#tool nuget:?package=PdfDocument&version=1.0.0
๐ 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.
๐ Table of Contents
- Why PdfDocument?
- Installation
- Quick Start
- Architecture
- API Reference
- Barcodes
- DANFE / NFe ยท DACTE / CTe
- Playground
- Benchmarks
- Performance Optimizations
- Tests
- Security
- Code Quality
- Project Structure
- License
๐ฏ 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
Via direct reference (recommended for development)
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 toFileStreamโ no buffering of the entire PDF in memory - Pre-allocated StringBuilder:
PdfCanvas._cmdspre-allocated with 4096 capacity โ fewer resizes - ArrayPool buffers:
EscapePdfStringrents byte/char buffers fromSystem.Buffers.ArrayPoolโ zero intermediate allocations perDrawTextcall - No content duplication: Removed unused
_objectsdictionary 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
Substringallocations - 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
DrawGridwith 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.Jsonor unsafe deserialization - โ
No logging: Library has zero
ILogger,Console, or log statements (CWE-117 mitigated) - โ
XXE prevention:
XmlReaderSettings.DtdProcessing = Prohibitin 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.cscentralizes all named constants (40+ constants) - โ
DRY:
WriteIndirectObjecteliminates repetition of offset recording - โ
DRY:
IsValidPdfNameshared betweenPdfBuilder.AddImageandPdfCanvas.DrawImage - โ
DRY:
DrawInfoLine,DrawSectioneliminate repetition in DANFE renderer - โ Single Responsibility: Each class has a clear responsibility
- โ
Null Safety:
Nullableenabled,ArgumentNullException.ThrowIfNullon all public APIs - โ
XML Documentation: All public classes and methods documented with
<summary> - โ
Primary constructors:
PdfPageuses primary constructor syntax (IDE0290) - โ Early Return: Early exit pattern with no nested else blocks
- โ
ReadOnlySpan: EAN13 uses spans to avoid
Substringallocations
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 | Versions 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. |
-
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 |