DEV Community

IronSoftware
IronSoftware

Posted on

PdfSharp on Linux and macOS: Cross-Platform Issues (Fixed)

Developers attempting to use PdfSharp on Linux or macOS frequently encounter font resolution failures, GDI+ dependency errors, and platform-specific exceptions that do not occur on Windows. The library was originally designed for .NET Framework on Windows, and while cross-platform support has improved with version 6.x and the community-maintained PdfSharpCore fork, significant gaps remain. This article examines the root causes, documents common errors, and presents an alternative approach using a library with native cross-platform support.

The Problem

PdfSharp's cross-platform compatibility issues stem from two fundamental architectural decisions: its historical dependency on GDI+ for graphics operations and its reliance on Windows-specific font resolution mechanisms.

The original PdfSharp library used System.Drawing.Common for image handling and graphics operations. On Windows, System.Drawing.Common leverages GDI+, which is part of the operating system. On Linux and macOS, System.Drawing.Common either requires libgdiplus (an unmaintained Mono project with known memory leaks) or fails outright with platform exceptions.

Version 6.x of PdfSharp introduced a "Core" build that removed the GDI+ dependency, but introduced a new problem: the Core build has no built-in font resolution strategy for non-Windows platforms. On macOS specifically, no fonts are found by default. On Linux, the default font resolver may or may not find fonts depending on the distribution and configuration. This means developers must implement custom font resolvers for any cross-platform deployment.

The community-maintained PdfSharpCore fork attempted to address these issues by replacing System.Drawing dependencies with SixLabors.ImageSharp, but it has its own limitations including TTF-only font support and ongoing font resolution issues in container environments.

Error Messages and Symptoms

Developers typically encounter one of these error patterns when running PdfSharp on Linux or macOS:

System.InvalidOperationException: No appropriate font found for family name 'Arial'.
Implement IFontResolver and assign to 'GlobalFontSettings.FontResolver' to use fonts.
   at PdfSharp.Drawing.XGlyphTypeface.GetOrCreateFrom(String familyName, FontResolvingOptions fontResolvingOptions)
   at PdfSharp.Drawing.XFont..ctor(String familyName, Double emSize, XFontStyleEx style)
Enter fullscreen mode Exit fullscreen mode
System.PlatformNotSupportedException: System.Drawing.Common is not supported on non-Windows platforms.
   at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
   at PdfSharp.Drawing.XImage.FromFile(String path)
Enter fullscreen mode Exit fullscreen mode
System.DllNotFoundException: Unable to load shared library 'user32.dll' or one of its dependencies.
   at MS.Win32.UnsafeNativeMethods.IntGetSystemMetrics(SM nIndex)
Enter fullscreen mode Exit fullscreen mode
PdfSharpException: No Fonts installed on this device!!
   at PdfSharpCore.Utils.FontResolver.ResolveFontFamily(String familyName)
Enter fullscreen mode Exit fullscreen mode

Symptoms include:

  • Applications that work on Windows development machines failing in Linux Docker containers
  • PDF generation crashing when any text rendering is attempted on macOS
  • Font substitution producing incorrect glyphs or garbled text
  • Image embedding failing with platform-not-supported exceptions
  • Applications requiring complex font resolver implementations for basic functionality

Who Is Affected

This issue impacts any deployment using PdfSharp outside of Windows environments:

Operating Systems: Ubuntu, Debian, Alpine Linux, Amazon Linux, CentOS, and all macOS versions. The problem is particularly severe on macOS where no fonts are found by default, and on Alpine Linux where many fonts are distributed in OTF format which PdfSharpCore does not support.

Framework Versions: .NET Core 3.1, .NET 5, .NET 6, .NET 7, .NET 8, and .NET 9. The Core build in PdfSharp 6.x targets modern .NET but requires manual font resolver configuration. Earlier versions (1.5x and below) have stronger GDI+ dependencies.

Use Cases: Any PDF generation requiring text rendering (which is virtually all PDF generation), containerized deployments, CI/CD pipelines running on Linux, macOS desktop applications, cloud deployments on AWS Lambda or Azure Functions.

Deployment Scenarios: Docker containers (especially multi-stage builds without font packages), Kubernetes pods, serverless functions, and any headless server environment.

Evidence from the Developer Community

The PdfSharp cross-platform compatibility issue has been reported consistently across GitHub Issues, Stack Overflow, and the official PdfSharp forums.

Timeline

Date Event Source
2017-01-01 PdfSharpNetStandard issues in Linux Docker containers reported GitHub Issues
2019-11-01 "No Fonts installed on this device" errors documented PdfSharpCore Issues
2020-03-01 Font resolver requirements for WSL/Linux/Mac clarified PdfSharp Documentation
2022-06-01 System.Drawing.Common deprecated for non-Windows by Microsoft .NET 6 Release
2023-01-01 PdfSharp 6.0 preview introduces Core build without GDI+ NuGet
2024-03-01 Font resolving issues continue in Alpine/Docker deployments GitHub Issues
2024-11-01 PdfSharp 6.2.x documents macOS has no default font resolution Official Docs
2025-01-01 Issues persist with font resolution in containerized environments Community Reports

Community Reports

"Won't work inside Linux docker container. System.TypeInitializationException: The type initializer for 'Gdip' threw an exception. This happens because System.Drawing.dll uses native Windows API for its operations."
— Developer, PdfSharpNetStandard GitHub Issues

"Everything was running fine on version 1.2.6, but since updating to 1.2.8 the default font resolver can no longer find fonts when deployed to a Linux container. No Fonts installed on this device!!"
— Developer, PdfSharpCore GitHub Issues, November 2019

"No fonts will be found under Linux or MacOS when using certain properties, so you should not use these properties for portable Core applications."
— PdfSharp Official Documentation, 2024

"Due to filtering clauses in the LinuxSystemFontResolver.cs, OTF fonts are not allowed to be used with PdfSharpCore - only TTF fonts are supported. This is problematic when using Docker environments with Alpine images that have many open source fonts in OTF format."
— Developer, PdfSharpCore GitHub Issues

The official documentation explicitly states: "When distributing applications that use the Core build, make sure to include a font resolver that handles all font requests your application depends on, so it can run on any computer that supports the Core build, including macOS and others."

Root Cause Analysis

The cross-platform issues stem from three distinct architectural limitations:

1. GDI+ Dependency (Legacy Builds)

PdfSharp versions prior to 6.x and the -GDI and -WPF package variants depend on System.Drawing.Common for graphics operations. Microsoft explicitly deprecated System.Drawing.Common for non-Windows platforms starting with .NET 6, recommending against its use. The documentation states: "System.Drawing requires additional libraries to be installed to use outside of Windows (libgdiplus on Linux for example) and is not officially supported in headless environments."

On Linux, System.Drawing.Common requires libgdiplus, which is unmaintained and contains memory leaks. On macOS, System.Drawing.Common is not supported at all in recent .NET versions.

2. No Cross-Platform Font Resolution Strategy

The fundamental problem with PdfSharp's Core build is architectural: "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."

Windows has the Windows Font Manager with a standardized API to enumerate and load fonts. Linux distributions store fonts in different locations (sometimes /usr/share/fonts/truetype, sometimes elsewhere) with varying formats. macOS has Core Text framework with completely different font management. PdfSharp's Core build punts on this problem entirely, requiring developers to implement custom IFontResolver implementations.

3. TTF-Only Support in PdfSharpCore

The community fork PdfSharpCore uses SixLabors.Fonts for font handling, which improved cross-platform compatibility. However, its implementation only supports TTF fonts, not OTF fonts. Many Linux distributions and font packages distribute fonts in OTF format, creating compatibility gaps.

Attempted Workarounds

The community has developed several approaches to work around these limitations.

Workaround 1: Use the Correct Package Variant

Approach: Use the base PDFsharp package (not PDFsharp-GDI or PDFsharp-WPF) for cross-platform deployments.

<!-- Cross-platform compatible -->
<PackageReference Include="PDFsharp" Version="6.2.3" />

<!-- Windows-only - will fail on Linux/macOS -->
<!-- <PackageReference Include="PDFsharp-GDI" Version="6.2.3" /> -->
Enter fullscreen mode Exit fullscreen mode

Limitations:

  • Still requires implementing a custom font resolver
  • Does not solve the font resolution problem, only removes the GDI+ dependency
  • Image handling capabilities differ from the GDI+ version

Workaround 2: Implement a Custom Font Resolver

Approach: Create a class implementing IFontResolver to handle font requests on all platforms.

using PdfSharp.Fonts;

public class CustomFontResolver : IFontResolver
{
    public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
    {
        // Map font family names to actual font files
        string fontName = familyName.ToLower() switch
        {
            "arial" => isBold ? "arialbd.ttf" : "arial.ttf",
            "times new roman" => isBold ? "timesbd.ttf" : "times.ttf",
            _ => "arial.ttf" // Fallback
        };

        return new FontResolverInfo(fontName);
    }

    public byte[] GetFont(string faceName)
    {
        // Load font bytes from embedded resources or file system
        string fontPath = Path.Combine(AppContext.BaseDirectory, "Fonts", faceName);
        if (File.Exists(fontPath))
            return File.ReadAllBytes(fontPath);

        // Try embedded resource
        var assembly = Assembly.GetExecutingAssembly();
        using var stream = assembly.GetManifestResourceStream($"MyApp.Fonts.{faceName}");
        if (stream != null)
        {
            using var ms = new MemoryStream();
            stream.CopyTo(ms);
            return ms.ToArray();
        }

        throw new FileNotFoundException($"Font not found: {faceName}");
    }
}

// Register the font resolver before any PDF operations
GlobalFontSettings.FontResolver = new CustomFontResolver();
Enter fullscreen mode Exit fullscreen mode

Limitations:

  • Requires bundling font files with the application or embedding as resources
  • Must handle all font variants (regular, bold, italic, bold-italic) manually
  • Font licensing requires including fonts legally
  • Significant development effort for comprehensive font coverage
  • Must be implemented before any XFont usage in the application

Workaround 3: Install Fonts in Docker Container

Approach: Install font packages in the Docker container at build time.

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime

# Install font packages
RUN apt-get update && apt-get install -y \
    fonts-liberation \
    fonts-dejavu-core \
    fontconfig \
    && rm -rf /var/lib/apt/lists/* \
    && fc-cache -fv
Enter fullscreen mode Exit fullscreen mode

Limitations:

  • Increases container image size
  • Still requires custom font resolver in PdfSharp 6.x
  • Font paths vary between distributions
  • Alpine Linux uses different package manager and font locations
  • Does not help with macOS deployments

Workaround 4: Use PdfSharpCore Fork

Approach: Use the community-maintained PdfSharpCore package which replaced GDI+ with SixLabors.ImageSharp.

<PackageReference Include="PdfSharpCore" Version="1.3.67" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
Enter fullscreen mode Exit fullscreen mode
// Required registration for encoding support
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Enter fullscreen mode Exit fullscreen mode

Limitations:

  • Only supports TTF fonts, not OTF fonts
  • Still has font resolution issues in containerized environments
  • Not officially maintained by empira (PdfSharp maintainers)
  • Feature gaps compared to official PdfSharp
  • Versioning does not align with official PdfSharp releases

A Different Approach: IronPDF

For teams where implementing and maintaining custom font resolvers is not acceptable, switching to a library with native cross-platform support eliminates these issues entirely. IronPDF uses an embedded Chromium rendering engine that handles fonts, images, and rendering natively on Windows, Linux, and macOS without requiring custom resolver implementations.

Why IronPDF Avoids This Issue

IronPDF's architecture differs fundamentally from PdfSharp in how it handles fonts and rendering. Rather than depending on System.Drawing or platform-specific font APIs, IronPDF embeds a Chromium browser engine that:

  • Uses Chromium's cross-platform font rendering subsystem
  • Handles font discovery and loading natively on each platform
  • Requires no custom font resolver implementation
  • Works identically in Docker containers, serverless environments, and desktop applications
  • Supports all font formats that Chromium supports (TTF, OTF, WOFF, WOFF2)

The Chromium engine manages its own font fallback chains and rendering, eliminating the need for developers to understand platform-specific font management.

Code Example

The following example demonstrates cross-platform PDF generation that works identically on Windows, Linux, and macOS without custom font resolvers:

using IronPdf;
using System;

public class CrossPlatformPdfGenerator
{
    public void GeneratePdfOnAnyPlatform()
    {
        // IronPDF automatically configures platform-specific binaries
        // No font resolver implementation required
        Installation.LinuxAndDockerDependenciesAutoConfig = true;

        // Create renderer - works identically on Windows, Linux, and macOS
        var renderer = new ChromePdfRenderer();

        // Configure rendering options
        renderer.RenderingOptions.MarginTop = 25;
        renderer.RenderingOptions.MarginBottom = 25;
        renderer.RenderingOptions.MarginLeft = 20;
        renderer.RenderingOptions.MarginRight = 20;

        // Generate PDF with various fonts - Chromium handles font resolution
        string htmlContent = @"
            <html>
            <head>
                <style>
                    body { font-family: Arial, Helvetica, sans-serif; }
                    h1 { font-family: 'Times New Roman', Times, serif; color: #2c3e50; }
                    .mono { font-family: 'Courier New', Courier, monospace; }
                    .content { padding: 20px; line-height: 1.6; }
                </style>
            </head>
            <body>
                <div class='content'>
                    <h1>Cross-Platform Document</h1>
                    <p>This text renders in Arial on all platforms.</p>
                    <p class='mono'>Monospace text for code examples.</p>
                    <p><strong>Bold text</strong> and <em>italic text</em> work automatically.</p>
                </div>
            </body>
            </html>";

        using (var pdf = renderer.RenderHtmlAsPdf(htmlContent))
        {
            pdf.SaveAs("cross-platform-document.pdf");
            Console.WriteLine($"PDF generated on {Environment.OSVersion.Platform}");
        }
    }

    public void GeneratePdfInDockerContainer()
    {
        // This same code works in Docker without font package installation
        // or custom font resolver implementation

        var renderer = new ChromePdfRenderer();

        // Enable CSS print media queries for better PDF output
        renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;

        // Render a complete webpage including all fonts and images
        using (var pdf = renderer.RenderUrlAsPdf("https://example.com"))
        {
            // Convert to images for thumbnail generation
            var images = pdf.ToPngImages("page_{0}.png");
            Console.WriteLine($"Generated {images.Length} page images");

            pdf.SaveAs("webpage-capture.pdf");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Key points about this code:

  • No IFontResolver implementation required
  • No font file bundling or embedding necessary
  • LinuxAndDockerDependenciesAutoConfig handles platform setup automatically
  • Chromium resolves and renders fonts natively on each platform
  • Font fallback chains (Arial -> Helvetica -> sans-serif) work as expected
  • Image operations work without SixLabors.ImageSharp or System.Drawing dependencies

Docker Deployment

Unlike PdfSharp, IronPDF Docker deployments do not require font package installation:

FROM mcr.microsoft.com/dotnet/aspnet:8.0

# No font packages required - IronPDF uses embedded Chromium

WORKDIR /app
COPY --from=build /app/publish .

ENTRYPOINT ["dotnet", "MyApp.dll"]
Enter fullscreen mode Exit fullscreen mode

API Reference

For details on cross-platform deployment:

Migration Considerations

Licensing

IronPDF is commercial software with per-developer licensing. A free trial is available for evaluation. Teams should evaluate IronPDF's licensing model against their deployment requirements before committing to migration.

API Differences

The APIs between PdfSharp and IronPDF differ significantly in approach:

  • PdfSharp uses low-level PDF primitives (XGraphics, XFont, XBrush); IronPDF primarily uses HTML/CSS rendering
  • PdfSharp requires manual layout and positioning; IronPDF leverages Chromium's layout engine
  • PdfSharp document manipulation uses PdfDocument; IronPDF uses PdfDocument but with different APIs
  • For programmatic drawing, PdfSharp may be more suitable; for document generation from HTML, IronPDF is more direct

Migration effort depends heavily on whether your codebase generates PDFs programmatically or from HTML templates.

What You Gain

  • Consistent behavior on Windows, Linux, and macOS without custom font resolver
  • Docker containers that work without font package installation
  • No platform-specific code paths for font handling
  • Chromium's font rendering quality and fallback behavior
  • Support for all web font formats (TTF, OTF, WOFF, WOFF2)

What to Consider

  • Commercial licensing cost vs PdfSharp's MIT license
  • Different rendering approach (HTML-centric vs programmatic drawing)
  • Larger deployment footprint due to embedded Chromium
  • Learning curve for teams experienced with PdfSharp's drawing API

Conclusion

PdfSharp's cross-platform limitations stem from architectural decisions around font resolution and graphics dependencies. While the Core build removed GDI+ dependencies, it requires developers to implement custom font resolvers for Linux and macOS deployments. For teams requiring reliable cross-platform PDF generation without platform-specific font handling code, using a library with native cross-platform support eliminates the root cause rather than working around it.


Jacob Mellor leads technical development at Iron Software and has 25+ years of experience building developer tools.


References

  1. PdfSharp Font Resolving Documentation{:rel="nofollow"} - Official documentation on font resolution requirements
  2. PdfSharpCore GitHub: No Fonts Installed Issue #125{:rel="nofollow"} - Font resolution failures in Linux containers
  3. PdfSharpCore GitHub: Linux Container Font Issue #406{:rel="nofollow"} - Container deployment problems
  4. PdfSharp Forum: System.Drawing.Common Not Supported{:rel="nofollow"} - GDI+ exception discussions
  5. PdfSharpNetStandard: Linux Docker Issue #6{:rel="nofollow"} - System.Drawing failures in containers
  6. PdfSharp Choose Version Documentation{:rel="nofollow"} - Package selection guidance
  7. PdfSharp .NET Framework Support{:rel="nofollow"} - Platform compatibility documentation
  8. PdfSharpCore GitHub: TTF Only Font Support #327{:rel="nofollow"} - OTF font limitation
  9. PdfSharp GitHub: Font Resolution Issue #20{:rel="nofollow"} - Segoe UI font not found regression
  10. PdfSharp Forum: Fonts Not Resolved on Docker and Alpine{:rel="nofollow"} - Alpine Linux font issues

For IronPDF documentation and tutorials, visit ironpdf.com.

Top comments (0)