Rework some text related functions

This commit is contained in:
Georg Hagen
2025-03-01 20:00:27 +01:00
parent bfff861673
commit 0a027b8bb7
8 changed files with 43 additions and 43 deletions

View File

@@ -10,6 +10,7 @@
#include <iterator>
#include <initializer_list>
#include <cstddef>
#include <cinttypes>
#include <vector>
#include <stdexcept>
#include <string>
@@ -324,6 +325,10 @@ namespace OpenVulkano
std::swap(size, other.size);
}
std::span<const uint8_t> AsBytes() const noexcept
{
return { reinterpret_cast<const uint8_t*>(data), size * sizeof(T) };
}
private:
void Resize(size_t newSize)
{

View File

@@ -14,16 +14,16 @@ namespace OpenVulkano::Scene
void BitmapFontAtlasGenerator::GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
const std::optional<std::string>& pngOutput)
{
Generate(fontFile, charset, pngOutput);
GenerateAtlas(Utils::ReadFile(fontFile), charset, pngOutput);
}
void BitmapFontAtlasGenerator::GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
const std::optional<std::string>& pngOutput)
{
Generate(fontData, charset, pngOutput);
Generate({ reinterpret_cast<const uint8_t*>(fontData.Data()), fontData.Size() }, charset, pngOutput);
}
void BitmapFontAtlasGenerator::Generate(const std::variant<std::string, Array<char>>& source,
void BitmapFontAtlasGenerator::Generate(const std::span<const uint8_t>& fontData,
const std::set<uint32_t>& chset,
const std::optional<std::string>& pngOutput)
{
@@ -33,7 +33,7 @@ namespace OpenVulkano::Scene
return;
}
const auto& [lib, face] = FontAtlasGeneratorBase::InitFreetype(source);
const auto& [lib, face] = FontAtlasGeneratorBase::InitFreetype(fontData);
FT_Set_Pixel_Sizes(face.get(), 0, m_pixelSizeConfig.CalculatePixelSize());
if (m_subpixelLayout != SubpixelLayout::UNKNOWN)
{

View File

@@ -47,7 +47,7 @@ namespace OpenVulkano::Scene
void GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
const std::optional<std::string>& pngOutput = std::nullopt) override;
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::span<const uint8_t>& fontData, const std::set<uint32_t>& chset, const std::optional<std::string>& pngOutput);
void FillGlyphsInfo(const std::vector<GlyphForPacking>& allGlyphs, const FtFaceRecPtr& face, double scaleFactor);
void FillSubpixelData(const FT_Bitmap& bitmap, const GlyphForPacking& glyph);
FT_Int32 GetGlyphRenderMode() const;

View File

@@ -40,7 +40,9 @@ namespace OpenVulkano::Scene
return nullptr;
}
const std::set<uint32_t>& setRef = (charset.empty() ? FontAtlasGeneratorBase::LoadAllGlyphs(fontData) : charset);
std::set<uint32_t> fallback;
if (charset.empty()) FontAtlasGeneratorBase::LoadAllGlyphs(fallback, fontData.AsBytes());
const std::set<uint32_t>& setRef = (charset.empty() ? fallback : charset);
FontIdentifier id(fontIdentifier, setRef, SubpixelLayout::UNKNOWN, 0,
msdf ? FontAtlasType::MSDF : FontAtlasType::SDF);
@@ -53,11 +55,11 @@ namespace OpenVulkano::Scene
if (msdf)
{
MsdfFontAtlasGenerator msdfGen;
msdfGen.GenerateAtlas(fontData, setRef);
msdfGen.GenerateAtlas(fontData, charset);
return m_atlasesCache.insert({ id, msdfGen.GetAtlas() }).first->second;
}
SdfFontAtlasGenerator sdfGen;
sdfGen.GenerateAtlas(fontData, setRef);
sdfGen.GenerateAtlas(fontData, charset);
return m_atlasesCache.insert({ id, sdfGen.GetAtlas() }).first->second;
}
@@ -72,7 +74,9 @@ namespace OpenVulkano::Scene
return nullptr;
}
const std::set<uint32_t>& setRef = (charset.empty() ? FontAtlasGeneratorBase::LoadAllGlyphs(fontData) : charset);
std::set<uint32_t> fallback;
if (charset.empty()) FontAtlasGeneratorBase::LoadAllGlyphs(fallback, fontData.AsBytes());
const std::set<uint32_t>& setRef = (charset.empty() ? fallback : charset);
FontIdentifier id(fontIdentifier, setRef, subpixelLayout, ptSize,
subpixelLayout ? FontAtlasType::BITMAP_SUBPIXEL : FontAtlasType::BITMAP);

View File

@@ -12,39 +12,32 @@
namespace OpenVulkano::Scene
{
std::pair<FtLibraryRecPtr, FtFaceRecPtr>
FontAtlasGeneratorBase::InitFreetype(const std::variant<std::string, Array<char>>& source)
FontAtlasGeneratorBase::InitFreetype(const std::span<const uint8_t>& data)
{
std::pair<FtLibraryRecPtr, FtFaceRecPtr> result;
FT_Library library;
auto error = FT_Init_FreeType(&library);
if (error)
{
throw std::runtime_error(fmt::format("Could not initalize freetype library. {}", GetFreetypeErrorDescription(error)));
throw std::runtime_error(fmt::format("Could not initialize freetype library. Error: {}", GetFreetypeErrorDescription(error)));
}
result.first = FtLibraryRecPtr(library);
FT_Face face;
if (std::holds_alternative<std::string>(source))
error = FT_New_Memory_Face(library, data.data(), data.size(), 0, &face);
if (error)
{
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)));
if (error == FT_Err_Unknown_File_Format) throw std::runtime_error("Unknown font file format");
throw std::runtime_error(fmt::format("Font file could not be read or is corrupted. Error: {}", GetFreetypeErrorDescription(error)));
}
result.second = FtFaceRecPtr(face);
// 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) };
return result;
}
std::string FontAtlasGeneratorBase::GetFreetypeErrorDescription(FT_Error error)
@@ -88,18 +81,16 @@ namespace OpenVulkano::Scene
info.advance = advance;
}
std::set<uint32_t> FontAtlasGeneratorBase::LoadAllGlyphs(const std::variant<std::string, Array<char>>& data)
size_t FontAtlasGeneratorBase::LoadAllGlyphs(std::set<uint32_t>& chars, const FtFaceRecPtr& face)
{
const auto& [lib, face] = InitFreetype(data);
std::set<uint32_t> s;
chars.clear();
FT_UInt glyphIndex;
FT_ULong unicode = FT_Get_First_Char(face.get(), &glyphIndex);
while (glyphIndex != 0)
{
s.insert(unicode);
chars.insert(unicode);
unicode = FT_Get_Next_Char(face.get(), unicode, &glyphIndex);
}
return s;
return chars.size();
}
}

View File

@@ -9,7 +9,6 @@
#include "IFontAtlasGenerator.hpp"
#include "Math/AABB.hpp"
#include "Extensions/FreetypeHelper.hpp"
#include <variant>
namespace OpenVulkano::Scene
{
@@ -25,11 +24,12 @@ namespace OpenVulkano::Scene
FontAtlasGeneratorBase(const int channelsCount) : m_channelsCount(channelsCount) {}
[[nodiscard]] const std::shared_ptr<FontAtlas>& GetAtlas() const final { return m_atlasData; }
[[nodiscard]] int GetAtlasChannelsCount() const { return m_channelsCount; }
[[nodiscard]] static std::set<uint32_t> LoadAllGlyphs(const std::variant<std::string, Array<char>>& data);
static size_t LoadAllGlyphs(std::set<uint32_t>& chars, const std::span<const uint8_t>& fontData) { auto [lib, face] = InitFreetype(fontData); return LoadAllGlyphs(chars, face); }
static size_t LoadAllGlyphs(std::set<uint32_t>& chars, const FtFaceRecPtr& face);
protected:
void SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size, const Math::AABB& aabb, double advance);
[[nodiscard]] static std::string GetFreetypeErrorDescription(FT_Error error);
[[nodiscard]] static std::pair<FtLibraryRecPtr, FtFaceRecPtr> InitFreetype(const std::variant<std::string, Array<char>>& source);
[[nodiscard]] static std::pair<FtLibraryRecPtr, FtFaceRecPtr> InitFreetype(const std::span<const uint8_t>& data);
};
}