// available only in FastReport.Core (non Skia) and Mono (for Linux) #if !SKIA && ((MONO && !WPF) || FRCORE) using FastReport.Fonts; using FastReport.Utils; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.InteropServices; namespace FastReport { public static partial class FontManager { private static readonly Dictionary _fonts = new(); private static void RegisterFontInternal(string filename) { IList ttfs = TrueTypeCollection.CheckFile(Fonts.TrueTypeCollection.CacheOptions.DoNotUpdate, filename); foreach (TrueTypeFont font in ttfs) { string fontName = font.FastName; string family2016 = TrueTypeFont.GetFontKey(font.Family2016, font); if (!_fonts.ContainsKey(fontName)) { _fonts.Add(fontName, new FontFromFile(filename)); } else { Debug.WriteLine($"Font '{fontName}' already present in collection.\n Files:\n {_fonts[fontName]}\n {filename}\n"); } if (!_fonts.ContainsKey(family2016)) { _fonts.Add(family2016, new FontFromFile(filename)); } } } /// /// Checks if the font name is contained in this collection. /// /// The name of the font. /// true if the font is contained in this collection. public static bool HasFont(string fontName) { return _fonts.ContainsKey(fontName); } /// /// Returns the font's stream. /// /// The name of the font. /// Either FileStream or MemoryStream containing font data. public static Stream GetFontStream(string fontName) { if (_fonts.TryGetValue(fontName, out var font)) { return font.GetFontStream(); } return null; } /// /// Adds a font from the specified file to this collection. /// /// A System.String that contains the file name of the font to add. /// true if the font is registered by application. public static bool AddFont(string filename) { bool success = false; if (File.Exists(filename)) { if (!_fonts.Values.OfType().Any(fontFile => fontFile._filepath == filename)) { PrivateFontCollection.AddFontFile(filename); RegisterFontInternal(filename); success = true; } else { Debug.WriteLine($"Font file '{filename}' already present in collection"); } } else { Debug.WriteLine($"Font file '{filename}' not found"); } return success; } /// /// Adds a font contained in system memory to this collection. /// /// The memory address of the font to add. /// The memory length of the font to add. public static void AddFont(IntPtr memory, int length) { PrivateFontCollection.AddMemoryFont(memory, length); string fontName = PrivateFontCollection.Families[PrivateFontCollection.Families.Length - 1].Name; if (!_fonts.ContainsKey(fontName)) _fonts.Add(fontName, new MemoryFont(memory, length)); } private abstract class DictionaryFont { public abstract Stream GetFontStream(); } private sealed class FontFromFile : DictionaryFont { internal readonly string _filepath; public FontFromFile(string filepath) { _filepath = filepath; } public override Stream GetFontStream() { return new FileStream(_filepath, FileMode.Open, FileAccess.Read); } public override string ToString() { return _filepath; } } private sealed class FontFromStream : DictionaryFont { private readonly Stream _stream; public FontFromStream(Stream stream) { _stream = stream; } public override Stream GetFontStream() { var newStream = new MemoryStream(); _stream.CopyTo(newStream); _stream.Position = 0; newStream.Position = 0; return newStream; } } private sealed class MemoryFont : DictionaryFont { private readonly IntPtr Memory; private readonly int Length; public MemoryFont(IntPtr memory, int length) { Memory = memory; Length = length; } public override Stream GetFontStream() { byte[] buffer = new byte[Length]; Marshal.Copy(Memory, buffer, 0, Length); return new MemoryStream(buffer); } } } } #endif