Skip to content

Commit 3b2a705

Browse files
committed
TextRendering, use blake3 hash + functions for setting and querying different faces and masters
1 parent e538015 commit 3b2a705

File tree

3 files changed

+86
-18
lines changed

3 files changed

+86
-18
lines changed

include/nbl/ext/TextRendering/TextRendering.h

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include <nbl/builtin/hlsl/cpp_compat/vector.hlsl>
1515
#include FT_FREETYPE_H
1616
#include FT_OUTLINE_H
17+
#include FT_TRUETYPE_TABLES_H
18+
#include FT_SFNT_NAMES_H
19+
#include FT_MULTIPLE_MASTERS_H
1720

1821
using namespace nbl;
1922
using namespace nbl::core;
@@ -67,16 +70,6 @@ class TextRenderer : public nbl::core::IReferenceCounted
6770

6871
class FontFace : public nbl::core::IReferenceCounted
6972
{
70-
71-
protected:
72-
73-
FontFace(core::smart_refctd_ptr<TextRenderer>&& textRenderer, FT_Face face, size_t hash)
74-
{
75-
m_textRenderer = std::move(textRenderer);
76-
m_ftFace = face;
77-
m_hash = hash;
78-
}
79-
8073
public:
8174

8275
// Face Global Metrics/Settings
@@ -100,14 +93,14 @@ class FontFace : public nbl::core::IReferenceCounted
10093
float64_t2 size;
10194
};
10295

103-
static core::smart_refctd_ptr<FontFace> create(core::smart_refctd_ptr<TextRenderer>&& textRenderer, const std::string& path)
96+
static core::smart_refctd_ptr<FontFace> create(core::smart_refctd_ptr<TextRenderer>&& textRenderer, const std::string& path, int faceIdx = 0)
10497
{
10598
FT_Face face;
106-
FT_Error res = FT_New_Face(textRenderer->m_ftLibrary, path.c_str(), 0, &face);
99+
FT_Error res = FT_New_Face(textRenderer->m_ftLibrary, path.c_str(), faceIdx, &face);
107100
if (res != 0)
108101
return nullptr;
109-
size_t hash = std::hash<std::string>{}(path);
110-
return core::smart_refctd_ptr<FontFace>(new FontFace(std::move(textRenderer), face, hash), core::dont_grab);
102+
103+
return core::smart_refctd_ptr<FontFace>(new FontFace(std::move(textRenderer), face, path), core::dont_grab);
111104
}
112105

113106
~FontFace()
@@ -141,7 +134,7 @@ class FontFace : public nbl::core::IReferenceCounted
141134
// transforms uv in glyph space to uv in the actual texture
142135
float32_t2 getUV(float32_t2 uv, float32_t2 glyphSize, uint32_t2 textureExtents, uint32_t msdfPixelRange);
143136

144-
size_t getHash() { return m_hash; }
137+
core::blake3_hash_t getHash() { return m_hash; }
145138

146139
// TODO: make these protected, it's only used for customized tests such as building shapes for hatches
147140
FT_GlyphSlot getGlyphSlot(uint32_t glyphId)
@@ -150,13 +143,88 @@ class FontFace : public nbl::core::IReferenceCounted
150143
assert(!error);
151144
return m_ftFace->glyph;
152145
}
146+
153147
FT_Face getFreetypeFace() { return m_ftFace; }
148+
154149
msdfgen::Shape generateGlyphShape(uint32_t glyphId);
150+
151+
// Functions to Set and Query Masters:
152+
153+
bool hasMultipleMasters() const
154+
{
155+
return FT_HAS_MULTIPLE_MASTERS(m_ftFace);
156+
}
157+
158+
uint32_t getMastersCount() const
159+
{
160+
uint32_t numMasters = 0u;
161+
if (hasMultipleMasters())
162+
{
163+
FT_MM_Var* multipleMasterData;
164+
FT_Error res = FT_Get_MM_Var(m_ftFace, &multipleMasterData);
165+
if (res == 0)
166+
{
167+
numMasters = multipleMasterData->num_namedstyles;
168+
FT_Done_MM_Var(m_textRenderer->m_ftLibrary, multipleMasterData);
169+
}
170+
}
171+
return numMasters;
172+
}
173+
174+
bool setMasterIndex(uint32_t index)
175+
{
176+
FT_Error res = FT_Set_Named_Instance(m_ftFace, index);
177+
if (res == 0)
178+
{
179+
calculateFaceHash();
180+
return true;
181+
}
182+
return false;
183+
}
184+
185+
// bits [0,15] are for faceIndex given to create function / constructor
186+
// bits [16,30] are for masterIndex given to `setMasterIndex` if it was ever called successfully
187+
// bit 31 is always 0
188+
// See FreeType documentation: https://freetype.org/freetype2/docs/reference/ft2-face_creation.html#ft_face
189+
int32_t getFaceIndex() const
190+
{
191+
return static_cast<int32_t>(m_ftFace->face_index);
192+
}
193+
194+
// Each face may have multiple masters. to change face index you need to recreate your face and use `int faceIdx` param
195+
uint32_t getNumFaces() const { return m_ftFace->num_faces; }
196+
197+
// Names:
198+
const char* getFontFamilyName() const { return m_ftFace->family_name; }
199+
const char* getStyleName() const { return m_ftFace->style_name; }
155200

156201
protected:
202+
203+
void calculateFaceHash()
204+
{
205+
core::blake3_hasher hasher;
206+
hasher.update(&m_ftFace->face_index, sizeof(FT_Long));
207+
hasher.update(&m_pathHash, sizeof(core::blake3_hash_t));
208+
m_hash = static_cast<blake3_hash_t>(hasher);
209+
}
210+
211+
FontFace(core::smart_refctd_ptr<TextRenderer>&& textRenderer, FT_Face face, const std::string& path)
212+
{
213+
m_textRenderer = std::move(textRenderer);
214+
m_ftFace = face;
215+
216+
// calculate hash path and store it
217+
core::blake3_hasher hasher;
218+
hasher.update(path.data(), path.size());
219+
m_pathHash = static_cast<blake3_hash_t>(hasher);
220+
// calculate final hash with faceIdx
221+
calculateFaceHash();
222+
}
223+
157224
core::smart_refctd_ptr<TextRenderer> m_textRenderer;
158225
FT_Face m_ftFace;
159-
size_t m_hash;
226+
core::blake3_hash_t m_pathHash;
227+
core::blake3_hash_t m_hash;
160228
};
161229

162230
// Helper class for building an msdfgen shape from a glyph

src/nbl/ext/TextRendering/TextRendering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ core::smart_refctd_ptr<ICPUImage> FontFace::generateGlyphMSDF(uint32_t baseMSDFP
136136
if (shape.contours.empty())
137137
{
138138
_NBL_DEBUG_BREAK_IF(true); // glyph id has no contours in it's shape for this font
139-
continue;
139+
return nullptr;
140140
}
141141

142142
auto shapeBounds = shape.getBounds();

0 commit comments

Comments
 (0)