1 // Written in the D programming language.
2 /++
3  + Authors: KanzakiKino
4  + Copyright: KanzakiKino 2018
5  + License: LGPL-3.0
6  +
7  + This module declares utilities related to font.
8 ++/
9 module g4d.ft.font;
10 import g4d.ft.lib,
11        g4d.util.bitmap,
12        g4d.exception;
13 import gl3n.linalg;
14 import std.conv,
15        std..string;
16 
17 /// A struct of one glyph.
18 struct Glyph
19 {
20     /// Bitmap of the glyph.
21     BitmapA bmp;
22     /// Size of moving from origin.
23     vec2i bearing;
24     /// Width of collision.
25     size_t advance;
26 }
27 
28 /// An object of Font.
29 class Font
30 {
31     protected static FT_Library _library;
32     protected static void initLibrary ()
33     {
34         if ( !_library ) {
35             DerelictFT.load();
36             enforce!FT_Init_FreeType( &_library );
37         }
38     }
39     protected static size_t _fontCount;
40 
41     protected FT_Face _face;
42 
43     ///
44     this ( string path )
45     {
46         initLibrary();
47         _fontCount++;
48 
49         enforce!FT_New_Face( _library, path.toStringz, 0, &_face );
50     }
51     ///
52     ~this ()
53     {
54         enforce!FT_Done_Face( _face );
55         if ( --_fontCount <= 0 ) {
56             enforce!FT_Done_FreeType( _library );
57             _library = null;
58         }
59     }
60 
61     protected Glyph createGlyph ( bool needbmp = true )
62     {
63         Glyph g;
64 
65         BitmapA bmp = null;
66         if ( needbmp ) {
67             auto ftbmp = _face.glyph.bitmap;
68             auto size  = vec2i(
69                     ftbmp.width.to!int, ftbmp.rows.to!int );
70             bmp = new BitmapA( size, ftbmp.buffer );
71         }
72 
73         auto metrics = _face.glyph.metrics;
74         auto bearing = vec2i( metrics.horiBearingX.to!int/64,
75                 metrics.horiBearingY.to!int/64 );
76 
77         return Glyph( bmp, bearing, metrics.horiAdvance/64 );
78     }
79 
80     /// Retrieves metrics only.
81     Glyph retrieveMetrics ( vec2i sz, dchar c )
82     {
83         enforce!FT_Set_Pixel_Sizes( _face, sz.x.to!uint, sz.y.to!uint );
84 
85         auto index = FT_Get_Char_Index( _face, c );
86         enforce!FT_Load_Glyph( _face, index, FT_LOAD_NO_BITMAP );
87 
88         return createGlyph( false );
89     }
90 
91     /// Renders the character.
92     Glyph render ( vec2i sz, dchar c )
93     {
94         enforce!FT_Set_Pixel_Sizes( _face, sz.x.to!uint, sz.y.to!uint );
95 
96         auto index = FT_Get_Char_Index( _face, c );
97         enforce!FT_Load_Glyph( _face, index, FT_LOAD_RENDER );
98 
99         return createGlyph( true );
100     }
101 }
102 
103 /// An object of font face. Font face knows its size.
104 class FontFace
105 {
106     protected Font _font;
107     /// Font.
108     const @property font () { return _font; }
109 
110     /// Size of the Font.
111     const vec2i size;
112 
113     ///
114     this ( Font f, vec2i s )
115     {
116         if ( s.x == 0 ) s.x = s.y;
117         if ( s.y == 0 ) s.y = s.x;
118         _font = f;
119         size  = s;
120     }
121 
122     /// Retrieves the metrics.
123     Glyph retrieveMetrics ( dchar c )
124     {
125         return _font.retrieveMetrics( size, c );
126     }
127 
128     /// Renders the character.
129     Glyph render ( dchar c )
130     {
131         return _font.render( size, c );
132     }
133 }