split font atlas generator to interface and implementation
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "Controller/FreeCamCameraController.hpp"
|
||||
#include "Image/ImageLoaderPng.hpp"
|
||||
#include "Scene/FontAtlasGenerator.hpp"
|
||||
#include "Scene/MsdfFontAtlasGenerator.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -67,7 +68,7 @@ namespace OpenVulkano
|
||||
m_drawablesPool.resize(N);
|
||||
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
Charset charset = FontAtlasGenerator::LoadAllGlyphs(fontPath);
|
||||
Charset charset = MsdfFontAtlasGenerator::LoadAllGlyphs(fontPath);
|
||||
//Charset charset = Charset::ASCII;
|
||||
//for (unicode_t c = 0x0410; c <= 0x041F; c++)
|
||||
//{
|
||||
@@ -133,7 +134,7 @@ namespace OpenVulkano
|
||||
PerspectiveCamera m_cam;
|
||||
OpenVulkano::FreeCamCameraController m_camController;
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
FontAtlasGenerator m_atlasGenerator;
|
||||
MsdfFontAtlasGenerator m_atlasGenerator;
|
||||
#endif
|
||||
std::vector<SimpleDrawable*> m_drawablesPool;
|
||||
std::vector<Node> m_nodesPool;
|
||||
|
||||
@@ -6,47 +6,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __has_include("msdfgen.h")
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <map>
|
||||
#include <variant>
|
||||
#include "Scene/AtlasMetadata.hpp"
|
||||
#include "Scene/Texture.hpp"
|
||||
#include "msdfgen.h"
|
||||
#include "msdfgen-ext.h"
|
||||
#include "msdf-atlas-gen/msdf-atlas-gen.h"
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
using namespace msdfgen;
|
||||
using namespace msdf_atlas;
|
||||
using namespace OpenVulkano::Scene;
|
||||
|
||||
class FontAtlasGenerator
|
||||
{
|
||||
public:
|
||||
using SdfGenerator = ImmediateAtlasGenerator<float, 1, sdfGenerator, BitmapAtlasStorage<msdfgen::byte, 1>>;
|
||||
static Charset LoadAllGlyphs(const std::variant<std::string, Array<char>>& data);
|
||||
void GenerateAtlas(const std::string& fontFile, const Charset& charset = Charset::ASCII,
|
||||
const std::optional<std::string>& pngOutput = std::nullopt);
|
||||
void GenerateAtlas(const msdfgen::byte* fontData, int length, const Charset& charset = Charset::ASCII,
|
||||
const std::optional<std::string>& pngOutput = std::nullopt);
|
||||
void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const;
|
||||
const Texture& GetAtlas() const { return m_atlasTex; }
|
||||
std::map<uint32_t, GlyphInfo>& GetGlyphsInfo() { return m_symbols; }
|
||||
AtlasMetadata& GetAtlasMetadata() { return m_meta; }
|
||||
SdfGenerator& GetFontAtlsGenerator() { return m_generator; }
|
||||
private:
|
||||
void Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset,
|
||||
const std::optional<std::string>& pngOutput);
|
||||
void SavePng(const BitmapConstRef<byte, 1>& storage, const std::string& output, int channels) const;
|
||||
private:
|
||||
SdfGenerator m_generator;
|
||||
Texture m_atlasTex;
|
||||
AtlasMetadata m_meta;
|
||||
std::map<uint32_t, GlyphInfo> m_symbols;
|
||||
virtual void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
||||
const std::optional<std::string>& pngOutput = std::nullopt) = 0;
|
||||
virtual void GenerateAtlas(const Array<char>& fontData, int length, const std::set<uint32_t>& charset,
|
||||
const std::optional<std::string>& pngOutput = std::nullopt) = 0;
|
||||
virtual void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const = 0;
|
||||
virtual const Texture& GetAtlas() const = 0;
|
||||
virtual std::map<uint32_t, GlyphInfo>& GetGlyphsInfo() = 0;
|
||||
virtual AtlasMetadata& GetAtlasMetadata() = 0;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#if __has_include("msdfgen.h")
|
||||
|
||||
#include "FontAtlasGenerator.hpp"
|
||||
#include "MsdfFontAtlasGenerator.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include "Scene/AtlasMetadata.hpp"
|
||||
#define STBI_MSC_SECURE_CRT
|
||||
@@ -22,7 +22,7 @@ namespace OpenVulkano::Scene
|
||||
using namespace msdfgen;
|
||||
using namespace msdf_atlas;
|
||||
|
||||
Charset FontAtlasGenerator::LoadAllGlyphs(const std::variant<std::string, Array<char>>& data)
|
||||
Charset MsdfFontAtlasGenerator::LoadAllGlyphs(const std::variant<std::string, Array<char>>& data)
|
||||
{
|
||||
FT_Library library;
|
||||
auto error = FT_Init_FreeType(&library);
|
||||
@@ -55,41 +55,49 @@ namespace OpenVulkano::Scene
|
||||
return s;
|
||||
}
|
||||
|
||||
void FontAtlasGenerator::GenerateAtlas(const std::string& fontFile, const Charset& charset,
|
||||
void MsdfFontAtlasGenerator::GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
||||
const std::optional<std::string>& pngOutput)
|
||||
{
|
||||
FreetypeHandle* ft;
|
||||
FontHandle* font;
|
||||
InitFreetypeFromFile(ft, font, fontFile);
|
||||
Charset s;
|
||||
std::for_each(s.begin(), s.end(), [&](uint32_t unicode) { s.add(unicode); });
|
||||
Generate(ft, font, s, pngOutput);
|
||||
}
|
||||
|
||||
void MsdfFontAtlasGenerator::GenerateAtlas(const Array<char>& fontData, int length,
|
||||
const std::set<uint32_t>& charset,
|
||||
const std::optional<std::string>& pngOutput)
|
||||
{
|
||||
FreetypeHandle* ft;
|
||||
FontHandle* font;
|
||||
InitFreetypeFromBuffer(ft, font, (const msdfgen::byte*)(fontData.Data()), length);
|
||||
Charset s;
|
||||
std::for_each(s.begin(), s.end(), [&](uint32_t unicode) { s.add(unicode); });
|
||||
Generate(ft, font, s, pngOutput);
|
||||
}
|
||||
|
||||
void MsdfFontAtlasGenerator::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()));
|
||||
}
|
||||
FreetypeHandle* ft;
|
||||
FontHandle* font;
|
||||
InitFreetypeFromFile(ft, font, fontFile);
|
||||
Generate(ft, font, charset, pngOutput);
|
||||
}
|
||||
|
||||
void FontAtlasGenerator::GenerateAtlas(const msdfgen::byte* fontData, int length, const Charset& charset,
|
||||
void MsdfFontAtlasGenerator::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");
|
||||
}
|
||||
FreetypeHandle* ft;
|
||||
FontHandle* font;
|
||||
InitFreetypeFromBuffer(ft, font, fontData, length);
|
||||
Generate(ft, font, charset, pngOutput);
|
||||
}
|
||||
|
||||
void FontAtlasGenerator::SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile) const
|
||||
void MsdfFontAtlasGenerator::SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile) const
|
||||
{
|
||||
if (m_symbols.empty())
|
||||
{
|
||||
@@ -126,7 +134,34 @@ namespace OpenVulkano::Scene
|
||||
fs.write(reinterpret_cast<const char*>(&packedFlag), sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void FontAtlasGenerator::Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset,
|
||||
void MsdfFontAtlasGenerator::InitFreetypeFromFile(FreetypeHandle*& ft, FontHandle*& font, const std::string& fontFile)
|
||||
{
|
||||
ft = initializeFreetype();
|
||||
if (!ft) { throw std::runtime_error("Failed to initialize freetype"); }
|
||||
font = loadFont(ft, fontFile.data());
|
||||
if (!font)
|
||||
{
|
||||
deinitializeFreetype(ft);
|
||||
ft = nullptr;
|
||||
throw std::runtime_error(fmt::format("Failed to load font from file {0}", fontFile.data()));
|
||||
}
|
||||
}
|
||||
|
||||
void MsdfFontAtlasGenerator::InitFreetypeFromBuffer(FreetypeHandle*& ft, FontHandle*& font,
|
||||
const msdfgen::byte* fontData, int length)
|
||||
{
|
||||
ft = initializeFreetype();
|
||||
if (!ft) { throw std::runtime_error("Failed to initialize freetype"); }
|
||||
font = loadFontData(ft, fontData, length);
|
||||
if (!font)
|
||||
{
|
||||
deinitializeFreetype(ft);
|
||||
ft = nullptr;
|
||||
throw std::runtime_error("Failed to load font data from given buffer");
|
||||
}
|
||||
}
|
||||
|
||||
void MsdfFontAtlasGenerator::Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset,
|
||||
const std::optional<std::string>& pngOutput)
|
||||
{
|
||||
m_symbols.clear();
|
||||
@@ -220,7 +255,8 @@ namespace OpenVulkano::Scene
|
||||
deinitializeFreetype(ft);
|
||||
}
|
||||
|
||||
void FontAtlasGenerator::SavePng(const BitmapConstRef<byte, 1>& storage, const std::string& output, int channels) const
|
||||
void MsdfFontAtlasGenerator::SavePng(const BitmapConstRef<byte, 1>& storage, const std::string& output,
|
||||
int channels) const
|
||||
{
|
||||
stbi_flip_vertically_on_write(1);
|
||||
if (std::filesystem::path(output).extension() == ".png")
|
||||
60
openVulkanoCpp/Scene/MsdfFontAtlasGenerator.hpp
Normal file
60
openVulkanoCpp/Scene/MsdfFontAtlasGenerator.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __has_include("msdfgen.h")
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <map>
|
||||
#include <variant>
|
||||
#include "Scene/AtlasMetadata.hpp"
|
||||
#include "FontAtlasGenerator.hpp"
|
||||
#include "Scene/Texture.hpp"
|
||||
#include "msdfgen.h"
|
||||
#include "msdfgen-ext.h"
|
||||
#include "msdf-atlas-gen/msdf-atlas-gen.h"
|
||||
#define MSDFGEN_AVAILABLE
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
using namespace msdfgen;
|
||||
using namespace msdf_atlas;
|
||||
using namespace OpenVulkano::Scene;
|
||||
|
||||
class MsdfFontAtlasGenerator : public FontAtlasGenerator
|
||||
{
|
||||
public:
|
||||
using SdfGenerator = ImmediateAtlasGenerator<float, 1, sdfGenerator, BitmapAtlasStorage<msdfgen::byte, 1>>;
|
||||
static Charset LoadAllGlyphs(const std::variant<std::string, Array<char>>& data);
|
||||
void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
||||
const std::optional<std::string>& pngOutput = std::nullopt) override;
|
||||
void GenerateAtlas(const Array<char>& fontData, int length, const std::set<uint32_t>& charset,
|
||||
const std::optional<std::string>& pngOutput = std::nullopt) override;
|
||||
void GenerateAtlas(const std::string& fontFile, const Charset& charset = Charset::ASCII,
|
||||
const std::optional<std::string>& pngOutput = std::nullopt);
|
||||
void GenerateAtlas(const msdfgen::byte* fontData, int length, const Charset& charset = Charset::ASCII,
|
||||
const std::optional<std::string>& pngOutput = std::nullopt);
|
||||
void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const override;
|
||||
const Texture& GetAtlas() const override { return m_atlasTex; }
|
||||
std::map<uint32_t, GlyphInfo>& GetGlyphsInfo() override { return m_symbols; }
|
||||
AtlasMetadata& GetAtlasMetadata() override { return m_meta; }
|
||||
SdfGenerator& GetFontAtlasGenerator() { return m_generator; }
|
||||
private:
|
||||
void InitFreetypeFromFile(FreetypeHandle*& ft, FontHandle*& font, const std::string& file);
|
||||
void InitFreetypeFromBuffer(FreetypeHandle*& ft, FontHandle*& font, const msdfgen::byte* fontData, int length);
|
||||
void Generate(FreetypeHandle* ft, FontHandle* font, const Charset& chset,
|
||||
const std::optional<std::string>& pngOutput);
|
||||
void SavePng(const BitmapConstRef<byte, 1>& storage, const std::string& output, int channels) const;
|
||||
private:
|
||||
SdfGenerator m_generator;
|
||||
Texture m_atlasTex;
|
||||
AtlasMetadata m_meta;
|
||||
std::map<uint32_t, GlyphInfo> m_symbols;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -18,11 +18,6 @@
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
using namespace msdfgen;
|
||||
using namespace msdf_atlas;
|
||||
#endif
|
||||
|
||||
Shader& TextDrawable::GetDefaultShader()
|
||||
{
|
||||
static bool once = true;
|
||||
@@ -113,7 +108,6 @@ namespace OpenVulkano::Scene
|
||||
m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3);
|
||||
}
|
||||
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
TextDrawable::TextDrawable(FontAtlasGenerator* fontAtlasGenerator, const TextConfig& config)
|
||||
{
|
||||
if (!fontAtlasGenerator) { throw std::runtime_error("FontAtlasGenerator is nullptr"); }
|
||||
@@ -123,7 +117,6 @@ namespace OpenVulkano::Scene
|
||||
m_material.texture = const_cast<Texture*>(&m_fontAtlasGenerator->GetAtlas());
|
||||
m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
void TextDrawable::GenerateText(const std::string& text, const Math::Vector3f& pos)
|
||||
{
|
||||
@@ -135,32 +128,36 @@ namespace OpenVulkano::Scene
|
||||
m_geometry.Close();
|
||||
m_geometry.Init(text.size() * 4, text.size() * 6);
|
||||
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
// TODO: better implementation to decide what to use: data from atlas generator or data read from file
|
||||
// we have msdf but loaded glyphs metadata from file before
|
||||
std::optional<std::reference_wrapper<std::map<unicode_t, GlyphInfo>>> glyphData;
|
||||
if (m_fontAtlasGenerator->GetGlyphsInfo().empty() && !m_glyphs.empty())
|
||||
AtlasMetadata* meta;
|
||||
std::map<uint32_t, GlyphInfo>* symbols;
|
||||
if (m_fontAtlasGenerator)
|
||||
{
|
||||
// texture is set in ctor
|
||||
glyphData = m_glyphs;
|
||||
if (m_fontAtlasGenerator->GetGlyphsInfo().empty() && !m_glyphs.empty())
|
||||
{
|
||||
// texture is set in ctor
|
||||
symbols = &m_glyphs;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just in case if FontAtlasGenerator changed it's atlas
|
||||
m_material.texture = const_cast<Texture*>(&m_fontAtlasGenerator->GetAtlas());
|
||||
symbols = &m_fontAtlasGenerator->GetGlyphsInfo();
|
||||
}
|
||||
meta = &m_fontAtlasGenerator->GetAtlasMetadata();
|
||||
}
|
||||
else
|
||||
{
|
||||
// just in case if FontAtlasGenerator changed it's atlas
|
||||
m_material.texture = const_cast<Texture*>(&m_fontAtlasGenerator->GetAtlas());
|
||||
glyphData = m_fontAtlasGenerator->GetGlyphsInfo();
|
||||
symbols = &m_glyphs;
|
||||
meta = &m_meta;
|
||||
}
|
||||
std::map<unicode_t, GlyphInfo>& symbols = glyphData.value();
|
||||
AtlasMetadata& meta = m_fontAtlasGenerator->GetAtlasMetadata();
|
||||
#else
|
||||
std::map<unicode_t, GlyphInfo>& symbols = m_glyphs;
|
||||
AtlasMetadata& meta = m_meta;
|
||||
#endif
|
||||
|
||||
const Texture& atlasTex = *m_material.texture;
|
||||
double cursorX = pos.x;
|
||||
auto begin = text.begin();
|
||||
auto end = text.end();
|
||||
const double lineHeight = meta.lineHeight;
|
||||
const double lineHeight = meta->lineHeight;
|
||||
double posY = pos.y;
|
||||
for (size_t i = 0; begin != end; i++)
|
||||
{
|
||||
@@ -171,11 +168,11 @@ namespace OpenVulkano::Scene
|
||||
cursorX = pos.x;
|
||||
continue;
|
||||
}
|
||||
if (symbols.find(c) != symbols.end())
|
||||
if (symbols->find(c) != symbols->end())
|
||||
{
|
||||
uint32_t vIdx = i * 4;
|
||||
uint32_t indices[] = { 1 + vIdx, 2 + vIdx, 3 + vIdx, 1 + vIdx, 3 + vIdx, 0 + vIdx };
|
||||
GlyphInfo& info = symbols.at(c);
|
||||
GlyphInfo& info = symbols->at(c);
|
||||
|
||||
// left bottom
|
||||
m_geometry.vertices[vIdx].position.x = info.xyz[0].x + cursorX;
|
||||
|
||||
@@ -19,20 +19,11 @@
|
||||
#include "Base/Logger.hpp"
|
||||
#include "AtlasMetadata.hpp"
|
||||
#include "Image/Image.hpp"
|
||||
#if __has_include("msdfgen.h")
|
||||
#include "msdfgen.h"
|
||||
#include "msdfgen-ext.h"
|
||||
#include "msdf-atlas-gen/msdf-atlas-gen.h"
|
||||
#define MSDFGEN_AVAILABLE 1
|
||||
#endif
|
||||
#include <map>
|
||||
#include "FontAtlasGenerator.hpp"
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
using namespace msdfgen;
|
||||
using namespace msdf_atlas;
|
||||
#endif // MSDFGEN_AVAILABLE
|
||||
|
||||
struct TextConfig
|
||||
{
|
||||
Math::Vector4f textColor = { 1, 1, 1, 1 };
|
||||
@@ -54,15 +45,12 @@ namespace OpenVulkano::Scene
|
||||
TextDrawable(const std::string& atlasMetadataFile, Texture* atlasTex, const TextConfig& config = TextConfig());
|
||||
TextDrawable(const Array<char>& atlasMetadata, Texture* atlasTex, const TextConfig& config = TextConfig());
|
||||
TextDrawable(const std::map<uint32_t, GlyphInfo>& glyphData, Texture* atlasTex, const TextConfig& config = TextConfig());
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
TextDrawable(FontAtlasGenerator* fontAtlasGenerator, const TextConfig& config = TextConfig());
|
||||
#endif
|
||||
void GenerateText(const std::string& text, const Math::Vector3f& pos = Math::Vector3f(0.f));
|
||||
void SetConfig(const TextConfig& cfg) { m_cfg = cfg; }
|
||||
void SetShader(Shader* shader) { m_shader = shader; }
|
||||
TextConfig& GetConfig() { return m_cfg; }
|
||||
Shader* GetShader() { return m_shader; }
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
void SetFontAtlasGenerator(FontAtlasGenerator* fontAtlasGenerator)
|
||||
{
|
||||
if (!fontAtlasGenerator || fontAtlasGenerator->GetGlyphsInfo().empty())
|
||||
@@ -73,7 +61,6 @@ namespace OpenVulkano::Scene
|
||||
m_fontAtlasGenerator = fontAtlasGenerator;
|
||||
}
|
||||
FontAtlasGenerator* GetFontAtlasGenerator() { return m_fontAtlasGenerator; }
|
||||
#endif
|
||||
private:
|
||||
Geometry m_geometry;
|
||||
Material m_material;
|
||||
@@ -81,9 +68,7 @@ namespace OpenVulkano::Scene
|
||||
std::map<uint32_t, GlyphInfo> m_glyphs;
|
||||
AtlasMetadata m_meta;
|
||||
std::unique_ptr<Image::Image> m_img;
|
||||
#ifdef MSDFGEN_AVAILABLE
|
||||
FontAtlasGenerator* m_fontAtlasGenerator = nullptr;
|
||||
#endif
|
||||
Shader* m_shader = &GetDefaultShader();
|
||||
TextConfig m_cfg;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user