How to Migrate from iText to IronPDF in C#
Migrating from iText to IronPDF moves your .NET PDF workflow from a programmatic API — building Paragraph, Table, and Cell objects in code — to an HTML-first approach with CSS3 and JavaScript support. This guide provides a step-by-step migration path that removes AGPL exposure and the need for a separate pdfHTML add-on.
Why Migrate from iText to IronPDF
The AGPL License Consideration
iText (owned by iText Group / Apryse Group NV) carries licensing characteristics commercial teams should weigh up front:
-
AGPL Viral License: If you use iText under its open-source license in a web application, the AGPL is typically interpreted as requiring you to release your application's source to anyone who interacts with it over a network. For closed-source commercial software this usually means buying a commercial license instead.
-
Subscription-Only Commercial Licensing: iText's commercial license is sold as an annual subscription based on PDF processing volume; a perpetual option is not advertised on the public pricing page (custom OEM terms are quote-only).
-
pdfHTML Add-On Cost: HTML-to-PDF requires the
itext.pdfhtmladd-on (currently 6.3.2), sold separately on top of the coreitextpackage (currently 9.6.0). -
Complex Licensing Audits: Enterprise deployments face licensing complexity and audit risk.
-
Programmatic-First API: Core iText builds PDFs by composing
Paragraph,Table, andCellobjects in code; pdfHTML lets you start from HTML. - Defined CSS Subset, No JS at Render Time: pdfHTML supports a defined subset of CSS and does not execute JavaScript while converting HTML to PDF (PDF-level JS form actions are a separate, supported feature).
iText vs IronPDF Comparison
| Feature | iText 9 / iTextSharp 5.x | IronPDF |
|---|---|---|
| License | AGPL (viral) or commercial annual subscription | Commercial, perpetual option |
| HTML-to-PDF | Separate itext.pdfhtml add-on (6.3.2) |
Built-in Chromium renderer |
| CSS Support | Defined CSS subset in pdfHTML | Full CSS3, Flexbox, Grid |
| JavaScript at render | pdfHTML does not run JS during HTML→PDF | Full JS execution at render time |
| API Paradigm | Programmatic (Paragraph, Table, Cell) | HTML-first with CSS |
| Learning Curve | Steep (PDF coordinate system) | Web developer friendly |
| Open Source Risk | Must open-source web apps under AGPL | No viral requirements |
| Pricing Model | Annual subscription (volume-based) or custom OEM | Perpetual or subscription |
For teams standardising on modern .NET, IronPDF's HTML-first approach leans on web development skills the team already has.
Migration Complexity Assessment
Estimated Effort by Feature
| Feature | Migration Complexity |
|---|---|
| HTML to PDF | Very Low |
| Merge PDFs | Low |
| Text and Images | Low |
| Tables | Medium |
| Headers/Footers | Medium |
| Security/Encryption | Low |
Paradigm Shift
The fundamental shift in this iText migration is from programmatic PDF construction to HTML-first rendering:
iText: PdfWriter → PdfDocument → Document → Add(Paragraph) → Add(Table)
IronPDF: ChromePdfRenderer → RenderHtmlAsPdf(htmlString) → SaveAs()
This paradigm shift is liberating: instead of learning iText's object model, you use HTML and CSS skills that web developers already possess.
Before You Start
Prerequisites
- .NET Environment: .NET Framework 4.6.2+ or .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet Access: Ability to install NuGet packages
- IronPDF License: Obtain your license key from ironpdf.com
NuGet Package Changes
# Remove iText packages (current naming is 'itext'; 'itext7' is the deprecated alias)
dotnet remove package itext
dotnet remove package itext.pdfhtml
dotnet remove package itext7
dotnet remove package itext7.pdfhtml
dotnet remove package itextsharp
# Install IronPDF
dotnet add package IronPdf
# Remove iText packages (current naming is 'itext'; 'itext7' is the deprecated alias)
dotnet remove package itext
dotnet remove package itext.pdfhtml
dotnet remove package itext7
dotnet remove package itext7.pdfhtml
dotnet remove package itextsharp
# Install IronPDF
dotnet add package IronPdf
License Configuration
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Identify iText Usage
# Find all iText references
grep -r "using iText\|using iTextSharp" --include="*.cs" .
grep -r "PdfWriter\|PdfDocument\|Document\|Paragraph\|Table\|Cell" --include="*.cs" .
grep -r "HtmlConverter\|ConverterProperties" --include="*.cs" .
# Find all iText references
grep -r "using iText\|using iTextSharp" --include="*.cs" .
grep -r "PdfWriter\|PdfDocument\|Document\|Paragraph\|Table\|Cell" --include="*.cs" .
grep -r "HtmlConverter\|ConverterProperties" --include="*.cs" .
Complete API Reference
Class Mappings
| iText 7+ Class | iTextSharp 5.x Class | IronPDF Equivalent |
|---|---|---|
PdfWriter |
PdfWriter |
ChromePdfRenderer |
PdfDocument |
Document |
PdfDocument |
Document |
Document |
ChromePdfRenderer.RenderHtmlAsPdf() |
Paragraph |
Paragraph |
HTML <p>, <h1>, etc. |
Table |
PdfPTable |
HTML <table> |
Cell |
PdfPCell |
HTML <td>, <th> |
Image |
Image |
HTML <img> |
PdfReader |
PdfReader |
PdfDocument.FromFile() |
PdfMerger |
N/A | PdfDocument.Merge() |
Namespace Mappings
| iText Namespace | IronPDF Equivalent |
|---|---|
iText.Kernel.Pdf |
IronPdf |
iText.Layout |
IronPdf |
iText.Layout.Element |
Use HTML elements |
iText.Html2pdf |
IronPdf (built-in) |
iText.IO.Image |
Use HTML <img> |
iText.Kernel.Utils |
IronPdf |
Code Migration Examples
Example 1: HTML to PDF Conversion
Before (iText):
// NuGet: Install-Package itext7
using iText.Html2pdf;
using System.IO;
class Program
{
static void Main()
{
string html = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>";
string outputPath = "output.pdf";
using (FileStream fs = new FileStream(outputPath, FileMode.Create))
{
HtmlConverter.ConvertToPdf(html, fs);
}
}
}
// NuGet: Install-Package itext7
using iText.Html2pdf;
using System.IO;
class Program
{
static void Main()
{
string html = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>";
string outputPath = "output.pdf";
using (FileStream fs = new FileStream(outputPath, FileMode.Create))
{
HtmlConverter.ConvertToPdf(html, fs);
}
}
}
Imports iText.Html2pdf
Imports System.IO
Class Program
Shared Sub Main()
Dim html As String = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
Dim outputPath As String = "output.pdf"
Using fs As FileStream = New FileStream(outputPath, FileMode.Create)
HtmlConverter.ConvertToPdf(html, fs)
End Using
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html As String = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End Class
The iText approach requires the separate itext.pdfhtml package (pdfHTML add-on, currently 6.3.2, sold separately on top of itext 9.6.0), creating a FileStream, and wrapping everything in using statements for proper disposal. The HtmlConverter.ConvertToPdf() method writes directly to the stream.
IronPDF's approach is cleaner: create a ChromePdfRenderer, call RenderHtmlAsPdf() with your HTML string, and call SaveAs() on the resulting PdfDocument. No separate packages, no stream management, and the Chromium rendering engine provides superior CSS3 and JavaScript support. See the HTML to PDF documentation for additional rendering options.
Example 2: Merge Multiple PDFs
Before (iText):
// NuGet: Install-Package itext7
using iText.Kernel.Pdf;
using iText.Kernel.Utils;
using System.IO;
class Program
{
static void Main()
{
string outputPath = "merged.pdf";
string[] inputFiles = { "document1.pdf", "document2.pdf", "document3.pdf" };
using (PdfWriter writer = new PdfWriter(outputPath))
using (PdfDocument pdfDoc = new PdfDocument(writer))
{
PdfMerger merger = new PdfMerger(pdfDoc);
foreach (string file in inputFiles)
{
using (PdfDocument sourcePdf = new PdfDocument(new PdfReader(file)))
{
merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages());
}
}
}
}
}
// NuGet: Install-Package itext7
using iText.Kernel.Pdf;
using iText.Kernel.Utils;
using System.IO;
class Program
{
static void Main()
{
string outputPath = "merged.pdf";
string[] inputFiles = { "document1.pdf", "document2.pdf", "document3.pdf" };
using (PdfWriter writer = new PdfWriter(outputPath))
using (PdfDocument pdfDoc = new PdfDocument(writer))
{
PdfMerger merger = new PdfMerger(pdfDoc);
foreach (string file in inputFiles)
{
using (PdfDocument sourcePdf = new PdfDocument(new PdfReader(file)))
{
merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages());
}
}
}
}
}
Imports iText.Kernel.Pdf
Imports iText.Kernel.Utils
Imports System.IO
Class Program
Shared Sub Main()
Dim outputPath As String = "merged.pdf"
Dim inputFiles As String() = {"document1.pdf", "document2.pdf", "document3.pdf"}
Using writer As New PdfWriter(outputPath)
Using pdfDoc As New PdfDocument(writer)
Dim merger As New PdfMerger(pdfDoc)
For Each file As String In inputFiles
Using sourcePdf As New PdfDocument(New PdfReader(file))
merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages())
End Using
Next
End Using
End Using
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System.Collections.Generic;
class Program
{
static void Main()
{
var pdfDocuments = new List<PdfDocument>
{
PdfDocument.FromFile("document1.pdf"),
PdfDocument.FromFile("document2.pdf"),
PdfDocument.FromFile("document3.pdf")
};
var merged = PdfDocument.Merge(pdfDocuments);
merged.SaveAs("merged.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System.Collections.Generic;
class Program
{
static void Main()
{
var pdfDocuments = new List<PdfDocument>
{
PdfDocument.FromFile("document1.pdf"),
PdfDocument.FromFile("document2.pdf"),
PdfDocument.FromFile("document3.pdf")
};
var merged = PdfDocument.Merge(pdfDocuments);
merged.SaveAs("merged.pdf");
}
}
Imports IronPdf
Imports System.Collections.Generic
Class Program
Shared Sub Main()
Dim pdfDocuments As New List(Of PdfDocument) From {
PdfDocument.FromFile("document1.pdf"),
PdfDocument.FromFile("document2.pdf"),
PdfDocument.FromFile("document3.pdf")
}
Dim merged = PdfDocument.Merge(pdfDocuments)
merged.SaveAs("merged.pdf")
End Sub
End Class
The iText merge operation requires significant boilerplate: creating a PdfWriter for output, wrapping it in a PdfDocument, creating a PdfMerger, then iterating through source files with nested using statements for each PdfDocument and PdfReader. You must also specify page ranges with merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages()).
IronPDF reduces this to three steps: load documents with PdfDocument.FromFile(), call the static PdfDocument.Merge() method with the list, and save. The entire merge operation becomes readable and maintainable. Learn more about merging and splitting PDFs.
Example 3: Create PDF with Text and Images
Before (iText):
// NuGet: Install-Package itext7
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.IO.Image;
class Program
{
static void Main()
{
string outputPath = "document.pdf";
using (PdfWriter writer = new PdfWriter(outputPath))
using (PdfDocument pdf = new PdfDocument(writer))
using (Document document = new Document(pdf))
{
document.Add(new Paragraph("Sample PDF Document"));
document.Add(new Paragraph("This document contains text and an image."));
Image img = new Image(ImageDataFactory.Create("image.jpg"));
img.SetWidth(200);
document.Add(img);
}
}
}
// NuGet: Install-Package itext7
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.IO.Image;
class Program
{
static void Main()
{
string outputPath = "document.pdf";
using (PdfWriter writer = new PdfWriter(outputPath))
using (PdfDocument pdf = new PdfDocument(writer))
using (Document document = new Document(pdf))
{
document.Add(new Paragraph("Sample PDF Document"));
document.Add(new Paragraph("This document contains text and an image."));
Image img = new Image(ImageDataFactory.Create("image.jpg"));
img.SetWidth(200);
document.Add(img);
}
}
}
Imports iText.Kernel.Pdf
Imports iText.Layout
Imports iText.Layout.Element
Imports iText.IO.Image
Class Program
Shared Sub Main()
Dim outputPath As String = "document.pdf"
Using writer As New PdfWriter(outputPath),
pdf As New PdfDocument(writer),
document As New Document(pdf)
document.Add(New Paragraph("Sample PDF Document"))
document.Add(New Paragraph("This document contains text and an image."))
Dim img As New Image(ImageDataFactory.Create("image.jpg"))
img.SetWidth(200)
document.Add(img)
End Using
End Sub
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = @"
<h1>Sample PDF Document</h1>
<p>This document contains text and an image.</p>
<img src='image.jpg' width='200' />";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = @"
<h1>Sample PDF Document</h1>
<p>This document contains text and an image.</p>
<img src='image.jpg' width='200' />";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html As String = "
<h1>Sample PDF Document</h1>
<p>This document contains text and an image.</p>
<img src='image.jpg' width='200' />"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("document.pdf")
End Sub
End Class
This example illustrates the paradigm shift most clearly. iText requires:
- Triple-nested
usingstatements (PdfWriter,PdfDocument,Document) - Creating
Paragraphobjects for each text element withnew Paragraph() - Using
ImageDataFactory.Create()to load images - Creating an
Imageobject and callingSetWidth()separately - Calling
document.Add()for each element
IronPDF uses standard HTML: <h1> for headings, <p> for paragraphs, and <img> for images with a width attribute. Web developers can leverage their existing skills immediately, and designers can style documents using CSS they already know.
Critical Migration Notes
Paradigm Shift: Programmatic to HTML-First
The most significant change in this iText migration is conceptual. iText builds PDFs programmatically:
// iText approach
document.Add(new Paragraph("Title")
.SetTextAlignment(TextAlignment.CENTER)
.SetFontSize(24)
.SetBold());
var table = new Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth();
table.AddHeaderCell(new Cell().Add(new Paragraph("ID")));
table.AddHeaderCell(new Cell().Add(new Paragraph("Name")));
// ... many more lines
// iText approach
document.Add(new Paragraph("Title")
.SetTextAlignment(TextAlignment.CENTER)
.SetFontSize(24)
.SetBold());
var table = new Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth();
table.AddHeaderCell(new Cell().Add(new Paragraph("ID")));
table.AddHeaderCell(new Cell().Add(new Paragraph("Name")));
// ... many more lines
' iText approach
document.Add(New Paragraph("Title") _
.SetTextAlignment(TextAlignment.CENTER) _
.SetFontSize(24) _
.SetBold())
Dim table = New Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth()
table.AddHeaderCell(New Cell().Add(New Paragraph("ID")))
table.AddHeaderCell(New Cell().Add(New Paragraph("Name")))
' ... many more lines
IronPDF uses HTML and CSS:
// IronPDF approach
string html = @"
<style>
h1 { text-align: center; font-size: 24px; font-weight: bold; }
table { width: 100%; border-collapse: collapse; }
th { background-color: #4CAF50; color: white; padding: 8px; }
</style>
<h1>Title</h1>
<table>
<tr><th>ID</th><th>Name</th></tr>
</table>";
var pdf = renderer.RenderHtmlAsPdf(html);
// IronPDF approach
string html = @"
<style>
h1 { text-align: center; font-size: 24px; font-weight: bold; }
table { width: 100%; border-collapse: collapse; }
th { background-color: #4CAF50; color: white; padding: 8px; }
</style>
<h1>Title</h1>
<table>
<tr><th>ID</th><th>Name</th></tr>
</table>";
var pdf = renderer.RenderHtmlAsPdf(html);
' IronPDF approach
Dim html As String = "
<style>
h1 { text-align: center; font-size: 24px; font-weight: bold; }
table { width: 100%; border-collapse: collapse; }
th { background-color: #4CAF50; color: white; padding: 8px; }
</style>
<h1>Title</h1>
<table>
<tr><th>ID</th><th>Name</th></tr>
</table>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
AGPL Exposure Removed
Under iText's AGPL terms, a web application that uses iText is typically expected to release its source to anyone who interacts with it over a network; the commercial license is the alternative path. IronPDF's commercial license allows deployment in proprietary software without viral licensing requirements.
No pdfHTML Add-On Required
iText requires the separate itext.pdfhtml add-on (currently 6.3.2) for HTML-to-PDF conversion, sold on top of the core itext package. IronPDF includes Chromium-based HTML rendering in the base package.
Method Replacement Patterns
| iText Pattern | IronPDF Replacement |
|---|---|
SetTextAlignment(TextAlignment.CENTER) |
CSS text-align: center |
SetFontSize(24) |
CSS font-size: 24px |
SetBold() |
CSS font-weight: bold |
new Table(3) |
HTML <table> |
AddHeaderCell(new Cell().Add(new Paragraph())) |
HTML <th> |
AddCell(new Cell().Add(new Paragraph())) |
HTML <td> |
Troubleshooting
Issue 1: PdfWriter/Document Pattern
Problem: Code uses the PdfWriter → PdfDocument → Document nesting pattern.
Solution: Replace with ChromePdfRenderer:
// Delete this iText pattern:
// using (var writer = new PdfWriter(outputPath))
// using (var pdfDoc = new PdfDocument(writer))
// using (var document = new Document(pdfDoc))
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
// Delete this iText pattern:
// using (var writer = new PdfWriter(outputPath))
// using (var pdfDoc = new PdfDocument(writer))
// using (var document = new Document(pdfDoc))
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs(outputPath)
Issue 2: HtmlConverter Not Found
Problem: Code uses iText.Html2pdf.HtmlConverter, which lives in the separately-purchased itext.pdfhtml add-on.
Solution: Use IronPDF's built-in HTML rendering:
// iText (requires pdfHTML add-on)
HtmlConverter.ConvertToPdf(html, fileStream);
// IronPDF (built-in)
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
// iText (requires pdfHTML add-on)
HtmlConverter.ConvertToPdf(html, fileStream);
// IronPDF (built-in)
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(outputPath);
' iText (requires pdfHTML add-on)
HtmlConverter.ConvertToPdf(html, fileStream)
' IronPDF (built-in)
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs(outputPath)
Issue 3: PdfMerger Complexity
Problem: iText's PdfMerger requires nested readers and page range specification.
Solution: Use IronPDF's static merge method:
// iText merger pattern (delete this)
// using (PdfDocument pdfDoc = new PdfDocument(writer))
// {
// PdfMerger merger = new PdfMerger(pdfDoc);
// foreach (string file in inputFiles)
// {
// using (PdfDocument sourcePdf = new PdfDocument(new PdfReader(file)))
// {
// merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages());
// }
// }
// }
// IronPDF (simple)
var merged = PdfDocument.Merge(pdfDocuments);
merged.SaveAs("merged.pdf");
// iText merger pattern (delete this)
// using (PdfDocument pdfDoc = new PdfDocument(writer))
// {
// PdfMerger merger = new PdfMerger(pdfDoc);
// foreach (string file in inputFiles)
// {
// using (PdfDocument sourcePdf = new PdfDocument(new PdfReader(file)))
// {
// merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages());
// }
// }
// }
// IronPDF (simple)
var merged = PdfDocument.Merge(pdfDocuments);
merged.SaveAs("merged.pdf");
' iText merger pattern (delete this)
' Using pdfDoc As New PdfDocument(writer)
' Dim merger As New PdfMerger(pdfDoc)
' For Each file As String In inputFiles
' Using sourcePdf As New PdfDocument(New PdfReader(file))
' merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages())
' End Using
' Next
' End Using
' IronPDF (simple)
Dim merged = PdfDocument.Merge(pdfDocuments)
merged.SaveAs("merged.pdf")
Migration Checklist
Pre-Migration
- Inventory all iText API calls in codebase
- Identify programmatic PDF construction patterns (Paragraph, Table, Cell)
- Document HtmlConverter usage (pdfHTML add-on)
- Assess AGPL compliance risk
- Obtain IronPDF license key
Code Migration
- Remove iText NuGet packages:
dotnet remove package itext(and the deprecateditext7alias, plusitext.pdfhtml/iTextSharpif present) - Install IronPDF NuGet package:
dotnet add package IronPdf - Update namespace imports (
using iText.*→using IronPdf) - Replace
PdfWriter/Documentpattern withChromePdfRenderer - Convert
Paragraph/Table/Cellto HTML elements - Replace
HtmlConverter.ConvertToPdf()withRenderHtmlAsPdf() - Update merge operations to
PdfDocument.Merge() - Add license key initialization at startup
Testing
- Test all PDF generation paths
- Verify visual output matches expectations
- Test with complex HTML/CSS content
- Benchmark performance
Post-Migration
- Remove iText license files and references
- Update documentation
- Cancel iText subscription (if applicable)
- Archive legacy iText code

