7 , m_textRenderer(textRenderer)
9 stringstream ss; ss <<
"content\\fonts\\" << name <<
".ttf";
10 string file = ss.str();
15 error = FT_New_Face( textRenderer->
m_ftLib,
19 if ( error == FT_Err_Unknown_File_Format )
21 cerr <<
"ERROR: Loading font '" << file <<
"' failed (Unknown file format)" << endl;
26 cerr <<
"ERROR: Loading font '" << file <<
"' failed (Could not read font-file)" << endl;
30 FT_Set_Char_Size(face,0,size*64,72,72);
34 map<int, uvec2> charToCoords;
39 for(uint row = 0; row < 15; row++)
43 for(uint col = 0; col < 15; col++)
45 uint i = 32 + row*15+col;
47 error = FT_Load_Char(face, i, FT_LOAD_RENDER);
50 cerr <<
"ERROR: Loading font '" << file <<
"' failed (char '"<< i <<
"')" << endl;
53 auto& g = face->glyph;
55 rowHeight = glm::max(rowHeight,(uint)g->bitmap.rows);
57 charToCoords[i] = uvec2(x, y);
59 x += g->bitmap.width + 5;
75 float ymin = 1000000000.0;
78 for(
int i = 32; i < 256; i++)
80 if(FT_Load_Char(face, i, FT_LOAD_RENDER))
83 auto& g = face->glyph;
84 auto& pixelCoords = charToCoords[i];
86 for (
int tx = 0 ; tx < g->bitmap.width ; tx ++)
87 for (
int ty = 0 ; ty < g-> bitmap.rows; ty ++)
89 m_atlasData[
m_atlasSize.x * (ty+pixelCoords.y) + pixelCoords.x + tx] = g->bitmap.buffer[(g->bitmap.rows-ty-1) * g->bitmap.pitch + tx];
94 glyph.size = vec2( g->bitmap.width, g->bitmap.rows );
95 glyph.advance = vec2( g->metrics.horiAdvance >> 6, g->metrics.vertAdvance >> 6 );
96 glyph.location = vec2( g->metrics.horiBearingX >> 6 , (g->metrics.horiBearingY - g->metrics.height) >> 6 );
97 glyph.texCoord1 = vec2(pixelCoords.x/static_cast<float>(
m_atlasSize.x),pixelCoords.y/static_cast<float>(
m_atlasSize.y));
98 glyph.texCoord2 = vec2((pixelCoords.x + glyph.size.x)/static_cast<float>(
m_atlasSize.x),(pixelCoords.y + glyph.size.y)/static_cast<float>(
m_atlasSize.y));
100 ymin =
static_cast<float>(glm::min(glyph.location.y,ymin));
101 ymax =
static_cast<float>(glm::max(glyph.location.y + glyph.size.y, ymax));
110 glActiveTexture(GL_TEXTURE0);
111 glBindTexture(GL_TEXTURE_2D,
m_atlas);
113 glPixelStorei(GL_PACK_ALIGNMENT,1);
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
119 glPixelStorei(GL_PACK_ALIGNMENT,4);
120 glBindTexture(GL_TEXTURE_2D, 0);
140 auto& g = gi->second;
142 size.x += g.advance.x / wndSize.x;
143 size.y = glm::max(size.y, g.advance.y / wndSize.y);
164 auto& g = gi->second;
166 float localX = x + g.location.x/wndSize.x;
167 float localY = g.location.y/wndSize.y;
169 float localW = g.size.x/wndSize.x;
170 float localH = g.size.y/wndSize.y;
172 x += g.advance.x/wndSize.x;
174 if ( g.size.x == 0 || g.size.y == 0 )
continue;
177 vertices->push_back(vec4( localX, localY, g.texCoord1.x, g.texCoord1.y));
178 vertices->push_back(vec4( localX + localW, localY, g.texCoord2.x, g.texCoord1.y));
179 vertices->push_back(vec4( localX, localY + localH, g.texCoord1.x, g.texCoord2.y));
180 vertices->push_back(vec4( localX, localY + localH, g.texCoord1.x, g.texCoord2.y));
181 vertices->push_back(vec4( localX + localW, localY, g.texCoord2.x, g.texCoord1.y));
182 vertices->push_back(vec4( localX + localW, localY + localH, g.texCoord2.x, g.texCoord2.y));
185 void Font::draw(
string const & text, vec4
const & color, vec2 position,
HAlign hAlign,
VAlign vAlign, vec2
const & scale)
207 glBindTexture(GL_TEXTURE_2D,
m_atlas);
210 shader->
uniform(
"color", color);
211 shader->uniform(
"location", position);
212 shader->uniform(
"scale", scale);
220 , m_shader(app->getShaders().get(
"font"))
222 auto error = FT_Init_FreeType( &
m_ftLib );
225 cerr <<
"ERROR: Could not init freetype-lib." << endl;
232 glBufferData(GL_ARRAY_BUFFER, 0,
nullptr, GL_STREAM_DRAW);
233 glBindBuffer(GL_ARRAY_BUFFER, 0);
235 glGenVertexArrays(1, &
m_vao);
236 glBindVertexArray(
m_vao);
240 glEnableVertexAttribArray(positionIndex);
241 glVertexAttribPointer(positionIndex, 4, GL_FLOAT, GL_FALSE, 0, 0);
243 glBindVertexArray(0);
244 glBindBuffer(GL_ARRAY_BUFFER, 0);
252 glDeleteVertexArrays(1, &
m_vao);
258 stringstream ss; ss << name <<
":" << size;
259 string key = ss.str();
260 auto found =
m_fonts.find(key);
263 return found->second.get();
266 entry.reset(
new Font(
this, name, size));
273 glBindVertexArray(
m_vao);
275 glActiveTexture(GL_TEXTURE0);
279 glBindVertexArray(0);
281 glBindTexture(GL_TEXTURE_2D, 0);
286 glBufferData(GL_ARRAY_BUFFER,
sizeof(vec4)*
m_vertices.size(),
m_vertices.data(), GL_STREAM_DRAW);
287 glBindBuffer(GL_ARRAY_BUFFER, 0);
289 glDrawArrays(GL_TRIANGLES, 0,
m_vertices.size());
void prepare(string const &text)
TextRenderer * m_textRenderer
void draw(string const &text, vec4 const &color, vec2 position, HAlign hAlign=HAlign::Left, VAlign vAlign=VAlign::Bottom, vec2 const &scale=vec2(1, 1))
Font(TextRenderer *textRenderer, string const &fontName, const uint fontSize)
Font * getFont(string const &name, uint const size)
static const uint position
TextRenderer(Application *app)
vec2 const & getSize() const
vector< char > m_atlasData
vec2 measure(string const &text)
vector< vec4 > m_vertices
GLint uniform(string const &name)