using System; using System.Collections.Generic; using Cyotek.Drawing.BitmapFont; using System.Linq; using System.Reflection; #if !XENKO using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; #else using Xenko.Core.Mathematics; using Xenko.Graphics; using Xenko.Graphics.Font; using Texture2D = Xenko.Graphics.Texture; #endif namespace SpriteFontPlus { #if BF2SF_INTERNAL internal #else public #endif class TextureWithOffset { public Texture2D Texture { get; set; } public Point Offset { get; set; } public TextureWithOffset(Texture2D texture) { if (texture == null) { throw new ArgumentNullException("texture"); } Texture = texture; } public TextureWithOffset(Texture2D texture, Point offset): this(texture) { Offset = offset; } } #if BF2SF_INTERNAL internal #else public #endif static class BMFontLoader { #if XENKO private static FontSystem _fontSystem; public static FontSystem FontSystem { get { if (_fontSystem != null) { return _fontSystem; } _fontSystem = new FontSystem(); FontSystem.Load(GraphicsDevice, null); return _fontSystem; } } public static GraphicsDevice GraphicsDevice; #endif private static SpriteFont Load(BitmapFont data, Func textureGetter) { if (data.Pages.Length > 1) { throw new NotSupportedException("For now only BMFonts with single texture are supported"); } var texture = textureGetter(data.Pages[0].FileName); #if !XENKO var glyphBounds = new List(); var cropping = new List(); var chars = new List(); var kerning = new List(); var characters = data.Characters.Values.OrderBy(c => c.Char); foreach (var character in characters) { var bounds = character.Bounds; bounds.Offset(texture.Offset); glyphBounds.Add(bounds); cropping.Add(new Rectangle(character.Offset.X, character.Offset.Y, bounds.Width, bounds.Height)); chars.Add(character.Char); kerning.Add(new Vector3(0, character.Bounds.Width, character.XAdvance - character.Bounds.Width)); } var constructorInfo = typeof(SpriteFont).GetTypeInfo().DeclaredConstructors.First(); var result = (SpriteFont)constructorInfo.Invoke(new object[] { texture.Texture, glyphBounds, cropping, chars, data.LineHeight, 0, kerning, ' ' }); return result; #else var textureRegion = textureGetter(data.Pages[0].FileName); var glyphs = new List(); foreach (var pair in data.Characters) { var character = pair.Value; var bounds = character.Bounds; bounds.X += textureRegion.Offset.X; bounds.Y += textureRegion.Offset.Y; var glyph = new Glyph { Character = character.Char, BitmapIndex = 0, Offset = new Vector2(character.Offset.X, character.Offset.Y), Subrect = bounds, XAdvance = character.XAdvance }; glyphs.Add(glyph); } var textures = new List { textureRegion.Texture }; return FontSystem.NewStatic(data.LineHeight, glyphs, textures, 0, data.LineHeight); #endif } public static SpriteFont LoadXml(string xml, Func textureGetter) { var data = new BitmapFont(); data.LoadXml(xml); return Load(data, textureGetter); } public static SpriteFont LoadText(string xml, Func textureGetter) { var data = new BitmapFont(); data.LoadText(xml); return Load(data, textureGetter); } public static SpriteFont Load(string str, Func textureGetter) { var data = new BitmapFont(); if (str.StartsWith("<")) { // xml data.LoadXml(str); } else { data.LoadText(str); } return Load(data, textureGetter); } } }