/* * 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 { std::pair FontAtlasGeneratorBase::InitFreetype(const std::variant>& source) { FT_Library library; auto error = FT_Init_FreeType(&library); if (error) { throw std::runtime_error(fmt::format("Could not initalize freetype library. {}", GetFreetypeErrorDescription(error))); } FT_Face face; if (std::holds_alternative(source)) { error = FT_New_Face(library, std::get<0>(source).c_str(), 0, &face); } else { auto& arr = std::get<1>(source); error = FT_New_Memory_Face(library, (const FT_Byte*) (arr.Data()), arr.Size(), 0, &face); } if (error == FT_Err_Unknown_File_Format) { throw std::runtime_error("Unknown font file format\n"); } else if (error) { throw std::runtime_error(fmt::format("Font file could not be opened or read or it's corrupted. {}", GetFreetypeErrorDescription(error))); } // some fancy font without unicode charmap if (face->charmap == nullptr) { throw std::runtime_error("Selected font doesn't contain unicode charmap"); } return { FtLibraryRecPtr(library), FtFaceRecPtr(face) }; } 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; } std::set FontAtlasGeneratorBase::LoadAllGlyphs(const std::variant>& data) { const auto& [lib, face] = InitFreetype(data); std::set s; FT_UInt glyphIndex; FT_ULong unicode = FT_Get_First_Char(face.get(), &glyphIndex); while (glyphIndex != 0) { s.insert(unicode); unicode = FT_Get_Next_Char(face.get(), unicode, &glyphIndex); } return s; } }