1 module sbylib.graphics.glyph.glyphstore; 2 3 import std; 4 import erupted; 5 import sbylib.graphics.glyph.glyph; 6 import sbylib.graphics.glyph.glyphtexture; 7 import sbylib.wrapper.freetype; 8 import sbylib.wrapper.vulkan; 9 10 class GlyphStore { 11 12 private Font font; 13 private GlyphTexture _texture; 14 private int[] currentX; 15 private Glyph[dchar] glyph; 16 17 this(string font, int height) { 18 this.font = FontLoader().load(font, height); 19 this._texture = new GlyphTexture(256, 256); 20 this.currentX = [0]; 21 } 22 23 ~this() { 24 this._texture.destroy(); 25 } 26 27 GlyphTexture texture() { 28 return _texture; 29 } 30 31 Glyph getGlyph(dchar c) { 32 if (auto r = c in glyph) return *r; 33 34 auto info = font.getLetterInfo(c); 35 36 auto result = glyph[c] = 37 new Glyph(info.character, 38 info.offsetX, info.offsetY, 39 info.width, info.height, 40 info.advance, 41 info.maxHeight); 42 43 write(info); 44 return result; 45 } 46 47 private void write(Character c) { 48 auto g = getGlyph(c.character); 49 auto idx = currentX.countUntil!(x => x + g.advance < this.texture.width); 50 51 if (idx == -1) { 52 if ((currentX.length + 1) * g.maxHeight < this.texture.height) { 53 idx = cast(int)currentX.length; 54 currentX ~= 0; 55 } else { 56 this.texture.resize(this.texture.width * 2, this.texture.height * 2); 57 idx = 0; 58 } 59 } 60 61 const x = currentX[idx]; 62 const y = idx * g.maxHeight; 63 VkOffset3D dstOffset = { 64 x: cast(int)(x+g.offsetX), 65 y: cast(int)(y+g.offsetY), 66 z: 0 67 }; 68 VkExtent3D dstExtent = { 69 width: cast(uint)g.width, 70 height: cast(uint)g.height, 71 depth: 1 72 }; 73 74 texture.write(c.bitmap, dstOffset, dstExtent); 75 76 g.x = x; 77 g.y = y; 78 currentX[idx] += g.advance; 79 } 80 }