#if WITHOUT_UNISCRIBE using System; using System.Collections.Generic; using System.Drawing; using FastReport.Fonts; using FastReport.Utils; using System.IO; #if !SKIA using System.Runtime.InteropServices; using FastReport.RichTextParser; using FastReport.Export.TTF; #endif using System.Diagnostics; namespace FastReport.Export.TTF { internal partial class ExportTTFFont { #if !SKIA internal static FontStream GetFontStream(Font source_font) { MemoryStream mem_stream; string fastFont = TrueTypeFont.GetFontKey(source_font); string path; bool fontFound = TrueTypeCollection.FontHash.TryGetValue(fastFont, out path); while(!fontFound) { var font = FontManager.GetFontStream(fastFont); if (font != null) { font.Position = 0; return new FontStream(font); } string substFont1 = source_font.FontFamily.Name + (!source_font.Bold ? "-B" : string.Empty) + (source_font.Italic ? "-I" : string.Empty); string substFont2 = source_font.FontFamily.Name + (source_font.Bold ? "-B" : string.Empty) + (!source_font.Italic ? "-I" : string.Empty); string substFont3 = source_font.FontFamily.Name + (!source_font.Bold ? "-B" : string.Empty) + (!source_font.Italic ? "-I" : string.Empty); lock (TrueTypeCollection.FontHash) { if (TrueTypeCollection.FontHash.IsEmpty) { TrueTypeCollection.CheckFontList(Utils.Config.FontListFolder); } } fontFound = TrueTypeCollection.FontHash.TryGetValue(fastFont, out path); if (fontFound) break; fontFound = TrueTypeCollection.FontHash.TryGetValue(substFont1, out path); if (fontFound) { TrueTypeCollection.FontHash.TryAdd(fastFont, path); break; } fontFound = TrueTypeCollection.FontHash.TryGetValue(substFont2, out path); if (fontFound) { TrueTypeCollection.FontHash.TryAdd(fastFont, path); break; } fontFound = TrueTypeCollection.FontHash.TryGetValue(substFont3, out path); if (fontFound) { TrueTypeCollection.FontHash.TryAdd(fastFont, path); break; } string substFont4 = DrawUtils.DefaultFont.FontFamily.Name + (DrawUtils.DefaultFont.Bold ? "-B" : string.Empty) + (DrawUtils.DefaultFont.Italic ? "-I" : string.Empty); fontFound = TrueTypeCollection.FontHash.TryGetValue(substFont4, out path); if(fontFound) { TrueTypeCollection.FontHash.TryAdd(fastFont, path); Debug.WriteLine("Font '{0}' not found. Trying substitue to default font", fastFont); // LOG break; } Debug.WriteLine("Default font not found. Set random font to avoid file not found exception"); // LOG var en = TrueTypeCollection.FontHash.GetEnumerator(); en.MoveNext(); path = en.Current.Value; break; } using (FileStream fontStream = new FileStream(path, FileMode.Open, FileAccess.Read)) { mem_stream = new MemoryStream(); fontStream.CopyTo(mem_stream); } mem_stream.Position = 0; return new FontStream(mem_stream); } public void FillOutlineTextMetrix() { if (sourceFont != null) { using (var fontState = new TTFState(sourceFont)) { var ttf = fontState.Value; ttf.GetOutlineTextMetrics(ref textMetric); postscript_name = ttf.PostscriptName; NeedSimulateBold = SourceFont.Bold && !ttf.Bold; NeedSimulateItalic = SourceFont.Italic && !ttf.Italic; } } } // libgdiplus version has no support for font fallback and returns one run. // Also support of complex scripts is almost non-existing. private List LayoutString(string str, bool rtl, Font originalFont) { int maxGlyphs = str.Length * 3; var run = new RunInfo(maxGlyphs) { Font = originalFont, }; for (int i = 0, j = 0; i < str.Length; i++) { if (str[i] > 0xD800 && str[i] < 0xDBFF && run.GlyphToUnicode[j] == null) { run.GlyphToUnicode[j] = str[i].ToString(); } else if (str[i] > 0xDC00 && str[i] < 0xDFFF && run.GlyphToUnicode[j] != null) { run.GlyphToUnicode[j++] += str[i].ToString(); } else { if (run.GlyphToUnicode[j] != null) j++; run.GlyphToUnicode[j++] = str[i].ToString(); } } using(var fontState = new TTFState(sourceFont)) { var ttf = fontState.Value; { // Why? Why we are switching font to arab script, if (rtl) ttf.Script = "arab"; int actualLength = ttf.GetGlyphIndices(str, sourceFont.Size / 0.75f, out run.Glyphs, out run.Widths, out run.Kernings, rtl); Array.Resize(ref run.Glyphs, actualLength); Array.Resize(ref run.GlyphToUnicode, actualLength); Array.Resize(ref run.Widths, actualLength); Array.Resize(ref run.Kernings, actualLength); } } List result = new List(); result.Add(run); return result; } private void InternalInit() { dpiFX = 1; } partial void InternalDispose(); #endif } } #endif