add opportunity to pack atlas and meta data in same file
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
#include "FontAtlasGenerator.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include "Scene/AtlasMetadata.hpp"
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include <fstream>
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
@@ -14,7 +16,41 @@ namespace OpenVulkano::Scene
|
||||
using namespace msdfgen;
|
||||
using namespace msdf_atlas;
|
||||
|
||||
void FontAtlasGenerator::GenerateAtlas(const std::string& fontFile, const Charset& charset, const std::optional<std::string>& pngOutput)
|
||||
Charset FontAtlasGenerator::LoadAllGlyphs(const std::variant<std::string, Array<char>>& data)
|
||||
{
|
||||
FT_Library library;
|
||||
auto error = FT_Init_FreeType(&library);
|
||||
if (error) { throw std::runtime_error("Could not initalize freetype library\n"); }
|
||||
FT_Face face;
|
||||
if (std::holds_alternative<std::string>(data))
|
||||
{
|
||||
error = FT_New_Face(library, std::get<0>(data).c_str(), 0, &face);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& arr = std::get<1>(data);
|
||||
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("Font file could not be opened or read or it's corrupted\n"); }
|
||||
|
||||
// some fancy font without unicode charmap
|
||||
if (face->charmap == nullptr) { throw std::runtime_error("Selected font doesn't contain unicode charmap"); }
|
||||
Charset s;
|
||||
FT_UInt glyphIndex;
|
||||
FT_ULong unicode = FT_Get_First_Char(face, &glyphIndex);
|
||||
while (glyphIndex != 0)
|
||||
{
|
||||
s.add(unicode);
|
||||
unicode = FT_Get_Next_Char(face, unicode, &glyphIndex);
|
||||
}
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(library);
|
||||
return s;
|
||||
}
|
||||
|
||||
void FontAtlasGenerator::GenerateAtlas(const std::string& fontFile, const Charset& charset,
|
||||
const std::optional<std::string>& pngOutput)
|
||||
{
|
||||
if (charset.empty())
|
||||
{
|
||||
@@ -47,20 +83,43 @@ namespace OpenVulkano::Scene
|
||||
Generate(ft, font, charset, pngOutput);
|
||||
}
|
||||
|
||||
void FontAtlasGenerator::SaveAtlasMetadataInfo(const std::string& outputFile) const
|
||||
void FontAtlasGenerator::SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile) const
|
||||
{
|
||||
if (m_symbols.empty())
|
||||
{
|
||||
{
|
||||
Logger::DATA->info("No glyphs loaded. Nothing to save.");
|
||||
return;
|
||||
}
|
||||
std::fstream fs(outputFile.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
|
||||
std::string fileName = outputFile;
|
||||
int extraMode = std::ios_base::trunc;
|
||||
uint32_t packedFlag = 0;
|
||||
if (packIntoSingleFile)
|
||||
{
|
||||
size_t ext = outputFile.find_last_of('.');
|
||||
if (ext == std::string::npos)
|
||||
{
|
||||
fileName += "_packed";
|
||||
}
|
||||
else
|
||||
{
|
||||
fileName.insert(ext - 1, "_packed");
|
||||
}
|
||||
savePng(m_generator.atlasStorage(), fileName.c_str());
|
||||
extraMode = std::ios_base::app;
|
||||
packedFlag = 1;
|
||||
}
|
||||
std::fstream fs(fileName.c_str(), std::ios_base::out | std::ios_base::binary | extraMode);
|
||||
fs.write(reinterpret_cast<const char*>(&m_meta), sizeof(AtlasMetadata));
|
||||
uint64_t metadataBytes = sizeof(AtlasMetadata);
|
||||
for (const auto& [key, val] : m_symbols)
|
||||
{
|
||||
{
|
||||
fs.write(reinterpret_cast<const char*>(&key), sizeof(uint32_t));
|
||||
fs.write(reinterpret_cast<const char*>(&val), sizeof(GlyphInfo));
|
||||
metadataBytes += sizeof(uint32_t);
|
||||
metadataBytes += sizeof(GlyphInfo);
|
||||
}
|
||||
fs.write(reinterpret_cast<const char*>(&metadataBytes), sizeof(uint64_t));
|
||||
fs.write(reinterpret_cast<const char*>(&packedFlag), sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void FontAtlasGenerator::Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset,
|
||||
@@ -77,7 +136,10 @@ namespace OpenVulkano::Scene
|
||||
int width = 1024, height = 1024;
|
||||
packer.setDimensions(width, height);
|
||||
// more value - more sdf impact
|
||||
packer.setPixelRange(26.0);
|
||||
// this setup is tricky. with low value and large amount of characters visible artifacts (extra lines) may appear.
|
||||
// with high value and large amount of characters sdf deals huge impact and characters are not readable anymore.
|
||||
const double pixelRange = std::min((width / (double)chset.size()) * 3, 26.0);
|
||||
packer.setPixelRange(pixelRange);
|
||||
packer.setMiterLimit(1.0);
|
||||
packer.pack(glyphsGeometry.data(), glyphsGeometry.size());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user