1 module d2d.font.bmfont; 2 3 import d2d; 4 5 import std.algorithm : max; 6 import std.utf : byDchar; 7 import std.path : buildPath; 8 9 import BM = bmfont; 10 import fs = std.file; 11 12 /// Implementation for AngelCode BMFont. 13 class BMFont : IFont 14 { 15 private: 16 BM.Font _handle = void; 17 Texture[] _textures; 18 string _textureFolder; 19 20 public: 21 ~this() 22 { 23 } 24 25 /// Creates a new BMFont instance with a textureFolder used as base path for texture loading 26 this(string textureFolder) 27 { 28 _textureFolder = textureFolder; 29 } 30 31 /// Handle to underlying `bmfont.Font` handle. 32 @property ref BM.Font handle() 33 { 34 return _handle; 35 } 36 37 /// All textures in the BMFont file 38 @property ref Texture[] textures() 39 { 40 return _textures; 41 } 42 43 /// Loads the font from a binary or text bmfont file. 44 override void load(string file, int sizeInPt) 45 { 46 _handle = BM.parseFnt(cast(ubyte[]) fs.read(file)); 47 foreach (page; _handle.pages) 48 textures ~= new Texture(buildPath(_textureFolder, page)); 49 } 50 51 /// Returns true if font has been loaded. 52 override @property bool valid() 53 { 54 return _handle.type != 0; 55 } 56 57 override void dispose() 58 { 59 } 60 61 /// Renders a string to an IText. 62 override IText render(string text, float scale = 1.0f) 63 { 64 BMText ret = new BMText(this); 65 ret.text = text; 66 ret.scale = scale; 67 return ret; 68 } 69 70 /// Renders a multiline string to an IText. 71 override IText renderMultiline(string text, float scale = 1.0f) 72 { 73 BMText ret = new BMText(this); 74 ret.text = text; 75 ret.scale = scale; 76 ret.multiline = true; 77 return ret; 78 } 79 80 /// Returns the line height of this font. 81 @property float lineHeight() 82 { 83 return cast(float) _handle.common.lineHeight; 84 } 85 86 /// Returns the dimensions of a string with this font. 87 override vec2 measureText(string text, float scale = 1.0f) 88 { 89 if (!text.length) 90 return vec2(0, 0); 91 int w, h; 92 dchar last; 93 foreach (c; text.byDchar) 94 { 95 auto bmChar = _handle.getChar(c); 96 w += bmChar.xadvance; 97 h = max(h, bmChar.yoffset + bmChar.height); 98 if (last != dchar.init) 99 w += _handle.getKerning(last, c); 100 last = c; 101 } 102 auto lastBmChar = _handle.getChar(last); 103 w = w - lastBmChar.xadvance + lastBmChar.xoffset + lastBmChar.width; 104 return vec2(w * scale, h * scale); 105 } 106 107 /// Returns the dimensions of a multiline string with this font. 108 override vec2 measureTextMultiline(string text, float scale = 1.0f) 109 { 110 string[] lines = text.split('\n'); 111 int w; 112 foreach (string line; lines) 113 { 114 vec2 size = measureText(line); 115 w = max(w, cast(int) size.x); 116 } 117 return vec2(w * scale, 118 ((lines.length - 1) * _handle.common.lineHeight + measureText(lines[$ - 1]).y) 119 * scale); 120 } 121 }