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  }