using FastReport.RichTextParser; using System.Collections.Concurrent; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.InteropServices; using FastReport.Export.TTF; using FastReport.Utils; using System.Diagnostics; using System; using System.Collections.Generic; using FastReport.Barcode.QRCode; namespace FastReport.Fonts { using FontStreamList = ConcurrentQueue; internal class FontStreamPool { const int MAX_STREAMS_PER_FONT = 2; static readonly ConcurrentDictionary pool = new ConcurrentDictionary(); #if SKIA internal static FontStream GetFontStream(Font source_font) { SkiaSharp.SKStreamAsset skStream = source_font.InternalTypeface.OpenStream(); Byte[] mb = new byte[skStream.Length]; skStream.Read(mb, mb.Length); MemoryStream memoryStream = new MemoryStream(mb); return new FontStream(memoryStream, true); } #endif internal static TrueTypeFont GetTTF(string fast_font, Font source_font) { TrueTypeFont result = null; pool.TryAdd(fast_font, new FontStreamList()); bool success = pool[fast_font].TryDequeue(out result); if (!success) { #if !SKIA FontStream font_stream = ExportTTFFont.GetFontStream(source_font); #else FontStream font_stream = GetFontStream(source_font); #endif if (font_stream == null) throw new Exception("Unable get font stream"); TrueTypeFont last_ttf = null; foreach (TrueTypeFont ttf in TrueTypeCollection.CreateFonts(font_stream)) { TrueTypeCollection.ParseFont(ttf, ""); if (ttf.Family == source_font.FontFamily.Name) { result = ttf; break; } var families = ttf.GetNames(NameTableClass.NameID.FamilyName); foreach (string family in families) { if (family == source_font.FontFamily.Name) { result = ttf; break; } last_ttf = ttf; } } if (result == null) { result = last_ttf; #if DEBUG Debug.WriteLine(source_font.FontFamily.Name, "Font family not found. Substituted ", result.Family); #endif } result.Stream.StreamFontFastName = fast_font; } result.Stream.Position = 0; return result; } internal static void ReleaseFontStream(TrueTypeFont fontStream) { if (! pool.TryGetValue(fontStream.Stream.StreamFontFastName, out var collection)) throw new System.ExecutionEngineException("pool of fonts error in ReleaseFontStream"); if (collection.Count < MAX_STREAMS_PER_FONT) { fontStream.Stream.Position = 0; fontStream.Stream.LeaveOpen = true; collection.Enqueue(fontStream); } else fontStream.Dispose(true); } FontStreamPool() { Debug.WriteLine("Problem"); } } }