Skip to content

Commit be7b034

Browse files
adeloboskoBobLd
andauthored
Added possibility to set additional directories to search fonts (#1422)
* fix(WindowsSystemFontLister): fix PSFonts typo * feat(SystemFontFinder): added possibility to set additional directories to search fonts useful for strict enviroments without preinstalled fonts / access realted to BobLd/PdfPig.Rendering.Skia#145 * refactor(set-additional-font-search-dirs): apply code review suggestions * refactor(set-additional-font-search-dirs): better to use HashSet + lock instead of ConcurrentBag after set it as private * reactor(set-additional-font-search-dirs): remove check * inside --------- Co-authored-by: BobLd <38405645+BobLd@users.noreply.github.com>
1 parent 790d497 commit be7b034

8 files changed

Lines changed: 93 additions & 37 deletions

src/UglyToad.PdfPig.Fonts/SystemFonts/AndroidSystemFontLister.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@
66

77
internal sealed class AndroidSystemFontLister : ISystemFontLister
88
{
9-
public IEnumerable<SystemFontRecord> GetAllFonts()
9+
public IEnumerable<SystemFontRecord> GetAllFonts(IEnumerable<string>? additionalDirectories)
1010
{
1111
var directories = new List<string>
1212
{
1313
"/system/fonts",
1414
};
1515

16+
if (additionalDirectories is not null)
17+
{
18+
directories.AddRange(additionalDirectories);
19+
}
20+
1621
foreach (var directory in directories)
1722
{
1823
try

src/UglyToad.PdfPig.Fonts/SystemFonts/BrowserSystemFontLister.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55

66
internal sealed class BrowserSystemFontLister : ISystemFontLister
77
{
8+
89
// Very early version, intended to help developing support for browser
910

10-
public IEnumerable<SystemFontRecord> GetAllFonts()
11+
public IEnumerable<SystemFontRecord> GetAllFonts(IEnumerable<string>? additionalDirectories)
1112
{
1213
yield break;
1314
}

src/UglyToad.PdfPig.Fonts/SystemFonts/IOSSystemFontLister.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
internal sealed class IOSSystemFontLister : ISystemFontLister
77
{
88
// Very early version, intended to help developing support for iOS
9-
10-
public IEnumerable<SystemFontRecord> GetAllFonts()
9+
public IEnumerable<SystemFontRecord> GetAllFonts(IEnumerable<string>? additionalDirectories)
1110
{
1211
yield break;
1312
}

src/UglyToad.PdfPig.Fonts/SystemFonts/ISystemFontLister.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44

55
internal interface ISystemFontLister
66
{
7-
IEnumerable<SystemFontRecord> GetAllFonts();
7+
IEnumerable<SystemFontRecord> GetAllFonts(IEnumerable<string>? additionalDirectories);
88
}
99
}

src/UglyToad.PdfPig.Fonts/SystemFonts/LinuxSystemFontLister.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
internal sealed class LinuxSystemFontLister : ISystemFontLister
88
{
9-
public IEnumerable<SystemFontRecord> GetAllFonts()
9+
public IEnumerable<SystemFontRecord> GetAllFonts(IEnumerable<string>? additionalDirectories)
1010
{
1111
var directories = new List<string>
1212
{
@@ -16,6 +16,11 @@ public IEnumerable<SystemFontRecord> GetAllFonts()
1616
"/usr/X11R6/lib/X11/fonts" // X
1717
};
1818

19+
if (additionalDirectories is not null)
20+
{
21+
directories.AddRange(additionalDirectories);
22+
}
23+
1924
try
2025
{
2126
var folder = Environment.GetEnvironmentVariable("$HOME");

src/UglyToad.PdfPig.Fonts/SystemFonts/MacSystemFontLister.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
internal sealed class MacSystemFontLister : ISystemFontLister
88
{
9-
public IEnumerable<SystemFontRecord> GetAllFonts()
9+
public IEnumerable<SystemFontRecord> GetAllFonts(IEnumerable<string>? additionalDirectories)
1010
{
1111
var directories = new List<string>
1212
{
@@ -15,6 +15,11 @@ public IEnumerable<SystemFontRecord> GetAllFonts()
1515
"/Network/Library/Fonts/" // network
1616
};
1717

18+
if (additionalDirectories is not null)
19+
{
20+
directories.AddRange(additionalDirectories);
21+
}
22+
1823
try
1924
{
2025
var folder = Environment.GetEnvironmentVariable("$HOME");

src/UglyToad.PdfPig.Fonts/SystemFonts/SystemFontFinder.cs

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ public sealed class SystemFontFinder : ISystemFontFinder
2626
/// </summary>
2727
private static readonly Lazy<IReadOnlyDictionary<char, SystemFontRecord[]>> FontsByFirstChar;
2828

29+
/// <summary>
30+
/// Additional directories where to search fonts
31+
/// </summary>
32+
private static readonly HashSet<string> AdditionalFontSearchDirectories = new HashSet<string>();
33+
private static readonly object FontSearchDirectoryLock = new();
34+
2935
/// <summary>
3036
/// The instance of <see cref="SystemFontFinder"/>.
3137
/// </summary>
@@ -95,22 +101,22 @@ static SystemFontFinder()
95101
lister = new LinuxSystemFontLister();
96102
}
97103
#if NET
98-
else if (OperatingSystem.IsAndroid())
99-
{
100-
lister = new AndroidSystemFontLister();
101-
}
102-
else if (OperatingSystem.IsBrowser())
103-
{
104-
lister = new BrowserSystemFontLister();
105-
}
106-
else if (OperatingSystem.IsMacCatalyst())
107-
{
108-
lister = new MacSystemFontLister();
109-
}
110-
else if (OperatingSystem.IsIOS())
111-
{
112-
lister = new IOSSystemFontLister();
113-
}
104+
else if (OperatingSystem.IsAndroid())
105+
{
106+
lister = new AndroidSystemFontLister();
107+
}
108+
else if (OperatingSystem.IsBrowser())
109+
{
110+
lister = new BrowserSystemFontLister();
111+
}
112+
else if (OperatingSystem.IsMacCatalyst())
113+
{
114+
lister = new MacSystemFontLister();
115+
}
116+
else if (OperatingSystem.IsIOS())
117+
{
118+
lister = new IOSSystemFontLister();
119+
}
114120
#endif
115121
else
116122
{
@@ -122,7 +128,13 @@ static SystemFontFinder()
122128
#error Missing ISystemFontLister for target framework
123129
#endif
124130

125-
AvailableFonts = new Lazy<IReadOnlyList<SystemFontRecord>>(() => lister.GetAllFonts().ToArray());
131+
AvailableFonts = new Lazy<IReadOnlyList<SystemFontRecord>>(() =>
132+
{
133+
lock (FontSearchDirectoryLock)
134+
{
135+
return lister.GetAllFonts(AdditionalFontSearchDirectories).ToArray();
136+
}
137+
});
126138

127139
FontsByFirstChar = new Lazy<IReadOnlyDictionary<char, SystemFontRecord[]>>(() =>
128140
{
@@ -358,4 +370,27 @@ private bool TryReadFile(string fileName, bool readNameFirst, string fontName, o
358370

359371
return true;
360372
}
373+
374+
/// <summary>
375+
/// Add a directory to the list of additional directories where to search for fonts.
376+
/// </summary>
377+
/// <param name="directory"></param>
378+
/// <exception cref="InvalidOperationException">
379+
/// Thrown when the available fonts have already been initialized and the font search directory is added too late.
380+
/// </exception>
381+
public static void AddFontSearchDirectory(string directory)
382+
{
383+
lock (FontSearchDirectoryLock)
384+
{
385+
if (AvailableFonts.IsValueCreated)
386+
{
387+
throw new InvalidOperationException("A font search directory cannot be added after the font collection has been initialized.");
388+
}
389+
390+
if (!string.IsNullOrWhiteSpace(directory))
391+
{
392+
AdditionalFontSearchDirectories.Add(directory);
393+
}
394+
}
395+
}
361396
}

src/UglyToad.PdfPig.Fonts/SystemFonts/WindowsSystemFontLister.cs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,36 @@
66

77
internal sealed class WindowsSystemFontLister : ISystemFontLister
88
{
9-
public IEnumerable<SystemFontRecord> GetAllFonts()
9+
public IEnumerable<SystemFontRecord> GetAllFonts(IEnumerable<string>? additionalDirectories)
1010
{
1111
var winDir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
1212

13-
var fonts = Path.Combine(winDir, "Fonts");
13+
var directories = new List<string>
14+
{
15+
Path.Combine(winDir, "Fonts"),
16+
Path.Combine(winDir, "PSFonts")
17+
};
18+
1419

15-
if (Directory.Exists(fonts))
20+
if (additionalDirectories is not null)
1621
{
17-
var files = Directory.GetFiles(fonts);
22+
directories.AddRange(additionalDirectories);
23+
}
1824

19-
foreach (var file in files)
25+
foreach (var directory in directories)
26+
{
27+
foreach (var record in GetForDirectory(directory))
2028
{
21-
if (SystemFontRecord.TryCreate(file, out var record))
22-
{
23-
yield return record;
24-
}
29+
yield return record;
2530
}
2631
}
32+
}
2733

28-
var psFonts = Path.Combine(winDir, "PSFonts");
29-
30-
if (Directory.Exists(psFonts))
34+
private IEnumerable<SystemFontRecord> GetForDirectory(string path)
35+
{
36+
if (Directory.Exists(path))
3137
{
32-
var files = Directory.GetFiles(fonts);
38+
var files = Directory.GetFiles(path);
3339

3440
foreach (var file in files)
3541
{

0 commit comments

Comments
 (0)