1 module des.gl.simple.textout;
2 
3 import des.fonts.ftglyphrender;
4 
5 import des.gl.simple;
6 import des.gl.simple.shader.text;
7 
8 import std.traits;
9 
10 wstring wformat(S,Args...)( S fmt, Args args )
11     if( is( S == string ) || is( S == wstring ) )
12 { return to!wstring( format( to!string(fmt), args ) ); }
13 
14 class BaseLineTextBox : GLSimpleObject
15 {
16 private:
17 
18     GLBuffer vert, uv;
19 
20     GLTexture tex;
21 
22     wstring output;
23     vec2 output_size;
24 
25     vec2 pos;
26 
27     BitmapFont font;
28 
29     void repos()
30     {
31         vec2[] vert_data;
32         vec2[] uv_data;
33 
34         output_size = vec2(0);
35 
36         float offsetx = 0;
37         foreach( c; output )
38             if( font.size[c].h > output_size.h )
39                 output_size.h = font.size[c].h;
40         
41         foreach( c; output )
42         {
43             output_size.w += font.size[c].w;
44 
45             {
46                 auto v1 = pos + vec2( font.bearing[c].x + offsetx, output_size.h + font.bearing[c].y );
47                 auto v2 = v1 + font.size[c];
48 
49                 vert_data ~= vec2( v1.x, v2.y );
50                 vert_data ~= v1;
51                 vert_data ~= vec2( v2.x, v1.y );
52 
53                 vert_data ~= v2;
54                 vert_data ~= vec2( v1.x, v2.y );
55                 vert_data ~= vec2( v2.x, v1.y );
56 
57                 offsetx += font.size[c].x;
58             }
59 
60             {
61                 auto uvoffset = vec2( font.offset[c] ) / vec2( font.texture.size );
62                 auto uvsize = vec2( font.size[c] ) / vec2( font.texture.size );
63 
64                 auto uv1 = uvoffset;
65                 auto uv2 = uv1 + uvsize;
66 
67                 uv_data ~= vec2( uv1.x, uv2.y );
68                 uv_data ~= uv1;
69                 uv_data ~= vec2( uv2.x, uv1.y );
70 
71                 uv_data ~= uv2;
72                 uv_data ~= vec2( uv1.x, uv2.y );
73                 uv_data ~= vec2( uv2.x, uv1.y );
74             }
75         }
76 
77         vert.setData( vert_data );
78         uv.setData( uv_data );
79     }
80 
81 public:
82     this( string font_name, uint size=24u )
83     {
84         super( SS_WIN_TEXT );
85 
86         vert = createArrayBuffer();
87         setAttribPointer( vert, shader.getAttribLocation( "vert" ), 2, GLType.FLOAT );
88 
89         uv = createArrayBuffer();
90         setAttribPointer( uv, shader.getAttribLocation( "uv" ), 2, GLType.FLOAT );
91 
92         tex = newEMM!GLTexture( GLTexture.Target.T2D );
93 
94         tex.setParameter( GLTexture.Parameter.MIN_FILTER, GLTexture.Filter.NEAREST );
95         tex.setParameter( GLTexture.Parameter.MAG_FILTER, GLTexture.Filter.NEAREST );
96 
97         GlyphParam gparam;
98         gparam.height = size;
99 
100         auto grender = FTGlyphRender.get( font_name );
101 
102         grender.setParams( gparam );
103 
104         font = grender.generateBitmapFont();
105 
106         tex.image( font.texture );
107 
108         text = "Default text";
109     }
110 
111     void draw( ivec2 win_size )
112     {
113         shader.setUniform!ivec2( "win_size", win_size );
114         tex.bind();
115             glDisable(GL_DEPTH_TEST);
116             drawArrays( DrawMode.TRIANGLES );
117         tex.unbind();
118     }
119 
120     @property
121     {
122         void text(T)( T t )
123             if( isSomeString!T )//TODO is convertable to wstring
124         {
125             import std.conv;
126             output = to!wstring( t );
127             repos();
128         }
129         wstring text(){ return output; }
130 
131         void position( vec2 pos )
132         { 
133             this.pos = pos; 
134             repos(); 
135         }
136 
137         void color( col3 col ){ shader.setUniform!col3( "color", col ); }
138 
139         vec2 size(){ return output_size; }
140     }
141 }