1 module ppc.backend.loaders.font.bitmap;
2 import ppc.backend.loaders.font;
3 import ppc.backend.packer;
4 import ppc.backend.cfile;
5 import ppc.backend.ft;
6 import ppc.backend;
7 import ppc.backend.signatures;
8 import std.utf;
9 
10 /++
11     A font that uses a bitmap as texture.
12 +/
13 class BitmapFont : Font {
14 private:
15     ubyte[] bitmapTexture;
16     GlyphInfo[dchar] glyphs;
17 
18 public:
19     override ref ubyte[] getTexture() {
20         return bitmapTexture;
21     }
22 
23     override GlyphInfo* opIndex(dchar c) {
24         if (c !in glyphs) return null;
25         return &glyphs[c];
26     }
27 }
28 
29 ubyte[] saveBMF(BitmapFont font) {
30     import msgpack : pack;
31     return WritableFileSigs.FontBMF~pack(font);
32 }
33 
34 BitmapFont loadBMF(MemFile file) {
35     import msgpack : unpack;
36     return unpack!BitmapFont(file.arrayptr[WritableFileSigs.FontBMF.length..file.length]);
37 }
38 
39 /++
40     Takes a font description and builds a bitmap font out of it via FreeType
41 +/
42 BitmapFont fromFontDescription(FontDescription description) {
43     BitmapFont bmf = new BitmapFont();
44     TexturePacker packer = new TexturePacker();
45     FreeType ft = new FreeType();
46     FontFace face = ft.open(description.font, description.faceIndex);
47     face.setPixelSizes(0u, description.size);
48 
49     foreach(series; description.characters) {
50         foreach(i; series.range.start..series.range.end) {
51             dchar ch = cast(dchar)i;
52 
53             // If we already have packed that glyph, skip packing it again.
54             if (ch in bmf.glyphs) continue;
55 
56             // Get character and pack it in to the texture
57             Glyph* glyph = face.getChar(ch);
58             if (glyph is null) continue;
59 
60             PVector origin = packer.packTexture(glyph.getPixels(), glyph.getDataSize());
61             GlyphInfo* info = new GlyphInfo(origin, glyph.getSize(), glyph.getAdvance(), glyph.getBearing());
62             bmf.glyphs[ch] = *info;
63         }
64     }
65     bmf.bitmapTexture = new ubyte[](packer.buffer.length);
66     bmf.bitmapTexture[] = packer.buffer;
67     bmf.atlasSize = packer.textureSize;
68     return bmf;
69 }