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 }