FontClient implementation 71/35371/4
authorVictor Cebollada <v.cebollada@samsung.com>
Wed, 11 Feb 2015 07:52:12 +0000 (07:52 +0000)
committerVictor Cebollada <v.cebollada@samsung.com>
Wed, 18 Feb 2015 14:52:07 +0000 (14:52 +0000)
Change-Id: Ic866f7014290b948b99f862565b91462d6c2e637
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
adaptors/public-api/file.list
text/dali/internal/text-abstraction/font-client-impl.cpp
text/dali/internal/text-abstraction/font-client-impl.h
text/dali/internal/text-abstraction/font-client-plugin-impl.cpp
text/dali/internal/text-abstraction/font-client-plugin-impl.h
text/dali/public-api/text-abstraction/font-client.cpp
text/dali/public-api/text-abstraction/font-client.h

index f0b1785..66502d6 100644 (file)
@@ -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 \
index 51f56d0..d069949 100644 (file)
@@ -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();
   }
 }
 
index be42c01..8965607 100644 (file)
@@ -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 );
index 2ba2693..fdd4980 100644 (file)
@@ -23,6 +23,9 @@
 #include <dali/public-api/text-abstraction/glyph-info.h>
 #include <dali/integration-api/debug.h>
 
+// EXTERNAL INCLUDES
+#include <fontconfig/fontconfig.h>
+
 /**
  * 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<const char*>( file ) );
-
-    return true;
+    InitSystemFonts();
   }
 
-  return false;
+  systemFonts = mSystemFonts;
 }
 
 void FontClient::Plugin::GetDescription( FontId id,
                                          FontDescription& fontDescription ) const
 {
-  // TODO
+  for( std::vector<FontIdCacheItem>::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<const FcChar8*>( fontFamily.c_str() ) );
+
+  // add a property to the pattern for the font family
+  FcPatternAddString( fontFamilyPattern, FC_STYLE, reinterpret_cast<const FcChar8*>( fontStyle.c_str() ) );
+
+  // Add a property of the pattern, to say we want to match TrueType fonts
+  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 );
+
+  // 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<const char*>( 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<CacheItem>::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<FontDescriptionCacheItem>::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<mFontCache.size(); ++i )
+  fontId = 0u;
+
+  for( std::vector<FontIdCacheItem>::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;
     }
   }
index 58163f4..e4995a7 100644 (file)
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
-#include <fontconfig/fontconfig.h>
+
+// 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<CacheItem> 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<CacheItem>                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<FontDescriptionCacheItem> 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<FontIdCacheItem>          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
index 027dbc5..90aa49a 100644 (file)
@@ -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 );
index 940f353..aa63353 100644 (file)
@@ -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.