2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/text-abstraction/font-client-plugin-impl.h>
22 #include <dali/public-api/common/dali-vector.h>
23 #include <dali/public-api/common/vector-wrapper.h>
24 #include <dali/public-api/text-abstraction/glyph-info.h>
25 #include <dali/integration-api/debug.h>
28 #include <fontconfig/fontconfig.h>
31 * Conversion from Fractional26.6 to float
35 const float FROM_266 = 1.0f / 64.0f;
37 const std::string FONT_FORMAT( "TrueType" );
38 const std::string DEFAULT_FONT_FAMILY_NAME( "Tizen" );
39 const std::string DEFAULT_FONT_STYLE( "Regular" );
47 namespace TextAbstraction
53 const bool FONT_FIXED_SIZE_BITMAP( true );
55 FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem( const FontFamily& fontFamily,
56 const FontStyle& fontStyle,
57 FontDescriptionId index )
58 : fontFamily( fontFamily ),
59 fontStyle( fontStyle ),
63 FontClient::Plugin::FontIdCacheItem::FontIdCacheItem( FontDescriptionId validatedFontId,
64 PointSize26Dot6 pointSize,
66 : validatedFontId( validatedFontId ),
67 pointSize( pointSize ),
71 FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
73 PointSize26Dot6 pointSize,
75 const FontMetrics& metrics,
76 bool isFixedSizeBitmap )
77 : mFreeTypeFace( ftFace ),
79 mPointSize( pointSize ),
82 mIsFixedSizeBitmap( isFixedSizeBitmap )
85 FontClient::Plugin::Plugin( unsigned int horizontalDpi,
86 unsigned int verticalDpi )
87 : mFreeTypeLibrary( NULL ),
88 mDpiHorizontal( horizontalDpi ),
89 mDpiVertical( verticalDpi ),
93 mValidatedFontCache(),
94 mFontDescriptionCache( 1u ),
97 int error = FT_Init_FreeType( &mFreeTypeLibrary );
98 if( FT_Err_Ok != error )
100 DALI_LOG_ERROR( "FreeType Init error: %d\n", error );
104 FontClient::Plugin::~Plugin()
106 FT_Done_FreeType( mFreeTypeLibrary );
109 void FontClient::Plugin::SetDpi( unsigned int horizontalDpi,
110 unsigned int verticalDpi )
112 mDpiHorizontal = horizontalDpi;
113 mDpiVertical = verticalDpi;
116 void FontClient::Plugin::SetDefaultFontFamily( const FontFamily& fontFamilyName,
117 const FontStyle& fontStyle )
119 mDefaultFonts.clear();
121 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamilyName,
124 FcResult result = FcResultMatch;
126 // Match the pattern.
127 FcFontSet* fontSet = FcFontSort( NULL /* use default configure */,
129 false /* don't trim */,
133 if( NULL != fontSet )
135 // Reserve some space to avoid reallocations.
136 mDefaultFonts.reserve( fontSet->nfont );
138 for( int i = 0u; i < fontSet->nfont; ++i )
140 FcPattern* fontPattern = fontSet->fonts[i];
144 // Skip fonts with no path
145 if( GetFcString( fontPattern, FC_FILE, path ) )
147 mDefaultFonts.push_back( FontDescription() );
148 FontDescription& fontDescription = mDefaultFonts.back();
150 fontDescription.path = path;
152 GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
153 GetFcString( fontPattern, FC_STYLE, fontDescription.style );
157 FcFontSetDestroy( fontSet );
160 FcPatternDestroy( fontFamilyPattern );
163 void FontClient::Plugin::GetDefaultFonts( FontList& defaultFonts )
165 if( mDefaultFonts.empty() )
167 SetDefaultFontFamily( DEFAULT_FONT_FAMILY_NAME,
168 DEFAULT_FONT_STYLE );
171 defaultFonts = mDefaultFonts;
174 void FontClient::Plugin::GetSystemFonts( FontList& systemFonts )
176 if( mSystemFonts.empty() )
181 systemFonts = mSystemFonts;
184 void FontClient::Plugin::GetDescription( FontId id,
185 FontDescription& fontDescription ) const
187 for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
188 endIt = mFontIdCache.end();
192 const FontIdCacheItem& item = *it;
194 if( item.fontId == id )
196 fontDescription = *( mFontDescriptionCache.begin() + item.validatedFontId );
201 DALI_LOG_ERROR( "FontClient::Plugin::GetDescription. No description found for the font ID %d\n", id );
204 PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id )
206 const FontId index = id - 1u;
209 index < mFontCache.size() )
211 return ( *( mFontCache.begin() + index ) ).mPointSize;
215 DALI_LOG_ERROR( "FontClient::Plugin::GetPointSize. Invalid font ID %d\n", id );
218 return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
221 FontId FontClient::Plugin::FindDefaultFont( Character charcode,
222 PointSize26Dot6 requestedSize )
224 // Create the list of default fonts if it has not been created.
225 if( mDefaultFonts.empty() )
227 SetDefaultFontFamily( DEFAULT_FONT_FAMILY_NAME,
228 DEFAULT_FONT_STYLE );
231 // Traverse the list of default fonts.
232 // Check for each default font if supports the character.
234 for( FontList::const_iterator it = mDefaultFonts.begin(),
235 endIt = mDefaultFonts.end();
239 const FontDescription& description = *it;
241 FcPattern* pattern = CreateFontFamilyPattern( description.family,
244 FcResult result = FcResultMatch;
245 FcPattern* match = FcFontMatch( NULL /* use default configure */, pattern, &result );
247 FcCharSet* charSet = NULL;
248 FcPatternGetCharSet( match, FC_CHARSET, 0u, &charSet );
250 if( FcCharSetHasChar( charSet, charcode ) )
252 Vector< PointSize26Dot6 > fixedSizes;
253 GetFixedSizes( description.family,
257 const Vector< PointSize26Dot6 >::SizeType count = fixedSizes.Count();
260 // If the font is not scalable, pick the largest size <= requestedSize
261 PointSize26Dot6 size = fixedSizes[0];
262 for( unsigned int i=1; i<count; ++i )
264 if( fixedSizes[i] <= requestedSize &&
265 fixedSizes[i] > size )
267 size = fixedSizes[i];
270 requestedSize = size;
273 return GetFontId( description.family,
283 FontId FontClient::Plugin::GetFontId( const FontPath& path,
284 PointSize26Dot6 pointSize,
286 bool cacheDescription )
290 if( NULL != mFreeTypeLibrary )
293 if( FindFont( path, pointSize, faceIndex, foundId ) )
299 id = CreateFont( path, pointSize, faceIndex, cacheDescription );
306 FontId FontClient::Plugin::GetFontId( const FontFamily& fontFamily,
307 const FontStyle& fontStyle,
308 PointSize26Dot6 pointSize,
309 FaceIndex faceIndex )
311 // This method uses three vectors which caches:
312 // * Pairs of non validated 'fontFamily, fontStyle' and an index to a vector with paths to font file names.
313 // * The path to font file names.
314 // * The font ids of pairs 'font point size, index to the vector with paths to font file names'.
316 // 1) Checks in the cache if the pair 'fontFamily, fontStyle' has been validated before.
317 // If it was it gets an index to the vector with paths to font file names. Otherwise,
318 // retrieves using font config a path to a font file name which matches with the pair
319 // 'fontFamily, fontStyle'. The path is stored in the chache.
321 // 2) Checks in the cache if the pair 'font point size, index to the vector with paths to
322 // fon file names' exists. If exists, it gets the font id. If it doesn't it calls
323 // the GetFontId() method with the path to the font file name and the point size to
326 // The font id to be returned.
329 // Check first if the pair font family and style have been validated before.
330 FontDescriptionId validatedFontId = 0u;
332 if( !FindValidatedFont( fontFamily,
336 // Use font config to validate the font family name and font style.
337 ValidateFont( fontFamily, fontStyle, validatedFontId );
340 // Check if exists a pair 'validatedFontId, pointSize' in the cache.
341 if( !FindFont( validatedFontId, pointSize, fontId ) )
343 // Retrieve the font file name path.
344 const FontDescription& description = *( mFontDescriptionCache.begin() + validatedFontId );
346 // Retrieve the font id. Do not cache the description as it has been already cached.
347 fontId = GetFontId( description.path,
352 // Cache the pair 'validatedFontId, pointSize' to improve the following queries.
353 mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
361 void FontClient::Plugin::ValidateFont( const FontFamily& fontFamily,
362 const FontStyle& fontStyle,
363 FontDescriptionId& validatedFontId )
365 // Create a font pattern.
366 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
369 FcResult result = FcResultMatch;
372 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
376 // Get the path to the font file name.
377 FontDescription description;
378 GetFcString( match, FC_FILE, description.path );
379 GetFcString( match, FC_FAMILY, description.family );
380 GetFcString( match, FC_STYLE, description.style );
382 // Set the index to the vector of paths to font file names.
383 validatedFontId = mFontDescriptionCache.size();
385 // Add the path to the cache.
386 mFontDescriptionCache.push_back( description );
388 // Cache the index and the pair font family name, font style.
389 FontDescriptionCacheItem item( fontFamily, fontStyle, validatedFontId );
390 mValidatedFontCache.push_back( item );
392 // destroyed the matched pattern
393 FcPatternDestroy( match );
397 DALI_LOG_ERROR( "FontClient::Plugin::ValidateFont failed for font %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
400 // destroy the pattern
401 FcPatternDestroy( fontFamilyPattern );
406 void FontClient::Plugin::GetFontMetrics( FontId fontId,
407 FontMetrics& metrics )
410 fontId-1 < mFontCache.size() )
412 metrics = mFontCache[fontId-1].mMetrics;
416 DALI_LOG_ERROR( "Invalid font ID %d\n", fontId );
420 GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId,
423 GlyphIndex index( 0 );
426 fontId-1 < mFontCache.size() )
428 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
430 index = FT_Get_Char_Index( ftFace, charcode );
436 bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
440 bool success( true );
442 for( unsigned int i=0; i<size; ++i )
444 FontId fontId = array[i].fontId;
447 fontId-1 < mFontCache.size() )
449 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
451 // Check to see if we should be loading a Fixed Size bitmap?
452 if ( mFontCache[fontId-1].mIsFixedSizeBitmap )
454 int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_COLOR );
455 if ( FT_Err_Ok == error )
457 // TODO passing height for metrics, should store width, height and advance
459 float height = mFontCache[ fontId -1 ].mMetrics.height;
460 array[i].width = height;
461 array[i].height = height;
462 array[i].advance = height;
463 array[i].xBearing = 0.0f;
464 array[i].yBearing = 0.0f;
469 DALI_LOG_ERROR( "FreeType Bitmap Load_Glyph error %d\n", error );
474 int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_DEFAULT );
476 if( FT_Err_Ok == error )
478 array[i].width = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
479 array[i].height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
482 array[i].xBearing = static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
483 array[i].yBearing = static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
484 array[i].advance = static_cast< float >( ftFace->glyph->metrics.horiAdvance ) * FROM_266;
488 array[i].xBearing = static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
489 array[i].yBearing = static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
490 array[i].advance = static_cast< float >( ftFace->glyph->metrics.vertAdvance ) * FROM_266;
507 BufferImage FontClient::Plugin::CreateBitmap( FontId fontId,
508 GlyphIndex glyphIndex )
513 fontId-1 < mFontCache.size() )
515 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
519 // Check to see if this is fixed size bitmap
520 if ( mFontCache[fontId-1].mIsFixedSizeBitmap )
522 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
526 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_DEFAULT );
528 if( FT_Err_Ok == error )
531 error = FT_Get_Glyph( ftFace->glyph, &glyph );
533 // Convert to bitmap if necessary
534 if ( FT_Err_Ok == error )
536 if( glyph->format != FT_GLYPH_FORMAT_BITMAP )
538 error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
539 if ( FT_Err_Ok == error )
541 FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
542 ConvertBitmap( bitmap, bitmapGlyph->bitmap );
546 DALI_LOG_ERROR( "FT_Get_Glyph Failed with error: %d\n", error );
551 ConvertBitmap( bitmap, ftFace->glyph->bitmap );
554 // Created FT_Glyph object must be released with FT_Done_Glyph
555 FT_Done_Glyph( glyph );
560 DALI_LOG_ERROR( "FT_Load_Glyph Failed with error: %d\n", error );
567 void FontClient::Plugin::InitSystemFonts()
569 FcFontSet* fontSet = GetFcFontSet();
573 // Reserve some space to avoid reallocations.
574 mSystemFonts.reserve( fontSet->nfont );
576 for( int i = 0u; i < fontSet->nfont; ++i )
578 FcPattern* fontPattern = fontSet->fonts[i];
582 // Skip fonts with no path
583 if( GetFcString( fontPattern, FC_FILE, path ) )
585 mSystemFonts.push_back( FontDescription() );
586 FontDescription& fontDescription = mSystemFonts.back();
588 fontDescription.path = path;
590 GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
591 GetFcString( fontPattern, FC_STYLE, fontDescription.style );
595 FcFontSetDestroy( fontSet );
599 FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontFamily& fontFamily,
600 const FontStyle& fontStyle )
602 // create the cached font family lookup pattern
603 // a pattern holds a set of names, each name refers to a property of the font
604 FcPattern* fontFamilyPattern = FcPatternCreate();
606 // add a property to the pattern for the font family
607 FcPatternAddString( fontFamilyPattern, FC_FAMILY, reinterpret_cast<const FcChar8*>( fontFamily.c_str() ) );
609 // add a property to the pattern for the font family
610 FcPatternAddString( fontFamilyPattern, FC_STYLE, reinterpret_cast<const FcChar8*>( fontStyle.c_str() ) );
612 // Add a property of the pattern, to say we want to match TrueType fonts
613 FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, reinterpret_cast<const FcChar8*>( FONT_FORMAT.c_str() ) );
615 // modify the config, with the mFontFamilyPatterm
616 FcConfigSubstitute( NULL /* use default configure */, fontFamilyPattern, FcMatchPattern );
618 // provide default values for unspecified properties in the font pattern
619 // e.g. patterns without a specified style or weight are set to Medium
620 FcDefaultSubstitute( fontFamilyPattern );
622 return fontFamilyPattern;
625 _FcFontSet* FontClient::Plugin::GetFcFontSet() const
627 // create a new pattern.
628 // a pattern holds a set of names, each name refers to a property of the font
629 FcPattern* pattern = FcPatternCreate();
631 // create an object set used to define which properties are to be returned in the patterns from FcFontList.
632 FcObjectSet* objectSet = FcObjectSetCreate();
634 // build an object set from a list of property names
635 FcObjectSetAdd( objectSet, FC_FILE );
636 FcObjectSetAdd( objectSet, FC_FAMILY );
637 FcObjectSetAdd( objectSet, FC_STYLE );
639 // get a list of fonts
640 // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
641 FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet );
643 // clear up the object set
646 FcObjectSetDestroy( objectSet );
648 // clear up the pattern
651 FcPatternDestroy( pattern );
657 bool FontClient::Plugin::GetFcString( const FcPattern* const pattern,
659 std::string& string )
661 FcChar8* file = NULL;
662 const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file );
664 if( FcResultMatch == retVal )
666 // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
667 string.assign( reinterpret_cast<const char*>( file ) );
675 FontId FontClient::Plugin::CreateFont( const FontPath& path,
676 PointSize26Dot6 pointSize,
678 bool cacheDescription )
682 // Create & cache new font face
684 int error = FT_New_Face( mFreeTypeLibrary,
689 if( FT_Err_Ok == error )
691 // Check to see if the font contains fixed sizes?
692 if ( ftFace->num_fixed_sizes && ftFace->available_sizes )
694 // Ensure this size is available
695 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
697 if ( pointSize == ftFace->available_sizes[ i ].size )
699 // Tell Freetype to use this size
700 error = FT_Select_Size( ftFace, i );
701 if ( FT_Err_Ok != error )
703 DALI_LOG_ERROR( "FreeType Select_Size error: %d\n", error );
707 // Indicate that the font is a fixed sized bitmap
708 FontMetrics metrics( 0.0f,
710 static_cast< float >( ftFace->available_sizes[ i ].height ) );
712 mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics, FONT_FIXED_SIZE_BITMAP ) );
713 id = mFontCache.size();
715 if( cacheDescription )
717 FontDescription description;
718 description.path = path;
719 description.family = FontFamily( ftFace->family_name );
720 description.style = FontStyle( ftFace->style_name );
722 mFontDescriptionCache.push_back( description );
729 // Can't find this size
730 std::stringstream sizes;
731 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
737 sizes << ftFace->available_sizes[ i ].size;
739 DALI_LOG_ERROR( "FreeType Font: %s, does not contain Bitmaps of size: %d. Available sizes are: %s\n",
740 path.c_str(), pointSize, sizes.str().c_str() );
744 error = FT_Set_Char_Size( ftFace,
750 if( FT_Err_Ok == error )
753 FT_Size_Metrics& ftMetrics = ftFace->size->metrics;
755 FontMetrics metrics( static_cast< float >( ftMetrics.ascender ) * FROM_266,
756 static_cast< float >( ftMetrics.descender ) * FROM_266,
757 static_cast< float >( ftMetrics.height ) * FROM_266 );
759 mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics ) );
760 id = mFontCache.size();
762 if( cacheDescription )
764 FontDescription description;
765 description.path = path;
766 description.family = FontFamily( ftFace->family_name );
767 description.style = FontStyle( ftFace->style_name );
769 mFontDescriptionCache.push_back( description );
774 DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", error, pointSize );
780 DALI_LOG_ERROR( "FreeType New_Face error: %d for %s\n", error, path.c_str() );
786 void FontClient::Plugin::ConvertBitmap( BufferImage& destBitmap,
787 FT_Bitmap srcBitmap )
789 if( srcBitmap.width*srcBitmap.rows > 0 )
791 switch( srcBitmap.pixel_mode )
793 case FT_PIXEL_MODE_GRAY:
795 if( srcBitmap.pitch == static_cast< int >( srcBitmap.width ) )
797 destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::L8 );
799 PixelBuffer* destBuffer = destBitmap.GetBuffer();
800 memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows );
805 case FT_PIXEL_MODE_BGRA:
807 if ( srcBitmap.pitch == static_cast< int >( srcBitmap.width << 2 ) )
809 destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::BGRA8888 );
811 PixelBuffer* destBuffer = destBitmap.GetBuffer();
812 memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows*4 );
818 DALI_LOG_ERROR( "FontClient Unable to create Bitmap of this PixelType\n" );
825 bool FontClient::Plugin::FindFont( const FontPath& path,
826 PointSize26Dot6 pointSize,
828 FontId& fontId ) const
831 for( std::vector<CacheItem>::const_iterator it = mFontCache.begin(),
832 endIt = mFontCache.end();
836 const CacheItem& cacheItem = *it;
838 if( cacheItem.mPointSize == pointSize &&
839 cacheItem.mFaceIndex == faceIndex &&
840 cacheItem.mPath == path )
850 bool FontClient::Plugin::FindValidatedFont( const FontFamily& fontFamily,
851 const FontStyle& fontStyle,
852 FontDescriptionId& validatedFontId )
854 validatedFontId = 0u;
856 for( std::vector<FontDescriptionCacheItem>::const_iterator it = mValidatedFontCache.begin(),
857 endIt = mValidatedFontCache.end();
861 const FontDescriptionCacheItem& item = *it;
863 if( ( fontFamily == item.fontFamily ) &&
864 ( fontStyle == item.fontStyle ) )
866 validatedFontId = item.index;
875 bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId,
876 PointSize26Dot6 pointSize,
881 for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
882 endIt = mFontIdCache.end();
886 const FontIdCacheItem& item = *it;
888 if( ( validatedFontId == item.validatedFontId ) &&
889 ( pointSize == item.pointSize ) )
891 fontId = item.fontId;
899 bool FontClient::Plugin::IsScalable( const FontPath& path )
902 int error = FT_New_Face( mFreeTypeLibrary,
906 if( FT_Err_Ok != error )
908 DALI_LOG_ERROR( "FreeType Cannot check font: %s\n", path.c_str() );
910 return ( ftFace->num_fixed_sizes == 0 );
913 bool FontClient::Plugin::IsScalable( const FontFamily& fontFamily, const FontStyle& fontStyle )
915 // Create a font pattern.
916 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
919 FcResult result = FcResultMatch;
922 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
926 // Get the path to the font file name.
928 GetFcString( match, FC_FILE, path );
929 return IsScalable( path );
931 DALI_LOG_ERROR( "FreeType Cannot check font: %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
935 void FontClient::Plugin::GetFixedSizes( const FontPath& path, Vector< PointSize26Dot6 >& sizes )
937 // Empty the caller container
941 int error = FT_New_Face( mFreeTypeLibrary,
945 if( FT_Err_Ok != error )
947 DALI_LOG_ERROR( "FreeType Cannot check font: %s\n", path.c_str() );
950 // Fetch the number of fixed sizes available
951 if ( ftFace->num_fixed_sizes && ftFace->available_sizes )
953 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
955 sizes.PushBack( ftFace->available_sizes[ i ].size );
960 void FontClient::Plugin::GetFixedSizes( const FontFamily& fontFamily,
961 const FontStyle& fontStyle,
962 Vector< PointSize26Dot6 >& sizes )
964 // Create a font pattern.
965 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
968 FcResult result = FcResultMatch;
971 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
975 // Get the path to the font file name.
977 GetFcString( match, FC_FILE, path );
978 return GetFixedSizes( path, sizes );
980 DALI_LOG_ERROR( "FreeType Cannot check font: %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
983 } // namespace Internal
985 } // namespace TextAbstraction