Rework some text related functions
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user