Bubba-3D  0.9.0
Awesome game engine!
FontManager.cpp
1 /*
2  * This file is part of Bubba-3D.
3  *
4  * Bubba-3D is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Bubba-3D is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with Bubba-3D. If not, see http://www.gnu.org/licenses/.
16  */
17 //
18 // Created by simon on 2016-03-11.
19 //
20 
21 #include <string>
22 #include <vector>
23 #include <cmath>
24 
25 #include <FontManager.h>
26 #include <stdexcept>
27 #include <Logger.h>
28 #include <GL/glew.h>
29 #include <functional>
30 #include <Font.h>
31 
32 #include <ft2build.h>
33 #include <glutil/glutil.h>
34 #include <Globals.h>
35 #include FT_FREETYPE_H
36 
37 
38 using namespace std;
39 
41  return getTex(false);
42 }
43 
44 GLuint* FontManager::getTex(bool force) {
45  if(!force && !initiated)
46  throw logic_error("Bad state: FontManager hasn't loaded any fonts yet.");
47 
48  static GLuint h = 0;
49  return &h;
50 }
51 
52 bool FontManager::FontDefinition::operator== (FontDefinition fd) const {
53  return fd.face == face && fd.pixelSize == pixelSize;
54 }
55 
56 std::string FontManager::FontDefinition::getFace() const {
57  return face;
58 }
59 
60 int FontManager::FontDefinition::getPixelSize() const {
61  return pixelSize;
62 }
63 
65 
66  static FontManager instance; // Guaranteed to be destroyed.
67  // Instantiated on first use.
68  return &instance;
69 
70 }
71 
72 FontManager::FontDefinition::FontDefinition(std::string face, int pixelSize) : face(face), pixelSize(pixelSize){ }
73 
74 Font* FontManager::loadAndFetchFont(std::string fontFace, int pixelSize) {
75  FontDefinition locate = FontDefinition(fontFace,pixelSize);
76  auto it = loadedFonts.find(locate);
77  if(it == loadedFonts.end()) {
78  loadFont(fontFace, pixelSize);
79  return loadedFonts.find(locate)->second;
80  }else
81  return it->second;
82 }
83 
84 void FontManager::loadFont(std::string fontFace, int pixelSize) {
85 
86  FontDefinition newFont = FontDefinition(fontFace,pixelSize);
87  loadedFonts.insert(std::pair<FontDefinition,Font*>(newFont,new Font(pixelSize)));
88 
89  unsigned int *width = (unsigned int*)calloc(sizeof(unsigned int),1);
90  unsigned int *height = (unsigned int*)calloc(sizeof(unsigned int),1);
91  *width = atlasWidth;
92  *height = atlasHeight;
93 
94  iterateGlyphs(newFont,width,height);
95 
96  atlasWidth = *width;
97  atlasHeight = *height;
98 
99  initTexture();
100 
101  drawGlyphs();
102 
103  Globals::set(Globals::FONT_TEXTURE_WIDTH,*width);
104  Globals::set(Globals::FONT_TEXTURE_HEIGHT,*height);
105 
106 }
107 
108 void FontManager::initTexture() {
109  GLuint* tex = getTex(true);
110 
111  if(initiated)
112  glDeleteTextures(1,tex);
113  else
114  initiated = true;
115 
116  glActiveTexture(GL_TEXTURE4);
117  glGenTextures(1, tex);
118  glBindTexture(GL_TEXTURE_2D, *tex);
119  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
120 
121  glTexStorage2D(GL_TEXTURE_2D,1,GL_R8,atlasWidth,atlasHeight);
122 }
123 
124 void FontManager::iterateGlyphs(FontDefinition def, unsigned int* width, unsigned int* height) {
125 
126  FT_Face face = (FT_Face)malloc(sizeof(FT_Face));
127 
128  if(int error = FT_New_Face(*ft_library,def.face.c_str(),0,&face)){
129  Logger::logError("Failed loading face '" + def.face + "'. Error code: " + std::to_string(error));
130  return;
131  }
132  FT_Set_Pixel_Sizes(face,0,def.pixelSize);
133  FT_GlyphSlot glyph = face->glyph;
134 
135  for(unsigned char c = 32; c < 128; c++){
136 
137  if(int error = FT_Load_Char(face,c,FT_LOAD_RENDER)){
138  Logger::logError("Failed loading char '" + std::to_string(c) + "'. Error code: " + std::to_string(error));
139  continue;
140  }
141 
142  *height = max(*height,glyph->bitmap.rows);
143  *width += glyph->bitmap.width;
144  }
145 
146 }
147 
148 void FontManager::drawGlyphs() {
149 
150  FT_Face face;
151  int x = 0;
152  for(auto fontIt : loadedFonts){
153 
154  Font* font = fontIt.second;
155  FontDefinition fDef = fontIt.first;
156  if(int error = FT_New_Face(*ft_library,fDef.face.c_str(),0,&face)){
157  Logger::logError("Failed loading face '" + fDef.face
158  + "'. Error code: " + std::to_string(error));
159  continue;
160  }
161  FT_Set_Pixel_Sizes(face,0,fDef.pixelSize);
162  FT_GlyphSlot glyph = face->glyph;
163 
164  for(unsigned char c = 32; c < 128; c++){
165 
166  if(int error = FT_Load_Char(face,c,FT_LOAD_RENDER)){
167  Logger::logError("Failed loading char '" + std::to_string(c)
168  + "'. Error code: " + std::to_string(error));
169  continue;
170  }
171 
172  if (glyph->bitmap.width > 0 && glyph->bitmap.rows > 0) {
173  glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, glyph->bitmap.width, glyph->bitmap.rows,
174  GL_RED, GL_UNSIGNED_BYTE, glyph->bitmap.buffer);
175  CHECK_GL_ERROR();
176  }
177 
178  font->addGlyph(glyph,x,c);
179  x += glyph->bitmap.width;
180 
181  }
182  }
183 }
184 
185 FontManager::FontManager() {
186 
187  ft_library = (FT_Library*)malloc(sizeof(FT_Library));
188  const int error = FT_Init_FreeType(ft_library);
189  if(error != 0) {
190  throw new runtime_error("Could not initiate FreeType. Error code: " + std::to_string(error));
191  }
192 }
193 
194 FontManager::~FontManager() {
195  if (ft_library != nullptr) {
196  free(ft_library);
197  }
198 }
Definition: Font.h:27
Font * loadAndFetchFont(std::string fontFace, int pixelSize)
Definition: FontManager.cpp:74
virtual void loadFont(std::string fontFace, int pixelSize)
Definition: FontManager.cpp:84
GLuint * getTex()
Definition: FontManager.cpp:40
static FontManager * getInstance()
Definition: FontManager.cpp:64