From 50e2982eac589699f8df20a56cb7eb42d3613c3a Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Wed, 11 Feb 2015 07:52:12 +0000 Subject: [PATCH] FontClient implementation Change-Id: Ic866f7014290b948b99f862565b91462d6c2e637 Signed-off-by: Victor Cebollada --- adaptors/public-api/file.list | 2 +- .../internal/text-abstraction/font-client-impl.cpp | 18 +- .../internal/text-abstraction/font-client-impl.h | 11 + .../text-abstraction/font-client-plugin-impl.cpp | 566 ++++++++++++++++----- .../text-abstraction/font-client-plugin-impl.h | 250 +++++++-- .../public-api/text-abstraction/font-client.cpp | 11 + .../dali/public-api/text-abstraction/font-client.h | 16 + 7 files changed, 718 insertions(+), 156 deletions(-) diff --git a/adaptors/public-api/file.list b/adaptors/public-api/file.list index f0b1785..66502d6 100644 --- a/adaptors/public-api/file.list +++ b/adaptors/public-api/file.list @@ -3,9 +3,9 @@ public_api_src_files = \ $(adaptor_public_api_dir)/adaptor-framework/application.cpp \ $(adaptor_public_api_dir)/adaptor-framework/bitmap-loader.cpp \ $(adaptor_public_api_dir)/adaptor-framework/bitmap-saver.cpp \ - $(adaptor_public_api_dir)/adaptor-framework/color-controller.cpp \ $(adaptor_public_api_dir)/adaptor-framework/clipboard.cpp \ $(adaptor_public_api_dir)/adaptor-framework/clipboard-event-notifier.cpp \ + $(adaptor_public_api_dir)/adaptor-framework/color-controller.cpp \ $(adaptor_public_api_dir)/adaptor-framework/device-layout.cpp \ $(adaptor_public_api_dir)/adaptor-framework/drag-and-drop-detector.cpp \ $(adaptor_public_api_dir)/adaptor-framework/event-feeder.cpp \ diff --git a/text/dali/internal/text-abstraction/font-client-impl.cpp b/text/dali/internal/text-abstraction/font-client-impl.cpp index 51f56d0..d069949 100644 --- a/text/dali/internal/text-abstraction/font-client-impl.cpp +++ b/text/dali/internal/text-abstraction/font-client-impl.cpp @@ -80,9 +80,26 @@ void FontClient::SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi ) } } +void FontClient::SetDefaultFontFamily( const std::string& fontFamilyName, + const std::string& fontStyle ) +{ + CreatePlugin(); + + mPlugin->SetDefaultFontFamily( fontFamilyName, fontStyle ); +} + +void FontClient::GetDefaultFonts( FontList& defaultFonts ) +{ + CreatePlugin(); + + mPlugin->GetDefaultFonts( defaultFonts ); +} + void FontClient::GetDescription( FontId id, FontDescription& fontDescription ) { CreatePlugin(); + + mPlugin->GetDescription( id, fontDescription ); } PointSize26Dot6 FontClient::GetPointSize( FontId id ) @@ -159,7 +176,6 @@ void FontClient::CreatePlugin() if( !mPlugin ) { mPlugin = new Plugin( mDpiHorizontal, mDpiVertical ); - mPlugin->Initialize(); } } diff --git a/text/dali/internal/text-abstraction/font-client-impl.h b/text/dali/internal/text-abstraction/font-client-impl.h index be42c01..8965607 100644 --- a/text/dali/internal/text-abstraction/font-client-impl.h +++ b/text/dali/internal/text-abstraction/font-client-impl.h @@ -61,6 +61,17 @@ public: void SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi ); /** + * @copydoc Dali::FontClient::SetDefaultFontFamily() + */ + void SetDefaultFontFamily( const std::string& fontFamilyName, + const std::string& fontStyle ); + + /** + * @copydoc Dali::FontClient::GetDefaultFonts() + */ + void GetDefaultFonts( FontList& defaultFonts ); + + /** * @copydoc Dali::FontClient::GetSystemFonts() */ void GetSystemFonts( FontList& systemFonts ); diff --git a/text/dali/internal/text-abstraction/font-client-plugin-impl.cpp b/text/dali/internal/text-abstraction/font-client-plugin-impl.cpp index 2ba2693..fdd4980 100644 --- a/text/dali/internal/text-abstraction/font-client-plugin-impl.cpp +++ b/text/dali/internal/text-abstraction/font-client-plugin-impl.cpp @@ -23,6 +23,9 @@ #include #include +// EXTERNAL INCLUDES +#include + /** * Conversion from Fractional26.6 to float */ @@ -44,9 +47,24 @@ namespace TextAbstraction namespace Internal { -FontClient::Plugin::CacheItem::CacheItem( FontId id, - FT_Face ftFace, - const std::string& path, +FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem( const FontFamily& fontFamily, + const FontStyle& fontStyle, + FontDescriptionId index ) +: fontFamily( fontFamily ), + fontStyle( fontStyle ), + index( index ) +{} + +FontClient::Plugin::FontIdCacheItem::FontIdCacheItem( FontDescriptionId validatedFontId, + PointSize26Dot6 pointSize, + FontId fontId ) +: validatedFontId( validatedFontId ), + pointSize( pointSize ), + fontId( fontId ) +{} + +FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace, + const FontPath& path, PointSize26Dot6 pointSize, FaceIndex face, const FontMetrics& metrics ) @@ -61,15 +79,13 @@ FontClient::Plugin::Plugin( unsigned int horizontalDpi, unsigned int verticalDpi ) : mFreeTypeLibrary( NULL ), mDpiHorizontal( horizontalDpi ), - mDpiVertical( verticalDpi ) -{} - -FontClient::Plugin::~Plugin() -{ - FT_Done_FreeType( mFreeTypeLibrary ); -} - -void FontClient::Plugin::Initialize() + mDpiVertical( verticalDpi ), + mSystemFonts(), + mDefaultFonts(), + mFontCache(), + mValidatedFontCache(), + mFontDescriptionCache( 1u ), + mFontIdCache() { int error = FT_Init_FreeType( &mFreeTypeLibrary ); if( FT_Err_Ok != error ) @@ -78,6 +94,11 @@ void FontClient::Plugin::Initialize() } } +FontClient::Plugin::~Plugin() +{ + FT_Done_FreeType( mFreeTypeLibrary ); +} + void FontClient::Plugin::SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi ) { @@ -85,35 +106,39 @@ void FontClient::Plugin::SetDpi( unsigned int horizontalDpi, mDpiVertical = verticalDpi; } -void FontClient::Plugin::GetSystemFonts( FontList& systemFonts ) +void FontClient::Plugin::SetDefaultFontFamily( const FontFamily& fontFamilyName, + const FontStyle& fontStyle ) { - if( mSystemFonts.empty() ) - { - InitSystemFonts(); - } + mDefaultFonts.clear(); - systemFonts = mSystemFonts; -} + FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamilyName, + fontStyle ); -void FontClient::Plugin::InitSystemFonts() -{ - FcFontSet* fontSet = GetFcFontSet(); + FcResult result = FcResultMatch; - if( fontSet ) + // Match the pattern. + FcFontSet* fontSet = FcFontSort( NULL /* use default configure */, + fontFamilyPattern, + false /* don't trim */, + NULL, + &result ); + + if( NULL != fontSet ) { - mSystemFonts.reserve( fontSet->nfont ); + // Reserve some space to avoid reallocations. + mDefaultFonts.reserve( fontSet->nfont ); for( int i = 0u; i < fontSet->nfont; ++i ) { FcPattern* fontPattern = fontSet->fonts[i]; - std::string path; + FontPath path; // Skip fonts with no path if( GetFcString( fontPattern, FC_FILE, path ) ) { - mSystemFonts.push_back( FontDescription() ); - FontDescription& fontDescription = mSystemFonts.back(); + mDefaultFonts.push_back( FontDescription() ); + FontDescription& fontDescription = mDefaultFonts.back(); fontDescription.path = path; @@ -124,79 +149,112 @@ void FontClient::Plugin::InitSystemFonts() FcFontSetDestroy( fontSet ); } + + FcPatternDestroy( fontFamilyPattern ); } -_FcFontSet* FontClient::Plugin::GetFcFontSet() const +void FontClient::Plugin::GetDefaultFonts( FontList& defaultFonts ) { - // create a new pattern. - // a pattern holds a set of names, each name refers to a property of the font - FcPattern* pattern = FcPatternCreate(); - - // create an object set used to define which properties are to be returned in the patterns from FcFontList. - FcObjectSet* objectSet = FcObjectSetCreate(); - - // build an object set from a list of property names - FcObjectSetAdd( objectSet, FC_FILE ); - FcObjectSetAdd( objectSet, FC_FAMILY ); - FcObjectSetAdd( objectSet, FC_STYLE ); - - // get a list of fonts - // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns - FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet ); - - // clear up the object set - if( objectSet ) + if( mDefaultFonts.empty() ) { - FcObjectSetDestroy( objectSet ); - } - // clear up the pattern - if( pattern ) - { - FcPatternDestroy( pattern ); + SetDefaultFontFamily( DEFAULT_FONT_FAMILY_NAME, + DEFAULT_FONT_STYLE ); } - return fontset; + defaultFonts = mDefaultFonts; } -bool FontClient::Plugin::GetFcString( const FcPattern* pattern, - const char* n, - std::string& string ) +void FontClient::Plugin::GetSystemFonts( FontList& systemFonts ) { - FcChar8* file = NULL; - const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file ); - - if( FcResultMatch == retVal ) + if( mSystemFonts.empty() ) { - // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*. - string.assign( reinterpret_cast( file ) ); - - return true; + InitSystemFonts(); } - return false; + systemFonts = mSystemFonts; } void FontClient::Plugin::GetDescription( FontId id, FontDescription& fontDescription ) const { - // TODO + for( std::vector::const_iterator it = mFontIdCache.begin(), + endIt = mFontIdCache.end(); + it != endIt; + ++it ) + { + const FontIdCacheItem& item = *it; + + if( item.fontId == id ) + { + fontDescription = *( mFontDescriptionCache.begin() + item.validatedFontId ); + } + } + + DALI_LOG_ERROR( "FontClient::Plugin::GetDescription. No description found for the font ID %d\n", id ); } PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id ) { - return 12*64; + const FontId index = id - 1u; + + if( id > 0u && + index < mFontCache.size() ) + { + return ( *( mFontCache.begin() + index ) ).mPointSize; + } + else + { + DALI_LOG_ERROR( "FontClient::Plugin::GetPointSize. Invalid font ID %d\n", id ); + } + + return TextAbstraction::FontClient::DEFAULT_POINT_SIZE; } FontId FontClient::Plugin::FindDefaultFont( Character charcode, PointSize26Dot6 pointSize ) { - // TODO - Use FcCharSetHasChar() - return FontId(0); + // Create the list of default fonts if it has not been created. + if( mDefaultFonts.empty() ) + { + SetDefaultFontFamily( DEFAULT_FONT_FAMILY_NAME, + DEFAULT_FONT_STYLE ); + } + + // Traverse the list of default fonts. + // Check for each default font if supports the character. + + for( FontList::const_iterator it = mDefaultFonts.begin(), + endIt = mDefaultFonts.end(); + it != endIt; + ++it ) + { + const FontDescription& description = *it; + + FcPattern* pattern = CreateFontFamilyPattern( description.family, + description.style ); + + FcResult result = FcResultMatch; + FcPattern* match = FcFontMatch( NULL /* use default configure */, pattern, &result ); + + FcCharSet* charSet = NULL; + FcPatternGetCharSet( match, FC_CHARSET, 0u, &charSet ); + + if( FcCharSetHasChar( charSet, charcode ) ) + { + return GetFontId( description.family, + description.style, + pointSize, + 0u ); + } + } + + return 0u; } -FontId FontClient::Plugin::GetFontId( const std::string& path, +FontId FontClient::Plugin::GetFontId( const FontPath& path, PointSize26Dot6 pointSize, - FaceIndex faceIndex ) + FaceIndex faceIndex, + bool cacheDescription ) { FontId id( 0 ); @@ -209,7 +267,7 @@ FontId FontClient::Plugin::GetFontId( const std::string& path, } else { - id = CreateFont( path, pointSize, faceIndex ); + id = CreateFont( path, pointSize, faceIndex, cacheDescription ); } } @@ -221,69 +279,91 @@ FontId FontClient::Plugin::GetFontId( const FontFamily& fontFamily, PointSize26Dot6 pointSize, FaceIndex faceIndex ) { - return 0u; -} - -GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId, - Character charcode ) -{ - GlyphIndex index( 0 ); - - if( fontId > 0 && - fontId-1 < mFontCache.size() ) + // This method uses three vectors which caches: + // * Pairs of non validated 'fontFamily, fontStyle' and an index to a vector with paths to font file names. + // * The path to font file names. + // * The font ids of pairs 'font point size, index to the vector with paths to font file names'. + + // 1) Checks in the cache if the pair 'fontFamily, fontStyle' has been validated before. + // If it was it gets an index to the vector with paths to font file names. Otherwise, + // retrieves using font config a path to a font file name which matches with the pair + // 'fontFamily, fontStyle'. The path is stored in the chache. + // + // 2) Checks in the cache if the pair 'font point size, index to the vector with paths to + // fon file names' exists. If exists, it gets the font id. If it doesn't it calls + // the GetFontId() method with the path to the font file name and the point size to + // get the font id. + + // The font id to be returned. + FontId fontId = 0u; + + // Check first if the pair font family and style have been validated before. + FontDescriptionId validatedFontId = 0u; + + if( !FindValidatedFont( fontFamily, + fontStyle, + validatedFontId ) ) { - FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace; + // Use font config to validate the font family name and font style. - index = FT_Get_Char_Index( ftFace, charcode ); - } + // Create a font pattern. + FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily, + fontStyle ); - return index; -} + FcResult result = FcResultMatch; -FontId FontClient::Plugin::CreateFont( const std::string& path, - PointSize26Dot6 pointSize, - FaceIndex faceIndex ) -{ - FontId id( 0 ); + // match the pattern + FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result ); - // Create & cache new font face - FT_Face ftFace; - int error = FT_New_Face( mFreeTypeLibrary, - path.c_str(), - 0, - &ftFace ); - - if( FT_Err_Ok == error ) - { - error = FT_Set_Char_Size( ftFace, - 0, - pointSize, - mDpiHorizontal, - mDpiVertical ); - - if( FT_Err_Ok == error ) + if( match ) { - id = mFontCache.size() + 1; + // Get the path to the font file name. + FontDescription description; + GetFcString( match, FC_FILE, description.path ); + GetFcString( match, FC_FAMILY, description.family ); + GetFcString( match, FC_STYLE, description.style ); - FT_Size_Metrics& ftMetrics = ftFace->size->metrics; + // Set the index to the vector of paths to font file names. + validatedFontId = mFontDescriptionCache.size(); - FontMetrics metrics( static_cast< float >( ftMetrics.ascender ) * FROM_266, - static_cast< float >( ftMetrics.descender ) * FROM_266, - static_cast< float >( ftMetrics.height ) * FROM_266 ); + // Add the path to the cache. + mFontDescriptionCache.push_back( description ); + + // Cache the index and the pair font family name, font style. + FontDescriptionCacheItem item( fontFamily, fontStyle, validatedFontId ); + mValidatedFontCache.push_back( item ); - mFontCache.push_back( CacheItem( id, ftFace, path, pointSize, faceIndex, metrics ) ); + // destroyed the matched pattern + FcPatternDestroy( match ); } else { - DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", pointSize ); + DALI_LOG_ERROR( "FontClient::Plugin::GetFontId failed for font %s %s\n", fontFamily.c_str(), fontStyle.c_str() ); } + + // destroy the pattern + FcPatternDestroy( fontFamilyPattern ); } - else + + // Check if exists a pair 'validatedFontId, pointSize' in the cache. + if( !FindFont( validatedFontId, pointSize, fontId ) ) { - DALI_LOG_ERROR( "FreeType New_Face error: %d for %s\n", error, path.c_str() ); + // Retrieve the font file name path. + const FontDescription& description = *( mFontDescriptionCache.begin() + validatedFontId ); + + // Retrieve the font id. Do not cache the description as it has been already cached. + fontId = GetFontId( description.path, + pointSize, + faceIndex, + false ); + + // Cache the pair 'validatedFontId, pointSize' to improve the following queries. + mFontIdCache.push_back( FontIdCacheItem( validatedFontId, + pointSize, + fontId ) ); } - return id; + return fontId; } void FontClient::Plugin::GetFontMetrics( FontId fontId, @@ -300,6 +380,22 @@ void FontClient::Plugin::GetFontMetrics( FontId fontId, } } +GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId, + Character charcode ) +{ + GlyphIndex index( 0 ); + + if( fontId > 0 && + fontId-1 < mFontCache.size() ) + { + FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace; + + index = FT_Get_Char_Index( ftFace, charcode ); + } + + return index; +} + bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array, uint32_t size, bool horizontal ) @@ -400,6 +496,171 @@ BitmapImage FontClient::Plugin::CreateBitmap( FontId fontId, return bitmap; } +void FontClient::Plugin::InitSystemFonts() +{ + FcFontSet* fontSet = GetFcFontSet(); + + if( fontSet ) + { + // Reserve some space to avoid reallocations. + mSystemFonts.reserve( fontSet->nfont ); + + for( int i = 0u; i < fontSet->nfont; ++i ) + { + FcPattern* fontPattern = fontSet->fonts[i]; + + FontPath path; + + // Skip fonts with no path + if( GetFcString( fontPattern, FC_FILE, path ) ) + { + mSystemFonts.push_back( FontDescription() ); + FontDescription& fontDescription = mSystemFonts.back(); + + fontDescription.path = path; + + GetFcString( fontPattern, FC_FAMILY, fontDescription.family ); + GetFcString( fontPattern, FC_STYLE, fontDescription.style ); + } + } + + FcFontSetDestroy( fontSet ); + } +} + +FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontFamily& fontFamily, + const FontStyle& fontStyle ) +{ + // create the cached font family lookup pattern + // a pattern holds a set of names, each name refers to a property of the font + FcPattern* fontFamilyPattern = FcPatternCreate(); + + // add a property to the pattern for the font family + FcPatternAddString( fontFamilyPattern, FC_FAMILY, reinterpret_cast( fontFamily.c_str() ) ); + + // add a property to the pattern for the font family + FcPatternAddString( fontFamilyPattern, FC_STYLE, reinterpret_cast( fontStyle.c_str() ) ); + + // Add a property of the pattern, to say we want to match TrueType fonts + FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, reinterpret_cast( FONT_FORMAT.c_str() ) ); + + // modify the config, with the mFontFamilyPatterm + FcConfigSubstitute( NULL /* use default configure */, fontFamilyPattern, FcMatchPattern ); + + // provide default values for unspecified properties in the font pattern + // e.g. patterns without a specified style or weight are set to Medium + FcDefaultSubstitute( fontFamilyPattern ); + + return fontFamilyPattern; +} + +_FcFontSet* FontClient::Plugin::GetFcFontSet() const +{ + // create a new pattern. + // a pattern holds a set of names, each name refers to a property of the font + FcPattern* pattern = FcPatternCreate(); + + // create an object set used to define which properties are to be returned in the patterns from FcFontList. + FcObjectSet* objectSet = FcObjectSetCreate(); + + // build an object set from a list of property names + FcObjectSetAdd( objectSet, FC_FILE ); + FcObjectSetAdd( objectSet, FC_FAMILY ); + FcObjectSetAdd( objectSet, FC_STYLE ); + + // get a list of fonts + // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns + FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet ); + + // clear up the object set + if( objectSet ) + { + FcObjectSetDestroy( objectSet ); + } + // clear up the pattern + if( pattern ) + { + FcPatternDestroy( pattern ); + } + + return fontset; +} + +bool FontClient::Plugin::GetFcString( const FcPattern* const pattern, + const char* const n, + std::string& string ) +{ + FcChar8* file = NULL; + const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file ); + + if( FcResultMatch == retVal ) + { + // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*. + string.assign( reinterpret_cast( file ) ); + + return true; + } + + return false; +} + +FontId FontClient::Plugin::CreateFont( const FontPath& path, + PointSize26Dot6 pointSize, + FaceIndex faceIndex, + bool cacheDescription ) +{ + FontId id( 0 ); + + // Create & cache new font face + FT_Face ftFace; + int error = FT_New_Face( mFreeTypeLibrary, + path.c_str(), + 0, + &ftFace ); + + if( FT_Err_Ok == error ) + { + error = FT_Set_Char_Size( ftFace, + 0, + pointSize, + mDpiHorizontal, + mDpiVertical ); + + if( FT_Err_Ok == error ) + { + id = mFontCache.size() + 1; + + FT_Size_Metrics& ftMetrics = ftFace->size->metrics; + + FontMetrics metrics( static_cast< float >( ftMetrics.ascender ) * FROM_266, + static_cast< float >( ftMetrics.descender ) * FROM_266, + static_cast< float >( ftMetrics.height ) * FROM_266 ); + + mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics ) ); + + if( cacheDescription ) + { + FontDescription description; + description.path = path; + description.family = FontFamily( ftFace->family_name ); + description.style = FontStyle( ftFace->style_name ); + + mFontDescriptionCache.push_back( description ); + } + } + else + { + DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", pointSize ); + } + } + else + { + DALI_LOG_ERROR( "FreeType New_Face error: %d for %s\n", error, path.c_str() ); + } + + return id; +} + void FontClient::Plugin::ConvertBitmap( BitmapImage& destBitmap, FT_Bitmap srcBitmap ) { @@ -419,18 +680,73 @@ void FontClient::Plugin::ConvertBitmap( BitmapImage& destBitmap, } } -bool FontClient::Plugin::FindFont( const std::string& path, +bool FontClient::Plugin::FindFont( const FontPath& path, PointSize26Dot6 pointSize, FaceIndex faceIndex, - FontId& found ) const + FontId& fontId ) const +{ + fontId = 0u; + for( std::vector::const_iterator it = mFontCache.begin(), + endIt = mFontCache.end(); + it != endIt; + ++it, ++fontId ) + { + const CacheItem& cacheItem = *it; + + if( cacheItem.mPointSize == pointSize && + cacheItem.mFaceIndex == faceIndex && + cacheItem.mPath == path ) + { + ++fontId; + return true; + } + } + + return false; +} + +bool FontClient::Plugin::FindValidatedFont( const FontFamily& fontFamily, + const FontStyle& fontStyle, + FontDescriptionId& validatedFontId ) +{ + validatedFontId = 0u; + + for( std::vector::const_iterator it = mValidatedFontCache.begin(), + endIt = mValidatedFontCache.end(); + it != endIt; + ++it ) + { + const FontDescriptionCacheItem& item = *it; + + if( ( fontFamily == item.fontFamily ) && + ( fontStyle == item.fontStyle ) ) + { + validatedFontId = item.index; + + return true; + } + } + + return false; +} + +bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId, + PointSize26Dot6 pointSize, + FontId& fontId ) { - for( unsigned int i=0; i::const_iterator it = mFontIdCache.begin(), + endIt = mFontIdCache.end(); + it != endIt; + ++it ) { - if( mFontCache[i].mPointSize == pointSize && - mFontCache[i].mPath == path && - mFontCache[i].mFaceIndex == faceIndex ) + const FontIdCacheItem& item = *it; + + if( ( validatedFontId == item.validatedFontId ) && + ( pointSize == item.pointSize ) ) { - found = i + 1; + fontId = item.fontId; return true; } } diff --git a/text/dali/internal/text-abstraction/font-client-plugin-impl.h b/text/dali/internal/text-abstraction/font-client-plugin-impl.h index 58163f4..e4995a7 100644 --- a/text/dali/internal/text-abstraction/font-client-plugin-impl.h +++ b/text/dali/internal/text-abstraction/font-client-plugin-impl.h @@ -26,7 +26,10 @@ #include #include FT_FREETYPE_H #include FT_GLYPH_H -#include + +// forward declarations of font config types. +struct _FcFontSet; +struct _FcPattern; namespace Dali { @@ -37,72 +40,261 @@ namespace TextAbstraction namespace Internal { +/** + *@brief Type used for indices addressing the vector with front descriptions of validated pairs 'font family name, font style'. + */ +typedef uint32_t FontDescriptionId; + +/** + * @brief FontClient implementation. + */ struct FontClient::Plugin { - struct CacheItem + /** + * @brief Caches an index to the vector of font descriptions for a given 'font family name, font style'. + */ + struct FontDescriptionCacheItem { - CacheItem( FontId id, FT_Face ftFace, const std::string& path, PointSize26Dot6 pointSize, FaceIndex face, const FontMetrics& metrics ); + FontDescriptionCacheItem( const FontFamily& fontFamily, + const FontStyle& fontStyle, + FontDescriptionId index ); - FT_Face mFreeTypeFace; - std::string mPath; - PointSize26Dot6 mPointSize; - FaceIndex mFaceIndex; - FontMetrics mMetrics; + FontFamily fontFamily; ///< The font family name. + FontStyle fontStyle; ///< The font style. + FontDescriptionId index; ///< Index to the vector of font descriptions. }; + /** + * @brief Caches the font id of the pair font point size and the index to the vector of font descriptions of validated fonts. + */ + struct FontIdCacheItem + { + FontIdCacheItem( FontDescriptionId validatedFontId, + PointSize26Dot6 pointSize, + FontId fontId ); + + FontDescriptionId validatedFontId; ///< Index to the vector with font descriptions. + PointSize26Dot6 pointSize; ///< The font point size. + FontId fontId; ///< The font id. + }; + + /** + * @brief Caches the FreeType face and font metrics of the triplet 'path to the font file name, font point size and face index'. + */ + struct CacheItem + { + CacheItem( FT_Face ftFace, + const FontPath& path, + PointSize26Dot6 pointSize, + FaceIndex face, + const FontMetrics& metrics ); + + FT_Face mFreeTypeFace; ///< The FreeType fance. + FontPath mPath; ///< The path to the font file name. + PointSize26Dot6 mPointSize; ///< The font point size. + FaceIndex mFaceIndex; ///< The face index. + FontMetrics mMetrics; ///< The font metrics. + }; + + /** + * Constructor. + * + * Initializes the FreeType library. + * Initializes the dpi values. + * + * @param[in] horizontalDpi The horizontal dpi. + * @param[in] verticalDpi The vertical dpi. + */ Plugin( unsigned int horizontalDpi, unsigned int verticalDpi ); + /** + * Default destructor. + * + * Frees any allocated resource. + */ ~Plugin(); - void Initialize(); - + /** + * @copydoc Dali::FontClient::SetDpi() + */ void SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi ); - void GetSystemFonts( FontList& systemFonts ); - - void InitSystemFonts(); + /** + * @copydoc Dali::FontClient::SetDefaultFontFamily() + */ + void SetDefaultFontFamily( const FontFamily& fontFamilyName, + const FontStyle& fontStyle ); - _FcFontSet* GetFcFontSet() const; + /** + * @copydoc Dali::FontClient::GetDefaultFonts() + */ + void GetDefaultFonts( FontList& defaultFonts ); - bool GetFcString( const FcPattern* pattern, const char* n, std::string& string ); + /** + * @copydoc Dali::FontClient::GetSystemFonts() + */ + void GetSystemFonts( FontList& systemFonts ); + /** + * @copydoc Dali::FontClient::GetDescription() + */ void GetDescription( FontId id, FontDescription& fontDescription ) const; + /** + * @copydoc Dali::FontClient::GetPointSize() + */ PointSize26Dot6 GetPointSize( FontId id ); + /** + * @copydoc Dali::FontClient::FindDefaultFont() + */ FontId FindDefaultFont( Character charcode, PointSize26Dot6 pointSize ); - FontId GetFontId( const std::string& path, PointSize26Dot6 pointSize, FaceIndex faceIndex ); + /** + * @see Dali::FontClient::GetFontId( const FontPath& path, PointSize26Dot6 pointSize, FaceIndex faceIndex ) + * + * @param[in] cacheDescription Whether to cache the font description. + */ + FontId GetFontId( const FontPath& path, PointSize26Dot6 pointSize, FaceIndex faceIndex, bool cacheDescription = true ); + /** + * @copydoc Dali::FontClient::GetFontId(const FontFamily& fontFamily, const FontStyle& fontStyle, PointSize26Dot6 pointSize, FaceIndex faceIndex ) + */ FontId GetFontId( const FontFamily& fontFamily, const FontStyle& fontStyle, PointSize26Dot6 pointSize, FaceIndex faceIndex ); - GlyphIndex GetGlyphIndex( FontId fontId, Character charcode ); - - FontId CreateFont( const std::string& path, PointSize26Dot6 pointSize, FaceIndex faceIndex ); - + /** + * @copydoc Dali::FontClient::GetFontMetrics() + */ void GetFontMetrics( FontId fontId, FontMetrics& metrics ); + /** + * @copydoc Dali::FontClient::GetGlyphIndex() + */ + GlyphIndex GetGlyphIndex( FontId fontId, Character charcode ); + + /** + * @copydoc Dali::FontClient::CreateMetrics() + */ bool GetGlyphMetrics( GlyphInfo* array, uint32_t size, bool horizontal ); + /** + * @copydoc Dali::FontClient::CreateBitmap() + */ BitmapImage CreateBitmap( FontId fontId, GlyphIndex glyphIndex ); - void ConvertBitmap( BitmapImage& destBitmap, FT_Bitmap srcBitmap ); - private: - bool FindFont( const std::string& path, PointSize26Dot6 pointSize, FaceIndex faceIndex, FontId& found ) const; - - FT_Library mFreeTypeLibrary; + /** + * Caches the fonts present in the platform. + * + * Calls GetFcFontSet() to retrieve the fonts. + */ + void InitSystemFonts(); - FontList mSystemFonts; + /** + * @brief Creates a font family pattern used to match fonts. + * + * @param[in] fontFamily The font family name. + * @param[in] fontStyle The font style. + * + * @return The pattern. + */ + _FcPattern* CreateFontFamilyPattern( const FontFamily& fontFamily, + const FontStyle& fontStyle ); + + /** + * Retrieves the fonts present in the platform. + * + * @return A font fonfig data structure with the platform's fonts. + */ + _FcFontSet* GetFcFontSet() const; - std::vector mFontCache; + /** + * Retrieves a font config object's value from a pattern. + * + * @param[in] pattern The font config pattern. + * @param[in] n The object. + * @param[out] string The object's value. + * + * @return @e true if the operation is successful. + */ + bool GetFcString( const _FcPattern* const pattern, const char* const n, std::string& string ); + + /** + * @brief Creates a font. + * + * @param[in] path The path to the font file name. + * @param[in] pointSize The font point size. + * @param[in] faceIndex A face index. + * @param[in] cacheDescription Whether to cache the font description. + * + * @return The font id. + */ + FontId CreateFont( const FontPath& path, PointSize26Dot6 pointSize, FaceIndex faceIndex, bool cacheDescription ); + + /** + * + * @param[in] destBitmap + * @param[in] srcBitmap + */ + void ConvertBitmap( BitmapImage& destBitmap, FT_Bitmap srcBitmap ); - unsigned int mDpiHorizontal; - unsigned int mDpiVertical; + /** + * @brief Finds in the cache if there is a triplet with the path to the font file name, the font point size and the face index. + * If there is one , if writes the font id in the param @p fontId. + * + * @param[in] path Path to the font file name. + * @param[in] pointSize The font point size. + * @param[in] faceIndex The face index. + * @param[out] fontId The font id. + * + * @return @e true if there triplet is found. + */ + bool FindFont( const FontPath& path, PointSize26Dot6 pointSize, FaceIndex faceIndex, FontId& fontId ) const; + + /** + * @brief Finds in the cahce a pair 'font family, font style'. + * If there is one, it writes the index to the vector with font descriptions in the param @p validatedFontId. + * + * @param[in] fontFamily The font family name. + * @param[in] fontStyle The font style. + * @param[out] validatedFontId The index to the vector with font descriptions. + * + * @return @e true if the pair is found. + */ + bool FindValidatedFont( const FontFamily& fontFamily, + const FontStyle& fontStyle, + FontDescriptionId& validatedFontId ); + + /** + * @brief Finds in the cache a pair 'validated font id and font point size'. + * If there is one it writes the font id in the param @p fontId. + * + * @param[in] validatedFontId Index to the vector with font descriptions. + * @param[in] pointSize The font point size. + * @param[out] fontId The font id. + * + * @return @e true if the pair is found. + */ + bool FindFont( FontDescriptionId validatedFontId, + PointSize26Dot6 pointSize, + FontId& fontId ); + + FT_Library mFreeTypeLibrary; ///< A handle to a FreeType library instance. + + unsigned int mDpiHorizontal; ///< Horizontal dpi. + unsigned int mDpiVertical; ///< Vertical dpi. + + FontList mSystemFonts; ///< Cached system fonts. + FontList mDefaultFonts; ///< Cached default fonts. + + std::vector mFontCache; ///< Caches the FreeType face and font metrics of the triplet 'path to the font file name, font point size and face index'. + std::vector mValidatedFontCache; ///< Caches indices to the vector of font descriptions for a given 'font family name, font style'. + FontList mFontDescriptionCache; ///< Caches font descriptions for the validated font family name and font style pairs. + std::vector mFontIdCache; ///< Caches font ids for the pairs of font point size and the index to the vector with font descriptions of the validated fonts. }; } // namespace Internal diff --git a/text/dali/public-api/text-abstraction/font-client.cpp b/text/dali/public-api/text-abstraction/font-client.cpp index 027dbc5..90aa49a 100644 --- a/text/dali/public-api/text-abstraction/font-client.cpp +++ b/text/dali/public-api/text-abstraction/font-client.cpp @@ -58,6 +58,17 @@ void FontClient::SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi ) GetImplementation(*this).SetDpi( horizontalDpi, verticalDpi ); } +void FontClient::SetDefaultFontFamily( const std::string& fontFamilyName, + const std::string& fontStyle ) +{ + GetImplementation(*this).SetDefaultFontFamily( fontFamilyName, fontStyle ); +} + +void FontClient::GetDefaultFonts( FontList& defaultFonts ) +{ + GetImplementation(*this).GetDefaultFonts( defaultFonts ); +} + void FontClient::GetSystemFonts( FontList& systemFonts ) { GetImplementation(*this).GetSystemFonts( systemFonts ); diff --git a/text/dali/public-api/text-abstraction/font-client.h b/text/dali/public-api/text-abstraction/font-client.h index 940f353..aa63353 100644 --- a/text/dali/public-api/text-abstraction/font-client.h +++ b/text/dali/public-api/text-abstraction/font-client.h @@ -112,6 +112,22 @@ public: void SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi ); /** + * Set the default font family and its style that should be used by the font client. + * + * @param[in] fontFamilyName The default name of the font's family. + * @param[in] fontStyle The default font's style. + */ + void SetDefaultFontFamily( const std::string& fontFamilyName, + const std::string& fontStyle ); + + /** + * @brief Retrieve the list of default fonts supported by the system. + * + * @param[out] defaultFonts A list of default font paths, family & style strings. + */ + void GetDefaultFonts( FontList& defaultFonts ); + + /** * @brief Retrieve the list of fonts supported by the system. * * @param[out] systemFonts A list of font paths, family & style strings. -- 2.7.4