Migration guides
Moving to Rivoli PDF from iText, PDFsharp, QuestPDF, or Aspose.
If you are coming from another PDF library, the fastest way to get productive is to map your existing mental model onto Rivoli PDF’s. This page does that mapping and shows a couple of before/after sketches. The Rivoli PDF code is real, verified API; the other-library snippets are illustrative shorthand, not exact ports.
The big idea
Section titled “The big idea”Rivoli PDF separates content from rendering. You build a document tree (a DOM of sections, blocks, and inlines), entirely in memory, then hand it to a layout engine and writer to produce pixels. The tree is plain data: serializable, diffable, cacheable. See The document model.
That separation is the key to translating from other libraries: whatever paradigm you are used to ends up producing the same tree.
- If you think in fluent composition (QuestPDF), our fluent helpers and
DocumentBuildergive you the same top-down, declarative feel. - If you think in low-level content streams (iText’s
Canvas/PdfCanvas, PDFsharp’sXGraphics), you instead describe content with model types:Paragraph,Table,ImageBlock, and the layout engine handles positioning. You stop placing text at coordinates and start describing structure. - If you think in document object models (Aspose’s
Document/Section), you are already most of the way there; the type names line up closely.
Concept mapping
Section titled “Concept mapping”| Concept | iText | PDFsharp | QuestPDF | Aspose.PDF | Rivoli PDF |
|---|---|---|---|---|---|
| Document root | Document / PdfDocument | PdfDocument | Document | Document | Document |
| Page grouping | new page / PdfPage | PdfPage | page settings | Page | Section |
| Paragraph of text | Paragraph | manual DrawString | .Text(...) | TextFragment/Paragraph | Paragraph + Run |
| Styled text span | Text / chunk | font + brush args | .Span(...).Bold() | TextSegment | Run / Span with Style |
| Table | Table / Cell | manual drawing | .Table(...) | Table/Row/Cell | Table / TableRow / TableCell |
| List | List / ListItem | manual | .Column + items | List | List / ListItem |
| Image | Image | XImage | .Image(...) | Image | ImageBlock / InlineImage |
| Fluent assembly | builder helpers | n/a | IDocument composition | n/a | DocumentBuilder + extension methods |
| Save to PDF | pdf.Close() | doc.Save(path) | .GeneratePdf(path) | doc.Save(path) | document.SavePdf(path) |
| Encryption / permissions | WriterProperties | SecuritySettings | n/a | Encryption | PdfSecuritySettings (via PdfDocumentRenderer) |
From QuestPDF’s fluent composition
Section titled “From QuestPDF’s fluent composition”QuestPDF users compose a document with nested fluent calls. Rivoli PDF’s fluent helpers read the same way: you build sections and add content with chainable methods.
// QuestPDF-style (illustrative)container.Page(page =>{ page.Content().Column(col => { col.Item().Text("Quarterly Report").FontSize(20).Bold(); col.Item().Text("Prepared by the finance team."); });});// Rivoli.Pdf: real APIusing Rivoli.Pdf;using Rivoli.Pdf.Model;using Rivoli.Pdf.Builders;
var doc = Document.Create("Quarterly Report");doc.DefaultPageSize = PageSize.A4;
var section = doc.AddSection();section .H1("Quarterly Report") .AddParagraph("Prepared by the finance team.") .AddTable(t => t .Header("Quarter", "Revenue") .Row("Q1", "$1.2M") .Row("Q2", "$1.5M"));
doc.SavePdf("report.pdf");Reusable components (QuestPDF’s IComponent pattern), map to ContainerBlock and
plain methods that return blocks. See Components & reuse.
From iText / PDFsharp’s low-level content
Section titled “From iText / PDFsharp’s low-level content”In iText and PDFsharp you often place content imperatively: pick a font, set a brush, draw a string at coordinates. In Rivoli PDF you describe what the content is and let the layout engine place it.
// PDFsharp-style (illustrative)var page = pdf.AddPage();var gfx = XGraphics.FromPdfPage(page);var font = new XFont("Helvetica", 11);gfx.DrawString("Hello, world.", font, XBrushes.Black, new XPoint(72, 72));// Rivoli.Pdf real API: structure, not coordinatesusing Rivoli.Pdf;using Rivoli.Pdf.Model;
var doc = Document.Create("Hello");doc.DefaultMargin = Margin.Standard;
var section = doc.AddSection();section.Add(new Paragraph("Hello, world.") .Add(" Styled inline too", new Style() .WithFontFamily("Helvetica") .WithFontSize(11) .WithForegroundColor(Color.Black)));
doc.SavePdf("hello.pdf");The payoff: the same tree lays out correctly for A4 or Letter without you touching a single coordinate, and you can serialize it to JSON, diff it, or cache it.
Security, PDF/A, and advanced output
Section titled “Security, PDF/A, and advanced output”The one-line SavePdf(path) covers everyday saving. For encryption, PDF/A
conformance, tagged output, or font subsetting, go through PdfDocumentRenderer with
PdfSaveOptions: the analogue of WriterProperties / SecuritySettings elsewhere:
using Rivoli.Pdf;using Rivoli.Pdf.Security;
var renderer = new PdfDocumentRenderer("1.7");renderer.RenderToFile(doc, "secure.pdf", new PdfSaveOptions{ SecuritySettings = new PdfSecuritySettings { UserPassword = "open-me", OwnerPassword = "owner", Algorithm = PdfEncryptionAlgorithm.Aes256, Permissions = PdfPermissions.Print | PdfPermissions.CopyContents, },});Migration checklist
Section titled “Migration checklist”- Stop thinking in pages and coordinates; think in sections, blocks, and inlines.
- Replace imperative drawing with model types and let the layout engine place content.
- Use
DocumentBuilderfor document-wide setup, fluent helpers for content, POCO for data-driven loops: mix freely. - Move encryption/PDF-A/tagging from save-time flags to
PdfSaveOptionsonPdfDocumentRenderer. - For anything reading-heavy, confirm current support in the examples gallery first.
See also
Section titled “See also”- The document model: the tree everything compiles down to.
- Working with the builder: the three construction styles.
- Examples gallery: runnable samples mapped to features.