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