14
14
#include < nbl/builtin/hlsl/cpp_compat/vector.hlsl>
15
15
#include FT_FREETYPE_H
16
16
#include FT_OUTLINE_H
17
+ #include FT_TRUETYPE_TABLES_H
18
+ #include FT_SFNT_NAMES_H
19
+ #include FT_MULTIPLE_MASTERS_H
17
20
18
21
using namespace nbl ;
19
22
using namespace nbl ::core;
@@ -67,16 +70,6 @@ class TextRenderer : public nbl::core::IReferenceCounted
67
70
68
71
class FontFace : public nbl ::core::IReferenceCounted
69
72
{
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
-
80
73
public:
81
74
82
75
// Face Global Metrics/Settings
@@ -100,14 +93,14 @@ class FontFace : public nbl::core::IReferenceCounted
100
93
float64_t2 size;
101
94
};
102
95
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 )
104
97
{
105
98
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);
107
100
if (res != 0 )
108
101
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);
111
104
}
112
105
113
106
~FontFace ()
@@ -141,7 +134,7 @@ class FontFace : public nbl::core::IReferenceCounted
141
134
// transforms uv in glyph space to uv in the actual texture
142
135
float32_t2 getUV (float32_t2 uv, float32_t2 glyphSize, uint32_t2 textureExtents, uint32_t msdfPixelRange);
143
136
144
- size_t getHash () { return m_hash; }
137
+ core:: blake3_hash_t getHash () { return m_hash; }
145
138
146
139
// TODO: make these protected, it's only used for customized tests such as building shapes for hatches
147
140
FT_GlyphSlot getGlyphSlot (uint32_t glyphId)
@@ -150,13 +143,88 @@ class FontFace : public nbl::core::IReferenceCounted
150
143
assert (!error);
151
144
return m_ftFace->glyph ;
152
145
}
146
+
153
147
FT_Face getFreetypeFace () { return m_ftFace; }
148
+
154
149
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 ; }
155
200
156
201
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
+
157
224
core::smart_refctd_ptr<TextRenderer> m_textRenderer;
158
225
FT_Face m_ftFace;
159
- size_t m_hash;
226
+ core::blake3_hash_t m_pathHash;
227
+ core::blake3_hash_t m_hash;
160
228
};
161
229
162
230
// Helper class for building an msdfgen shape from a glyph
0 commit comments