const uint32_t UNICODE_CR_LF = 0x85;
const uint32_t UNICODE_CHAR_START = 0x20; // start range of unicode characters (below are control chars)
+const std::string FONT_FORMAT( "TrueType" );
+const std::string DEFAULT_FONT_FAMILY_NAME( "Tizen" );
+const std::string DEFAULT_FONT_STYLE( "Regular" );
+
+const std::string NULL_FONT_FAMILY_NAME( "" );
+const FontController::StyledFontFamily NULL_STYLED_FONT_FAMILY( std::make_pair( NULL_FONT_FAMILY_NAME, std::string( "" ) ) );
/**
* @param[in] pattern pointer to a font config pattern
- * @return font style name or an empty string if the font has no style
+ * @param[out] familyName font family name or an empty string if the font is not found.
+ * @return Whether a font is found.
*/
-std::string GetFontStyle( const FcPattern *pattern )
+bool GetFontFamily( const FcPattern* pattern, std::string& familyName )
{
- std::string styleName;
- FcChar8 *style(NULL);
- FcResult retVal = FcPatternGetString( pattern, FC_STYLE, 0, &style );
+ FcChar8* family = NULL;
+ const FcResult retVal = FcPatternGetString( pattern, FC_FAMILY, 0u, &family );
- if( FcResultMatch == retVal)
- {
- styleName = reinterpret_cast<const char*>(style);
- }
- else
+ if( FcResultMatch != retVal )
{
- styleName = "";
+ familyName.clear();
+ return false;
}
- return styleName;
+
+ // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
+ familyName.assign( reinterpret_cast<const char*>( family ) );
+
+ return true;
}
-std::string GetFontFamily( const FcPattern *pattern )
+/**
+ * @param[in] pattern pointer to a font config pattern
+ * @param[out] fontStyle font style name or an empty string if the font has no style.
+ * @return Whether a font style is found.
+ */
+bool GetFontStyle( const FcPattern* pattern, std::string& fontStyle )
{
- std::string familyName;
- FcChar8 *family(NULL);
- FcResult retVal = FcPatternGetString( pattern, FC_FAMILY, 0, &family );
+ FcChar8* style = NULL;
+ const FcResult retVal = FcPatternGetString( pattern, FC_STYLE, 0u, &style );
- if( FcResultMatch == retVal)
+ if( FcResultMatch != retVal)
{
- familyName = reinterpret_cast<const char*>(family);
+ // Has no style.
+ fontStyle.clear();
+ return false;
}
- else
+
+ // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
+ fontStyle.assign( reinterpret_cast<const char*>( style ) );
+
+ return true;
+}
+
+/**
+ * @param[in] pattern pointer to a font config pattern
+ * @param[out] fileName font file name or an empty string if the font is not found.
+ * @return Whether a font is found.
+ */
+bool GetFileName( const FcPattern* pattern, std::string& fileName )
+{
+ FcChar8* file = NULL;
+ const FcResult retVal = FcPatternGetString( pattern, FC_FILE, 0u, &file );
+
+ if( FcResultMatch != retVal )
{
- familyName = "";
+ // Has no file name.
+ fileName.clear();
+ return false;
}
- return familyName;
+
+ // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
+ fileName.assign( reinterpret_cast<const char*>( file ) );
+
+ return true;
}
bool CheckFontInstallPath( FontController::FontListMode listMode, const std::string& fileName )
const std::size_t preloadLength = preloadPath.length();
const std::size_t downloadLength = downloadPath.length();
- if( 0 == preloadPath.compare(0, preloadLength, fileName, 0, preloadLength) ||
- 0 == downloadPath.compare(0, downloadLength, fileName, 0, downloadLength))
+ if( ( 0u == preloadPath.compare( 0u, preloadLength, fileName, 0u, preloadLength ) ) ||
+ ( 0u == downloadPath.compare( 0u, downloadLength, fileName, 0u, downloadLength ) ) )
{
return true;
}
const std::string& appPath( SETTING_FONT_APP_FONT_PATH );
const std::size_t appLength = appPath.length();
- if( 0 == appPath.compare(0, appLength, fileName, 0, appLength) )
+ if( 0u == appPath.compare( 0u, appLength, fileName, 0u, appLength ) )
{
return true;
}
}
default:
{
- DALI_ASSERT_DEBUG(0 && "unhandled FontListMode");
+ DALI_ASSERT_DEBUG( false && "unhandled FontListMode" );
return false;
}
}
FcConfigEnableHome(true);
}
-void FontController::CreatePreferedFontList( )
+FontController::~FontController()
{
- StyledFontFamily tizenFont;
- tizenFont.first = "Tizen";
- tizenFont.second = "Regular";
+ // clear the font family cache
+ ClearFontFamilyCache();
- // clear the current list
- mPreferredFonts.clear();
+ // Clear the preferred font list.
+ ClearPreferredFontList();
+}
- _FcPattern* searchPattern = CreateFontFamilyPattern( tizenFont );
+const std::string& FontController::GetFontPath( const StyledFontFamily& styledFontFamily )
+{
+ DALI_ASSERT_DEBUG( !styledFontFamily.first.empty() && !styledFontFamily.second.empty() && "FontController::GetFontPath(): The font name or the font style is empty. Probably they have not been validated." );
- FcResult result(FcResultMatch);
+ // lock the mFontFamilyCacheMutex and don't release it until the function finishes.
+ // If we release it then another thread may try to create the same duplicate data.
+ boost::mutex::scoped_lock lock( mFontFamilyCacheMutex );
- // Match the pattern.
- std::string previousFont;
+ StyledFontFamily closestStyledFontFamilyMatch;
- FcFontSet* fontSet = FcFontSort( NULL /* use default configure */, searchPattern, false /* don't trim */, NULL, &result );
+ // first check to see if the font has been matched before.
+ closestStyledFontFamilyMatch = GetMatchedFont( styledFontFamily );
- for( int i=0; i < fontSet->nfont; ++i)
+ if( closestStyledFontFamilyMatch.first.empty() )
{
- // we have already filled in the first entry with the default font
- _FcPattern* pattern = fontSet->fonts[i];
-
- StyledFontFamily styledFont;
-
- styledFont.first = GetFontFamily( pattern );
- styledFont.second = GetFontStyle( pattern );
-
- if( styledFont.first != previousFont )
- {
- mPreferredFonts.push_back( styledFont );
- }
- if( i == 0 )
- {
- mDefaultStyledFont = styledFont;
- }
- previousFont = styledFont.first;
+ // The font is not in the matches font cache. Use the given one.
+ closestStyledFontFamilyMatch = styledFontFamily;
}
- FcPatternDestroy( searchPattern );
- FcFontSetDestroy( fontSet );
+ return GetCachedFontPath( closestStyledFontFamilyMatch );
}
-FontController::~FontController()
-{
- // clear the font family cache
- ClearFontFamilyCache();
-}
-
-std::string FontController::GetFontPath( const StyledFontFamily& styledFontFamily )
-{
- StyledFontFamily closestMachedStyledFontFamily;
- bool isDefault( false );
-
- // if the font was not found, the path will be an empty string
- return GetFontFamilyPath( styledFontFamily, isDefault, closestMachedStyledFontFamily );
-}
-
-FontList FontController::GetFontList( FontListMode fontListMode )
+void FontController::GetFontList( FontListMode fontListMode, FontList& fontList )
{
// protect the mFontList from access by multiple threads
// this is locked for the entire function, because we don't want two functions
// if we have already scanned for fonts, return the cached values
if ( !mFontSystemList.empty() )
{
- return GetCachedFontList( fontListMode );
+ GetCachedFontList( fontListMode, fontList );
+
+ return;
}
// font list needs to be cached
boost::mutex::scoped_lock lock( mFontConfigMutex );
// use font config to get the font set which contains a list of fonts
- FcFontSet* fontset = GetFontSet();
+ FcFontSet* fontSet = GetFontSet();
- DALI_LOG_INFO (gLogFilter, Debug::Verbose, "number of fonts found: %d\n", fontset->nfont);
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "number of fonts found: %d\n", fontSet->nfont );
- if( fontset )
+ if( fontSet )
{
std::string preload_path(SETTING_FONT_PRELOAD_FONT_PATH);
std::string download_path(SETTING_FONT_DOWNLOADED_FONT_PATH);
std::string application_path(SETTING_FONT_APP_FONT_PATH);
- FcChar8 *file(NULL);
- FcChar8 *family(NULL);
- FcResult retVal;
- for( int i = 0; i < fontset->nfont; ++i)
+ for( int i = 0u; i < fontSet->nfont; ++i )
{
- retVal = FcPatternGetString(fontset->fonts[i], FC_FILE, 0, &file);
- if( FcResultMatch != retVal)
- {
- continue; // has no file name
- }
+ FcPattern* fontPattern = fontSet->fonts[i];
+ std::string fileName;
- retVal = FcPatternGetString(fontset->fonts[i], FC_FAMILY, 0, &family);
- if( FcResultMatch != retVal)
+ if( !GetFileName( fontPattern, fileName ) )
{
- continue; // has no font name
+ continue; // Has no file name. Jump to the next iteration.
}
- std::string fileName(reinterpret_cast<const char*>(file));
-
// this is checking to make sure the font is in either the normal font path, or download path
- if( 0 == preload_path.compare(0, preload_path.length(), fileName, 0, preload_path.length()) ||
- 0 == download_path.compare(0, download_path.length(), fileName, 0, download_path.length()) ||
- 0 == application_path.compare(0, application_path.length(), fileName, 0, application_path.length()) )
+ if( 0u == preload_path.compare( 0u, preload_path.length(), fileName, 0u, preload_path.length() ) ||
+ 0u == download_path.compare( 0u, download_path.length(), fileName, 0u, download_path.length() ) ||
+ 0u == application_path.compare( 0u, application_path.length(), fileName, 0u, application_path.length() ) )
{
- const std::string fontFamily( reinterpret_cast<const char*>(family));
- const std::string fontStyle = GetFontStyle( fontset->fonts[i]);
+ StyledFontFamily styledFontFamily;
+
+ if( !GetFontFamily( fontPattern, styledFontFamily.first ) )
+ {
+ continue; // Has no font name. Jump to the next iteration.
+ }
+
+ GetFontStyle( fontPattern, styledFontFamily.second );
// Add the font to the either the system or application font list
- AddToFontList( fileName, std::make_pair( fontFamily, fontStyle ) );
+ AddToFontList( fileName, styledFontFamily );
}
}
// delete the font set
- FcFontSetDestroy(fontset);
+ FcFontSetDestroy( fontSet );
}
else
{
- DALI_ASSERT_ALWAYS( 0 && "No valid fonts found on system." );
+ DALI_ASSERT_ALWAYS( false && "No valid fonts found on system." );
}
+
// return the font list for the specified mode
- return GetCachedFontList( fontListMode );
+ GetCachedFontList( fontListMode, fontList );
}
-bool FontController::ValidateFontFamilyName( const StyledFontFamily& styledFontFamily, bool& isDefaultSystemFont, StyledFontFamily& closestStyledFontFamilyMatch )
+bool FontController::ValidateFontFamilyName( const StyledFontFamily& styledFontFamily,
+ bool& isDefaultSystemFontFamily,
+ bool& isDefaultSystemFontStyle,
+ StyledFontFamily& closestStyledFontFamilyMatch )
{
- // get font family path also finds the closest match
- std::string path = GetFontFamilyPath( styledFontFamily, isDefaultSystemFont, closestStyledFontFamilyMatch );
+ // Initialize the defaults to false as the validation process supposes the given font is correct.
+ isDefaultSystemFontFamily = false;
+ isDefaultSystemFontStyle = false;
+
+ // default the closest Match to empty
+ closestStyledFontFamilyMatch.first.clear();
+ closestStyledFontFamilyMatch.second.clear();
+
+ // lock the mFontFamilyCacheMutex and don't release it until the function finishes.
+ // If we release it then another thread may try to create the same duplicate data.
+ boost::mutex::scoped_lock lock( mFontFamilyCacheMutex );
- // it should always find a closest match
- DALI_ASSERT_ALWAYS( !closestStyledFontFamilyMatch.first.empty() && "Cannot find closest match for font family" );
+ StyledFontFamily styledFontFamilyToCheck = styledFontFamily;
- if( path.empty() )
+ // if the font is blank, then use the default font if it has been cached
+ if( styledFontFamilyToCheck.first.empty() && ( !mDefaultStyledFont.first.empty() ) )
{
- return false;
+ styledFontFamilyToCheck.first = mDefaultStyledFont.first;
+
+ // No font family is given, default system font is used.
+ isDefaultSystemFontFamily = true;
}
- else
+
+ if( styledFontFamilyToCheck.second.empty() && ( !mDefaultStyledFont.second.empty() ) )
+ {
+ styledFontFamilyToCheck.second = mDefaultStyledFont.second;
+
+ // No font style is given, default system font is used.
+ isDefaultSystemFontStyle = true;
+ }
+
+ // first check to see if the font has been matched before.
+ closestStyledFontFamilyMatch = GetMatchedFont( styledFontFamilyToCheck );
+
+ if( !closestStyledFontFamilyMatch.first.empty() )
+ {
+ // The font has been cached before.
+ return true;
+ }
+
+ // check the cache
+ const std::string& fontFileName = GetCachedFontPath( styledFontFamilyToCheck );
+
+ if( !fontFileName.empty() )
{
+ // The font has been cached before.
+
+ closestStyledFontFamilyMatch = styledFontFamilyToCheck;
+
return true;
}
+
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose,"Failed to find %s %s in cache, querying FontConfig for a match\n", styledFontFamily.first.c_str(), styledFontFamily.second.c_str() );
+
+ // it's not in the cache, find a match using font config and add it to the cache
+ boost::mutex::scoped_lock fcLock( mFontConfigMutex );
+
+ // create the pattern
+ FcPattern* fontFamilyPattern = CreateFontFamilyPattern( styledFontFamilyToCheck );
+
+ FcResult result(FcResultMatch);
+
+ // match the pattern
+ FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
+
+ bool validFont = false;
+
+ if( match )
+ {
+ validFont = true;
+
+ CacheFontInfo( match, styledFontFamilyToCheck, closestStyledFontFamilyMatch );
+
+ // destroyed the matched pattern
+ FcPatternDestroy( match );
+ }
+ else
+ {
+ DALI_LOG_ERROR( "FcFontMatch failed for font %s %s\n", styledFontFamilyToCheck.first.c_str(), styledFontFamilyToCheck.second.c_str() );
+ }
+
+ // destroy the pattern
+ FcPatternDestroy( fontFamilyPattern );
+
+ return validFont;
}
-FontController::StyledFontFamily FontController::GetFontFamilyForChars(const TextArray& charsRequested)
+const FontController::StyledFontFamily& FontController::GetFontFamilyForChars( const TextArray& charsRequested )
{
- if( mPreferredFonts.empty() )
+ if( 0u == mPreferredFonts.Count() )
{
CreatePreferedFontList();
}
// Cycle through the preferred list of fonts on the system for 'Tizen'.
- for( std::size_t n = 0; n < mPreferredFonts.size() ; n++ )
+ for( std::size_t n = 0u; n < mPreferredFonts.Count(); ++n )
{
- StyledFontFamily font = mPreferredFonts[n];
+ const StyledFontFamily& font = *mPreferredFonts[n];
- // First make sure it is cached so we can access it's character set object
- std::string filePath = GetFontPath( font );
- if( filePath.empty())
+ if( !mPreferredFontsValidated[n] )
{
- filePath = GetFontPath( font );
+ // First make sure it is validated and cached so we can access it's character set object
+ bool isDefaultSystemFontFamily = false;
+ bool isDefaultSystemFontStyle = false;
+ StyledFontFamily closestStyledFontFamilyMatch;
+ ValidateFontFamilyName( font,
+ isDefaultSystemFontFamily,
+ isDefaultSystemFontStyle,
+ closestStyledFontFamilyMatch );
+
+ mPreferredFontsValidated[n] = true;
}
- if( filePath.empty())
+ const std::string& filePath = GetFontPath( font );
+
+ if( filePath.empty() )
{
continue;
}
- bool matched = FontFamilySupportsText( font, charsRequested);
+
+ const bool matched = FontFamilySupportsText( font, charsRequested );
if( matched )
{
return font;
}
}
+
// return empty string
- return StyledFontFamily();
+ return NULL_STYLED_FONT_FAMILY;
}
-void FontController::CacheFontInfo(FcPattern* pattern, const StyledFontFamily& inputStyledFontFamily, StyledFontFamily& closestStyledFontFamilyMatch )
+void FontController::CacheFontInfo( FcPattern* pattern, const StyledFontFamily& inputStyledFontFamily, StyledFontFamily& closestStyledFontFamilyMatch )
{
- FcChar8 *family, *file;
- FcCharSet *matchedCharSet;
- FcResult retVal;
-
// Check we can get the following data from the pattern
- retVal = FcPatternGetString( pattern, FC_FAMILY, 0, &family );
- if( retVal != FcResultMatch )
+ if( !GetFontFamily( pattern, closestStyledFontFamilyMatch.first ) )
{
- DALI_LOG_INFO (gLogFilter, Debug::Verbose,"CacheFontInfo failed to get family information from pattern %s %s\n",inputStyledFontFamily.first.c_str(),inputStyledFontFamily.second.c_str());
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "CacheFontInfo failed to get family information from pattern %s %s\n", inputStyledFontFamily.first.c_str(), inputStyledFontFamily.second.c_str() );
return;
}
- retVal = FcPatternGetString( pattern, FC_FILE, 0, &file);
- if( retVal!= FcResultMatch)
+
+ std::string fileName;
+ if( !GetFileName( pattern, fileName ) )
{
- DALI_LOG_INFO (gLogFilter, Debug::Verbose,"CacheFontInfo failed to get file information from pattern %s %s\n",inputStyledFontFamily.first.c_str(),inputStyledFontFamily.second.c_str());
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "CacheFontInfo failed to get file information from pattern %s %s\n", inputStyledFontFamily.first.c_str(), inputStyledFontFamily.second.c_str() );
return;
}
- retVal = FcPatternGetCharSet( pattern, FC_CHARSET, 0, &matchedCharSet);
- if( retVal!= FcResultMatch)
+
+ FcCharSet* matchedCharSet = NULL;
+ const FcResult retVal = FcPatternGetCharSet( pattern, FC_CHARSET, 0u, &matchedCharSet );
+ if( retVal != FcResultMatch )
{
- DALI_LOG_INFO (gLogFilter, Debug::Verbose,"CacheFontInfo failed to get character set from pattern %s %s\n",inputStyledFontFamily.first.c_str(),inputStyledFontFamily.second.c_str());
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "CacheFontInfo failed to get character set from pattern %s %s\n", inputStyledFontFamily.first.c_str(), inputStyledFontFamily.second.c_str() );
return;
}
- // have to use reinterpret_cast because FcChar8 is unsigned char *, not a char *
- std::string familyName = reinterpret_cast<const char*>(family);
- std::string fileName = reinterpret_cast<const char*>(file);
- std::string fontStyle = GetFontStyle( pattern );
-
- closestStyledFontFamilyMatch = std::make_pair( familyName, fontStyle );
+ GetFontStyle( pattern, closestStyledFontFamilyMatch.second );
// Add the match to the font cache
AddCachedFont( closestStyledFontFamilyMatch, fileName, matchedCharSet );
-
if( ( !inputStyledFontFamily.first.empty() &&
- inputStyledFontFamily.first != familyName ) ||
- ( inputStyledFontFamily.second != fontStyle ))
+ ( inputStyledFontFamily.first != closestStyledFontFamilyMatch.first ) ) &&
+ ( !inputStyledFontFamily.second.empty() &&
+ ( inputStyledFontFamily.second != closestStyledFontFamilyMatch.second ) ) )
{
// if the font family used to create the pattern was not found in the match then
// store it in the MissingFont container
- AddFontNotFound( inputStyledFontFamily, closestStyledFontFamilyMatch );
+ AddMatchedFont( inputStyledFontFamily, closestStyledFontFamilyMatch );
}
}
-bool FontController::AllGlyphsSupported(const StyledFontFamily& styledFontFamily, const TextArray& text)
+bool FontController::AllGlyphsSupported( const StyledFontFamily& styledFontFamily, const TextArray& text )
{
- StyledFontFamily closestStyledFontFamilyMatch;
- bool isDefault( false );
-
- // make sure the font is cached first.
- std::string path = GetFontFamilyPath( styledFontFamily, isDefault, closestStyledFontFamilyMatch );
-
- if( path.empty() )
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "font family not found \n");
- return false;
- }
-
- return FontFamilySupportsText( styledFontFamily, text);
+ // The font has already been validated by the font implementation.
+ return FontFamilySupportsText( styledFontFamily, text );
}
void FontController::SetDefaultFontFamily( const StyledFontFamily& styledFontFamily )
{
// reload font configuration files
- bool ok = FcInitReinitialize();
+ const bool ok = FcInitReinitialize();
DALI_ASSERT_ALWAYS( ok && "FcInitReinitialize failed");
CreatePreferedFontList();
}
-void FontController::AddCachedFont(const StyledFontFamily& styledFontFamily, const std::string& fontPath, _FcCharSet *characterSet)
+void FontController::AddCachedFont( const StyledFontFamily& styledFontFamily, const std::string& fontPath, _FcCharSet *characterSet )
{
- if( styledFontFamily.first.empty() )
- {
- return;
- }
-
FontFamilyLookup::const_iterator iter = mFontFamilyCache.find( styledFontFamily );
if( iter == mFontFamilyCache.end() )
{
item.FcCharSet = FcCharSetCopy( characterSet ); // increase the ref count on the char set
mFontFamilyCache[ styledFontFamily ] = item;
- DALI_LOG_INFO (gLogFilter, Debug::Verbose,"Caching font %s %s\n",styledFontFamily.first.c_str(), styledFontFamily.second.c_str());
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Caching font %s %s\n", styledFontFamily.first.c_str(), styledFontFamily.second.c_str() );
}
}
-FontList FontController::GetCachedFontList( FontListMode fontListMode ) const
+void FontController::GetCachedFontList( FontListMode fontListMode, FontList& fontList ) const
{
// return a list of fonts, for the FontListMode
switch( fontListMode )
{
case LIST_SYSTEM_FONTS:
{
- return mFontSystemList;
+ fontList.insert( fontList.end(), mFontSystemList.begin(), mFontSystemList.end() );
+ return;
}
case LIST_APPLICATION_FONTS:
{
- return mFontApplicationList;
+ fontList.insert( fontList.end(), mFontApplicationList.begin(), mFontApplicationList.end() );
+ return;
}
case LIST_ALL_FONTS:
{
// add both system and application fonts together
- FontList list( mFontSystemList );
- list.insert( list.end(), mFontApplicationList.begin(), mFontApplicationList.end() );
- return list;
+ fontList.insert( fontList.end(), mFontSystemList.begin(), mFontSystemList.end() );
+ fontList.insert( fontList.end(), mFontApplicationList.begin(), mFontApplicationList.end() );
+ return;
}
}
- DALI_ASSERT_ALWAYS(!"GetCachedFontList called with invalid value.");
+ DALI_ASSERT_ALWAYS( false && "GetCachedFontList called with invalid value." );
}
-std::string FontController::GetCachedFontPath( const StyledFontFamily& styledFontFamily ) const
+
+const std::string& FontController::GetCachedFontPath( const StyledFontFamily& styledFontFamily ) const
{
if( !mFontFamilyCache.empty() )
{
return (*iter).second.FontFileName;
}
}
- return "";
+
+ return NULL_FONT_FAMILY_NAME;
}
FcCharSet* FontController::GetCachedFontCharacterSet( const StyledFontFamily& styledFontFamily ) const
return NULL;
}
-std::string FontController::GetFontFamilyPath( const StyledFontFamily& styledFontFamily, bool& isDefaultSystemFont, StyledFontFamily& closestStyledFontFamilyMatch )
-{
- // Lets suppose the given font family is ok.
- isDefaultSystemFont = false;
-
- // default the closest Match to empty
- closestStyledFontFamilyMatch = std::make_pair("","");
-
- std::string font( styledFontFamily.first );
- std::string style( styledFontFamily.second );
-
- // lock the mFontFamilyCacheMutex and don't release it until the function finishes.
- // If we release it then another thread may try to create the same duplicate data.
- boost::mutex::scoped_lock lock( mFontFamilyCacheMutex );
-
- // if the font is blank, then use the default font if it has been cached
- if( font.empty() && ( !mDefaultStyledFont.first.empty() ) )
- {
- font = mDefaultStyledFont.first;
- style = mDefaultStyledFont.second;
-
- // No font family is given, default system font is used.
- isDefaultSystemFont = true;
- }
-
- StyledFontFamily styledFontFamilyToCheck = std::make_pair( font, style );
-
- // first check to see if the font has been marked as not found
- closestStyledFontFamilyMatch = GetFontNotFound( styledFontFamilyToCheck );
-
- if( !closestStyledFontFamilyMatch.first.empty() )
- {
- // the font wasn't found, so return an empty path
- return "";
- }
-
- // check the cache
- std::string fontFileName = GetCachedFontPath( styledFontFamilyToCheck );
-
- if( !fontFileName.empty() )
- {
- closestStyledFontFamilyMatch = std::make_pair( font, style );
-
- return fontFileName;
- }
-
- DALI_LOG_INFO( gLogFilter, Debug::Verbose,"Failed to find %s %s in cache, querying FontConfig for a match\n", styledFontFamily.first.c_str(), styledFontFamily.second.c_str());
-
- // it's not in the cache, find a match using font config and add it to the cache
- boost::mutex::scoped_lock fcLock( mFontConfigMutex );
-
- // create the pattern
- _FcPattern *fontFamilyPattern = CreateFontFamilyPattern( std::make_pair( font, style ) );
-
- FcResult result(FcResultMatch);
-
- // match the pattern
- _FcPattern *match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
-
- if( match )
- {
- CacheFontInfo(match, std::make_pair( font, style ), closestStyledFontFamilyMatch);
-
- fontFileName = GetCachedFontPath(closestStyledFontFamilyMatch);
-
- // destroyed the matched pattern
- FcPatternDestroy( match );
- }
- else
- {
- DALI_LOG_ERROR("FcFontMatch failed for font %s %s\n",font.c_str(),style.c_str());
- }
-
- // destroy the pattern
- FcPatternDestroy( fontFamilyPattern );
-
- if( closestStyledFontFamilyMatch != styledFontFamily )
- {
- // the font wasn't font, so return an empty path
- return "";
- }
- else
- {
- return fontFileName;
- }
-}
-
-_FcPattern* FontController::CreateFontFamilyPattern(const StyledFontFamily& styledFontFamily)
+_FcPattern* FontController::CreateFontFamilyPattern( const StyledFontFamily& styledFontFamily )
{
// 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();
+ FcPattern* fontFamilyPattern = FcPatternCreate();
// add a property to the pattern for the font family
- FcPatternAddString( fontFamilyPattern, FC_FAMILY, (FcChar8 *)(styledFontFamily.first.c_str()));
+ FcPatternAddString( fontFamilyPattern, FC_FAMILY, reinterpret_cast<const FcChar8*>( styledFontFamily.first.c_str() ) );
// add a property to the pattern for the font family
- FcPatternAddString( fontFamilyPattern, FC_STYLE, (FcChar8 *)(styledFontFamily.second.c_str()));
+ FcPatternAddString( fontFamilyPattern, FC_STYLE, reinterpret_cast<const FcChar8*>( styledFontFamily.second.c_str() ) );
// Add a property of the pattern, to say we want to match TrueType fonts
- FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, (FcChar8 *)"TrueType");
+ FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, reinterpret_cast<const FcChar8*>( FONT_FORMAT.c_str() ) );
// modify the config, with the mFontFamilyPatterm
FcConfigSubstitute( NULL /* use default configure */, fontFamilyPattern, FcMatchPattern );
return fontFamilyPattern;
}
-bool FontController::IsAControlCharacter(uint32_t character) const
+bool FontController::IsAControlCharacter( uint32_t character ) const
{
// UNICODE_CHAR_START is the space character
// below it are the control characters that we want to ignore.
- if( character < UNICODE_CHAR_START ||
- character == UNICODE_CR_LF )
- {
- return true;
- }
- else
- {
- return false;
- }
+ return( ( character < UNICODE_CHAR_START ) ||
+ ( character == UNICODE_CR_LF ) );
}
-bool FontController::FontFamilySupportsText(const StyledFontFamily& styledFontFamily, const TextArray& text )
+bool FontController::FontFamilySupportsText( const StyledFontFamily& styledFontFamily, const TextArray& text )
{
- _FcCharSet* charSet = GetCachedFontCharacterSet( styledFontFamily );
+ FcCharSet* charSet = GetCachedFontCharacterSet( styledFontFamily );
DALI_ASSERT_ALWAYS( charSet && "No cached character set for font family" );
- size_t textLength = text.size();
+ const size_t textLength = text.size();
// quick early exit before accessing font config for text arrays which are just a single control character
- if( textLength == 1 )
+ if( textLength == 1u )
{
- if( IsAControlCharacter( text[0] ) )
+ if( IsAControlCharacter( *text.begin() ) )
{
return true;
}
// protect font config
boost::mutex::scoped_lock fcLock( mFontConfigMutex );
- for( TextArray::const_iterator iter = text.begin(), endIter = text.end(); iter != endIter; ++iter)
+ for( TextArray::const_iterator iter = text.begin(), endIter = text.end(); iter != endIter; ++iter )
{
const uint32_t character = (*iter);
// if it's a control character then don't test it
- if( IsAControlCharacter( character) )
+ if( IsAControlCharacter( character ) )
{
continue;
}
// test to see if the character set supports the character
- FcBool hasChar = FcCharSetHasChar(charSet, character );
- if( !hasChar )
+ if( !FcCharSetHasChar( charSet, character ) )
{
return false;
}
{
// should be called by the destructor only
- for( FontFamilyLookup::iterator iter = mFontFamilyCache.begin(), enditer = mFontFamilyCache.end(); iter != enditer; ++iter)
+ for( FontFamilyLookup::iterator iter = mFontFamilyCache.begin(), enditer = mFontFamilyCache.end(); iter != enditer; ++iter )
{
FontCacheItem& cacheItem = (*iter).second;
mFontFamilyCache.clear();
}
-void FontController::AddToFontList(const std::string& fileName, const StyledFontFamily& styledFontFamily)
+void FontController::AddToFontList( const std::string& fileName, const StyledFontFamily& styledFontFamily )
{
- bool systemFont = CheckFontInstallPath(LIST_SYSTEM_FONTS, fileName);
+ const bool systemFont = CheckFontInstallPath( LIST_SYSTEM_FONTS, fileName );
FontList* fontList(NULL);
{
// create a new pattern.
// a pattern holds a set of names, each name refers to a property of the font
- FcPattern *pattern = FcPatternCreate();
+ FcPattern* pattern = FcPatternCreate();
// create an object set used to define which properties are to be returned in the patterns from FcFontList.
- FcObjectSet *objectSet = FcObjectSetCreate();
+ FcObjectSet* objectSet = FcObjectSetCreate();
// build an object set from a list of property names
- FcObjectSetAdd( objectSet, FC_FAMILY);
- FcObjectSetAdd( objectSet, FC_STYLE);
- FcObjectSetAdd( objectSet, FC_FILE);
+ FcObjectSetAdd( objectSet, FC_FAMILY );
+ FcObjectSetAdd( objectSet, FC_STYLE );
+ FcObjectSetAdd( objectSet, FC_FILE );
// 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);
+ 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 )
{
FcPatternDestroy( pattern );
}
+
return fontset;
}
-_FcCharSet* FontController::CreateCharacterSet(const TextArray& charsRequested)
+_FcCharSet* FontController::CreateCharacterSet( const TextArray& charsRequested )
{
// create the character set object
FcCharSet* charSet = FcCharSetCreate();
bool validCharAdded(false);
// add valid characters to the character set.
- for (TextArray::const_iterator iter = charsRequested.begin(), endIter = charsRequested.end(); iter != endIter; ++iter)
+ for( TextArray::const_iterator iter = charsRequested.begin(), endIter = charsRequested.end(); iter != endIter; ++iter )
{
const uint32_t character = (*iter);
// if it's not a control character then add it
if( !IsAControlCharacter( character ) )
{
- FcBool ok = FcCharSetAddChar(charSet, character );
+ FcBool ok = FcCharSetAddChar( charSet, character );
if( ok )
{
validCharAdded = true;
return charSet;
}
-void FontController::AddFontNotFound( const StyledFontFamily& missingStyledFontFamily, StyledFontFamily& closestStyledFontFamilyMatch )
+void FontController::AddMatchedFont( const StyledFontFamily& missingStyledFontFamily, StyledFontFamily& closestStyledFontFamilyMatch )
{
-
// we store the missing font, and the name of the font that font config found as the closet match
- mFontsNotFound[ missingStyledFontFamily ] = closestStyledFontFamilyMatch;
+ mMatchedFontsFound[ missingStyledFontFamily ] = closestStyledFontFamilyMatch;
+}
+
+const FontController::StyledFontFamily& FontController::GetMatchedFont( const StyledFontFamily& styledFontFamily ) const
+{
+ if( mMatchedFontsFound.empty() )
+ {
+ return NULL_STYLED_FONT_FAMILY;
+ }
+
+ MatchedFontLookup::const_iterator iter = mMatchedFontsFound.find( styledFontFamily );
+ if( iter != mMatchedFontsFound.end() )
+ {
+ return iter->second;
+ }
+
+ return NULL_STYLED_FONT_FAMILY;
}
-FontController::StyledFontFamily FontController::GetFontNotFound(const StyledFontFamily& styledFontFamily) const
+void FontController::CreatePreferedFontList( )
{
- if( mFontsNotFound.empty() )
+ StyledFontFamily tizenFont;
+ tizenFont.first = DEFAULT_FONT_FAMILY_NAME;
+ tizenFont.second = DEFAULT_FONT_STYLE;
+
+ // clear the current list
+ ClearPreferredFontList();
+
+ FcPattern* searchPattern = CreateFontFamilyPattern( tizenFont );
+
+ FcResult result(FcResultMatch);
+
+ // Match the pattern.
+ StyledFontFamily previousFont;
+
+ FcFontSet* fontSet = FcFontSort( NULL /* use default configure */, searchPattern, false /* don't trim */, NULL, &result );
+
+ for( int i = 0u; i < fontSet->nfont; ++i )
{
- return std::make_pair("","");
+ // we have already filled in the first entry with the default font
+ FcPattern* pattern = fontSet->fonts[i];
+
+ StyledFontFamily* styledFont = new StyledFontFamily();
+
+ GetFontFamily( pattern, styledFont->first );
+ GetFontStyle( pattern, styledFont->second );
+
+ if( *styledFont != previousFont )
+ {
+ mPreferredFonts.PushBack( styledFont );
+ }
+ if( i == 0u )
+ {
+ mDefaultStyledFont = *styledFont;
+ }
+ previousFont = *styledFont;
}
- FontsNotFound::const_iterator iter = mFontsNotFound.find( styledFontFamily );
- if( iter != mFontsNotFound.end() )
+ // Set all fonts to non validated.
+ mPreferredFontsValidated.Resize( fontSet->nfont, false );
+
+ FcPatternDestroy( searchPattern );
+ FcFontSetDestroy( fontSet );
+}
+
+void FontController::ClearPreferredFontList()
+{
+ for( Vector<StyledFontFamily*>::Iterator it = mPreferredFonts.Begin(), endIt = mPreferredFonts.End(); it != endIt; ++it )
{
- return (*iter).second;
+ delete *it;
}
- return std::make_pair("","");
+ mPreferredFonts.Clear();
}
} // namespace SlpPlatform
// INTERNAL INCLUDES
#include "../../interfaces/font-controller.h"
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/map-wrapper.h>
// EXTERNAL INCLUDES
#include <boost/thread.hpp>
-#include <map>
// forward declarations of font config types
* Internally caches the font file name for every font family passed in
* @copydoc Dali::Platform::FontController::GetFontPath()
*/
- virtual std::string GetFontPath( const StyledFontFamily& styledFontFamily );
+ virtual const std::string& GetFontPath( const StyledFontFamily& styledFontFamily );
/**
* Internally caches the font list the first time it is called.
* @copydoc Dali::Platform::FontController::GetFontList()
*/
- virtual FontList GetFontList( FontListMode fontListMode );
+ virtual void GetFontList( FontListMode fontListMode, FontList& fontList );
/**
* @copydoc Dali::Platform::FontController::ValidateFontFamilyName()
*/
- virtual bool ValidateFontFamilyName(const StyledFontFamily& styledFontFamily, bool& isDefaultSystemFont, StyledFontFamily& closestStyledFontFamilyMatch);
+ virtual bool ValidateFontFamilyName( const StyledFontFamily& styledFontFamily,
+ bool& isDefaultSystemFontFamily,
+ bool& isDefaultSystemFontStyle,
+ StyledFontFamily& closestStyledFontFamilyMatch );
/**
* @copydoc Dali::Platform::FontController::GetFontFamilyForChars()
*/
- virtual StyledFontFamily GetFontFamilyForChars( const TextArray& charsRequested);
+ virtual const StyledFontFamily& GetFontFamilyForChars( const TextArray& charsRequested);
/**
* @copydoc Dali::Platform::FontController::AllGlyphsSupported()
*/
- virtual bool AllGlyphsSupported(const StyledFontFamily& styledFontFamily, const TextArray& text);
+ virtual bool AllGlyphsSupported( const StyledFontFamily& styledFontFamily, const TextArray& text );
/**
* @copydoc Dali::Platform::FontController::SetDefaultFontFamily()
* @param[in] fontListMode the font list mode
* @return font list
*/
- FontList GetCachedFontList( FontListMode fontListMode ) const;
+ void GetCachedFontList( FontListMode fontListMode, FontList& fontList ) const;
/**
* returns the font path given a font family.
* @param[in] styledFontFamily The name of the font's family and the font's style.
- * @return font path.
+ * @return The font's file name path.
*/
- std::string GetCachedFontPath( const StyledFontFamily& styledFontFamily ) const;
+ const std::string& GetCachedFontPath( const StyledFontFamily& styledFontFamily ) const;
/**
* returns the cached character set for a font family.
* @param[in] fontPath font path.
* @param[in] characterSet font config character set object (not const because it's ref count is increased).
*/
- void AddCachedFont( const StyledFontFamily& styledFontFamily, const std::string& fontPath,_FcCharSet *characterSet);
-
- /**
- * Given a font family and its style, it will return the path for that font family.
- * If the font family is not found, then the closestMatchFamily is set
- * to the closes matching font family.
- * @param[in] styledFontFamily The name of the font's family and the font's style.
- * @param[out] isDefaultSystemFont Whether this font has been created with a default system font.
- * @param[out] closestStyledFontFamilyMatch name found based on the user input family name and style.
- * @return path of the font family
- */
- std::string GetFontFamilyPath( const StyledFontFamily& styledFontFamily, bool& isDefaultSystemFont, StyledFontFamily& closestStyledFontFamilyMatch );
-
+ void AddCachedFont( const StyledFontFamily& styledFontFamily, const std::string& fontPath, _FcCharSet *characterSet );
/**
* Store information held in a fontconfig pattern, into the font cache.
* Stores font name, filename and character set.
* @param[in] pattern pointer to a font config pattern.
* @param[in] inputStyledFontFamily font family name with its style used to perform the pattern match.
- * @param[out] closestStyledFontFamilyMatch mached family name and style.
+ * @param[out] closestStyledFontFamilyMatch matched family name and style.
*/
void CacheFontInfo( _FcPattern* pattern, const StyledFontFamily& inputStyledFontFamily, StyledFontFamily& closestStyledFontFamilyMatch );
/**
* Checks whether a character is a control character.
*/
- bool IsAControlCharacter(uint32_t character) const;
+ bool IsAControlCharacter( uint32_t character ) const;
/**
* Checks cached fonts to see if they support the text.
* @param text text array.
* @return true if the font family supports the text false if not.
*/
- bool FontFamilySupportsText(const StyledFontFamily& styledFontFamily, const TextArray& text );
+ bool FontFamilySupportsText( const StyledFontFamily& styledFontFamily, const TextArray& text );
/**
* Clear the font family cache.
* @param fileName the font full filename with path
* @param styledFontFamily The name of the font's family and the font's style.
*/
- void AddToFontList( const std::string& fileName, const StyledFontFamily& styledFontFamily);
+ void AddToFontList( const std::string& fileName, const StyledFontFamily& styledFontFamily );
/**
* Returns a FontConfig font set, which has a list of fonts.
* @param charsRequested array of characters.
* @return a pointer to _FcCharSet object on success, NULL on failure.
*/
- _FcCharSet* CreateCharacterSet(const TextArray& charsRequested);
+ _FcCharSet* CreateCharacterSet( const TextArray& charsRequested );
/**
- * Add a font that has not been found on the system.
+ * Add a font that has not been found on the system but a match has been found.
* @param[in] missingStyledFontFamily the missing font and its style to add.
* @param[in] closestStyledFontFamilyMatch it's nearest font and its style match.
*/
- void AddFontNotFound( const StyledFontFamily& missingStyledFontFamily, StyledFontFamily& closestStyledFontFamilyMatch );
+ void AddMatchedFont( const StyledFontFamily& missingStyledFontFamily, StyledFontFamily& closestStyledFontFamilyMatch );
/**
* Check the cache to see if a font and its style has been added to the missing fonts list.
* @param styledFontFamily the font and its style to check.
* @return the closest styled font that the missing styled font has been matched with by font-config.
*/
- StyledFontFamily GetFontNotFound(const StyledFontFamily& styledFontFamily) const;
+ const StyledFontFamily& GetMatchedFont( const StyledFontFamily& styledFontFamily ) const;
/**
* Create a preferred list of fonts to use for when GetFontFamilyForChars() is called.
void CreatePreferedFontList();
/**
+ * Deletes all preferred fonts.
+ */
+ void ClearPreferredFontList();
+
+ /**
* Font cache item.
*/
struct FontCacheItem
_FcCharSet* FcCharSet; ///< font config character set, used to test if a character is supported
};
- typedef std::map<StyledFontFamily, FontCacheItem> FontFamilyLookup; ///< lookup for font names and font cache itmes
+ typedef std::map<StyledFontFamily, FontCacheItem> FontFamilyLookup; ///< lookup for font names and font cache itmes
- typedef std::map<StyledFontFamily, StyledFontFamily> FontsNotFound; ///< lookup for fonts that don't exist, and their nearest match return by FontConfig
+ typedef std::map<StyledFontFamily, StyledFontFamily> MatchedFontLookup; ///< lookup for fonts that don't exist, and their nearest match return by FontConfig
boost::mutex mFontConfigMutex; ///< FontConfig needs serializing because it isn't thread safe
boost::mutex mFontFamilyCacheMutex; ///< to protect the FontFamilyCache data
FontList mFontApplicationList; ///< cached list of application fonts
FontFamilyLookup mFontFamilyCache; ///< cache of font names and corresponding font cache items
- FontsNotFound mFontsNotFound; ///< lookup for fonts that haven't been found on the sytem, and the nearest matching font.
- std::vector< StyledFontFamily > mPreferredFonts; ///< Ordered list of preferred fonts.
+ MatchedFontLookup mMatchedFontsFound; ///< lookup for fonts that haven't been found on the sytem, and the nearest matching font.
+ Vector<StyledFontFamily*> mPreferredFonts; ///< Ordered list of preferred fonts.
+ Vector<bool> mPreferredFontsValidated; ///< Stores which of the prefered fonts have been validated.
};