1 module des.gl.simple.textout; 2 3 import des.fonts; 4 5 import des.gl; 6 7 import std.traits; 8 import std.conv; 9 import std.string; 10 11 import des.util.logsys; 12 import des.util.arch.emm; 13 14 wstring wformat(S,Args...)( S fmt, Args args ) 15 if( is( S == string ) || is( S == wstring ) ) 16 { return to!wstring( format( to!string(fmt), args ) ); } 17 18 enum SS_WIN_TEXT = 19 `//### vert 20 #version 330 21 in vec2 vert; 22 in vec2 uv; 23 24 uniform ivec2 win_size; 25 uniform vec2 offset; 26 27 out vec2 ex_uv; 28 29 void main(void) 30 { 31 vec2 tr_vert = ( vert + offset ) / win_size * 2 - 1; 32 gl_Position = vec4( tr_vert.x, -tr_vert.y, 0, 1); 33 ex_uv = uv; 34 } 35 //### frag 36 #version 330 37 uniform sampler2DRect ttu; 38 uniform vec4 color; 39 40 in vec2 ex_uv; 41 42 out vec4 result; 43 44 void main(void) 45 { 46 result = vec4( 1,1,1, texture( ttu, ivec2( ex_uv.x, ex_uv.y ) ).r ) * color; 47 }`; 48 49 class BaseLineTextBox : GLDrawObject 50 { 51 private: 52 53 CommonGLShaderProgram shader; 54 55 public GLArrayBuffer vert, uv; 56 57 GLTextureRectangle tex; 58 59 wstring output; 60 61 vec2 offset; 62 63 BitmapFont font; 64 65 float spacing = 1.5; 66 67 fRegion2 rect; 68 69 void update() 70 { 71 if( output.length == 0 ) return; 72 73 vec2[] vert_data; 74 vec2[] uv_data; 75 76 auto ch_offset = vec2(0); 77 78 rect = fRegion2(0); 79 80 std.stdio.writeln( font.height ); 81 std.stdio.writeln( font.image.size ); 82 83 foreach( c; output ) 84 { 85 if( c == '\n' ) 86 { 87 ch_offset.x = 0; 88 ch_offset.y += font.height * spacing; 89 continue; 90 } 91 92 if( c !in font.info ) 93 { 94 logger.error( "Character "w ~ c ~ "not in bitmap font."w ); 95 continue; 96 } 97 98 auto chsz = vec2( font.info[c].glyph.size ); 99 auto p = ch_offset + font.info[c].glyph.pos; 100 vert_data ~= computeRectPts( p, chsz ); 101 102 rect = rect.expand(p).expand(p+chsz); 103 104 auto buf = computeRectPts( vec2( font.info[c].offset ), chsz ); 105 106 if( font.height != 16 ) 107 std.stdio.writeln( buf ); 108 109 uv_data ~= buf; 110 111 ch_offset += font.info[c].glyph.next; 112 } 113 114 std.stdio.writeln(); 115 116 vert.setData( vert_data ); 117 uv.setData( uv_data ); 118 } 119 120 auto computeRectPts(T)( in Vector!(2,T) v1, in Vector!(2,T) sz ) 121 { 122 alias VV=Vector!(2,T); 123 auto v2 = v1 + sz; 124 return [ v1, VV( v1.x, v2.y ), VV( v2.x, v1.y ), 125 v2, VV( v2.x, v1.y ), VV( v1.x, v2.y ) ]; 126 //return [ VV( v1.x, v2.y ), v1, VV( v2.x, v1.y ), 127 // v2, VV( v1.x, v2.y ), VV( v2.x, v1.y ) ]; 128 } 129 130 public: 131 132 this( string font_name, uint size=24u ) 133 { 134 shader = newEMM!CommonGLShaderProgram( parseGLShaderSource( SS_WIN_TEXT ) ); 135 136 vert = newEMM!GLArrayBuffer; 137 setAttribPointer( vert, shader.getAttribLocation( "vert" ), 2, GLType.FLOAT ); 138 139 uv = newEMM!GLArrayBuffer; 140 setAttribPointer( uv, shader.getAttribLocation( "uv" ), 2, GLType.FLOAT ); 141 142 tex = newEMM!GLTextureRectangle(0); 143 144 tex.setMinFilter( GLTexture.Filter.NEAREST ); 145 tex.setMagFilter( GLTexture.Filter.NEAREST ); 146 147 FontRenderParam gparam; 148 gparam.height = size; 149 150 auto grender = FTFontRender.get( font_name ); 151 152 auto symbols = "!\"#$%&'()*+,-./0123456789:;<=>?@[\\]^_`{|}~^? "w; 153 auto english = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"w; 154 auto russian = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя"w; 155 156 grender.setParams( gparam ); 157 font = grender.generateBitmapFont( symbols ~ english ~ russian ); 158 159 tex.setImage( font.image ); 160 } 161 162 void draw( ivec2 win_size ) 163 { 164 if( output.length == 0 ) return; 165 shader.setUniform!ivec2( "win_size", win_size ); 166 tex.bind(); 167 glDisable(GL_DEPTH_TEST); 168 drawArrays( DrawMode.TRIANGLES, 0, vert.elementCount ); 169 tex.unbind(); 170 } 171 172 @property 173 { 174 void text(T)( T t ) if( isSomeString!T ) 175 { 176 import std.conv; 177 output = to!wstring( t ); 178 update(); 179 } 180 181 wstring text(){ return output; } 182 183 void position( vec2 pos ) 184 { 185 offset = pos; 186 shader.setUniform!vec2( "offset", offset ); 187 } 188 189 vec2 position() const { return offset; } 190 191 void color( vec4 col ){ shader.setUniform!vec4( "color", col ); } 192 193 fRegion2 rectangle() const { return rect; } 194 } 195 }