Skip to content
Open
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
1 change: 1 addition & 0 deletions src/EPPlus.Compression/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
using System.Security;

[assembly: InternalsVisibleTo("EPPlus, PublicKey=00240000048000009400000006020000002400005253413100040000010001002981343969ed86fe604c56a84c61e33109424ef07bb458ff12e9533c11ea23ac8ef7e014b2a2de4ceb5f7528f963c755fe9b32f09cc35d21de94319d2a952a6e663cd46d6d98465998c77b52093d4f17cdc20ec054751244696f08afa6f4417d85267b147b73b6a3f5e9015b9dfd3dcc3328ce63df53a7c08a5544c1526ea5a5")]
[assembly: InternalsVisibleTo("EPPlus.Fonts.OpenType, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f506ded61f2e8f2c2a377e72c15f7de76a83bd0e1dc4425e95db0e9fd6cb4703d2ab8d9e666fe1f7738fca0b5695025d7de7292c0cc0b7ea3a5948f42681521523b7e94bb6827dfc7b102dd9b8b60216c86b1b462a37f155d14ab8a97987652e4691ceb1f2455df986c0bdf73dd3ce0de3327a057fbf6560db070c1444f313be")]
[assembly: AllowPartiallyTrustedCallers]
11 changes: 6 additions & 5 deletions src/EPPlus.DrawingRenderer.Tests/TestFontMeasurer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,11 @@ public void SpaceCase()
var layout = SystemFolderEngine.GetTextLayoutEngineForFont(mf);
var output = layout.WrapText(text, 11f, 39.4);

var shaper = OpenTypeFonts.GetShaperForFont(mf);
var engine = new OpenTypeFontEngine(cfg =>
{
cfg.SearchSystemDirectories = true;
});
var shaper = engine.GetShaperForFont(mf);
var shapes2 = shaper.ShapeLight("nec rhoncus");
var width= shapes2.GetWidthInPoints(11f);
//var shaper = OpenTypeFonts.GetShaperForFont(mf);
Expand Down Expand Up @@ -198,10 +202,7 @@ public void LoremIpsumTesting()

var engine = new OpenTypeFontEngine(x => x.SearchSystemDirectories = true);
var layout = engine.GetTextLayoutEngineForFont(mf);

//var wrappedStrings = layout.WrapRichText(new List<string>() { text }, new List<MeasurementFont>() { mf }, 39.4f);

var shaper = OpenTypeFonts.GetShaperForFont(mf);
var shaper = engine.GetShaperForFont(mf);

var wrappedStrings = layout.WrapText(text, 11f, 39.4);

Expand Down
4 changes: 4 additions & 0 deletions src/EPPlus.Export.Pdf.Tests/FontTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,13 @@ public void AddFontData_Embedded_FontResourcePointsAtType0Dict()
{
var settings = CreateSettings(engine, true);
var dictionaries = CreateDictionariesWithSingleFont(settings, engine);
var docSettings = PdfDocumentSettings.From(settings);

var excelPdf = new ExcelPdf();
excelPdf.SetPageSettingsForTest(settings);
excelPdf.SetDocumentSettingsForTest(PdfDocumentSettings.From(settings));
excelPdf.SetDictionariesForTest(dictionaries);
excelPdf.SetDocumentSettingsForTest(docSettings);
excelPdf.AddFontData();

var fontResource = dictionaries.GetFont(settings, TestFontName, FontSubFamily.Regular);
Expand Down Expand Up @@ -150,11 +152,13 @@ public void AddFontData_Embedded_DoesNotEmitSimpleFontObject()
{
var settings = CreateSettings(engine, true);
var dictionaries = CreateDictionariesWithSingleFont(settings, engine);
var docSettings = PdfDocumentSettings.From(settings);

var excelPdf = new ExcelPdf();
excelPdf.SetPageSettingsForTest(settings);
excelPdf.SetDocumentSettingsForTest(PdfDocumentSettings.From(settings));
excelPdf.SetDictionariesForTest(dictionaries);
excelPdf.SetDocumentSettingsForTest(docSettings);
excelPdf.AddFontData();

foreach (var obj in excelPdf._document)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ public static void ClassInitialize(TestContext testContext)
_testOutputAvailable = false;
}

OpenTypeFonts.ClearFontCache();
_initialized = true;
}
}
Expand Down
24 changes: 12 additions & 12 deletions src/EPPlus.Export.Pdf.Tests/Helpers/FontTestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ public static void AssertFontValid(
/// <param name="fontFolders">Folders to search for fonts</param>
/// <returns>Serialized subset bytes</returns>
public static byte[] SubsetAndSerialize(
OpenTypeFontEngine engine,
string fontName,
string text,
List<string> fontFolders)
string text)
{
var font = OpenTypeFonts.LoadFont(fontName, FontSubFamily.Regular);
var font = engine.LoadFont(fontName, FontSubFamily.Regular);
var subset = font.CreateSubset(text);
return subset.Serialize();
}
Expand All @@ -96,11 +96,11 @@ public static byte[] SubsetAndSerialize(
/// Creates a subset and serializes it to bytes (char array overload)
/// </summary>
public static byte[] SubsetAndSerialize(
OpenTypeFontEngine engine,
string fontName,
char[] chars,
List<string> fontFolders)
char[] chars)
{
var font = OpenTypeFonts.LoadFont(fontName, FontSubFamily.Regular);
var font = engine.LoadFont(fontName, FontSubFamily.Regular);
var subset = font.CreateSubset(chars);
return subset.Serialize();
}
Expand All @@ -113,11 +113,11 @@ public static byte[] SubsetAndSerialize(
/// <param name="fontFolders">Folders to search for fonts</param>
/// <returns>Parsed subset font (validated)</returns>
public static OpenTypeFont RoundtripSubset(
OpenTypeFontEngine engine,
string fontName,
string text,
List<string> fontFolders)
string text)
{
var font = OpenTypeFonts.LoadFont(fontName, FontSubFamily.Regular);
var font = engine.LoadFont(fontName, FontSubFamily.Regular);
var subset = font.CreateSubset(text);
var bytes = subset.Serialize();

Expand All @@ -132,11 +132,11 @@ public static OpenTypeFont RoundtripSubset(
/// Performs a full roundtrip with char array
/// </summary>
public static OpenTypeFont RoundtripSubset(
OpenTypeFontEngine engine,
string fontName,
char[] chars,
List<string> fontFolders)
char[] chars)
{
var font = OpenTypeFonts.LoadFont(fontName, FontSubFamily.Regular);
var font = engine.LoadFont(fontName, FontSubFamily.Regular);
var subset = font.CreateSubset(chars);
var bytes = subset.Serialize();

Expand Down
57 changes: 0 additions & 57 deletions src/EPPlus.Fonts.OpenType.Benchmarks/FontCacheBenchmarks.cs

This file was deleted.

This file was deleted.

81 changes: 51 additions & 30 deletions src/EPPlus.Fonts.OpenType.Benchmarks/FontLoadingBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,4 @@
/*************************************************************************************************
Required Notice: Copyright (C) EPPlus Software AB.
This software is licensed under PolyForm Noncommercial License 1.0.0
and may only be used for noncommercial purposes
https://polyformproject.org/licenses/noncommercial/1.0.0/

A commercial license to use this software can be purchased at https://epplussoftware.com
*************************************************************************************************
Date Author Change
*************************************************************************************************
01/20/2025 EPPlus Software AB Initial implementation
*************************************************************************************************/
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes;
using EPPlus.Fonts.OpenType;
using OfficeOpenXml.Interfaces.Fonts;
using System.Collections.Generic;
Expand All @@ -24,6 +12,12 @@ public class FontLoadingBenchmarks
{
private List<string> _fontFolders;

// Kept across iterations: its font cache is warm after the first load.
private OpenTypeFontEngine _warmEngine;

// Rebuilt before every cold iteration by IterationSetup.
private OpenTypeFontEngine _coldEngine;

[GlobalSetup]
public void Setup()
{
Expand All @@ -35,41 +29,68 @@ public void Setup()
}

_fontFolders = new List<string> { fontsPath };

_warmEngine = CreateEngine();
_warmEngine.LoadFont("Roboto", FontSubFamily.Regular);
}

[Benchmark]
public OpenTypeFont Load_Roboto_Regular_ColdCache()
[GlobalCleanup]
public void Cleanup()
{
OpenTypeFonts.ClearFontCache(); // Clear INNE i benchmark
return OpenTypeFonts.LoadFont("Roboto", FontSubFamily.Regular);
_warmEngine?.Dispose();
_coldEngine?.Dispose();
}

[Benchmark]
public OpenTypeFont Load_Roboto_Regular_WarmCache()
private OpenTypeFontEngine CreateEngine()
{
// Load UTAN att cleara - använder cache från GlobalSetup eller warmup
return OpenTypeFonts.LoadFont("Roboto", FontSubFamily.Regular);
return new OpenTypeFontEngine(cfg =>
{
foreach (var folder in _fontFolders)
{
cfg.FontDirectories.Add(folder);
}
// The benchmark measures loading the test fonts, not whatever happens to be
// installed on the machine running it.
cfg.SearchSystemDirectories = false;
});
}

[IterationSetup(Target = nameof(Load_ColdCache))]
public void ColdSetup()
{
_coldEngine?.Dispose();
_coldEngine = CreateEngine();
}

[Benchmark]
public OpenTypeFont Load_Roboto_Bold_ColdCache()
[Arguments(FontSubFamily.Regular)]
[Arguments(FontSubFamily.Bold)]
[Arguments(FontSubFamily.Italic)]
[Arguments(FontSubFamily.BoldItalic)]
public OpenTypeFont Load_ColdCache(FontSubFamily subFamily)
{
OpenTypeFonts.ClearFontCache();
return OpenTypeFonts.LoadFont("Roboto", FontSubFamily.Bold);
return _coldEngine.LoadFont("Roboto", subFamily);
}

[Benchmark]
public OpenTypeFont Load_Roboto_Italic_ColdCache()
public OpenTypeFont Load_Roboto_Regular_WarmCache()
{
OpenTypeFonts.ClearFontCache();
return OpenTypeFonts.LoadFont("Roboto", FontSubFamily.Italic);
return _warmEngine.LoadFont("Roboto", FontSubFamily.Regular);
}

[Benchmark]
public OpenTypeFont Load_Roboto_BoldItalic_ColdCache()
public OpenTypeFont[] Load_FromCache_AllSubFamilies()
{
OpenTypeFonts.ClearFontCache();
return OpenTypeFonts.LoadFont("Roboto", FontSubFamily.BoldItalic);
// Four distinct cache keys in sequence — the pattern a document with all four
// styles produces. Unlike the single-font warm benchmark, this measures four
// separate lookups rather than one repeated.
return new[]
{
_warmEngine.LoadFont("Roboto", FontSubFamily.Regular),
_warmEngine.LoadFont("Roboto", FontSubFamily.Bold),
_warmEngine.LoadFont("Roboto", FontSubFamily.Italic),
_warmEngine.LoadFont("Roboto", FontSubFamily.BoldItalic)
};
}
}
}
2 changes: 1 addition & 1 deletion src/EPPlus.Fonts.OpenType.Benchmarks/RichTextBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void Setup()
}

Console.WriteLine("\nLoading Roboto Regular...");
var font = OpenTypeFonts.LoadFont(FontFamily, FontSubFamily.Regular);
var font = fontEngine.LoadFont(FontFamily, FontSubFamily.Regular);

Console.WriteLine(string.Format("Loaded: {0} {1} ({2} glyphs)",
font.FullName, font.SubFamily, font.GlyfTable.Glyphs.Count));
Expand Down
7 changes: 6 additions & 1 deletion src/EPPlus.Fonts.OpenType.Benchmarks/SubsettingBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ public void Setup()
}

_fontFolders = new List<string> { fontsPath };
_roboto = OpenTypeFonts.LoadFont("Roboto", FontSubFamily.Regular);
var fontEngine = new OpenTypeFontEngine(cfg =>
{
cfg.FontDirectories.Add(fontsPath);
cfg.SearchSystemDirectories = false;
});
_roboto = fontEngine.LoadFont("Roboto", FontSubFamily.Regular);
}

[Benchmark]
Expand Down
Loading
Loading