Files
mmd-pdf/third_party/PdfSharpCore/Utils/FontResolver.cs

248 lines
9.2 KiB
C#

using System.Linq;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
using PdfSharpCore.Internal;
using PdfSharpCore.Drawing;
using PdfSharpCore.Fonts;
using SixLabors.Fonts;
namespace PdfSharpCore.Utils
{
public class FontResolver
: IFontResolver
{
public string DefaultFontName => "Arial";
private static readonly Dictionary<string, FontFamilyModel> InstalledFonts = new Dictionary<string, FontFamilyModel>();
private static readonly string[] SSupportedFonts;
public FontResolver()
{
}
static FontResolver()
{
string fontDir;
bool isOSX = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX);
if (isOSX)
{
fontDir = "/Library/Fonts/";
SSupportedFonts = System.IO.Directory.GetFiles(fontDir, "*.ttf", System.IO.SearchOption.AllDirectories);
SetupFontsFiles(SSupportedFonts);
return;
}
bool isLinux = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux);
if (isLinux)
{
SSupportedFonts = LinuxSystemFontResolver.Resolve();
SetupFontsFiles(SSupportedFonts);
return;
}
bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows);
if (isWindows)
{
fontDir = System.Environment.ExpandEnvironmentVariables(@"%SystemRoot%\Fonts");
var fontPaths = new List<string>();
var systemFontPaths = System.IO.Directory.GetFiles(fontDir, "*.ttf", System.IO.SearchOption.AllDirectories);
fontPaths.AddRange(systemFontPaths);
var appdataFontDir = System.Environment.ExpandEnvironmentVariables(@"%LOCALAPPDATA%\Microsoft\Windows\Fonts");
if(System.IO.Directory.Exists(appdataFontDir))
{
var appdataFontPaths = System.IO.Directory.GetFiles(appdataFontDir, "*.ttf", System.IO.SearchOption.AllDirectories);
fontPaths.AddRange(appdataFontPaths);
}
SSupportedFonts = fontPaths.ToArray();
SetupFontsFiles(SSupportedFonts);
return;
}
throw new System.NotImplementedException("FontResolver not implemented for this platform (PdfSharpCore.Utils.FontResolver.cs).");
}
private readonly struct FontFileInfo
{
private FontFileInfo(string path, FontDescription fontDescription)
{
this.Path = path;
this.FontDescription = fontDescription;
}
public string Path { get; }
public FontDescription FontDescription { get; }
public string FamilyName => this.FontDescription.FontFamilyInvariantCulture;
public XFontStyle GuessFontStyle()
{
switch (this.FontDescription.Style)
{
case FontStyle.Bold:
return XFontStyle.Bold;
case FontStyle.Italic:
return XFontStyle.Italic;
case FontStyle.BoldItalic:
return XFontStyle.BoldItalic;
default:
return XFontStyle.Regular;
}
}
public static FontFileInfo Load(string path)
{
FontDescription fontDescription = FontDescription.LoadDescription(path);
return new FontFileInfo(path, fontDescription);
}
}
public static void SetupFontsFiles(string[] sSupportedFonts)
{
List<FontFileInfo> tempFontInfoList = new List<FontFileInfo>();
foreach (string fontPathFile in sSupportedFonts)
{
try
{
FontFileInfo fontInfo = FontFileInfo.Load(fontPathFile);
Debug.WriteLine(fontPathFile);
tempFontInfoList.Add(fontInfo);
}
// The e variable only exists under DEBUG: naming it unconditionally leaves Release
// builds with CS0168 (declared but never used), which is what the split clause avoids.
#if DEBUG
catch (System.Exception e)
{
System.Console.Error.WriteLine(e);
}
#else
catch (System.Exception)
{
}
#endif
}
// Deserialize all font families
foreach (IGrouping<string, FontFileInfo> familyGroup in tempFontInfoList.GroupBy(info => info.FamilyName))
try
{
string familyName = familyGroup.Key;
FontFamilyModel family = DeserializeFontFamily(familyName, familyGroup);
InstalledFonts.Add(familyName.ToLower(), family);
}
// Split clause for the same CS0168 reason as the load loop above.
#if DEBUG
catch (System.Exception e)
{
System.Console.Error.WriteLine(e);
}
#else
catch (System.Exception)
{
}
#endif
}
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
private static FontFamilyModel DeserializeFontFamily(string fontFamilyName, IEnumerable<FontFileInfo> fontList)
{
FontFamilyModel font = new FontFamilyModel { Name = fontFamilyName };
// there is only one font
if (fontList.Count() == 1)
font.FontFiles.Add(XFontStyle.Regular, fontList.First().Path);
else
{
foreach (FontFileInfo info in fontList)
{
XFontStyle style = info.GuessFontStyle();
if (!font.FontFiles.ContainsKey(style))
font.FontFiles.Add(style, info.Path);
}
}
return font;
}
public virtual byte[] GetFont(string faceFileName)
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
string ttfPathFile = "";
try
{
ttfPathFile = SSupportedFonts.ToList().First(x => x.ToLower().Contains(
System.IO.Path.GetFileName(faceFileName).ToLower())
);
using (System.IO.Stream ttf = System.IO.File.OpenRead(ttfPathFile))
{
ttf.CopyTo(ms);
ms.Position = 0;
return ms.ToArray();
}
}
catch (System.Exception e)
{
System.Console.WriteLine(e);
throw new System.Exception("No Font File Found - " + faceFileName + " - " + ttfPathFile);
}
}
}
public bool NullIfFontNotFound { get; set; } = false;
public virtual FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
{
if (InstalledFonts.Count == 0)
throw new System.IO.FileNotFoundException("No Fonts installed on this device!");
if (InstalledFonts.TryGetValue(familyName.ToLower(), out FontFamilyModel family))
{
if (isBold && isItalic)
{
if (family.FontFiles.TryGetValue(XFontStyle.BoldItalic, out string boldItalicFile))
return new FontResolverInfo(System.IO.Path.GetFileName(boldItalicFile));
}
else if (isBold)
{
if (family.FontFiles.TryGetValue(XFontStyle.Bold, out string boldFile))
return new FontResolverInfo(System.IO.Path.GetFileName(boldFile));
}
else if (isItalic)
{
if (family.FontFiles.TryGetValue(XFontStyle.Italic, out string italicFile))
return new FontResolverInfo(System.IO.Path.GetFileName(italicFile));
}
if (family.FontFiles.TryGetValue(XFontStyle.Regular, out string regularFile))
return new FontResolverInfo(System.IO.Path.GetFileName(regularFile));
return new FontResolverInfo(System.IO.Path.GetFileName(family.FontFiles.First().Value));
}
if (NullIfFontNotFound)
return null;
string ttfFile = InstalledFonts.First().Value.FontFiles.First().Value;
return new FontResolverInfo(System.IO.Path.GetFileName(ttfFile));
}
}
}