1#ifndef CSCI441_FONT_HPP
2#define CSCI441_FONT_HPP
30 explicit Font(
const char* filename);
40 [[nodiscard]] GLboolean
isLoaded()
const {
return _loaded; }
48 void setScale(GLfloat scaleX, GLfloat scaleY);
64 void draw(
const char* str, GLfloat x, GLfloat y)
const;
96 FT_Library _ftLibrary;
114 struct CharacterInfo {
146 } _fontCharacters[128];
163 if(FT_Init_FreeType(&_ftLibrary)) {
164 fprintf(stderr,
"[font | ERROR]: Could not init freetype library\n");
168 if(FT_New_Face(_ftLibrary, filename, 0, &_fontFace)) {
169 fprintf(stderr,
"[font | ERROR]: Could not open font\n");
173 FT_Set_Pixel_Sizes(_fontFace, 0, 20);
175 const auto g = _fontFace->glyph;
179 for(
int i = 32; i < 128; i++) {
180 if(FT_Load_Char(_fontFace, i, FT_LOAD_RENDER)) {
181 fprintf(stderr,
"[font | ERROR]: Loading character %c failed!\n", i);
185 w += g->bitmap.width;
186 h = (h > g->bitmap.rows ? h : g->bitmap.rows);
193 glActiveTexture(GL_TEXTURE0);
194 glGenTextures(1, &_texHandle);
195 glBindTexture(GL_TEXTURE_2D, _texHandle);
196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
199 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
200 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
201 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
205 for(
int i = 32; i < 128; i++) {
206 if(FT_Load_Char(_fontFace, i, FT_LOAD_RENDER))
209 _fontCharacters[i].ax =
static_cast<GLfloat
>( g->advance.x >> 6 );
210 _fontCharacters[i].ay =
static_cast<GLfloat
>( g->advance.y >> 6 );
212 _fontCharacters[i].bw =
static_cast<GLfloat
>( g->bitmap.width );
213 _fontCharacters[i].bh =
static_cast<GLfloat
>( g->bitmap.rows );
215 _fontCharacters[i].bl =
static_cast<GLfloat
>( g->bitmap_left );
216 _fontCharacters[i].bt =
static_cast<GLfloat
>( g->bitmap_top );
218 _fontCharacters[i].tx =
static_cast<GLfloat
>(x) /
static_cast<GLfloat
>(w);
220 glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);
222 x += g->bitmap.width;
225 glGenVertexArrays(1, &_vao);
226 glBindVertexArray(_vao);
227 glGenBuffers(1, &_vbo);
228 glBindBuffer(GL_ARRAY_BUFFER, _vbo);
229 glEnableVertexAttribArray(0);
230 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0,
nullptr);
236 glDeleteVertexArrays(1, &_vao);
237 glDeleteBuffers(1, &_vbo);
238 glDeleteTextures(1, &_texHandle);
239 FT_Done_Face(_fontFace);
240 FT_Done_FreeType(_ftLibrary);
244 if (_scaleX > 0 && _scaleY > 0) {
251 glBindVertexArray(_vao);
252 glBindBuffer(GL_ARRAY_BUFFER, _vbo);
253 glActiveTexture(GL_TEXTURE0);
254 glBindTexture(GL_TEXTURE_2D, _texHandle);
263 } coords[6 * strlen(str)];
267 for(
const char *p = str; *p; p++) {
268 const auto characterIndex =
static_cast<int>(*p);
269 const auto character = _fontCharacters[characterIndex];
270 const auto x2 = x + character.bl * _scaleX;
271 const auto y2 = -y - character.bt * _scaleY;
272 const auto w = character.bw * _scaleX;
273 const auto h = character.bh * _scaleY;
276 x += character.ax * _scaleX;
277 y += character.ay * _scaleY;
283 coords[n++] = (FontPoint){x2, -y2 , character.tx, 0};
284 coords[n++] = (FontPoint){x2 + w, -y2 , character.tx + character.bw / _atlasWidth, 0};
285 coords[n++] = (FontPoint){x2, -y2 - h, character.tx, character.bh / _atlasHeight};
287 coords[n++] = (FontPoint){x2 + w, -y2 , character.tx + character.bw / _atlasWidth, 0};
288 coords[n++] = (FontPoint){x2, -y2 - h, character.tx, character.bh / _atlasHeight};
289 coords[n++] = (FontPoint){x2 + w, -y2 - h, character.tx + character.bw / _atlasWidth, character.bh / _atlasHeight};
291 glBufferData(GL_ARRAY_BUFFER,
sizeof( coords ), coords, GL_DYNAMIC_DRAW);
292 glDrawArrays(GL_TRIANGLES, 0, n);
Stores character glyphs corresponding to a ttf file and draws text to the screen.
Definition: Font.hpp:19
GLboolean isLoaded() const
tracks if font file was loaded successfully
Definition: Font.hpp:40
~Font()
cleanup CPU and GPU memory
Definition: Font.hpp:235
Font()=delete
do not allow default Font objects to be constructed
void draw(const char *str, GLfloat x, GLfloat y) const
draws a text string at a given (x,y) window coordinate with the currently set scale
Definition: Font.hpp:257
void bind() const
make this font active, binding its VAO, VBO, and 2D texture to GL_TEXTURE0
Definition: Font.hpp:250
void setScale(GLfloat scaleX, GLfloat scaleY)
set the amount to scale each glyph when drawing
Definition: Font.hpp:243
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17