private void LoadFont() { var buffer = File.ReadAllBytes("Fonts/DroidSans.ttf"); var buffer2 = File.ReadAllBytes("Fonts/DroidSansJapanese.ttf"); var tempBitmap = new byte[FontBitmapWidth * FontBitmapHeight]; var fontBaker = new FontBaker(); fontBaker.Begin(tempBitmap, FontBitmapWidth, FontBitmapHeight); fontBaker.Add(buffer, 32, new [] { FontBakerCharacterRange.BasicLatin, FontBakerCharacterRange.Latin1Supplement, FontBakerCharacterRange.LatinExtendedA, FontBakerCharacterRange.Cyrillic, }); fontBaker.Add(buffer2, 32, new [] { FontBakerCharacterRange.Hiragana, FontBakerCharacterRange.Katakana }); var _charData = fontBaker.End(); // Offset by minimal offset float minimumOffsetY = 10000; foreach (var pair in _charData) { if (pair.Value.yoff < minimumOffsetY) { minimumOffsetY = pair.Value.yoff; } } var keys = _charData.Keys.ToArray(); foreach (var key in keys) { var pc = _charData[key]; pc.yoff -= minimumOffsetY; _charData[key] = pc; } var rgb = new Color[FontBitmapWidth * FontBitmapHeight]; for (var i = 0; i < tempBitmap.Length; ++i) { var b = tempBitmap[i]; rgb[i].R = b; rgb[i].G = b; rgb[i].B = b; rgb[i].A = b; } _fontTexture = new Texture2D(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.Keys.OrderBy(a => a); foreach (var key in orderedKeys) { var character = _charData[key]; var bounds = new Rectangle(character.x0, character.y0, character.x1 - character.x0, character.y1 - character.y0); glyphBounds.Add(bounds); cropping.Add(new Rectangle((int)character.xoff, (int)character.yoff, bounds.Width, bounds.Height)); chars.Add(key); kerning.Add(new Vector3(0, bounds.Width, character.xadvance - bounds.Width)); } var constructorInfo = typeof(SpriteFont).GetTypeInfo().DeclaredConstructors.First(); _font = (SpriteFont)constructorInfo.Invoke(new object[] { _fontTexture, glyphBounds, cropping, chars, 20, 0, kerning, ' ' }); }
// 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, ' ' })); }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. _spriteBatch = new SpriteBatch(GraphicsDevice); // TODO: use this.Content to load your game content here // Create white texture _white = new Texture2D(GraphicsDevice, 1, 1); _white.SetData(new[] { Color.White }); // Load image data into memory var path = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); path = Path.Combine(path, "image.jpg"); var buffer = File.ReadAllBytes(path); var image = StbImage.LoadFromMemory(buffer, StbImage.STBI_rgb_alpha); _image = new Texture2D(GraphicsDevice, image.Width, image.Height, false, SurfaceFormat.Color); _image.SetData(image.Data); // Load ttf buffer = File.ReadAllBytes("Fonts/DroidSans.ttf"); var buffer2 = File.ReadAllBytes("Fonts/DroidSansJapanese.ttf"); var tempBitmap = new byte[FontBitmapWidth * FontBitmapHeight]; var fontBaker = new FontBaker(); fontBaker.Begin(tempBitmap, FontBitmapWidth, FontBitmapHeight); fontBaker.Add(buffer, 32, new [] { FontBakerCharacterRange.BasicLatin, FontBakerCharacterRange.Latin1Supplement, FontBakerCharacterRange.LatinExtendedA, FontBakerCharacterRange.Cyrillic, }); fontBaker.Add(buffer2, 32, new [] { FontBakerCharacterRange.Hiragana, FontBakerCharacterRange.Katakana }); _charData = fontBaker.End(); // Offset by minimal offset float minimumOffsetY = 10000; foreach (var pair in _charData) { if (pair.Value.yoff < minimumOffsetY) { minimumOffsetY = pair.Value.yoff; } } var keys = _charData.Keys.ToArray(); foreach (var key in keys) { var pc = _charData[key]; pc.yoff -= minimumOffsetY; _charData[key] = pc; } var rgb = new Color[FontBitmapWidth * FontBitmapHeight]; for (var i = 0; i < tempBitmap.Length; ++i) { var b = tempBitmap[i]; rgb[i].R = b; rgb[i].G = b; rgb[i].B = b; rgb[i].A = b; } _fontTexture = new Texture2D(GraphicsDevice, FontBitmapWidth, FontBitmapHeight); _fontTexture.SetData(rgb); // Load ogg path = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); path = Path.Combine(path, "Adeste_Fideles.ogg"); buffer = File.ReadAllBytes(path); int chan, sampleRate; var audioShort = StbVorbis.decode_vorbis_from_memory(buffer, out sampleRate, out chan); byte[] audioData = new byte[audioShort.Length / 2 * 4]; for (var i = 0; i < audioShort.Length; ++i) { if (i * 2 >= audioData.Length) { break; } var b1 = (byte)(audioShort[i] >> 8); var b2 = (byte)(audioShort[i] & 256); audioData[i * 2 + 0] = b2; audioData[i * 2 + 1] = b1; } _effect = new DynamicSoundEffectInstance(sampleRate, AudioChannels.Stereo) { Volume = 0.5f }; _effect.SubmitBuffer(audioData); GC.Collect(); }
public void ApplyFontFile([NotNull] string fileName) { _fontTexture?.Dispose(); var fontData = File.ReadAllBytes(fileName); var tempBitmap = new byte[FontBitmapWidth * FontBitmapHeight]; var fontBaker = new FontBaker(); fontBaker.Begin(tempBitmap, FontBitmapWidth, FontBitmapHeight); var fontSizeInPx = PointToPixel(FontSize); fontBaker.Add(fontData, fontSizeInPx, new[] { FontBakerCharacterRange.BasicLatin, FontBakerCharacterRange.Latin1Supplement, FontBakerCharacterRange.LatinExtendedA, FontBakerCharacterRange.LatinExtendedB, // FontBakerCharacterRange.Cyrillic }); var charData = fontBaker.End(); var minOffsetY = float.MaxValue; foreach (var kv in charData) { if (kv.Value.yoff < minOffsetY) { minOffsetY = kv.Value.yoff; } } var keys = charData.Keys.ToArray(); foreach (var key in keys) { var pc = charData[key]; pc.yoff -= minOffsetY; charData[key] = pc; } var rgba = new Color[FontBitmapWidth * FontBitmapHeight]; for (var i = 0; i < tempBitmap.Length; ++i) { var b = tempBitmap[i]; rgba[i].R = b; rgba[i].G = b; rgba[i].B = b; rgba[i].A = b; } var fontTexture = new Texture2D(_graphicsDevice, FontBitmapWidth, FontBitmapHeight, false, SurfaceFormat.Color); fontTexture.SetData(rgba); var glyphBounds = new List <Rectangle>(); var cropping = new List <Rectangle>(); var chars = new List <char>(); var kerning = new List <Vector3>(); var orderedKeys = charData.Keys.OrderBy(a => a); foreach (var key in orderedKeys) { var character = charData[key]; var bounds = new Rectangle( character.x0, character.y0, character.x1 - character.x0, character.y1 - character.y0); glyphBounds.Add(bounds); cropping.Add(new Rectangle((int)character.xoff, (int)character.yoff, bounds.Width, bounds.Height)); chars.Add(key); kerning.Add(new Vector3(0, bounds.Width, character.xadvance - bounds.Width)); } // The constructor is made public from 3.7. // But since we are using 3.6, we have to use reflection to access it. var constructor = typeof(SpriteFont).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, SpriteFontConstructorTypes, null); if (constructor == null) { throw new MissingMethodException("Cannot access constructor of " + nameof(_spriteFont)); } var spriteFont = (SpriteFont)constructor.Invoke(new object[] { fontTexture, glyphBounds, cropping, chars, LineSpacing, Spacing, kerning, DefaultCharacter }); _charData = charData; _fontTexture = fontTexture; _spriteFont = spriteFont; }