/* * get unicode font ranges */ public static List<FontRange> GetFontUnicodeRanges(Font font) { Graphics g = Graphics.FromHwnd(IntPtr.Zero); IntPtr hdc = g.GetHdc(); IntPtr hFont = font.ToHfont(); IntPtr old = SelectObject(hdc, hFont); uint size = GetFontUnicodeRanges(hdc, IntPtr.Zero); IntPtr glyphSet = Marshal.AllocHGlobal((int)size); GetFontUnicodeRanges(hdc, glyphSet); List<FontRange> fontRanges = new List<FontRange>(); int count = Marshal.ReadInt32(glyphSet, 12); for (int i = 0; i < count; i++) { FontRange range = new FontRange(); range.Low = (UInt16)Marshal.ReadInt16(glyphSet, 16 + i * 4); range.High = (UInt16)(range.Low + Marshal.ReadInt16(glyphSet, 18 + i * 4) - 1); fontRanges.Add(range); } SelectObject(hdc, old); Marshal.FreeHGlobal(glyphSet); g.ReleaseHdc(hdc); g.Dispose(); return fontRanges; }
/// <summary> /// Gets the unicode ranges for font. /// </summary> /// <param name="font">The font.</param> /// <returns></returns> public List <FontRange> GetUnicodeRangesForFont(Font font) { Graphics g = Graphics.FromHwnd(IntPtr.Zero); IntPtr hdc = g.GetHdc(); IntPtr hFont = font.ToHfont(); IntPtr old = SelectObject(hdc, hFont); uint size = GetFontUnicodeRanges(hdc, IntPtr.Zero); IntPtr glyphSet = Marshal.AllocHGlobal((int)size); GetFontUnicodeRanges(hdc, glyphSet); List <FontRange> fontRanges = new List <FontRange>(); int count = Marshal.ReadInt32(glyphSet, 12); for (int i = 0; i < count; i++) { FontRange range = new FontRange(); range.Low = (UInt16)Marshal.ReadInt16(glyphSet, 16 + i * 4); range.High = (UInt16)(range.Low + Marshal.ReadInt16(glyphSet, 18 + i * 4) - 1); fontRanges.Add(range); } SelectObject(hdc, old); Marshal.FreeHGlobal(glyphSet); g.ReleaseHdc(hdc); g.Dispose(); return(fontRanges); }
// Copied / Adapted from: // https://github.com/StbSharp/StbTrueTypeSharp/tree/master/samples/StbTrueTypeSharp.MonoGame.Test public static SpriteFont LoadFont(string path, float fontHeight, FontRange fontRange = FontRange.Latin) { var fontBaker = new FontBaker(); fontBaker.Begin(FontBitmapWidth, FontBitmapHeight); if (fontRange == FontRange.Latin) { fontBaker.Add(File.ReadAllBytes(path), fontHeight, new[] { CharacterRange.BasicLatin, CharacterRange.Latin1Supplement, CharacterRange.LatinExtendedA, CharacterRange.LatinExtendedB, CharacterRange.Greek, LatinSymbols }); } else if (fontRange == FontRange.Japanese) { fontBaker.Add(File.ReadAllBytes(path), fontHeight, new[] { CharacterRange.BasicLatin, CharacterRange.Latin1Supplement, CharacterRange.LatinExtendedA, CharacterRange.LatinExtendedB, CharacterRange.Greek, LatinSymbols, ExtendedSymbols, CharacterRange.Hiragana, CharacterRange.Katakana, CharacterRange.CjkSymbolsAndPunctuation, CharacterRange.CjkUnifiedIdeographs }); } var _charData = fontBaker.End(); // Offset by minimal offset int minimumOffsetY = 10000; foreach (var pair in _charData.Glyphs) { if (pair.Value.YOffset < minimumOffsetY) { minimumOffsetY = pair.Value.YOffset; } } var keys = _charData.Glyphs.Keys.ToArray(); foreach (var key in keys) { var pc = _charData.Glyphs[key]; pc.YOffset -= minimumOffsetY; _charData.Glyphs[key] = pc; } var rgb = new Color[FontBitmapWidth * FontBitmapHeight]; for (var i = 0; i < _charData.Bitmap.Length; ++i) { var b = _charData.Bitmap[i]; rgb[i].R = b; rgb[i].G = b; rgb[i].B = b; rgb[i].A = b; } var fontTexture = new Texture2D(Globals.GraphicsManager.GraphicsDevice, FontBitmapWidth, FontBitmapHeight); fontTexture.SetData(rgb); var glyphBounds = new List <Rectangle>(); var cropping = new List <Rectangle>(); var chars = new List <char>(); var kerning = new List <Vector3>(); var orderedKeys = _charData.Glyphs.Keys.OrderBy(a => a); foreach (var key in orderedKeys) { var character = _charData.Glyphs[key]; var bounds = new Rectangle(character.X, character.Y, character.Width, character.Height); glyphBounds.Add(bounds); cropping.Add(new Rectangle(character.XOffset, character.YOffset, bounds.Width, bounds.Height)); chars.Add((char)key); kerning.Add(new Vector3(0, bounds.Width, character.XAdvance - bounds.Width)); } var constructorInfo = typeof(SpriteFont).GetTypeInfo().DeclaredConstructors.First(); var spacing = cropping.Max(x => x.Height); return((SpriteFont)constructorInfo.Invoke(new object[] { fontTexture, glyphBounds, cropping, chars, spacing, 0, kerning, ' ' })); }