1414#include FT_BITMAP_H
1515#include FT_STROKER_H
1616#include FT_TRUETYPE_TABLES_H
17+ #include < atomic>
1718#include < cstdlib>
1819#include < cstring>
1920
@@ -43,15 +44,20 @@ template <typename T, typename U> inline T reinterpret( const U& input ) {
4344}
4445
4546// Combine outline thickness, boldness and font glyph index into a single 64-bit key
46- EE::Uint64 combine ( float outlineThickness, bool bold, EE::Uint32 index ) {
47- return ( static_cast <EE::Uint64>( reinterpret<EE::Uint32>( outlineThickness * 100 ) ) << 33 ) |
47+ EE::Uint64 combine ( float outlineThickness, bool bold, EE::Uint32 index,
48+ EE::Uint32 fontInternalId ) {
49+ return ( static_cast <EE::Uint64>( reinterpret<EE::Uint32>( fontInternalId ) ) << 48 ) |
50+ ( static_cast <EE::Uint64>( reinterpret<EE::Uint32>( outlineThickness * 100 ) ) << 33 ) |
4851 ( static_cast <EE::Uint64>( bold ) << 32 ) | index;
4952}
5053
5154} // namespace
5255
5356namespace EE { namespace Graphics {
5457
58+ static std::map<std::string, Uint32> fontsInternalIds;
59+ static std::atomic<Uint32> fontInternalIdCounter{ 0 };
60+
5561FontTrueType* FontTrueType::New ( const std::string& FontName ) {
5662 return eeNew ( FontTrueType, ( FontName ) );
5763}
@@ -156,6 +162,10 @@ bool FontTrueType::loadFromFile( const std::string& filename ) {
156162 // Store the font information
157163 mInfo .family = face->family_name ? face->family_name : std::string ();
158164
165+ auto fontInternalId = fontsInternalIds.find ( mInfo .family );
166+ if ( fontsInternalIds.end () == fontInternalId )
167+ fontsInternalIds[mInfo .family ] = ++fontInternalIdCounter;
168+
159169 sendEvent ( Event::Load );
160170
161171 return true ;
@@ -226,6 +236,10 @@ bool FontTrueType::loadFromMemory( const void* data, std::size_t sizeInBytes, bo
226236 // Store the font information
227237 mInfo .family = face->family_name ? face->family_name : std::string ();
228238
239+ auto fontInternalId = fontsInternalIds.find ( mInfo .family );
240+ if ( fontsInternalIds.end () == fontInternalId )
241+ fontsInternalIds[mInfo .family ] = ++fontInternalIdCounter;
242+
229243 sendEvent ( Event::Load );
230244
231245 return true ;
@@ -309,6 +323,10 @@ bool FontTrueType::loadFromStream( IOStream& stream ) {
309323 // Store the font information
310324 mInfo .family = face->family_name ? face->family_name : std::string ();
311325
326+ auto fontInternalId = fontsInternalIds.find ( mInfo .family );
327+ if ( fontsInternalIds.end () == fontInternalId )
328+ fontsInternalIds[mInfo .family ] = ++fontInternalIdCounter;
329+
312330 sendEvent ( Event::Load );
313331
314332 return true ;
@@ -333,18 +351,30 @@ const FontTrueType::Info& FontTrueType::getInfo() const {
333351 return mInfo ;
334352}
335353
336- Uint64 FontTrueType::getIndexKey ( Uint32 index, bool bold, Float outlineThickness ) const {
337- return combine ( outlineThickness, bold, index );
354+ Uint64 FontTrueType::getIndexKey ( Uint32 fontInternalId, Uint32 index, bool bold,
355+ Float outlineThickness ) const {
356+ return combine ( outlineThickness, bold, index, fontInternalId );
338357}
339358
340359bool FontTrueType::hasGlyph ( Uint32 codePoint ) const {
341- return FT_Get_Char_Index ( static_cast <FT_Face>( mFace ), codePoint ) != 0 ;
360+ return getGlyphIndex ( codePoint ) != 0 ;
361+ }
362+
363+ Uint32 FontTrueType::getGlyphIndex ( const Uint32& codePoint ) const {
364+ Uint32 index;
365+ auto indexIter = mCodePointIndexCache .find ( codePoint );
366+ if ( mCodePointIndexCache .end () != indexIter ) {
367+ index = indexIter->second ;
368+ } else {
369+ index = FT_Get_Char_Index ( static_cast <FT_Face>( mFace ), codePoint );
370+ mCodePointIndexCache [codePoint] = index;
371+ }
372+ return index;
342373}
343374
344375const Glyph& FontTrueType::getGlyph ( Uint32 codePoint, unsigned int characterSize, bool bold,
345376 Float outlineThickness ) const {
346- FT_Face face = static_cast <FT_Face>( mFace );
347- Uint32 index = FT_Get_Char_Index ( face, codePoint );
377+ Uint32 index = getGlyphIndex ( codePoint );
348378
349379 if ( Font::isEmojiCodePoint ( codePoint ) && !mIsColorEmojiFont && !mIsEmojiFont ) {
350380 if ( !mIsColorEmojiFont && FontManager::instance ()->getColorEmojiFont () != nullptr &&
@@ -360,7 +390,7 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
360390 FontTrueType* fontEmoji =
361391 static_cast <FontTrueType*>( FontManager::instance ()->getColorEmojiFont () );
362392 return fontEmoji->getGlyph ( codePoint, characterSize, bold, outlineThickness,
363- mPages [ characterSize] , maxWidth );
393+ getPage ( characterSize ) , maxWidth );
364394 } else if ( !mIsEmojiFont && FontManager::instance ()->getEmojiFont () != nullptr &&
365395 FontManager::instance ()->getEmojiFont ()->getType () == FontType::TTF ) {
366396
@@ -370,11 +400,10 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
370400 Glyph monospaceGlyph = getGlyph ( ' ' , characterSize, bold, outlineThickness );
371401 maxWidth = monospaceGlyph.advance ;
372402 }
373-
374403 FontTrueType* fontEmoji =
375404 static_cast <FontTrueType*>( FontManager::instance ()->getEmojiFont () );
376405 return fontEmoji->getGlyph ( codePoint, characterSize, bold, outlineThickness,
377- mPages [ characterSize] , maxWidth );
406+ getPage ( characterSize ) , maxWidth );
378407 }
379408 }
380409
@@ -384,8 +413,7 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
384413const Glyph& FontTrueType::getGlyph ( Uint32 codePoint, unsigned int characterSize, bool bold,
385414 Float outlineThickness, Page& page,
386415 const Float& forzeSize ) const {
387- FT_Face face = static_cast <FT_Face>( mFace );
388- Uint32 index = FT_Get_Char_Index ( face, codePoint );
416+ Uint32 index = getGlyphIndex ( codePoint );
389417 return getGlyphByIndex ( index, characterSize, bold, outlineThickness, page, forzeSize );
390418}
391419
@@ -396,7 +424,7 @@ const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int character
396424 GlyphTable& glyphs = page.glyphs ;
397425
398426 // Build the key by combining the code point, bold flag, and outline thickness
399- Uint64 key = getIndexKey ( index, bold, outlineThickness );
427+ Uint64 key = getIndexKey ( fontsInternalIds[ mInfo . family ], index, bold, outlineThickness );
400428
401429 // Search the glyph into the cache
402430 GlyphTable::const_iterator it = glyphs.find ( key );
@@ -413,22 +441,23 @@ const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int character
413441
414442const Glyph& FontTrueType::getGlyphByIndex ( Uint32 index, unsigned int characterSize, bool bold,
415443 Float outlineThickness ) const {
416- return getGlyphByIndex ( index, characterSize, bold, outlineThickness, mPages [ characterSize] ,
444+ return getGlyphByIndex ( index, characterSize, bold, outlineThickness, getPage ( characterSize ) ,
417445 0 .f );
418446}
419447
420448GlyphDrawable* FontTrueType::getGlyphDrawable ( Uint32 codePoint, unsigned int characterSize,
421449 bool bold, Float outlineThickness ) const {
422- GlyphDrawableTable& drawables = mPages [ characterSize] .drawables ;
450+ GlyphDrawableTable& drawables = getPage ( characterSize ) .drawables ;
423451
424- Uint64 key = getIndexKey ( codePoint, bold, outlineThickness );
452+ Uint64 key = getIndexKey ( getPage ( characterSize ).fontInternalId , getGlyphIndex ( codePoint ),
453+ bold, outlineThickness );
425454
426455 auto it = drawables.find ( key );
427456 if ( it != drawables.end () ) {
428457 return it->second ;
429458 } else {
430459 const Glyph& glyph = getGlyph ( codePoint, characterSize, bold, outlineThickness );
431- auto & page = mPages [ characterSize] ;
460+ auto & page = getPage ( characterSize ) ;
432461 GlyphDrawable* region = GlyphDrawable::New (
433462 page.texture , glyph.textureRect ,
434463 String::format ( " %s_%d_%u" , mFontName .c_str (), characterSize, codePoint ) );
@@ -442,15 +471,15 @@ GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int ch
442471Float FontTrueType::getKerning ( Uint32 first, Uint32 second, unsigned int characterSize,
443472 bool bold ) const {
444473 // Special case where first or second is 0 (null character)
445- if ( first == 0 || second == 0 )
474+ if ( first == 0 || second == 0 || isMonospace () )
446475 return 0 .f ;
447476
448477 FT_Face face = static_cast <FT_Face>( mFace );
449478
450479 if ( face && setCurrentSize ( characterSize ) ) {
451480 // Convert the characters to indices
452- FT_UInt index1 = FT_Get_Char_Index ( face, first );
453- FT_UInt index2 = FT_Get_Char_Index ( face, second );
481+ FT_UInt index1 = getGlyphIndex ( first );
482+ FT_UInt index2 = getGlyphIndex ( second );
454483
455484 // Retrieve position compensation deltas generated by FT_LOAD_FORCE_AUTOHINT flag
456485 auto firstRsbDelta = static_cast <float >( getGlyph ( first, characterSize, bold ).rsbDelta );
@@ -543,7 +572,7 @@ Float FontTrueType::getUnderlineThickness( unsigned int characterSize ) const {
543572}
544573
545574Texture* FontTrueType::getTexture ( unsigned int characterSize ) const {
546- return mPages [ characterSize] .texture ;
575+ return getPage ( characterSize ) .texture ;
547576}
548577
549578bool FontTrueType::loaded () const {
@@ -998,6 +1027,24 @@ bool FontTrueType::setCurrentSize( unsigned int characterSize ) const {
9981027 }
9991028}
10001029
1030+ FontTrueType::Page& FontTrueType::getPage ( unsigned int characterSize ) const {
1031+ auto pageIt = mPages .find ( characterSize );
1032+ if ( pageIt == mPages .end () ) {
1033+ mPages .insert ( std::make_pair ( characterSize,
1034+ std::make_unique<Page>( fontsInternalIds[mInfo .family ] ) ) );
1035+ pageIt = mPages .find ( characterSize );
1036+ }
1037+ return *pageIt->second ;
1038+ }
1039+
1040+ void FontTrueType::setIsEmojiFont ( bool isEmojiFont ) {
1041+ mIsEmojiFont = isEmojiFont;
1042+ }
1043+
1044+ void FontTrueType::setIsColorEmojiFont ( bool isColorEmojiFont ) {
1045+ mIsColorEmojiFont = isColorEmojiFont;
1046+ }
1047+
10011048bool FontTrueType::isColorEmojiFont () const {
10021049 return mIsColorEmojiFont ;
10031050}
@@ -1006,6 +1053,10 @@ bool FontTrueType::isMonospace() const {
10061053 return FT_IS_FIXED_WIDTH ( static_cast <FT_Face>( mFace ) );
10071054}
10081055
1056+ bool FontTrueType::isEmojiFont () const {
1057+ return mIsEmojiFont ;
1058+ }
1059+
10091060bool FontTrueType::getBoldAdvanceSameAsRegular () const {
10101061 return mBoldAdvanceSameAsRegular ;
10111062}
@@ -1014,7 +1065,8 @@ void FontTrueType::setBoldAdvanceSameAsRegular( bool boldAdvanceSameAsRegular )
10141065 mBoldAdvanceSameAsRegular = boldAdvanceSameAsRegular;
10151066}
10161067
1017- FontTrueType::Page::Page () : texture( NULL ), nextRow( 3 ) {
1068+ FontTrueType::Page::Page ( const Uint32 fontInternalId ) :
1069+ texture ( NULL ), nextRow( 3 ), fontInternalId( fontInternalId ) {
10181070 // Make sure that the texture is initialized by default
10191071 Image image;
10201072 image.create ( 128 , 128 , 4 );
0 commit comments