/// <summary> /// At first this method looks if there is <see cref="CharCache"/> for a given height. /// If not - the method creates such <see cref="CharCache"/>. /// The rest of the logic is on <see cref="CharCache"/>. /// </summary> /// <param name="code">Char to obtain.</param> /// <param name="heightHint">Desired height. It will be rounded to int to reduce number of caches.</param> /// <returns></returns> public FontChar Get(char code, float heightHint) { var roundedHeight = (heightHint * Window.Current.PixelScale).Round(); CharCache charChache; if (!charCaches.TryGetValue(roundedHeight, out charChache)) { charCaches[roundedHeight] = charChache = new CharCache(roundedHeight, fontRenderer, textures); } var c = charChache.Get(code); if (c.Texture == null) { c.Texture = textures[c.TextureIndex]; } return(c); }
/// <summary> /// Generates Tangerine Font. /// </summary> /// <param name="config"> Tangerine Font Config. </param> /// <param name="assetDirectory"> Path to asset directory. </param> /// <param name="outputPath"> Path for Tangerine Font and it's textures </param> public static void GenerateFont(TftConfig config, string assetDirectory, string outputPath) { var fontCharCollection = new FontCharCollection(); var chars = new CharCache(config.Height, null, fontCharCollection.Textures) { Padding = config.Padding, MinTextureSize = config.TextureSize, MaxTextureSize = config.TextureSize, }; var missingCharacters = new List <char>(); var margin = new Vector2(config.Margin * .5f); foreach (var charSet in config.CharSets) { var fontPath = AssetPath.Combine(assetDirectory, charSet.Font); if (!File.Exists(fontPath)) { Console.WriteLine($"Missing font: {fontPath}\n Please ensure font existence!!!"); return; } var fontData = File.ReadAllBytes(fontPath); chars.FontRenderer = new FontRenderer(fontData) { LcdSupported = false }; missingCharacters.Clear(); foreach (var c in charSet.Chars) { if (config.ExcludeChars.Any(character => character == c)) { continue; } var fontChar = chars.Get(c); if (fontChar == FontChar.Null) { missingCharacters.Add(c); continue; } fontChar.ACWidths += margin; if (config.IsSdf) { fontChar.ACWidths *= config.SdfScale; fontChar.Height *= config.SdfScale; fontChar.Width *= config.SdfScale; fontChar.Padding *= config.SdfScale; fontChar.VerticalOffset *= config.SdfScale; if (fontChar.KerningPairs != null) { for (int i = 0; i < fontChar.KerningPairs.Count; i++) { var pair = fontChar.KerningPairs[i]; pair.Kerning *= config.SdfScale; fontChar.KerningPairs[i] = pair; } } } fontCharCollection.Add(fontChar); } if (missingCharacters.Count > 0) { Console.WriteLine($"Characters: {string.Join("", missingCharacters)} -- are missing in font {charSet.Font}"); } GenerateKerningPairs(fontCharCollection, chars.FontRenderer.Face, config); } if (config.IsSdf) { foreach (var texture in fontCharCollection.Textures) { SdfConverter.ConvertToSdf(texture.GetPixels(), texture.ImageSize.Width, texture.ImageSize.Height, config.Padding / 2); } } using (var font = new Font(fontCharCollection)) { SaveAsTft(font, config, assetDirectory, outputPath); } }