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/vector-wrapper.h>
23 #include <dali/public-api/text-abstraction/glyph-info.h>
24 #include <dali/integration-api/debug.h>
27 #include <fontconfig/fontconfig.h>
30 * Conversion from Fractional26.6 to float
34 const float FROM_266 = 1.0f / 64.0f;
36 const std::string FONT_FORMAT( "TrueType" );
37 const std::string DEFAULT_FONT_FAMILY_NAME( "Tizen" );
38 const std::string DEFAULT_FONT_STYLE( "Regular" );
44 namespace TextAbstraction
50 const bool FONT_FIXED_SIZE_BITMAP( true );
52 FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem( const FontFamily& fontFamily,
53 const FontStyle& fontStyle,
54 FontDescriptionId index )
55 : fontFamily( fontFamily ),
56 fontStyle( fontStyle ),
60 FontClient::Plugin::FontIdCacheItem::FontIdCacheItem( FontDescriptionId validatedFontId,
61 PointSize26Dot6 pointSize,
63 : validatedFontId( validatedFontId ),
64 pointSize( pointSize ),
68 FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
70 PointSize26Dot6 pointSize,
72 const FontMetrics& metrics,
73 bool isFixedSizeBitmap )
74 : mFreeTypeFace( ftFace ),
76 mPointSize( pointSize ),
79 mIsFixedSizeBitmap( isFixedSizeBitmap )
82 FontClient::Plugin::Plugin( unsigned int horizontalDpi,
83 unsigned int verticalDpi )
84 : mFreeTypeLibrary( NULL ),
85 mDpiHorizontal( horizontalDpi ),
86 mDpiVertical( verticalDpi ),
90 mValidatedFontCache(),
91 mFontDescriptionCache( 1u ),
94 int error = FT_Init_FreeType( &mFreeTypeLibrary );
95 if( FT_Err_Ok != error )
97 DALI_LOG_ERROR( "FreeType Init error: %d\n", error );
101 FontClient::Plugin::~Plugin()
103 FT_Done_FreeType( mFreeTypeLibrary );
106 void FontClient::Plugin::SetDpi( unsigned int horizontalDpi,
107 unsigned int verticalDpi )
109 mDpiHorizontal = horizontalDpi;
110 mDpiVertical = verticalDpi;
113 void FontClient::Plugin::SetDefaultFontFamily( const FontFamily& fontFamilyName,
114 const FontStyle& fontStyle )
116 mDefaultFonts.clear();
118 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamilyName,
121 FcResult result = FcResultMatch;
123 // Match the pattern.
124 FcFontSet* fontSet = FcFontSort( NULL /* use default configure */,
126 false /* don't trim */,
130 if( NULL != fontSet )
132 // Reserve some space to avoid reallocations.
133 mDefaultFonts.reserve( fontSet->nfont );
135 for( int i = 0u; i < fontSet->nfont; ++i )
137 FcPattern* fontPattern = fontSet->fonts[i];
141 // Skip fonts with no path
142 if( GetFcString( fontPattern, FC_FILE, path ) )
144 mDefaultFonts.push_back( FontDescription() );
145 FontDescription& fontDescription = mDefaultFonts.back();
147 fontDescription.path = path;
149 GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
150 GetFcString( fontPattern, FC_STYLE, fontDescription.style );
154 FcFontSetDestroy( fontSet );
157 FcPatternDestroy( fontFamilyPattern );
160 void FontClient::Plugin::GetDefaultFonts( FontList& defaultFonts )
162 if( mDefaultFonts.empty() )
164 SetDefaultFontFamily( DEFAULT_FONT_FAMILY_NAME,
165 DEFAULT_FONT_STYLE );
168 defaultFonts = mDefaultFonts;
171 void FontClient::Plugin::GetSystemFonts( FontList& systemFonts )
173 if( mSystemFonts.empty() )
178 systemFonts = mSystemFonts;
181 void FontClient::Plugin::GetDescription( FontId id,
182 FontDescription& fontDescription ) const
184 for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
185 endIt = mFontIdCache.end();
189 const FontIdCacheItem& item = *it;
191 if( item.fontId == id )
193 fontDescription = *( mFontDescriptionCache.begin() + item.validatedFontId );
198 DALI_LOG_ERROR( "FontClient::Plugin::GetDescription. No description found for the font ID %d\n", id );
201 PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id )
203 const FontId index = id - 1u;
206 index < mFontCache.size() )
208 return ( *( mFontCache.begin() + index ) ).mPointSize;
212 DALI_LOG_ERROR( "FontClient::Plugin::GetPointSize. Invalid font ID %d\n", id );
215 return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
218 FontId FontClient::Plugin::FindDefaultFont( Character charcode,
219 PointSize26Dot6 pointSize )
221 // Create the list of default fonts if it has not been created.
222 if( mDefaultFonts.empty() )
224 SetDefaultFontFamily( DEFAULT_FONT_FAMILY_NAME,
225 DEFAULT_FONT_STYLE );
228 // Traverse the list of default fonts.
229 // Check for each default font if supports the character.
231 for( FontList::const_iterator it = mDefaultFonts.begin(),
232 endIt = mDefaultFonts.end();
236 const FontDescription& description = *it;
238 FcPattern* pattern = CreateFontFamilyPattern( description.family,
241 FcResult result = FcResultMatch;
242 FcPattern* match = FcFontMatch( NULL /* use default configure */, pattern, &result );
244 FcCharSet* charSet = NULL;
245 FcPatternGetCharSet( match, FC_CHARSET, 0u, &charSet );
247 if( FcCharSetHasChar( charSet, charcode ) )
249 return GetFontId( description.family,
259 FontId FontClient::Plugin::GetFontId( const FontPath& path,
260 PointSize26Dot6 pointSize,
262 bool cacheDescription )
266 if( NULL != mFreeTypeLibrary )
269 if( FindFont( path, pointSize, faceIndex, foundId ) )
275 id = CreateFont( path, pointSize, faceIndex, cacheDescription );
282 FontId FontClient::Plugin::GetFontId( const FontFamily& fontFamily,
283 const FontStyle& fontStyle,
284 PointSize26Dot6 pointSize,
285 FaceIndex faceIndex )
287 // This method uses three vectors which caches:
288 // * Pairs of non validated 'fontFamily, fontStyle' and an index to a vector with paths to font file names.
289 // * The path to font file names.
290 // * The font ids of pairs 'font point size, index to the vector with paths to font file names'.
292 // 1) Checks in the cache if the pair 'fontFamily, fontStyle' has been validated before.
293 // If it was it gets an index to the vector with paths to font file names. Otherwise,
294 // retrieves using font config a path to a font file name which matches with the pair
295 // 'fontFamily, fontStyle'. The path is stored in the chache.
297 // 2) Checks in the cache if the pair 'font point size, index to the vector with paths to
298 // fon file names' exists. If exists, it gets the font id. If it doesn't it calls
299 // the GetFontId() method with the path to the font file name and the point size to
302 // The font id to be returned.
305 // Check first if the pair font family and style have been validated before.
306 FontDescriptionId validatedFontId = 0u;
308 if( !FindValidatedFont( fontFamily,
312 // Use font config to validate the font family name and font style.
313 ValidateFont( fontFamily, fontStyle, validatedFontId );
316 // Check if exists a pair 'validatedFontId, pointSize' in the cache.
317 if( !FindFont( validatedFontId, pointSize, fontId ) )
319 // Retrieve the font file name path.
320 const FontDescription& description = *( mFontDescriptionCache.begin() + validatedFontId );
322 // Retrieve the font id. Do not cache the description as it has been already cached.
323 fontId = GetFontId( description.path,
328 // Cache the pair 'validatedFontId, pointSize' to improve the following queries.
329 mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
337 void FontClient::Plugin::ValidateFont( const FontFamily& fontFamily,
338 const FontStyle& fontStyle,
339 FontDescriptionId& validatedFontId )
341 // Create a font pattern.
342 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
345 FcResult result = FcResultMatch;
348 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
352 // Get the path to the font file name.
353 FontDescription description;
354 GetFcString( match, FC_FILE, description.path );
355 GetFcString( match, FC_FAMILY, description.family );
356 GetFcString( match, FC_STYLE, description.style );
358 // Set the index to the vector of paths to font file names.
359 validatedFontId = mFontDescriptionCache.size();
361 // Add the path to the cache.
362 mFontDescriptionCache.push_back( description );
364 // Cache the index and the pair font family name, font style.
365 FontDescriptionCacheItem item( fontFamily, fontStyle, validatedFontId );
366 mValidatedFontCache.push_back( item );
368 // destroyed the matched pattern
369 FcPatternDestroy( match );
373 DALI_LOG_ERROR( "FontClient::Plugin::ValidateFont failed for font %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
376 // destroy the pattern
377 FcPatternDestroy( fontFamilyPattern );
382 void FontClient::Plugin::GetFontMetrics( FontId fontId,
383 FontMetrics& metrics )
386 fontId-1 < mFontCache.size() )
388 metrics = mFontCache[fontId-1].mMetrics;
392 DALI_LOG_ERROR( "Invalid font ID %d\n", fontId );
396 GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId,
399 GlyphIndex index( 0 );
402 fontId-1 < mFontCache.size() )
404 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
406 index = FT_Get_Char_Index( ftFace, charcode );
412 bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
416 bool success( true );
418 for( unsigned int i=0; i<size; ++i )
420 FontId fontId = array[i].fontId;
423 fontId-1 < mFontCache.size() )
425 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
427 // Check to see if we should be loading a Fixed Size bitmap?
428 if ( mFontCache[fontId-1].mIsFixedSizeBitmap )
430 int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_COLOR );
431 if ( FT_Err_Ok == error )
433 // TODO passing height for metrics, should store width, height and advance
435 float height = mFontCache[ fontId -1 ].mMetrics.height;
436 array[i].width = height;
437 array[i].height = height;
438 array[i].advance = height;
439 array[i].xBearing = 0.0f;
440 array[i].yBearing = 0.0f;
445 DALI_LOG_ERROR( "FreeType Bitmap Load_Glyph error %d\n", error );
450 int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_DEFAULT );
452 if( FT_Err_Ok == error )
454 array[i].width = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
455 array[i].height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
458 array[i].xBearing = static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
459 array[i].yBearing = static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
460 array[i].advance = static_cast< float >( ftFace->glyph->metrics.horiAdvance ) * FROM_266;
464 array[i].xBearing = static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
465 array[i].yBearing = static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
466 array[i].advance = static_cast< float >( ftFace->glyph->metrics.vertAdvance ) * FROM_266;
483 BufferImage FontClient::Plugin::CreateBitmap( FontId fontId,
484 GlyphIndex glyphIndex )
489 fontId-1 < mFontCache.size() )
491 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
495 // Check to see if this is fixed size bitmap
496 if ( mFontCache[fontId-1].mIsFixedSizeBitmap )
498 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
502 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_DEFAULT );
504 if( FT_Err_Ok == error )
507 error = FT_Get_Glyph( ftFace->glyph, &glyph );
509 // Convert to bitmap if necessary
510 if ( FT_Err_Ok == error )
512 if( glyph->format != FT_GLYPH_FORMAT_BITMAP )
514 error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
515 if ( FT_Err_Ok == error )
517 FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
518 ConvertBitmap( bitmap, bitmapGlyph->bitmap );
522 DALI_LOG_ERROR( "FT_Get_Glyph Failed with error: %d\n", error );
527 ConvertBitmap( bitmap, ftFace->glyph->bitmap );
530 // Created FT_Glyph object must be released with FT_Done_Glyph
531 FT_Done_Glyph( glyph );
536 DALI_LOG_ERROR( "FT_Load_Glyph Failed with error: %d\n", error );
543 void FontClient::Plugin::InitSystemFonts()
545 FcFontSet* fontSet = GetFcFontSet();
549 // Reserve some space to avoid reallocations.
550 mSystemFonts.reserve( fontSet->nfont );
552 for( int i = 0u; i < fontSet->nfont; ++i )
554 FcPattern* fontPattern = fontSet->fonts[i];
558 // Skip fonts with no path
559 if( GetFcString( fontPattern, FC_FILE, path ) )
561 mSystemFonts.push_back( FontDescription() );
562 FontDescription& fontDescription = mSystemFonts.back();
564 fontDescription.path = path;
566 GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
567 GetFcString( fontPattern, FC_STYLE, fontDescription.style );
571 FcFontSetDestroy( fontSet );
575 FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontFamily& fontFamily,
576 const FontStyle& fontStyle )
578 // create the cached font family lookup pattern
579 // a pattern holds a set of names, each name refers to a property of the font
580 FcPattern* fontFamilyPattern = FcPatternCreate();
582 // add a property to the pattern for the font family
583 FcPatternAddString( fontFamilyPattern, FC_FAMILY, reinterpret_cast<const FcChar8*>( fontFamily.c_str() ) );
585 // add a property to the pattern for the font family
586 FcPatternAddString( fontFamilyPattern, FC_STYLE, reinterpret_cast<const FcChar8*>( fontStyle.c_str() ) );
588 // Add a property of the pattern, to say we want to match TrueType fonts
589 FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, reinterpret_cast<const FcChar8*>( FONT_FORMAT.c_str() ) );
591 // modify the config, with the mFontFamilyPatterm
592 FcConfigSubstitute( NULL /* use default configure */, fontFamilyPattern, FcMatchPattern );
594 // provide default values for unspecified properties in the font pattern
595 // e.g. patterns without a specified style or weight are set to Medium
596 FcDefaultSubstitute( fontFamilyPattern );
598 return fontFamilyPattern;
601 _FcFontSet* FontClient::Plugin::GetFcFontSet() const
603 // create a new pattern.
604 // a pattern holds a set of names, each name refers to a property of the font
605 FcPattern* pattern = FcPatternCreate();
607 // create an object set used to define which properties are to be returned in the patterns from FcFontList.
608 FcObjectSet* objectSet = FcObjectSetCreate();
610 // build an object set from a list of property names
611 FcObjectSetAdd( objectSet, FC_FILE );
612 FcObjectSetAdd( objectSet, FC_FAMILY );
613 FcObjectSetAdd( objectSet, FC_STYLE );
615 // get a list of fonts
616 // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
617 FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet );
619 // clear up the object set
622 FcObjectSetDestroy( objectSet );
624 // clear up the pattern
627 FcPatternDestroy( pattern );
633 bool FontClient::Plugin::GetFcString( const FcPattern* const pattern,
635 std::string& string )
637 FcChar8* file = NULL;
638 const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file );
640 if( FcResultMatch == retVal )
642 // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
643 string.assign( reinterpret_cast<const char*>( file ) );
651 FontId FontClient::Plugin::CreateFont( const FontPath& path,
652 PointSize26Dot6 pointSize,
654 bool cacheDescription )
658 // Create & cache new font face
660 int error = FT_New_Face( mFreeTypeLibrary,
665 if( FT_Err_Ok == error )
667 // Check to see if the font contains fixed sizes?
668 if ( ftFace->num_fixed_sizes && ftFace->available_sizes )
670 // Ensure this size is available
671 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
673 if ( pointSize == ftFace->available_sizes[ i ].size )
675 // Tell Freetype to use this size
676 error = FT_Select_Size( ftFace, i );
677 if ( FT_Err_Ok != error )
679 DALI_LOG_ERROR( "FreeType Select_Size error: %d\n", error );
683 // Indicate that the font is a fixed sized bitmap
684 FontMetrics metrics( 0.0f,
686 static_cast< float >( ftFace->available_sizes[ i ].height ) );
688 mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics, FONT_FIXED_SIZE_BITMAP ) );
689 id = mFontCache.size();
691 if( cacheDescription )
693 FontDescription description;
694 description.path = path;
695 description.family = FontFamily( ftFace->family_name );
696 description.style = FontStyle( ftFace->style_name );
698 mFontDescriptionCache.push_back( description );
705 // Can't find this size
706 std::stringstream sizes;
707 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
713 sizes << ftFace->available_sizes[ i ].size;
715 DALI_LOG_ERROR( "FreeType Font: %s, does not contain Bitmaps of size: %d. Available sizes are: %s\n",
716 path.c_str(), pointSize, sizes.str().c_str() );
720 error = FT_Set_Char_Size( ftFace,
726 if( FT_Err_Ok == error )
729 FT_Size_Metrics& ftMetrics = ftFace->size->metrics;
731 FontMetrics metrics( static_cast< float >( ftMetrics.ascender ) * FROM_266,
732 static_cast< float >( ftMetrics.descender ) * FROM_266,
733 static_cast< float >( ftMetrics.height ) * FROM_266 );
735 mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics ) );
736 id = mFontCache.size();
738 if( cacheDescription )
740 FontDescription description;
741 description.path = path;
742 description.family = FontFamily( ftFace->family_name );
743 description.style = FontStyle( ftFace->style_name );
745 mFontDescriptionCache.push_back( description );
750 DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", error, pointSize );
756 DALI_LOG_ERROR( "FreeType New_Face error: %d for %s\n", error, path.c_str() );
762 void FontClient::Plugin::ConvertBitmap( BufferImage& destBitmap,
763 FT_Bitmap srcBitmap )
765 if( srcBitmap.width*srcBitmap.rows > 0 )
767 switch( srcBitmap.pixel_mode )
769 case FT_PIXEL_MODE_GRAY:
771 if( srcBitmap.pitch == static_cast< int >( srcBitmap.width ) )
773 destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::L8 );
775 PixelBuffer* destBuffer = destBitmap.GetBuffer();
776 memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows );
781 case FT_PIXEL_MODE_BGRA:
783 if ( srcBitmap.pitch == static_cast< int >( srcBitmap.width << 2 ) )
785 destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::BGRA8888 );
787 PixelBuffer* destBuffer = destBitmap.GetBuffer();
788 memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows*4 );
794 DALI_LOG_ERROR( "FontClient Unable to create Bitmap of this PixelType\n" );
801 bool FontClient::Plugin::FindFont( const FontPath& path,
802 PointSize26Dot6 pointSize,
804 FontId& fontId ) const
807 for( std::vector<CacheItem>::const_iterator it = mFontCache.begin(),
808 endIt = mFontCache.end();
812 const CacheItem& cacheItem = *it;
814 if( cacheItem.mPointSize == pointSize &&
815 cacheItem.mFaceIndex == faceIndex &&
816 cacheItem.mPath == path )
826 bool FontClient::Plugin::FindValidatedFont( const FontFamily& fontFamily,
827 const FontStyle& fontStyle,
828 FontDescriptionId& validatedFontId )
830 validatedFontId = 0u;
832 for( std::vector<FontDescriptionCacheItem>::const_iterator it = mValidatedFontCache.begin(),
833 endIt = mValidatedFontCache.end();
837 const FontDescriptionCacheItem& item = *it;
839 if( ( fontFamily == item.fontFamily ) &&
840 ( fontStyle == item.fontStyle ) )
842 validatedFontId = item.index;
851 bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId,
852 PointSize26Dot6 pointSize,
857 for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
858 endIt = mFontIdCache.end();
862 const FontIdCacheItem& item = *it;
864 if( ( validatedFontId == item.validatedFontId ) &&
865 ( pointSize == item.pointSize ) )
867 fontId = item.fontId;
875 bool FontClient::Plugin::IsScalable( const FontPath& path )
878 int error = FT_New_Face( mFreeTypeLibrary,
882 if( FT_Err_Ok != error )
884 DALI_LOG_ERROR( "FreeType Cannot check font: %s\n", path.c_str() );
886 return ( ftFace->num_fixed_sizes == 0 );
889 bool FontClient::Plugin::IsScalable( const FontFamily& fontFamily, const FontStyle& fontStyle )
891 // Create a font pattern.
892 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
895 FcResult result = FcResultMatch;
898 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
902 // Get the path to the font file name.
904 GetFcString( match, FC_FILE, path );
905 return IsScalable( path );
907 DALI_LOG_ERROR( "FreeType Cannot check font: %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
911 void FontClient::Plugin::GetFixedSizes( const FontPath& path, Dali::Vector< PointSize26Dot6 >& sizes )
913 // Empty the caller container
917 int error = FT_New_Face( mFreeTypeLibrary,
921 if( FT_Err_Ok != error )
923 DALI_LOG_ERROR( "FreeType Cannot check font: %s\n", path.c_str() );
926 // Fetch the number of fixed sizes available
927 if ( ftFace->num_fixed_sizes && ftFace->available_sizes )
929 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
931 sizes.PushBack( ftFace->available_sizes[ i ].size );
936 void FontClient::Plugin::GetFixedSizes( const FontFamily& fontFamily,
937 const FontStyle& fontStyle,
938 Dali::Vector< PointSize26Dot6 >& sizes )
940 // Create a font pattern.
941 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
944 FcResult result = FcResultMatch;
947 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
951 // Get the path to the font file name.
953 GetFcString( match, FC_FILE, path );
954 return GetFixedSizes( path, sizes );
956 DALI_LOG_ERROR( "FreeType Cannot check font: %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
959 } // namespace Internal
961 } // namespace TextAbstraction