Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions src/EPPlus.Export.Pdf/PdfResources/PdfFontResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal class PdfFontResource : PdfResource
internal int fontWidthObjectNumber = -1;
internal int cidSetObjectNumber = -1;
internal OpenTypeFont fontData;
private OpenTypeFontEngine _fontEngine;
private int firstChar = 32;
private int lastChar = 255;
private CIDSystemInfo cidSystemInfo = null;
Expand All @@ -55,13 +56,14 @@ public PdfFontResource(string fontName, FontSubFamily subFamily, int labelNumber
: base("F", labelNumber)
{
this.fontName = fontName;
fontData = OpenTypeFonts.LoadFont(fontName, subFamily, pageSettings.FontDirectories, pageSettings.SearchSystemDirectories);
fontSubsetManager = new FontSubsetManager(fontData);
_fontEngine = pageSettings.FontEngine;
fontData = _fontEngine.LoadFont(fontName, subFamily);
fontSubsetManager = new FontSubsetManager(pageSettings.FontEngine, fontData);
}

internal static OpenTypeFont GetFontData(PdfPageSettings pageSettings, string fontName, FontSubFamily subFamily)
{
return OpenTypeFonts.LoadFont(fontName,subFamily, pageSettings.FontDirectories, pageSettings.SearchSystemDirectories);
return pageSettings.FontEngine.LoadFont(fontName,subFamily);
}

//Get font data from fontResources. If font does not exsist, add it to fontResources.
Expand All @@ -81,12 +83,6 @@ internal static OpenTypeFont GetFontResourceData(Dictionary<string, PdfFontResou
return fontResources[FontData.FullFontName].fontData;
}

internal void CreateSubset()
{
fontData = fontData.CreateSubset(Subset);
Shaper = new TextShaper(fontData);
}

//Get the Font Descriptor object to write in PDF.
internal PdfFontDescriptor GetFontDescriptorObject(int objectNumber, int version = 0)
{
Expand Down
30 changes: 30 additions & 0 deletions src/EPPlus.Export.Pdf/PdfSettings/PdfPageSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Date Author Change
27/11/2025 EPPlus Software AB EPPlus 9
*************************************************************************************************/
using EPPlus.Export.Pdf.PdfSettings.PdfPageSizes;
using EPPlus.Fonts.OpenType;
using System.Collections.Generic;
using System.Linq;

namespace EPPlus.Export.Pdf.PdfSettings
{
Expand All @@ -20,6 +22,34 @@ namespace EPPlus.Export.Pdf.PdfSettings
/// </summary>
public class PdfPageSettings
{
private OpenTypeFontEngine _fontEngine;
public OpenTypeFontEngine FontEngine
{
get
{
if(_fontEngine == null)
{
_fontEngine = new OpenTypeFontEngine(x =>
{
if(FontDirectories != null && FontDirectories.Any())
{
foreach(var dir in FontDirectories)
{
if (!System.IO.Directory.Exists(dir))
{
throw new System.IO.DirectoryNotFoundException($"Font directory not found: {dir}");
}
x.FontDirectories.Add(dir);
}
x.SearchSystemDirectories = SearchSystemDirectories;

}

});
}
return _fontEngine;
}
}
/// <summary>
/// Add additional folders to search for fonts.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ public class ExtractCharWidthsBenchmark
public void Setup()
{
var fontFolders = new List<string> { /* your font paths */ };
var font = OpenTypeFonts.LoadFont("Calibri");
_shaper = new TextShaper(font);
var fontEngine = new OpenTypeFontEngine(x =>
{
x.SearchSystemDirectories = true;
});
var font = fontEngine.LoadFont("Calibri");
_shaper = new TextShaper(fontEngine, font);
_options = ShapingOptions.Default;

// Short: typical Excel cell
Expand Down
5 changes: 3 additions & 2 deletions src/EPPlus.Fonts.OpenType.Benchmarks/RichTextBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,14 @@ public void Setup()

// Configure the global font system to search the benchmark's local Fonts directory
// exclusively. Must happen before any LoadFont call.
OpenTypeFonts.Configure(cfg =>
var fontEngine = new OpenTypeFontEngine(cfg =>
{
cfg.Reset();
cfg.FontDirectories.Add(fontsPath);
cfg.SearchSystemDirectories = false;
});


Console.WriteLine("\nAvailable Roboto fonts:");
foreach (var file in Directory.GetFiles(fontsPath, "Roboto*.ttf"))
{
Expand All @@ -74,7 +75,7 @@ public void Setup()
Console.WriteLine(string.Format("Loaded: {0} {1} ({2} glyphs)",
font.FullName, font.SubFamily, font.GlyfTable.Glyphs.Count));

var shaper = new TextShaper(font);
var shaper = new TextShaper(fontEngine, font);
_layoutEngine = new TextLayoutEngine(shaper);

Console.WriteLine("\nPre-warming font cache (Regular, Bold, Italic)...");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,14 @@ public List<string> New_Wrap_10Paragraphs_Sequential()
[Benchmark]
public double[] OnlyExtractWidths()
{
var font = OpenTypeFonts.LoadFont(FontFamily, FontSubFamily.Regular);
var shaper = new TextShaper(font);
var fontsPath = Path.Combine(AppContext.BaseDirectory, "Fonts");
var fontEngine = new OpenTypeFontEngine(x =>
{
x.FontDirectories.Add(fontsPath);
x.SearchSystemDirectories = false;
});
var font = fontEngine.LoadFont(FontFamily, FontSubFamily.Regular);
var shaper = new TextShaper(fontEngine, font);
return shaper.ExtractCharWidths(LoremIpsum20Para, FontSize, ShapingOptions.Default);
}

Expand Down
10 changes: 8 additions & 2 deletions src/EPPlus.Fonts.OpenType.Benchmarks/TextShapingBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,27 @@ namespace EPPlus.Fonts.OpenType.Benchmarks
public class TextShapingBenchmarks
{
private OpenTypeFont _roboto;
private OpenTypeFontEngine _engine;
private TextShaper _shaper;

[GlobalSetup] // Runs once before all benchmarks
public void Setup()
{
var fontsPath = Path.Combine(AppContext.BaseDirectory, "Fonts");
_engine = new OpenTypeFontEngine(x =>
{
x.FontDirectories.Add(fontsPath);
x.SearchSystemDirectories = false;
});

if (!Directory.Exists(fontsPath))
{
throw new DirectoryNotFoundException($"Fonts directory not found: {fontsPath}");
}

var fontFolders = new List<string> { fontsPath };
_roboto = OpenTypeFonts.LoadFont("Roboto", FontSubFamily.Regular);
_shaper = new TextShaper(_roboto);
_roboto = _engine.LoadFont("Roboto", FontSubFamily.Regular);
_shaper = new TextShaper(_engine, _roboto);
}

[Benchmark]
Expand Down
Loading
Loading