Skip to content

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.

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 DocumentBuilder give you the same top-down, declarative feel.
  • If you think in low-level content streams (iText’s Canvas/PdfCanvas, PDFsharp’s XGraphics), 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.
ConceptiTextPDFsharpQuestPDFAspose.PDFRivoli PDF
Document rootDocument / PdfDocumentPdfDocumentDocumentDocumentDocument
Page groupingnew page / PdfPagePdfPagepage settingsPageSection
Paragraph of textParagraphmanual DrawString.Text(...)TextFragment/ParagraphParagraph + Run
Styled text spanText / chunkfont + brush args.Span(...).Bold()TextSegmentRun / Span with Style
TableTable / Cellmanual drawing.Table(...)Table/Row/CellTable / TableRow / TableCell
ListList / ListItemmanual.Column + itemsListList / ListItem
ImageImageXImage.Image(...)ImageImageBlock / InlineImage
Fluent assemblybuilder helpersn/aIDocument compositionn/aDocumentBuilder + extension methods
Save to PDFpdf.Close()doc.Save(path).GeneratePdf(path)doc.Save(path)document.SavePdf(path)
Encryption / permissionsWriterPropertiesSecuritySettingsn/aEncryptionPdfSecuritySettings (via PdfDocumentRenderer)

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 API
using 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 coordinates
using 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.

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,
},
});