// IAEngine: 2D Game Engine by IA // Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include #include #include #include FT_FREETYPE_H namespace ia::iae { Map FontManager::s_fonts; FT_Library g_freetype; VOID FontManager::Initialize() { if (FT_Init_FreeType(&g_freetype)) THROW_UNKNOWN("Failed to initialize the FreeType font library"); LoadFont("Roboto", "Resources/Fonts/Roboto-Black.ttf"); } VOID FontManager::Terminate() { for(const auto& f: s_fonts) { for(const auto& t: f->Value.Chars) GPUResourceManager::DestroyTexture(t.Texture); } FT_Done_FreeType(g_freetype); } VOID FontManager::LoadFont(IN CONST String &name, IN CONST String &path) { STATIC Vector GLYPH_PIXEL_DATA; Font result; const auto fontSize = 16; FT_Face face; if (FT_New_Face(g_freetype, path.c_str(), 0, &face)) THROW_UNKNOWN("Failed to load the TrueType font '", path, "'"); FT_Set_Pixel_Sizes(face, 0, fontSize); const auto charCount = static_cast(sizeof(result.Chars) / sizeof(result.Chars[0])); for (UINT8 c = 0; c < charCount; c++) { if (FT_Load_Char(face, c, FT_LOAD_RENDER)) THROW_UNKNOWN("Failed to load character '", (CHAR) c, "' of TrueType font '", path, "'"); const auto glyphSize = face->glyph->bitmap.pitch * face->glyph->bitmap.rows; if(!glyphSize) continue; GLYPH_PIXEL_DATA.clear(); GLYPH_PIXEL_DATA.resize(glyphSize << 2); for(SIZE_T t = 0; t < glyphSize; t++) { const auto pi= t<<2; const auto p = face->glyph->bitmap.buffer[t]; GLYPH_PIXEL_DATA[pi + 0] = p; GLYPH_PIXEL_DATA[pi + 1] = p; GLYPH_PIXEL_DATA[pi + 2] = p; GLYPH_PIXEL_DATA[pi + 3] = p; } result.Chars[c] = { IVec2(face->glyph->bitmap.width, face->glyph->bitmap.rows), IVec2(face->glyph->bitmap_left, face->glyph->bitmap_top), static_cast(face->glyph->advance.x) >> 6, GPUResourceManager::CreateTexture(SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET, face->glyph->bitmap.width, face->glyph->bitmap.rows, GLYPH_PIXEL_DATA.data()), }; } FT_Done_Face(face); s_fonts[name] = IA_MOVE(result); } } // namespace ia::iae