Migrating a PDFsharp project from .NET Framework to .NET Core, .NET 6, or .NET 8 often results in runtime exceptions related to fonts, System.Drawing, or missing platform dependencies. The original PDFsharp library was built around Windows-specific APIs, and while recent versions have added cross-platform support, developers continue to encounter obstacles when deploying to Linux servers, Docker containers, or macOS environments.
The Problem
PDFsharp's architecture historically relied on System.Drawing.Common and GDI+ for two critical operations: font resolution and image handling. When Microsoft deprecated System.Drawing.Common for non-Windows platforms in .NET 6+, PDFsharp users faced a choice between staying on Windows-only builds or navigating a complex migration path.
The official PDFsharp 6.x release introduced a "Core" build that removes the GDI+ dependency, but this creates a new problem: the Core build has no built-in font resolution strategy for non-Windows platforms. Developers must implement a custom IFontResolver interface before any text can be rendered to a PDF.
This manifests in several ways depending on the deployment environment:
- Attempting to create an
XFontobject throws an exception stating no fonts are available - Applications that worked in development on Windows fail when deployed to Linux containers
- PDF generation succeeds but uses incorrect or fallback fonts, producing unexpected output
- Docker deployments require additional configuration that documentation does not clearly explain
Error Messages and Symptoms
The most common error when running PDFsharp Core on Linux or macOS:
System.InvalidOperationException: No appropriate font found.
at PdfSharp.Fonts.PlatformFontResolver.ResolveTypeface(String familyName, Boolean isBold, Boolean isItalic)
When using the older PDFsharp 1.5x with .NET Core:
System.TypeLoadException: Could not resolve type with token 01000060 from typeref
(expected class 'System.Drawing.Graphics' in assembly 'System.Drawing.Common, Version=4.0.0.0')
Docker containers running Alpine Linux may show:
System.DllNotFoundException: Unable to load shared library 'user32.dll' or one of its dependencies
And when the PlatformFontResolver fails to locate system fonts:
InvalidOperationException: No Fonts installed on this device
Who Is Affected
This issue impacts developers in several scenarios.
Cloud and Container Deployments: Applications running on AWS Lambda, Azure Functions, Google Cloud Run, or Kubernetes clusters with Linux-based containers cannot use PDFsharp without significant configuration work. The typical development workflow of building on Windows and deploying to Linux breaks down.
Cross-Platform Applications: .NET MAUI, Blazor WebAssembly, and other cross-platform frameworks cannot rely on PDFsharp's default font resolution. Each target platform requires explicit font handling code.
CI/CD Pipelines: Build servers running Linux agents may fail tests or produce different PDF output than developer machines running Windows, creating inconsistent behavior between environments.
Framework Versions: The compatibility matrix is complex:
- PDFsharp 1.5x works with .NET Framework 4.x but has limited .NET Core support
- PDFsharp 6.x targets .NET 6, .NET 8, .NET 9, and .NET 10
- The -GDI and -WPF variants only work on Windows
- The Core variant works cross-platform but requires custom font resolver implementation
Evidence from the Developer Community
The challenges with PDFsharp on .NET Core have been documented across multiple platforms since 2020.
Timeline
| Date | Event | Source |
|---|---|---|
| 2020-02-05 | Stack Overflow question confirms PDFsharp does not work with .NET Core | Stack Overflow |
| 2021-08-20 | PdfSharpCore users report font resolution failures in Linux containers | GitHub |
| 2022-03-15 | GitHub issue documents .NET 6 incompatibility with PDFsharp 1.50 | GitHub |
| 2022-06-10 | Forum thread describes System.Drawing.Common errors | PDFsharp Forum |
| 2023-01-15 | Docker/Alpine Linux font issues documented | PDFsharp Forum |
| 2024-01-01 | PDFsharp 6.x documentation acknowledges custom font resolver requirement | Official Docs |
| 2024-11-12 | .NET 6 end of support, PDFsharp 6.2.3 drops .NET 6 compilation target | GitHub |
Community Reports
"No, PDFsharp does not work with .NET Core yet. Yes, you can get third-party libraries that support the PDFsharp APIs with .NET Core."
— Stack Overflow answer, February 2020
The official documentation itself states the limitation clearly:
"In the Core build, PlatformFontResolver throws an exception by default. The reason is that the .NET version of the Core build runs on all platforms/operating systems .NET runs on and there is no general font resolving strategy on all these platforms."
— PDFsharp Documentation, Font Resolving
Multiple GitHub issues in the PdfSharpCore repository document developers struggling with font resolution after deploying to production Linux environments, only to discover their Windows development setup masked the underlying platform dependency.
Root Cause Analysis
The fundamental issue stems from PDFsharp's original design targeting Windows desktop applications where System.Drawing and GDI+ provide font enumeration and rendering services. When .NET went cross-platform, these dependencies became problematic.
System.Drawing.Common Deprecation: Microsoft explicitly warns against using System.Drawing.Common on non-Windows platforms. The library relies on libgdiplus on Linux, which is not maintained to the same standard as the Windows GDI+ implementation and can introduce memory leaks and rendering inconsistencies.
No Universal Font Resolution: Unlike Windows, which has a centralized font registration system accessible via GDI+, Linux distributions store fonts in various locations with different naming conventions. macOS uses yet another approach with its Core Text framework. PDFsharp's team chose not to implement platform-specific font resolution for the Core build, instead requiring developers to provide their own implementation.
PdfSharpCore Fork Limitations: The community-maintained PdfSharpCore fork attempted to solve this by using SixLabors.Fonts and SixLabors.ImageSharp. However, this introduces its own constraints:
- Only TTF font format is supported; OTF fonts cannot be used
- The fork is based on an older PDFsharp version
- SixLabors libraries have their own licensing considerations
- Documentation is sparse
API Surface Changes: Migrating from PDFsharp 1.5x to 6.x involves namespace changes and some breaking API modifications. PdfSharpCore uses different namespaces entirely (PdfSharpCore instead of PdfSharp), requiring search-and-replace operations across codebases.
Attempted Workarounds
Workaround 1: Implement Custom IFontResolver
The official recommendation is to implement the IFontResolver interface and set it via GlobalFontSettings.FontResolver at application startup.
using PdfSharp.Fonts;
public class CustomFontResolver : IFontResolver
{
public byte[] GetFont(string faceName)
{
// Load font bytes from embedded resource or file system
var assembly = typeof(CustomFontResolver).Assembly;
using var stream = assembly.GetManifestResourceStream($"MyApp.Fonts.{faceName}.ttf");
if (stream == null)
throw new InvalidOperationException($"Font {faceName} not found");
using var ms = new MemoryStream();
stream.CopyTo(ms);
return ms.ToArray();
}
public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
{
// Map requested font families to embedded font face names
var faceName = familyName.ToLower() switch
{
"arial" when isBold && isItalic => "arialbi",
"arial" when isBold => "arialbd",
"arial" when isItalic => "ariali",
"arial" => "arial",
_ => "arial" // Fallback
};
return new FontResolverInfo(faceName);
}
}
// At application startup
GlobalFontSettings.FontResolver = new CustomFontResolver();
Limitations:
- Every font family and style combination must be explicitly mapped
- Fonts must be embedded as resources, increasing assembly size
- The resolver cannot be changed after any XFont has been created
- No fallback to system fonts for missing entries
- Requires acquiring and distributing font files (licensing considerations)
Workaround 2: Use PdfSharpCore Instead
Some developers switch to the PdfSharpCore NuGet package, which uses SixLabors libraries for cross-platform font and image handling.
// Change namespace from PdfSharp to PdfSharpCore
using PdfSharpCore.Drawing;
using PdfSharpCore.Pdf;
// Then use similar API
var document = new PdfDocument();
var page = document.AddPage();
var gfx = XGraphics.FromPdfPage(page);
var font = new XFont("Arial", 12);
gfx.DrawString("Hello", font, XBrushes.Black, new XPoint(50, 50));
Limitations:
- Based on older PDFsharp codebase
- Only TTF fonts are supported
- Different namespace requires code changes
- SixLabors.Fonts has its own quirks with font discovery
- Less active maintenance than official PDFsharp
Workaround 3: Install libgdiplus in Docker
For the GDI build variant, some developers install libgdiplus in their Docker containers.
FROM mcr.microsoft.com/dotnet/aspnet:8.0
RUN apt-get update && apt-get install -y --no-install-recommends \
libgdiplus \
libc6-dev \
&& rm -rf /var/lib/apt/lists/*
# Symbolic link sometimes required
RUN ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll
Limitations:
- Only works with PDFsharp-GDI variant, not the Core build
- Increases container image size significantly
- libgdiplus has known memory leak issues
- Microsoft explicitly recommends against System.Drawing.Common for server workloads
- Does not solve font resolution; fonts must still be installed in the container
Workaround 4: Use Windows-Only Packages
Developers who only target Windows can use the PDFsharp-gdi or PDFsharp-wpf NuGet packages, which continue to use the platform's native font resolution.
<PackageReference Include="PDFsharp-gdi" Version="6.2.3" />
Limitations:
- Locks the application to Windows deployment only
- Cannot use in Linux containers, cloud functions, or cross-platform scenarios
- Target framework must include
-windowssuffix:net8.0-windows
A Different Approach: IronPDF
For developers who need to generate PDFs on .NET 6, .NET 8, or later across multiple platforms without implementing custom font resolvers or managing platform-specific dependencies, IronPDF offers an alternative architecture.
IronPDF embeds a Chromium rendering engine that handles font resolution, CSS styling, and HTML rendering internally. The library does not depend on System.Drawing.Common or require custom font resolver implementations. The same code runs on Windows, Linux, macOS, and Docker without configuration changes.
Why IronPDF Avoids These Issues
IronPDF's architecture differs fundamentally from PDFsharp's drawing-based approach:
Self-contained rendering: The embedded Chromium engine includes font handling, eliminating the need for external font resolution APIs or custom resolvers.
HTML/CSS input: Instead of programmatic drawing calls with explicit font objects, IronPDF accepts HTML and CSS, using web-standard font specifications that Chromium interprets.
Cross-platform binaries: IronPDF ships platform-specific native binaries that are automatically selected at runtime based on the deployment environment.
Docker-ready: No additional packages like libgdiplus are required. The library works with standard .NET runtime containers.
Code Example
using IronPdf;
public class CrossPlatformPdfGenerator
{
public void GeneratePdf()
{
// Works identically on Windows, Linux, macOS, and Docker
var renderer = new ChromePdfRenderer();
// Configure rendering options if needed
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
// Render HTML content to PDF
// Fonts are handled by the embedded Chromium engine
string htmlContent = @"
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
h1 { color: #333; }
p { font-size: 14px; line-height: 1.6; }
</style>
</head>
<body>
<h1>Cross-Platform PDF Generation</h1>
<p>This document renders consistently across all platforms
without custom font resolver configuration.</p>
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
public void RenderFromUrl()
{
var renderer = new ChromePdfRenderer();
// Render any web page, including pages with web fonts
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}
Key points about this approach:
- No
IFontResolverimplementation required - HTML/CSS syntax is familiar to most developers
- Web fonts (Google Fonts, custom fonts via @font-face) work automatically
- Same code deploys to any .NET-supported platform
API Reference
For details on the methods and configuration options used above:
Migration Considerations
Licensing
PDFsharp is open source under the MIT license, making it free for any use. IronPDF is commercial software with a licensing fee. A free trial is available for evaluation before purchase. Organizations should factor licensing costs into the total cost of ownership, balanced against development time spent implementing and maintaining custom font resolvers.
API Differences
PDFsharp uses a programmatic drawing model with explicit coordinate placement:
// PDFsharp approach
gfx.DrawString("Hello", font, brush, x, y);
gfx.DrawRectangle(pen, x, y, width, height);
IronPDF uses an HTML/CSS model:
// IronPDF approach
renderer.RenderHtmlAsPdf("<p style='margin-left: 50px'>Hello</p>");
For applications with heavy use of PDFsharp's drawing APIs, migration requires restructuring PDF generation logic around HTML templates. For applications that already generate HTML reports or use template engines, IronPDF may integrate more naturally.
What You Gain
- Cross-platform deployment without custom font resolver code
- No libgdiplus or System.Drawing.Common dependencies
- Consistent rendering across Windows, Linux, macOS, and Docker
- Full CSS support including Flexbox, Grid, and web fonts
- JavaScript execution for dynamic content
What to Consider
- Commercial license required for production use
- Larger package size due to embedded Chromium
- Different mental model (HTML templates vs programmatic drawing)
- Potential refactoring effort for existing PDFsharp codebases
Conclusion
PDFsharp's .NET Core compatibility has improved with version 6.x, but cross-platform font resolution remains a challenge that requires custom implementation. Developers deploying to Linux, Docker, or macOS must either implement IFontResolver, use the community-maintained PdfSharpCore fork with its limitations, or accept Windows-only deployment.
For projects where cross-platform consistency and minimal configuration are priorities, evaluating IronPDF's Chromium-based approach may reduce development complexity and deployment issues.
Jacob Mellor built IronPDF and has spent 25+ years developing commercial software tools for .NET developers.
References
- PDFsharp Font Resolving Documentation{:rel="nofollow"} - Official documentation on font resolver requirements
- Is it possible to use PDFsharp with .NET Core? - Stack Overflow{:rel="nofollow"} - Community discussion on .NET Core compatibility
- PdfSharpCore GitHub Repository{:rel="nofollow"} - Community fork for .NET Core
- PDFsharp GitHub - .NET 6 Compatibility Issue{:rel="nofollow"} - Discussion of .NET 6 incompatibility
- PDFsharp Forum - Fonts not resolved on Docker{:rel="nofollow"} - Forum thread on Docker deployment issues
- Choose the best PDFsharp build{:rel="nofollow"} - Official guidance on build variants
- PdfSharpCore Font Limitations{:rel="nofollow"} - Discussion of TTF-only font support
For the latest IronPDF documentation and tutorials, visit ironpdf.com.
Top comments (0)