7 #include <unordered_map>
31 using std::unordered_map;
54 bool GUIFont::ftInitialized =
false;
55 FT_Library GUIFont::ftLibrary;
57 GUIFont::GUIFont(
const string& pathName,
const string& fileName,
int size): textureAtlas(
"font:" + pathName +
"/" + fileName +
"@" + to_string(size))
60 FileSystem::getInstance()->getContent(pathName, fileName,
ttfData);
65 .flags = FT_OPEN_MEMORY,
67 .memory_size = (int)
ttfData.size(),
75 Console::println(
"GUIFont::parse(): Could not load font: " + pathName +
"/" + fileName);
80 FT_Set_Pixel_Sizes(
ftFace, 0, size);
89 for (
const auto& [charId, character]:
chars)
delete character;
98 Console::println(
"GUIFont::parse(): Could not initialize freetype library");
105 auto font =
new GUIFont(pathName, fileName, size);
106 font->addCharactersToFont(
" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ^0123456789°!"$%&/()=?+*-<>|#,;.:'\"");
114 if (FT_Load_Char(
ftFace, charId, FT_LOAD_RENDER))
116 Console::println(
"GUIFont::addToTextureAtlas(): Could not load glyph: " + Character::toString(charId) +
"(" + to_string(charId) +
")");
121 auto glyphBitmapWidth =
ftFace->glyph->bitmap.width;
122 auto glyphBitmapHeight =
ftFace->glyph->bitmap.rows;
123 auto glyphBitmapBuffer =
ftFace->glyph->bitmap.buffer;
124 auto glyphByteBuffer =
ByteBuffer(glyphBitmapWidth * glyphBitmapHeight * 4);
125 for (
int y = glyphBitmapHeight - 1; y >= 0; y--) {
126 for (
auto x = 0; x < glyphBitmapWidth; x++) {
127 auto v = glyphBitmapBuffer[y * glyphBitmapWidth + x];
128 glyphByteBuffer.put(v);
129 glyphByteBuffer.put(v);
130 glyphByteBuffer.put(v);
131 glyphByteBuffer.put(v == 0?0:(v < 0xff / 2?v * 2:0xff));
136 auto glyphTexture =
new Texture(
137 Character::toString(charId),
138 Texture::TEXTUREDEPTH_RGBA,
139 Texture::TEXTUREFORMAT_RGBA,
140 glyphBitmapWidth, glyphBitmapHeight,
141 glyphBitmapWidth, glyphBitmapHeight,
142 Texture::TEXTUREFORMAT_RGBA,
145 glyphTexture->acquireReference();
148 auto glyphTextureSmoothed = TextureReader::smooth(glyphTexture,
string());
149 glyphTexture->releaseReference();
155 glyphTextureSmoothed->releaseReference();
164 ftFace->glyph->bitmap_left,
166 ftFace->glyph->advance.x >> 6
168 chars[charId] = character;
176 auto renderer = Engine::getInstance()->getRenderer();
177 auto contextIdx = renderer->CONTEXTINDEX_DEFAULT;
180 renderer->bindTexture(contextIdx,
textureId);
187 for (
auto i = 0;; i++) {
189 if (atlasTexture ==
nullptr) {
195 if (character ==
nullptr) {
196 Console::println(
"GUIFont::updateCharacters(): Could not find character for font character '" + atlasTexture->texture->getId() +
"'");
199 character->x = atlasTexture->left;
200 character->y = atlasTexture->top;
201 character->rotated = atlasTexture->orientation == TextureAtlas::AtlasTexture::ORIENTATION_ROTATED;
217 if (length == 0) length = text.
length();
220 for (; u8It.hasNext() ==
true && i < index && i < length; i++) {
221 auto characterId = u8It.next();
223 if (character ==
nullptr)
continue;
224 x += character->getXAdvance();
233 if (length == 0) length = text.
length();
236 for (; u8It.hasNext() ==
true && index < length; index++) {
237 auto characterId = u8It.next();
239 if (character ==
nullptr)
continue;
240 auto xAdvance = character->getXAdvance();
242 if (x - xAdvance / 2 > textX) {
253 for (
auto i = 0; u8It.hasNext() ==
true; i++) {
254 auto characterId = u8It.
next();
256 if (character ==
nullptr)
continue;
257 width += character->getXAdvance();
265 for (
auto i = 0; u8It.hasNext() ==
true; i++) {
266 auto characterId = u8It.
next();
268 if (character ==
nullptr)
continue;
269 x += character->getXAdvance();
270 if (x > width)
return i;
283 float width = character->
getWidth();
287 float textureCharLeft = character->
getX();
288 float textureCharTop = character->
getY();
292 ((left) / (screenWidth / 2.0f)) - 1.0f,
293 ((screenHeight - top) / (screenHeight / 2.0f)) - 1.0f,
294 color[0], color[1], color[2], color[3],
295 textureCharLeft / textureWidth, textureCharTop / textureHeight,
296 ((left + width) / (screenWidth / 2.0f)) - 1.0f,
297 ((screenHeight - top) / (screenHeight / 2.0f)) - 1.0f,
298 color[0], color[1], color[2], color[3],
299 (textureCharLeft + textureCharWidth) / textureWidth, textureCharTop / textureHeight,
300 ((left + width) / (screenWidth / 2.0f)) - 1.0f,
301 ((screenHeight - top - height) / (screenHeight / 2.0f)) - 1.0f,
302 color[0], color[1], color[2], color[3],
303 (textureCharLeft + textureCharWidth) / textureWidth,
304 (textureCharTop + textureCharHeight) / textureHeight,
305 ((left) / (screenWidth / 2.0f)) - 1.0f, ((screenHeight - top - height) / (screenHeight / 2.0f)) - 1.0f,
306 color[0], color[1], color[2], color[3],
307 (textureCharLeft) / textureWidth,
308 (textureCharTop + textureCharHeight) / textureHeight,
325 ((left) / (screenWidth / 2.0f)) - 1.0f,
326 ((screenHeight - top) / (screenHeight / 2.0f)) - 1.0f,
327 color[0], color[1], color[2], color[3],
329 ((left + width) / (screenWidth / 2.0f)) - 1.0f,
330 ((screenHeight - top) / (screenHeight / 2.0f)) - 1.0f,
331 color[0], color[1], color[2], color[3],
333 ((left + width) / (screenWidth / 2.0f)) - 1.0f,
334 ((screenHeight - top - height) / (screenHeight / 2.0f)) - 1.0f,
335 color[0], color[1], color[2], color[3],
337 ((left) / (screenWidth / 2.0f)) - 1.0f, ((screenHeight - top - height) / (screenHeight / 2.0f)) - 1.0f,
338 color[0], color[1], color[2], color[3],
349 auto inSelection =
false;
350 auto currentColor = color;
351 auto currentBackgroundColor = backgroundColor;
352 if (selectionStartIndex != -1 && selectionEndIndex != -1) {
356 for (
auto i = offset; u8It.hasNext() ==
true && (length == 0 || i < length); i++) {
357 auto characterId = u8It.next();
359 if (character ==
nullptr)
continue;
360 auto currentInSelection = i >= selectionStartIndex && i < selectionEndIndex;
361 if (currentInSelection != inSelection) {
363 inSelection = currentInSelection;
364 currentColor = inSelection ==
true?backgroundColor:color;
365 currentBackgroundColor = inSelection ==
true?color:backgroundColor;
368 currentX += character->getXAdvance();
377 for (
auto i = offset; u8It.hasNext() ==
true && (length == 0 || i < length); i++) {
378 auto characterId = u8It.next();
380 if (character ==
nullptr)
continue;
381 auto currentInSelection = i >= selectionStartIndex && i < selectionEndIndex;
382 if (currentInSelection != inSelection) {
385 inSelection = currentInSelection;
386 currentColor = inSelection ==
true?backgroundColor:color;
387 currentBackgroundColor = inSelection ==
true?color:backgroundColor;
390 currentX += character->getXAdvance();
void drawString(GUIRenderer *guiRenderer, int x, int y, const MutableString &text, int offset, int length, const GUIColor &color, int selectionStartIndex=-1, int selectionEndIndex=-1, const GUIColor &backgroundColor=GUIColor::GUICOLOR_TRANSPARENT)
Draw string.
GUICharacter * getCharacter(uint32_t charId)
Get character defintion.
unordered_map< uint32_t, GUICharacter * > chars
GUICharacter * addToTextureAtlas(uint32_t charId)
Add character with given id to texture atlas.
void drawCharacter(GUIRenderer *guiRenderer, GUICharacter *character, int x, int y, const GUIColor &color=GUIColor::GUICOLOR_WHITE)
Draw character.
void drawCharacterBackground(GUIRenderer *guiRenderer, GUICharacter *character, int x, int y, int lineHeight, const GUIColor &color)
Draw background.
vector< uint8_t > ttfData
int getTextIndexX(const MutableString &text, int offset, int length, int index)
Get text index X of given text and index.
int getTextIndexByX(const MutableString &text, int offset, int length, int textX)
Get text index by text and X in space of text.
void updateFontInternal()
Do the update work.
static bool ftInitialized
static FT_Library ftLibrary
TextureAtlas textureAtlas
GUIFont(const string &pathName, const string &fileName, int size)
Public constructor.
static GUIFont * parse(const string &pathName, const string &fileName, int size)
Parse the font definition file.
void updateFont()
Update font texture atlas and character definitions.
int getTextIndexXAtWidth(const MutableString &text, int width)
Get text index X at width.
int getTextWidth(const MutableString &text)
Text width.
void bindTexture(int32_t textureId)
Bind texture.
GUIScreenNode * getScreenNode()
void addQuad(float x1, float y1, float colorR1, float colorG1, float colorB1, float colorA1, float tu1, float tv1, float x2, float y2, float colorR2, float colorG2, float colorB2, float colorA2, float tu2, float tv2, float x3, float y3, float colorR3, float colorG3, float colorB3, float colorA3, float tu3, float tv3, float x4, float y4, float colorR4, float colorG4, float colorB4, float colorA4, float tu4, float tv4, bool solidColor=false, bool rotated=false)
Add quad Note: quad vertices order 1 2 +-—+ | | | | +-—+ 4 3.
void setFontColor(const GUIColor &color)
Set effect color mul.
File system singleton class.
Mutable utf8 aware string class.
const UTF8CharacterIterator getUTF8CharacterIterator() const
const AtlasTexture * getAtlasTexture(int textureIdx)
Returns specific atlas texture information within atlas.
int addTexture(Texture *texture)
Add texture.
void update()
Update texture atlas.
UTF8 string character iterator.
void seekCharacterPosition(int position) const
Seek character position.
std::exception Exception
Exception base class.