Files
OpenVulkano/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.cpp
2025-03-01 20:00:27 +01:00

97 lines
2.8 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "FontAtlasGeneratorBase.hpp"
#include "FontAtlas.hpp"
#include "Base/Logger.hpp"
#include <filesystem>
namespace OpenVulkano::Scene
{
std::pair<FtLibraryRecPtr, FtFaceRecPtr>
FontAtlasGeneratorBase::InitFreetype(const std::span<const uint8_t>& data)
{
std::pair<FtLibraryRecPtr, FtFaceRecPtr> result;
FT_Library library;
auto error = FT_Init_FreeType(&library);
if (error)
{
throw std::runtime_error(fmt::format("Could not initialize freetype library. Error: {}", GetFreetypeErrorDescription(error)));
}
result.first = FtLibraryRecPtr(library);
FT_Face face;
error = FT_New_Memory_Face(library, data.data(), data.size(), 0, &face);
if (error)
{
if (error == FT_Err_Unknown_File_Format) throw std::runtime_error("Unknown font file format");
throw std::runtime_error(fmt::format("Font file could not be read or is corrupted. Error: {}", GetFreetypeErrorDescription(error)));
}
result.second = FtFaceRecPtr(face);
// some fancy font without unicode charmap
if (face->charmap == nullptr)
{
throw std::runtime_error("Selected font doesn't contain unicode charmap");
}
return result;
}
std::string FontAtlasGeneratorBase::GetFreetypeErrorDescription(FT_Error error)
{
if (const char* s = FT_Error_String(error))
{
return s;
}
return fmt::format("Error code is {}", error);
}
void FontAtlasGeneratorBase::SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size,
const Math::AABB& aabb, double advance)
{
const auto& resolution = m_atlasData->GetTexture()->resolution;
const double l = aabb.min.x;
const double r = aabb.max.x;
const double t = aabb.max.y;
const double b = aabb.min.y;
info.pos[0].x = bearing.x;
info.pos[0].y = size.y - bearing.y;
info.uv[0].x = l / resolution.x;
info.uv[0].y = b / resolution.y;
info.pos[1].x = bearing.x + size.x;
info.pos[1].y = size.y - bearing.y;
info.uv[1].x = r / resolution.x;
info.uv[1].y = b / resolution.y;
info.pos[2].x = bearing.x + size.x;
info.pos[2].y = bearing.y;
info.uv[2].x = r / resolution.x;
info.uv[2].y = t / resolution.y;
info.pos[3].x = bearing.x;
info.pos[3].y = bearing.y;
info.uv[3].x = l / resolution.x;
info.uv[3].y = t / resolution.y;
info.advance = advance;
}
size_t FontAtlasGeneratorBase::LoadAllGlyphs(std::set<uint32_t>& chars, const FtFaceRecPtr& face)
{
chars.clear();
FT_UInt glyphIndex;
FT_ULong unicode = FT_Get_First_Char(face.get(), &glyphIndex);
while (glyphIndex != 0)
{
chars.insert(unicode);
unicode = FT_Get_Next_Char(face.get(), unicode, &glyphIndex);
}
return chars.size();
}
}