# Fonts

RadPdfProcessing automatically discovers installed system fonts in cross-platform **.NET Standard** and **.NET (Target OS: *None*)** applications. The `FixedExtensibilityManager` class also lets you provide font data explicitly when your application needs fonts that are not installed on the host system.

## Setting and Exporting Fonts

RadPdfProcessing loads font data when it creates text and exports a PDF. On cross-platform targets, the first access to `FixedExtensibilityManager.FontsProvider` automatically activates the system-font provider. You do not need to register a provider for fonts that are installed in a supported system font directory.

The system-font provider searches the following locations. The provider scans directories recursively and uses supported `.ttf`, `.otf`, and `.ttc` files that it can access and parse.

| Platform | Default font locations                                                                                                                                                  |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Windows  | The Windows `Fonts` directory and the current user's `Microsoft\Windows\Fonts` directory.                                                                               |
| Linux    | `/usr/share/fonts`, `/usr/local/share/fonts`, `/var/lib/flatpak/exports/share/fonts`, the user's `~/.fonts` directory, and the user's `~/.local/share/fonts` directory. |
| macOS    | `/System/Library/Fonts`, `/Library/Fonts`, and the current user's `~/Library/Fonts` directory.                                                                          |
| iOS      | `/System/Library/Fonts` and `/Library/Fonts`.                                                                                                                           |
| Android  | `/system/fonts`, `/system/product/fonts`, and `/product/fonts`.                                                                                                         |

The provider builds its font index lazily. If a directory does not exist, a font file is inaccessible, a file is larger than 50 MB, or a font file is corrupted or unsupported, the provider skips that item. The provider returns no data for a font family that is not found, so the resulting document can use font substitution according to the PDF and application settings.

When you assign a custom provider to `FixedExtensibilityManager.FontsProvider`, the custom provider takes precedence. Use a custom provider when you need to:

* Bundle fonts with your application instead of relying on fonts installed on the host system.
* Use fonts stored in an application-specific location or another data source.
* Control font resolution for repeatable output across machines, containers, or mobile devices.

You can find a detailed `FixedExtensibilityManager` and `FontsProvider` implementation in the [How to implement a FontsProvider](https://www.telerik.com/document-processing-libraries/documentation/knowledge-base/pdfprocessing-implement-fontsprovider) article.

> important When converting a document (for example, DOCX or HTML) to PDF format, the system-font provider can resolve a font only when the matching font is installed in a directory that the provider searches. Fonts embedded in the source document, fonts stored in another application location, and custom fonts that are not installed require a custom provider that returns the font data. If the requested font cannot be resolved, the PDF model can substitute another font, which may change the document's appearance or text layout.

## Implementing a FontsProviderBase

```C#
public class FontsProvider : Telerik.Documents.Extensibility.FontsProviderBase
{
    public override byte[] GetFontData(Telerik.Documents.Core.Fonts.FontProperties fontProperties)
    {
        string fontFileName = fontProperties.FontFamilyName + ".ttf";
        string fontFolder = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);

        //The fonts can differ depending on the file
        if (fontProperties.FontFamilyName == "Arial")
        {
            if (fontProperties.FontStyle == FontStyles.Italic && fontProperties.FontWeight == FontWeights.Bold)
            {
                fontFileName = $"arialbi.ttf";
            }
            else if (fontProperties.FontStyle == FontStyles.Italic)
            {
                fontFileName = $"ariali.ttf";
            }
            else if (fontProperties.FontWeight == FontWeights.Normal)
            {
                fontFileName = "arial.ttf";
            }
            else if (fontProperties.FontWeight == FontWeights.Bold)
            {
                fontFileName = $"arialbd.ttf";
            }
        }

        //...add more fonts if needed...

        DirectoryInfo directory = new DirectoryInfo(fontFolder);
        FileInfo[] fontFiles = directory.GetFiles();

        var fontFile = fontFiles.FirstOrDefault(f => f.Name.Equals(fontFileName, StringComparison.InvariantCultureIgnoreCase));
        if (fontFile != null)
        {
            var targetPath = fontFile.FullName;
            using (FileStream fileStream = File.OpenRead(targetPath))
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    fileStream.CopyTo(memoryStream);
                    return memoryStream.ToArray();
                }
            }
        }

        return null;
    }
}

public abstract class StreamFontsProviderBase : Telerik.Documents.Extensibility.FontsProviderBase
{
    public virtual Stream GetFontStream(Telerik.Documents.Core.Fonts.FontProperties fontProperties)
    {
        return null;
    }
}

public class StreamFontsProvider : StreamFontsProviderBase
{
    public override byte[] GetFontData(Telerik.Documents.Core.Fonts.FontProperties fontProperties)
    {
        return null;
    }

    public override Stream GetFontStream(Telerik.Documents.Core.Fonts.FontProperties fontProperties)
    {
        if (fontProperties.FontFamilyName == "Some Font")
        {
            return File.OpenRead("some-font.ttf");
        }

        return null;
    }
}
```

```C#
Telerik.Documents.Extensibility.FontsProviderBase fontsProvider = new FontsProvider();
Telerik.Documents.Extensibility.FixedExtensibilityManager.FontsProvider = fontsProvider;
```

### Providing Font Streams

To provide fonts stored outside system font directories, override `FontsProviderBase.GetFontStream(FontProperties)`. The method must return a readable, seekable stream.

This approach lets RadPdfProcessing read font data lazily instead of requiring the provider to load the complete font into a `byte[]`.

```C#
public override byte[] GetFontData(Telerik.Documents.Core.Fonts.FontProperties fontProperties)
{
    return null;
}

public override Stream GetFontStream(Telerik.Documents.Core.Fonts.FontProperties fontProperties)
{
    if (fontProperties.FontFamilyName == "Some Font")
    {
        return File.OpenRead("some-font.ttf");
    }

    return null;
}
```

Override `GetFontData(FontProperties)` because it is abstract. Return `null` when the provider serves all fonts through `GetFontStream()`.

RadPdfProcessing owns the stream that `GetFontStream()` returns. Return a new stream for every request. Do not dispose the stream after returning it.

Providers that override only `GetFontData(FontProperties)` remain supported. The base `GetFontStream()` method creates a stream from the returned byte array.

## See Also

* [Standard Fonts](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/concepts/fonts)
* [Cross-Platform Support](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/cross-platform/overview)
* [Images](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/cross-platform/images)
* [Inserting Special Symbols in PDF using RadPdfProcessing](https://www.telerik.com/document-processing-libraries/documentation/knowledge-base/inserting-special-symbols-pdf-radpdfprocessing)
* [How to Eliminate Formatting Issues when Exporting XLSX to PDF Format](https://www.telerik.com/document-processing-libraries/documentation/knowledge-base/exporting-xlsx-to-pdf-formatting-issues)
* [Resolving Missing Content in Exported PDF Files](https://www.telerik.com/document-processing-libraries/documentation/knowledge-base/missing-content-pdf-radwordsprocessing)
* [Validating Fonts when Using Telerik Document Processing](https://www.telerik.com/document-processing-libraries/documentation/knowledge-base/validating-fonts-document-processing)
* [Preserving Original Bold, Italic and Regular Fonts When Exporting PDF Documents Using PdfProcessing in .NET Standard](https://www.telerik.com/document-processing-libraries/documentation/knowledge-base/pdfprocessing-prevent-font-conversion-embedding-fonts)
* [Resolving Font Differences Between Client and Server-Side PDF Generation in Telerik Document Processing](https://www.telerik.com/document-processing-libraries/documentation/knowledge-base/consistent-pdf-font-formatting)
