92 lines
3.2 KiB
C++
92 lines
3.2 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 "FontAtlasGenerator.hpp"
|
|
#include "Base/Logger.hpp"
|
|
|
|
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)
|
|
{
|
|
if (charset.empty())
|
|
{
|
|
Logger::RENDER->info("Provided charset is empty. Atlas will not be generated");
|
|
return;
|
|
}
|
|
// TODO: dynamic atlas and add only those symbols which are not present yet in current atlas
|
|
FreetypeHandle* ft = initializeFreetype();
|
|
if (!ft) { throw std::runtime_error("Failed to initialize freetype"); }
|
|
FontHandle* font = loadFont(ft, fontFile.data());
|
|
if (!font)
|
|
{
|
|
deinitializeFreetype(ft);
|
|
throw std::runtime_error(fmt::format("Failed to load font from file {0}", fontFile.data()));
|
|
}
|
|
Generate(ft, font, charset, pngOutput);
|
|
}
|
|
|
|
void FontAtlasGenerator::GenerateAtlas(const msdfgen::byte* fontData, int length, const Charset& charset,
|
|
const std::optional<std::string>& pngOutput)
|
|
{
|
|
FreetypeHandle* ft = initializeFreetype();
|
|
if (!ft) { throw std::runtime_error("Failed to initialize freetype"); }
|
|
FontHandle* font = loadFontData(ft, fontData, length);
|
|
if (!font)
|
|
{
|
|
deinitializeFreetype(ft);
|
|
throw std::runtime_error("Failed to load font data from given buffer");
|
|
}
|
|
Generate(ft, font, charset, pngOutput);
|
|
}
|
|
|
|
void FontAtlasGenerator::Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset,
|
|
const std::optional<std::string>& pngOutput)
|
|
{
|
|
m_symbols.clear();
|
|
std::vector<GlyphGeometry> glyphsGeometry;
|
|
// FontGeometry is a helper class that loads a set of glyphs from a single font.
|
|
FontGeometry fontGeometry(&glyphsGeometry);
|
|
fontGeometry.loadCharset(font, 1, chset);
|
|
|
|
TightAtlasPacker packer;
|
|
packer.setDimensionsConstraint(DimensionsConstraint::SQUARE);
|
|
int width = 1024, height = 1024;
|
|
packer.setDimensions(width, height);
|
|
// more value - more sdf impact
|
|
packer.setPixelRange(26.0);
|
|
packer.setMiterLimit(1.0);
|
|
packer.pack(glyphsGeometry.data(), glyphsGeometry.size());
|
|
|
|
m_generator.resize(width, height);
|
|
GeneratorAttributes attributes;
|
|
m_generator.setAttributes(attributes);
|
|
m_generator.setThreadCount(4);
|
|
m_generator.generate(glyphsGeometry.data(), glyphsGeometry.size());
|
|
|
|
int idx = 0;
|
|
const BitmapConstRef<byte, 1>& storage = m_generator.atlasStorage();
|
|
m_atlasTex.resolution = Math::Vector3ui(storage.width, storage.height, 1);
|
|
m_atlasTex.textureBuffer = (msdfgen::byte*) storage.pixels;
|
|
m_atlasTex.format = OpenVulkano::DataFormat::R8_UNORM;
|
|
m_atlasTex.size = storage.width * storage.height * 1; // 1 channel
|
|
for (const auto& glyph: glyphsGeometry)
|
|
{
|
|
GlyphInfo& info = m_symbols[glyph.getCodepoint()];
|
|
info.geometry = glyph;
|
|
info.glyphBox = m_generator.getLayout()[idx++];
|
|
}
|
|
if (pngOutput && !pngOutput->empty())
|
|
{
|
|
savePng(m_generator.atlasStorage(), pngOutput->c_str());
|
|
}
|
|
destroyFont(font);
|
|
deinitializeFreetype(ft);
|
|
}
|
|
}
|