1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . IO ;
4+ using System . Linq ;
5+ using System . Runtime . InteropServices ;
6+
7+ namespace FontStashSharp
8+ {
9+ public class SystemFonts
10+ {
11+ private static readonly IReadOnlyCollection < string > StandardFontLocations ;
12+
13+ private readonly IReadOnlyCollection < string > _searchDirectories ;
14+ private readonly IEnumerable < string > _paths ;
15+
16+ static SystemFonts ( )
17+ {
18+ if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
19+ {
20+ StandardFontLocations = new [ ]
21+ {
22+ @"%SYSTEMROOT%\Fonts" ,
23+ @"%APPDATA%\Microsoft\Windows\Fonts" ,
24+ @"%LOCALAPPDATA%\Microsoft\Windows\Fonts" ,
25+ } ;
26+ }
27+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
28+ {
29+ StandardFontLocations = new [ ]
30+ {
31+ "%HOME%/.fonts/" ,
32+ "%HOME%/.local/share/fonts/" ,
33+ "/usr/local/share/fonts/" ,
34+ "/usr/share/fonts/" ,
35+ } ;
36+ }
37+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) )
38+ {
39+ StandardFontLocations = new [ ]
40+ {
41+ // As documented on "Mac OS X: Font locations and their purposes"
42+ // https://web.archive.org/web/20191015122508/https://support.apple.com/en-us/HT201722
43+ "%HOME%/Library/Fonts/" ,
44+ "/Library/Fonts/" ,
45+ "/System/Library/Fonts/" ,
46+ "/Network/Library/Fonts/" ,
47+ } ;
48+ }
49+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "Android" ) ) )
50+ {
51+ StandardFontLocations = new [ ]
52+ {
53+ "/system/fonts/"
54+ } ;
55+ }
56+ else
57+ {
58+ StandardFontLocations = Array . Empty < string > ( ) ;
59+ }
60+ }
61+
62+ public SystemFonts ( )
63+ {
64+ string [ ] expanded = StandardFontLocations . Select ( x => Environment . ExpandEnvironmentVariables ( x ) ) . ToArray ( ) ;
65+ string [ ] existingDirectories = expanded . Where ( x => Directory . Exists ( x ) ) . ToArray ( ) ;
66+
67+ // We do this to provide a consistent experience with case sensitive file systems.
68+ _paths = existingDirectories
69+ . SelectMany ( x => Directory . EnumerateFiles ( x , "*.*" , SearchOption . AllDirectories ) )
70+ . Where ( x => Path . GetExtension ( x ) . Equals ( ".ttf" , StringComparison . OrdinalIgnoreCase )
71+ || Path . GetExtension ( x ) . Equals ( ".ttc" , StringComparison . OrdinalIgnoreCase )
72+ || Path . GetExtension ( x ) . Equals ( ".otf" , StringComparison . OrdinalIgnoreCase ) ) ;
73+
74+ _searchDirectories = existingDirectories ;
75+ }
76+
77+ public byte [ ] GetFontData ( string fileName )
78+ {
79+ if ( string . IsNullOrEmpty ( fileName ) )
80+ {
81+ throw new ArgumentException ( "Font name cannot be null or empty." , nameof ( fileName ) ) ;
82+ }
83+
84+ foreach ( string path in _paths )
85+ {
86+ if ( Path . GetFileName ( path ) . StartsWith ( fileName , StringComparison . OrdinalIgnoreCase ) )
87+ {
88+ try
89+ {
90+ return File . ReadAllBytes ( path ) ;
91+ }
92+ catch
93+ {
94+ return Array . Empty < byte > ( ) ;
95+ }
96+ }
97+ }
98+
99+ return Array . Empty < byte > ( ) ;
100+ }
101+ }
102+ }
0 commit comments