1 // Written in the D programming language.
2 /++
3  + Authors: KanzakiKino
4  + Copyright: KanzakiKino 2018
5  + License: LGPL-3.0
6 ++/
7 module g4d.ft.texture;
8 import g4d.ft.font,
9        g4d.ft.lib,
10        g4d.gl.buffer,
11        g4d.gl.texture,
12        g4d.math.rational,
13        g4d.util.bitmap;
14 import gl3n.linalg;
15 import std.algorithm,
16        std.array,
17        std.conv;
18 
19 /// A texture of text.
20 class TextTexture : Tex2D
21 {
22     /// A metrics data of characters.
23     struct Metrics
24     {
25         /// Size in pixel.
26         vec2i size;
27         /// UV coordinates.
28         /// [left,top, right,top, right,bottom, left,bottom,]
29         float[8] uv;
30 
31         /// Width of collision.
32         ulong horiAdvance;
33         /// Size of moving from origin.
34         vec2i horiBearing;
35     }
36 
37     protected Metrics[dchar] _chars;
38     /// Metrics data of characters drawn this texture.
39     const @property chars () { return _chars; }
40 
41     /// Creates text texture from FontFace and text.
42     this ( FontFace face, dstring text )
43     {
44         text = text.uniq.array;
45         super( renderBitmap( face, text ), true );
46     }
47 
48     protected BitmapA renderBitmap ( FontFace face, dstring text )
49     {
50         auto size = vec2i( face.size );
51         size.x   *= text.length;
52 
53         auto result = new BitmapA( size );
54 
55         size.x = size.x.nextPower2;
56         size.y = size.y.nextPower2;
57 
58         Glyph   g;
59         Metrics m;
60         int     pos = 0;
61         float   left, top, right, bottom;
62 
63         foreach ( c; text ) {
64             g = face.render( c );
65 
66             result.overwrite( vec2i(pos,0), g.bmp );
67 
68             m.size        = g.bmp.size;
69             m.horiBearing = g.bearing;
70             m.horiAdvance = g.advance;
71 
72             left   = pos*1f / size.x;
73             top    = 0;
74             pos   += m.size.x;
75             right  = pos*1f / size.x;
76             bottom = m.size.y*1f / size.y;
77 
78             m.uv = [
79                 left,top, right,top, right,bottom, left,bottom,
80             ];
81 
82             _chars[c] = m;
83             g.bmp.dispose();
84         }
85         return result;
86     }
87 }