some more refactoring and improvements
This commit is contained in:
@@ -80,14 +80,9 @@ namespace OpenVulkano
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MSDFGEN_AVAILABLE) && CREATE_NEW_ATLAS
|
#if defined(MSDFGEN_AVAILABLE) && CREATE_NEW_ATLAS
|
||||||
std::set<uint32_t> s = SdfFontAtlasGenerator::LoadAllGlyphs(fontPath);
|
std::set<uint32_t> s = SdfFontAtlasGeneratorT::LoadAllGlyphs(fontPath);
|
||||||
msdf_atlas::Charset charset;
|
m_atlasGenerator.GenerateAtlas(fontPath, s);
|
||||||
for (uint32_t c : s)
|
m_msdfAtlasGenerator.GenerateAtlas(fontPath, s);
|
||||||
{
|
|
||||||
charset.add(c);
|
|
||||||
}
|
|
||||||
m_atlasGenerator.GenerateAtlas(fontPath, charset);
|
|
||||||
m_msdfAtlasGenerator.GenerateAtlas(fontPath, charset);
|
|
||||||
m_atlasGenerator.SaveAtlasMetadataInfo("sdf_atlas.png");
|
m_atlasGenerator.SaveAtlasMetadataInfo("sdf_atlas.png");
|
||||||
m_msdfAtlasGenerator.SaveAtlasMetadataInfo("msdf_atlas");
|
m_msdfAtlasGenerator.SaveAtlasMetadataInfo("msdf_atlas");
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <zlib.h>
|
||||||
#include "Data/Containers/Array.hpp"
|
#include "Data/Containers/Array.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
@@ -195,25 +196,7 @@ namespace OpenVulkano
|
|||||||
static Array<char> ReadFile(const char (&filePath)[N], bool emptyOnMissing = false,
|
static Array<char> ReadFile(const char (&filePath)[N], bool emptyOnMissing = false,
|
||||||
bool nullTerminateString = false)
|
bool nullTerminateString = false)
|
||||||
{
|
{
|
||||||
std::ifstream file(filePath, std::ios::ate | std::ios::binary);
|
return ReadFile(std::string(filePath), emptyOnMissing, nullTerminateString);
|
||||||
if (!file.is_open())
|
|
||||||
{
|
|
||||||
if (emptyOnMissing)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
throw std::runtime_error("Failed to open file '" + std::string(filePath) + "'!");
|
|
||||||
}
|
|
||||||
const size_t fileSize = static_cast<size_t>(file.tellg());
|
|
||||||
Array<char> data(fileSize + nullTerminateString);
|
|
||||||
file.seekg(0);
|
|
||||||
file.read(data.Data(), fileSize);
|
|
||||||
if (nullTerminateString)
|
|
||||||
{
|
|
||||||
data[fileSize] = '\0';
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@@ -223,6 +206,26 @@ namespace OpenVulkano
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char* STBZlibCompressor(unsigned char* data, int data_len, int* out_len, int quality)
|
||||||
|
{
|
||||||
|
uLong maxCompressedSize = compressBound(data_len);
|
||||||
|
void* outData = malloc(maxCompressedSize);
|
||||||
|
if (!outData)
|
||||||
|
{
|
||||||
|
*out_len = 0;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
int result = compress2(static_cast<Bytef*>(outData), &maxCompressedSize, data, data_len, Z_BEST_COMPRESSION);
|
||||||
|
if (result != Z_OK)
|
||||||
|
{
|
||||||
|
free(outData);
|
||||||
|
*out_len = 0;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
*out_len = static_cast<int>(maxCompressedSize);
|
||||||
|
return static_cast<unsigned char*>(outData);
|
||||||
|
}
|
||||||
|
|
||||||
static std::string DemangleTypeName(const char* name);
|
static std::string DemangleTypeName(const char* name);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,23 @@ namespace OpenVulkano::Scene
|
|||||||
m_atlasData = std::make_shared<AtlasData>();
|
m_atlasData = std::make_shared<AtlasData>();
|
||||||
const auto& [lib, face] = FontAtlasGeneratorBase::InitFreetype(source);
|
const auto& [lib, face] = FontAtlasGeneratorBase::InitFreetype(source);
|
||||||
|
|
||||||
// TODO: add flexibility to set your own size
|
Math::Vector2ui cellSize;
|
||||||
const Math::Vector2ui cellSize = { 24, 24 };
|
if (m_pixelSizeConfig.isPixelSize)
|
||||||
// set pixel width/height lower than glyph size above, otherwise some glyphs will be cropped or some overlapping will be present
|
{
|
||||||
FT_Set_Pixel_Sizes(face.get(), 0, cellSize.y - cellSize.y / 3);
|
cellSize = { m_pixelSizeConfig.size, m_pixelSizeConfig.size };
|
||||||
|
// set pixel width/height lower than glyph size above, otherwise some glyphs will be cropped or some overlapping will be present
|
||||||
|
FT_Set_Pixel_Sizes(face.get(), 0, cellSize.y - cellSize.y / 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const float pixelSize = (m_pixelSizeConfig.size * m_pixelSizeConfig.dpi) / 72.0f;
|
||||||
|
//int fontHeight = round((face->bbox.yMax - face->bbox.yMin) * pixelSize / face->units_per_EM);
|
||||||
|
//int fontWidth = round((face->bbox.xMax - face->bbox.xMin) * pixelSize / face->units_per_EM);
|
||||||
|
cellSize = { pixelSize, pixelSize };
|
||||||
|
FT_Set_Char_Size(face.get(), 0, static_cast<FT_F26Dot6>(m_pixelSizeConfig.size) * 64,
|
||||||
|
static_cast<FT_UInt>(m_pixelSizeConfig.dpi), static_cast<FT_UInt>(m_pixelSizeConfig.dpi));
|
||||||
|
}
|
||||||
|
|
||||||
const double sq = std::sqrt(chset.size());
|
const double sq = std::sqrt(chset.size());
|
||||||
const size_t glyphsPerRow = (static_cast<size_t>(sq)) + (sq - static_cast<size_t>(sq) != 0);
|
const size_t glyphsPerRow = (static_cast<size_t>(sq)) + (sq - static_cast<size_t>(sq) != 0);
|
||||||
const size_t rows = (chset.size() / glyphsPerRow) + (chset.size() % glyphsPerRow != 0);
|
const size_t rows = (chset.size() / glyphsPerRow) + (chset.size() % glyphsPerRow != 0);
|
||||||
@@ -68,6 +81,8 @@ namespace OpenVulkano::Scene
|
|||||||
if (slot->bitmap.width > cellSize.x || slot->bitmap.rows > cellSize.y)
|
if (slot->bitmap.width > cellSize.x || slot->bitmap.rows > cellSize.y)
|
||||||
{
|
{
|
||||||
Logger::APP->warn("Glyph size exceeds grid cell size: {}x{} exceeds {}x{}", slot->bitmap.width, slot->bitmap.rows, cellSize.x, cellSize.y);
|
Logger::APP->warn("Glyph size exceeds grid cell size: {}x{} exceeds {}x{}", slot->bitmap.width, slot->bitmap.rows, cellSize.x, cellSize.y);
|
||||||
|
// skip such glyph for now to avoid crash
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t firstGlyphByte = (gridPos.y * cellSize.x + gridPos.x * atlasResolution.x * cellSize.y);
|
const size_t firstGlyphByte = (gridPos.y * cellSize.x + gridPos.x * atlasResolution.x * cellSize.y);
|
||||||
|
|||||||
@@ -10,16 +10,24 @@
|
|||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
|
struct FontPixelSizeConfig
|
||||||
|
{
|
||||||
|
float size = 16.f;
|
||||||
|
float dpi = 72.f;
|
||||||
|
bool isPixelSize = true;
|
||||||
|
};
|
||||||
|
|
||||||
class BitmapFontAtlasGenerator : public FontAtlasGeneratorBase
|
class BitmapFontAtlasGenerator : public FontAtlasGeneratorBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BitmapFontAtlasGenerator() : FontAtlasGeneratorBase(1) {}
|
BitmapFontAtlasGenerator(FontPixelSizeConfig config = FontPixelSizeConfig()) : FontAtlasGeneratorBase(1), m_pixelSizeConfig(config) {}
|
||||||
void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
||||||
const std::optional<std::string>& pngOutput = std::nullopt) override;
|
const std::optional<std::string>& pngOutput = std::nullopt) override;
|
||||||
void GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
|
void GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
|
||||||
const std::optional<std::string>& pngOutput = std::nullopt) override;
|
const std::optional<std::string>& pngOutput = std::nullopt) override;
|
||||||
private:
|
private:
|
||||||
void Generate(const std::variant<std::string, Array<char>>& source, const std::set<uint32_t>& chset, const std::optional<std::string>& pngOutput);
|
void Generate(const std::variant<std::string, Array<char>>& source, const std::set<uint32_t>& chset, const std::optional<std::string>& pngOutput);
|
||||||
|
private:
|
||||||
|
FontPixelSizeConfig m_pixelSizeConfig;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,13 @@
|
|||||||
|
|
||||||
#include "FontAtlasGeneratorBase.hpp"
|
#include "FontAtlasGeneratorBase.hpp"
|
||||||
#include "Base/Logger.hpp"
|
#include "Base/Logger.hpp"
|
||||||
#define STBI_MSC_SECURE_CRT
|
#include <zlib.h>
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
||||||
#include <stb_image_write.h>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#define STBI_MSC_SECURE_CRT
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#define STBIW_ZLIB_COMPRESS OpenVulkano::Utils::STBZlibCompressor
|
||||||
|
#include <stb_image_write.h>
|
||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
@@ -86,6 +88,7 @@ namespace OpenVulkano::Scene
|
|||||||
}
|
}
|
||||||
fs.write(reinterpret_cast<const char*>(&metadataBytes), sizeof(uint64_t));
|
fs.write(reinterpret_cast<const char*>(&metadataBytes), sizeof(uint64_t));
|
||||||
fs.write(reinterpret_cast<const char*>(&packedFlag), sizeof(uint32_t));
|
fs.write(reinterpret_cast<const char*>(&packedFlag), sizeof(uint32_t));
|
||||||
|
fs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontAtlasGeneratorBase::SavePng(std::string output) const
|
void FontAtlasGeneratorBase::SavePng(std::string output) const
|
||||||
@@ -105,17 +108,8 @@ namespace OpenVulkano::Scene
|
|||||||
// generate texture
|
// generate texture
|
||||||
m_atlasData->img = std::make_unique<Image::Image>();
|
m_atlasData->img = std::make_unique<Image::Image>();
|
||||||
m_atlasData->img->resolution = Math::Vector3ui(textureResolution, 1);
|
m_atlasData->img->resolution = Math::Vector3ui(textureResolution, 1);
|
||||||
if (m_channelsCount == 1)
|
m_atlasData->img->dataFormat = m_channelsCount == 1 ? DataFormat::R8_UNORM : DataFormat::R8G8B8A8_UNORM;
|
||||||
{
|
m_atlasData->img->data = Array<uint8_t>(m_atlasData->img->dataFormat.CalculatedSize(textureResolution.x, textureResolution.y));
|
||||||
m_atlasData->img->data = Array<uint8_t>(textureResolution.x * textureResolution.y);
|
|
||||||
m_atlasData->img->dataFormat = OpenVulkano::DataFormat::R8_UNORM;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// RGBA
|
|
||||||
m_atlasData->img->data = Array<uint8_t>(textureResolution.x * textureResolution.y * 4);
|
|
||||||
m_atlasData->img->dataFormat = OpenVulkano::DataFormat::R8G8B8A8_UNORM;
|
|
||||||
}
|
|
||||||
m_atlasData->texture.resolution = m_atlasData->img->resolution;
|
m_atlasData->texture.resolution = m_atlasData->img->resolution;
|
||||||
m_atlasData->texture.textureBuffer = m_atlasData->img->data.Data();
|
m_atlasData->texture.textureBuffer = m_atlasData->img->data.Data();
|
||||||
m_atlasData->texture.format = m_atlasData->img->dataFormat;
|
m_atlasData->texture.format = m_atlasData->img->dataFormat;
|
||||||
|
|||||||
Reference in New Issue
Block a user