Text Rendering
This commit is contained in:
97
Engine/Src/Imp/CPP/FontManager.cpp
Normal file
97
Engine/Src/Imp/CPP/FontManager.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <FontManager.hpp>
|
||||
|
||||
#include <Renderer/GPUResourceManager.hpp>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
Map<String, FontManager::Font> 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<UINT8> 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<UINT8>(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<UINT32>(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
|
||||
Reference in New Issue
Block a user