Skip to content

Majorsilence.Pdf

Peter Gill edited this page Jul 1, 2026 · 2 revisions

Majorsilence.Pdf is a pure-managed, zero native-dependency PDF generation library for .NET. It is a separate, lower-level library from the RDL report engine — use it when you want to build a PDF page-by-page in code rather than designing an .rdl report. It targets netstandard2.0, net6.0, net8.0, and net10.0, and produces PDF 1.4, PDF 1.7, and PDF 2.0 output with optional PDF/A conformance.

Password protection and digital signatures are provided by the companion package Majorsilence.Pdf.Security.

<PackageReference Include="Majorsilence.Pdf" />
<PackageReference Include="Majorsilence.Pdf.Security" /> <!-- optional: passwords & signatures -->

A full, runnable console app covering every feature below (fonts, shapes, tables, images, merging, PDF/A, encryption, signatures, RTL text, and more) lives in the repo at Examples/MajorsilencePdfExample.

Quick Start

using Majorsilence.Pdf;

PdfDocument.Create()
    .WithTitle("Hello World")
    .WithAuthor("Majorsilence.Pdf")
    .AddPage(PageSizes.A4, canvas =>
    {
        var heading = TextStyle.Default.WithFamily("LiberationSans").WithSize(36).WithBold();
        var body    = TextStyle.Default.WithFamily("LiberationSans").WithSize(12);

        canvas.DrawText("Hello, World!", 72, 100, heading);
        canvas.DrawText(
            "Generated with Majorsilence.Pdf — a zero-dependency PDF library.",
            72, 155, body);
    })
    .Save("hello.pdf");

Shapes and Lines

DrawRectangle, DrawEllipse, DrawPolygon, and DrawLine accept a ShapeStyle or StrokeStyle for fill, border, dashing, and opacity:

canvas.DrawRectangle(410, 50, 150, 80,
    ShapeStyle.Filled(PdfColor.Yellow).WithStroke(PdfColor.Orange, 2f));

canvas.DrawRectangle(50, 175, 150, 80,
    ShapeStyle.Stroked(PdfColor.DarkGray, 1.5f).Dashed());

canvas.DrawEllipse(410, 300, 80, 80,
    ShapeStyle.Filled(PdfColor.Green).WithStroke(PdfColor.DarkGray, 1f));

canvas.DrawLine(x1, y, x2, y,
    StrokeStyle.Default.WithWidth(2f).WithColor(PdfColor.Blue).Dashed());

Tables

PdfTable lays out a header row, alternating row backgrounds, borders, and per-cell text styles, with automatic word-wrapping inside cells:

var table = new PdfTable(new float[] { 180, 80, 90, 90 })
    .WithHeaderBackground(new PdfColor(26, 86, 160))
    .WithAlternateRowBackground(new PdfColor(240, 245, 252))
    .WithBorder(new PdfColor(200, 200, 200), 0.5f)
    .WithCellPadding(5f)
    .WithCellTextStyle(TextStyle.Default.WithFamily("LiberationSans").WithSize(10))
    .WithHeaderTextStyle(
        TextStyle.Default.WithFamily("LiberationSans").WithSize(10)
                         .WithBold().WithColor(PdfColor.White));

table.AddRow("Product",          "Qty", "Unit Price", "Total");
table.AddRow("PDF Library Pro",  "3",   "$400.00",    "$1 200.00");
table.AddRow("Report Designer",  "1",   "$250.00",    "$250.00");

canvas.DrawTable(table, 72, 92, out float tableBottom);

Multi-line Text Wrapping

DrawTextBox word-wraps text into a bounding box and returns the character index where it overflowed, so a document can continue the text on the next page:

int overflowAt = canvas.DrawTextBox(
    text:        longText,
    x:           72,
    y:           100,
    width:       400,
    height:      600,
    style:       TextStyle.Default.WithSize(11),
    lineSpacing: 1.4f);

if (overflowAt < longText.Length)
{
    // Continue on the next page/box
    canvas.DrawTextBox(longText.Substring(overflowAt), 72, 100, 400, 120, TextStyle.Default.WithSize(11));
}

Images

Raw JPEG bytes are embedded directly; other formats are supplied as decoded raw RGB24 bytes and get FlateDecode-compressed automatically:

byte[] jpegBytes = File.ReadAllBytes("photo.jpg");
canvas.DrawImage(jpegBytes, jpegWidth, jpegHeight, isJpeg: true,
    x: 72, y: 105, width: 200, height: 150);

Merging PDFs

PdfMerger combines PDFs produced separately (e.g. a cover page built one way and content built another) into a single document:

byte[] sourceA = PdfDocument.Create()
    .AddPage(PageSizes.A4, canvas => { /* cover page */ })
    .ToBytes();

byte[] sourceB = PdfDocument.Create()
    .AddPage(PageSizes.A4, canvas => { /* content page */ })
    .ToBytes();

byte[] merged = new PdfMerger()
    .Add(sourceA)
    .Add(sourceB)
    .WithTitle("Quarterly Report")
    .WithAuthor("Example Corp")
    .Merge();

File.WriteAllBytes("report.pdf", merged);

Fonts and Unicode

Register TrueType fonts with a FontRegistry and set a fallback family for glyphs the primary font doesn't cover (useful for accented Latin, Greek, Cyrillic, and other scripts):

var registry = new FontRegistry()
    .AddDirectory("/path/to/fonts")
    .AddFallback("NotoSans");

PdfDocument.Create()
    .WithFontRegistry(registry)
    .AddPage(PageSizes.A4, canvas =>
    {
        canvas.DrawText("café résumé наизусть", 72, 72,
            TextStyle.Default.WithFamily("LiberationSans").WithSize(14));
    })
    .Save("unicode.pdf");

Right-to-left scripts (Hebrew, Arabic) are supported via TextStyle.WithRightToLeft() combined with TextAlignment.Right.

PDF/A Conformance

WithConformance() sets the correct PDF version, embeds an sRGB ICC output intent, and writes the required XMP conformance claim. PDF/A requires embedded TrueType fonts (standard Type1 fonts aren't permitted) and cannot be combined with encryption:

PdfDocument.Create()
    .WithConformance(PdfConformance.PdfA2b)  // or PdfA1b, PdfA3b
    .WithFontRegistry(registry)
    .AddPage(PageSizes.A4, canvas => { /* ... */ })
    .Save("archive.pdf");

Password Protection and Signatures

These require the Majorsilence.Pdf.Security package:

using Majorsilence.Pdf.Security;

var security = PdfSecurity.Protect(userPassword: "open123", ownerPassword: "owner456")
    .WithPermissions(PdfPermissions.Print | PdfPermissions.CopyText);

PdfDocument.Create()
    .WithSecurity(security)
    .AddPage(PageSizes.A4, canvas => { /* ... */ })
    .Save("protected.pdf");

Digital signatures (PKCS#7 detached, SHA-256) are added with WithSignature(new PdfSignatureOptions(certificate)).

PdfNative — using Majorsilence.Pdf from non-.NET languages

PdfNative is a Native AOT-compiled C API (libpdfnative.so / .dylib / pdfnative.dll) that exposes the same document, canvas, table, merge, and security primitives as Majorsilence.Pdf to any language that can call a C ABI — Python, PHP, Ruby, Rust, or plain C — with no .NET runtime required at the call site. It ships opacity, PDF/A conformance, digital signing, and public-key encryption support, matching the managed library's feature set.

pdf_init();
void* doc = pdf_doc_create();
pdf_doc_set_title(doc, "My Report");
void* canvas = pdf_doc_add_page(doc, 595.28f, 841.89f); // A4
pdf_canvas_draw_text(canvas, "Hello, PDF!", 72, 100, NULL);
pdf_canvas_close(canvas);
pdf_doc_save_file(doc, "/tmp/output.pdf");
pdf_doc_close(doc);

The header (PdfNative/pdfnative.h) documents the full C API with quick-start, table, merge, and security examples. Prebuilt platform/architecture zips (Windows/Linux/macOS, x64/arm64) are attached to each GitHub release. Like Majorsilence.Pdf, it is tri-licensed (MIT, Apache 2.0, or BSD 2-Clause).

See Also

Clone this wiki locally