/* * 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 namespace OpenVulkano::Scene { void IFontAtlasGenerator::GenerateAtlas(const std::filesystem::path& fontFile, const std::set& charset) { GenerateAtlas(Utils::ReadFile(fontFile), charset); } std::pair FontAtlasGeneratorBase::InitFreetype(const std::span& data) { std::pair 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& 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(); } }