diff --git a/include/eepp/graphics/fontmanager.hpp b/include/eepp/graphics/fontmanager.hpp index 167175dca..92280d71c 100644 --- a/include/eepp/graphics/fontmanager.hpp +++ b/include/eepp/graphics/fontmanager.hpp @@ -23,7 +23,12 @@ class EE_API FontManager : public ResourceManager { /** @brief Adds a new font to the manager */ Graphics::Font* add( Graphics::Font* Font ); + void setColorEmojiFont( Graphics::Font* font ) { mColorEmojiFont = font; } + + Font* getColorEmojiFont() const { return mColorEmojiFont; } + protected: + Font* mColorEmojiFont{ nullptr }; FontManager(); }; diff --git a/include/eepp/graphics/fonttruetype.hpp b/include/eepp/graphics/fonttruetype.hpp index 92759a973..40a90c263 100644 --- a/include/eepp/graphics/fonttruetype.hpp +++ b/include/eepp/graphics/fonttruetype.hpp @@ -58,6 +58,8 @@ class EE_API FontTrueType : public Font { * advance like a regular glyph (useful for monospaced fonts). */ void setBoldAdvanceSameAsRegular( bool boldAdvanceSameAsRegular ); + bool isColorEmojiFont() const; + protected: explicit FontTrueType( const std::string& FontName ); @@ -89,7 +91,7 @@ class EE_API FontTrueType : public Font { void cleanup(); Glyph loadGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, - Float outlineThickness ) const; + Float outlineThickness, Page& page ) const; Rect findGlyphRect( Page& page, unsigned int width, unsigned int height ) const; diff --git a/src/eepp/graphics/fonttruetype.cpp b/src/eepp/graphics/fonttruetype.cpp index 30d92d43d..fc64871c1 100644 --- a/src/eepp/graphics/fonttruetype.cpp +++ b/src/eepp/graphics/fonttruetype.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -74,13 +75,28 @@ FontTrueType::~FontTrueType() { cleanup(); } -bool isColorEmojiFont( const FT_Face& face ) { +bool checkIsColorEmojiFont( const FT_Face& face ) { static const uint32_t tag = FT_MAKE_TAG( 'C', 'B', 'D', 'T' ); unsigned long length = 0; FT_Load_Sfnt_Table( face, tag, 0, nullptr, &length ); return length > 0; } +bool isEmojiCodePoint( const Uint32& codePoint ) { + const Uint32 rangeMin = 127744; + const Uint32 rangeMax = 131069; + const Uint32 rangeMin2 = 126980; + const Uint32 rangeMax2 = 127569; + const Uint32 rangeMin3 = 169; + const Uint32 rangeMax3 = 174; + const Uint32 rangeMin4 = 8205; + const Uint32 rangeMax4 = 12953; + return ( ( rangeMin <= codePoint && codePoint <= rangeMax ) || + ( rangeMin2 <= codePoint && codePoint <= rangeMax2 ) || + ( rangeMin3 <= codePoint && codePoint <= rangeMax3 ) || + ( rangeMin4 <= codePoint && codePoint <= rangeMax4 ) ); +} + bool FontTrueType::loadFromFile( const std::string& filename ) { if ( !FileSystem::fileExists( filename ) && PackManager::instance()->isFallbackToPacksActive() ) { @@ -118,7 +134,10 @@ bool FontTrueType::loadFromFile( const std::string& filename ) { } mFace = face; - mIsColorEmojiFont = isColorEmojiFont( static_cast( mFace ) ); + mIsColorEmojiFont = checkIsColorEmojiFont( static_cast( mFace ) ); + + if ( mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() == nullptr ) + FontManager::instance()->setColorEmojiFont( this ); FT_Stroker stroker = nullptr; if ( !mIsColorEmojiFont ) { @@ -183,7 +202,10 @@ bool FontTrueType::loadFromMemory( const void* data, std::size_t sizeInBytes, bo } mFace = face; - mIsColorEmojiFont = isColorEmojiFont( static_cast( mFace ) ); + mIsColorEmojiFont = checkIsColorEmojiFont( static_cast( mFace ) ); + + if ( mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() == nullptr ) + FontManager::instance()->setColorEmojiFont( this ); // Load the stroker that will be used to outline the font FT_Stroker stroker = nullptr; @@ -256,9 +278,12 @@ bool FontTrueType::loadFromStream( IOStream& stream ) { } mFace = face; - mIsColorEmojiFont = isColorEmojiFont( static_cast( mFace ) ); + mIsColorEmojiFont = checkIsColorEmojiFont( static_cast( mFace ) ); FT_Stroker stroker = nullptr; + if ( mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() == nullptr ) + FontManager::instance()->setColorEmojiFont( this ); + if ( !mIsColorEmojiFont ) { // Load the stroker that will be used to outline the font if ( FT_Stroker_New( static_cast( mLibrary ), &stroker ) != 0 ) { @@ -326,7 +351,8 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz return it->second; } else { // Not found: we have to load it - Glyph glyph = loadGlyph( codePoint, characterSize, bold, outlineThickness ); + Glyph glyph = + loadGlyph( codePoint, characterSize, bold, outlineThickness, mPages[characterSize] ); return glyphs.insert( std::make_pair( key, glyph ) ).first->second; } } @@ -473,6 +499,9 @@ FontTrueType& FontTrueType::operator=( const FontTrueType& right ) { void FontTrueType::cleanup() { sendEvent( Event::Unload ); + if ( FontManager::existsSingleton() && FontManager::instance()->getColorEmojiFont() == this ) + FontManager::instance()->setColorEmojiFont( nullptr ); + mCallbacks.clear(); mNumCallBacks = 0; @@ -515,10 +544,19 @@ void FontTrueType::cleanup() { } Glyph FontTrueType::loadGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, - Float outlineThickness ) const { + Float outlineThickness, Page& page ) const { // The glyph to return Glyph glyph; + if ( !mIsColorEmojiFont && isEmojiCodePoint( codePoint ) ) { + if ( FontManager::instance()->getColorEmojiFont() != nullptr && + FontManager::instance()->getColorEmojiFont()->getType() == FontType::TTF ) { + FontTrueType* fontEmoji = + static_cast( FontManager::instance()->getColorEmojiFont() ); + return fontEmoji->loadGlyph( codePoint, characterSize, bold, outlineThickness, page ); + } + } + // First, transform our ugly void* to a FT_Face FT_Face face = static_cast( mFace ); if ( !face ) { @@ -619,9 +657,6 @@ Glyph FontTrueType::loadGlyph( Uint32 codePoint, unsigned int characterSize, boo destWidth += 2 * padding; destHeight += 2 * padding; - // Get the glyphs page corresponding to the character size - Page& page = mPages[characterSize]; - // Find a good position for the new glyph into the texture glyph.textureRect = findGlyphRect( page, destWidth, destHeight ); @@ -698,8 +733,6 @@ Glyph FontTrueType::loadGlyph( Uint32 codePoint, unsigned int characterSize, boo if ( scale < 1.f ) { dest.scale( scale ); pixelPtr = dest.getPixels(); - dest.saveToFile( String::format( "/home/downloads/%uld.png", codePoint ), - Image::SAVE_TYPE_PNG ); glyph.bounds.Left *= scale; glyph.bounds.Right *= scale; glyph.bounds.Top *= scale; @@ -859,6 +892,10 @@ bool FontTrueType::setCurrentSize( unsigned int characterSize ) const { } } +bool FontTrueType::isColorEmojiFont() const { + return mIsColorEmojiFont; +} + bool FontTrueType::getBoldAdvanceSameAsRegular() const { return mBoldAdvanceSameAsRegular; } diff --git a/src/examples/fonts/fonts.cpp b/src/examples/fonts/fonts.cpp index 5a16a2284..d22e06b9e 100644 --- a/src/examples/fonts/fonts.cpp +++ b/src/examples/fonts/fonts.cpp @@ -62,13 +62,16 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); // Create a new text string - String Txt( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod " + String Txt( "πŸ‘½Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod " "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, " "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo " "consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse " "cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " "proident, sunt in culpa qui officia deserunt mollit anim id est laborum." ); + fontEmoji = FontTrueType::New( "NotoColorEmoji" ); + fontEmoji->loadFromFile( "assets/fonts/NotoColorEmoji.ttf" ); + fontTest = FontTrueType::New( "DejaVuSansMono" ); fontTest->loadFromFile( "assets/fonts/DejaVuSansMono.ttf" ); @@ -82,7 +85,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { // Create a gradient int size = (int)Txt.size(); - for ( int i = 0; i < size; i++ ) { + for ( int i = 1; i < size; i++ ) { text.setFillColor( Color( 255 * i / size, 0, 0, 255 ), i, i + 1 ); } @@ -117,9 +120,6 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { text5.setString( "Lorem ipsum dolor sit amet, consectetur adipisicing elit." ); text5.setFontSize( 38 ); - fontEmoji = FontTrueType::New( "NotoColorEmoji" ); - fontEmoji->loadFromFile( "assets/fonts/NotoColorEmoji.ttf" ); - text6.setFont( fontEmoji ); text6.setFontSize( 64 ); text6.setString( "πŸ‘½ πŸ˜€ πŸ’© πŸ˜ƒ πŸ‘»" );