1#ifndef CSCI441_FONT_HPP
2#define CSCI441_FONT_HPP
10#include "LogUtils.hpp"
32 explicit Font(
const char* filename);
42 [[nodiscard]] GLboolean
isLoaded()
const {
return _loaded; }
50 void setScale(GLfloat scaleX, GLfloat scaleY);
66 void draw(
const char* str, GLfloat x, GLfloat y)
const;
98 FT_Library _ftLibrary;
116 struct CharacterInfo {
148 } _fontCharacters[128];
165 if(FT_Init_FreeType(&_ftLibrary)) {
170 if(FT_New_Face(_ftLibrary, filename, 0, &_fontFace)) {
175 FT_Set_Pixel_Sizes(_fontFace, 0, 20);
177 const auto g = _fontFace->glyph;
181 for(
int i = 32; i < 128; i++) {
182 if(FT_Load_Char(_fontFace, i, FT_LOAD_RENDER)) {
187 w += g->bitmap.width;
188 h = (h > g->bitmap.rows ? h : g->bitmap.rows);
195 glActiveTexture(GL_TEXTURE0);
196 glGenTextures(1, &_texHandle);
197 glBindTexture(GL_TEXTURE_2D, _texHandle);
198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
199 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
202 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
203 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED,
static_cast<GLsizei
>(w),
static_cast<GLsizei
>(h), 0, GL_RED, GL_UNSIGNED_BYTE,
nullptr);
207 for(
int i = 32; i < 128; i++) {
208 if(FT_Load_Char(_fontFace, i, FT_LOAD_RENDER))
211 _fontCharacters[i].ax =
static_cast<GLfloat
>( g->advance.x >> 6 );
212 _fontCharacters[i].ay =
static_cast<GLfloat
>( g->advance.y >> 6 );
214 _fontCharacters[i].bw =
static_cast<GLfloat
>( g->bitmap.width );
215 _fontCharacters[i].bh =
static_cast<GLfloat
>( g->bitmap.rows );
217 _fontCharacters[i].bl =
static_cast<GLfloat
>( g->bitmap_left );
218 _fontCharacters[i].bt =
static_cast<GLfloat
>( g->bitmap_top );
220 _fontCharacters[i].tx =
static_cast<GLfloat
>(x) /
static_cast<GLfloat
>(w);
222 glTexSubImage2D(GL_TEXTURE_2D, 0,
static_cast<GLint
>(x), 0,
static_cast<GLint
>(g->bitmap.width),
static_cast<GLint
>(g->bitmap.rows), GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);
224 x += g->bitmap.width;
227 glGenVertexArrays(1, &_vao);
228 glBindVertexArray(_vao);
229 glGenBuffers(1, &_vbo);
230 glBindBuffer(GL_ARRAY_BUFFER, _vbo);
231 glEnableVertexAttribArray(0);
232 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0,
nullptr);
238 glDeleteVertexArrays(1, &_vao);
239 glDeleteBuffers(1, &_vbo);
240 glDeleteTextures(1, &_texHandle);
241 FT_Done_Face(_fontFace);
242 FT_Done_FreeType(_ftLibrary);
246 if (_scaleX > 0 && _scaleY > 0) {
253 glBindVertexArray(_vao);
254 glBindBuffer(GL_ARRAY_BUFFER, _vbo);
255 glActiveTexture(GL_TEXTURE0);
256 glBindTexture(GL_TEXTURE_2D, _texHandle);
266 const auto coords = (FontPoint*)malloc(
sizeof(FontPoint) * 6 * strlen(str));
270 for(
const char *p = str; *p; p++) {
271 const auto characterIndex =
static_cast<int>(*p);
272 const auto character = _fontCharacters[characterIndex];
273 const auto x2 = x + character.bl * _scaleX;
274 const auto y2 = -y - character.bt * _scaleY;
275 const auto w = character.bw * _scaleX;
276 const auto h = character.bh * _scaleY;
279 x += character.ax * _scaleX;
280 y += character.ay * _scaleY;
286 coords[n++] = (FontPoint){x2, -y2 , character.tx, 0};
287 coords[n++] = (FontPoint){x2 + w, -y2 , character.tx + character.bw /
static_cast<GLfloat
>(_atlasWidth), 0};
288 coords[n++] = (FontPoint){x2, -y2 - h, character.tx, character.bh /
static_cast<GLfloat
>(_atlasHeight)};
290 coords[n++] = (FontPoint){x2 + w, -y2 , character.tx + character.bw /
static_cast<GLfloat
>(_atlasWidth), 0};
291 coords[n++] = (FontPoint){x2, -y2 - h, character.tx, character.bh /
static_cast<GLfloat
>(_atlasHeight)};
292 coords[n++] = (FontPoint){x2 + w, -y2 - h, character.tx + character.bw /
static_cast<GLfloat
>(_atlasWidth), character.bh /
static_cast<GLfloat
>(_atlasHeight)};
294 glBufferData(GL_ARRAY_BUFFER,
static_cast<GLsizeiptr
>(
sizeof(FontPoint) * 6 * strlen(str)), coords, GL_DYNAMIC_DRAW);
295 glDrawArrays(GL_TRIANGLES, 0, n);
Stores character glyphs corresponding to a ttf file and draws text to the screen.
Definition: Font.hpp:21
GLboolean isLoaded() const
tracks if font file was loaded successfully
Definition: Font.hpp:42
~Font()
cleanup CPU and GPU memory
Definition: Font.hpp:237
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:259
void bind() const
make this font active, binding its VAO, VBO, and 2D texture to GL_TEXTURE0
Definition: Font.hpp:252
void setScale(GLfloat scaleX, GLfloat scaleY)
set the amount to scale each glyph when drawing
Definition: Font.hpp:245
void logError(const char *MSG,...)
log a message to both the standard error stream and file
Definition: LogUtils.hpp:128
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17