// 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