2 * Copyright (c) 2017 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/devel-api/text-abstraction/font-list.h>
23 #include <dali/public-api/common/dali-vector.h>
24 #include <dali/public-api/common/vector-wrapper.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/platform-abstraction.h>
27 #include <dali/internal/text-abstraction/font-client-helper.h>
28 #include <platform-abstractions/portable/image-operations.h>
29 #include <adaptor-impl.h>
32 #include <fontconfig/fontconfig.h>
37 #if defined(DEBUG_ENABLED)
38 Dali::Integration::Log::Filter* gLogFilter = Dali::Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_FONT_CLIENT");
42 * Conversion from Fractional26.6 to float
44 const float FROM_266 = 1.0f / 64.0f;
45 const float POINTS_PER_INCH = 72.f;
47 const std::string FONT_FORMAT( "TrueType" );
48 const std::string DEFAULT_FONT_FAMILY_NAME( "Tizen" );
49 const int DEFAULT_FONT_WIDTH = 100; // normal
50 const int DEFAULT_FONT_WEIGHT = 80; // normal
51 const int DEFAULT_FONT_SLANT = 0; // normal
53 const uint32_t ELLIPSIS_CHARACTER = 0x2026;
55 // http://www.freedesktop.org/software/fontconfig/fontconfig-user.html
57 // NONE -1 --> DEFAULT_FONT_WIDTH (NORMAL) will be used.
67 const int FONT_WIDTH_TYPE_TO_INT[] = { -1, 50, 63, 75, 87, 100, 113, 125, 150, 200 };
68 const unsigned int NUM_FONT_WIDTH_TYPE = sizeof( FONT_WIDTH_TYPE_TO_INT ) / sizeof( int );
70 // NONE -1 --> DEFAULT_FONT_WEIGHT (NORMAL) will be used.
72 // ULTRA_LIGHT, EXTRA_LIGHT 40
74 // DEMI_LIGHT, SEMI_LIGHT 55
78 // DEMI_BOLD, SEMI_BOLD 180
80 // ULTRA_BOLD, EXTRA_BOLD 205
81 // BLACK, HEAVY, EXTRA_BLACK 210
82 const int FONT_WEIGHT_TYPE_TO_INT[] = { -1, 0, 40, 50, 55, 75, 80, 100, 180, 200, 205, 210 };
83 const unsigned int NUM_FONT_WEIGHT_TYPE = sizeof( FONT_WEIGHT_TYPE_TO_INT ) / sizeof( int );
85 // NONE -1 --> DEFAULT_FONT_SLANT (NORMAL) will be used.
89 const int FONT_SLANT_TYPE_TO_INT[] = { -1, 0, 100, 110 };
90 const unsigned int NUM_FONT_SLANT_TYPE = sizeof( FONT_SLANT_TYPE_TO_INT ) / sizeof( int );
99 namespace TextAbstraction
106 * @brief Returns the FontWidth's enum index for the given width value.
108 * @param[in] width The width value.
110 * @return The FontWidth's enum index.
112 FontWidth::Type IntToWidthType( int width )
114 return static_cast<FontWidth::Type>( ValueToIndex( width, FONT_WIDTH_TYPE_TO_INT, NUM_FONT_WIDTH_TYPE - 1u ) );
118 * @brief Returns the FontWeight's enum index for the given weight value.
120 * @param[in] weight The weight value.
122 * @return The FontWeight's enum index.
124 FontWeight::Type IntToWeightType( int weight )
126 return static_cast<FontWeight::Type>( ValueToIndex( weight, FONT_WEIGHT_TYPE_TO_INT, NUM_FONT_WEIGHT_TYPE - 1u ) );
130 * @brief Returns the FontSlant's enum index for the given slant value.
132 * @param[in] slant The slant value.
134 * @return The FontSlant's enum index.
136 FontSlant::Type IntToSlantType( int slant )
138 return static_cast<FontSlant::Type>( ValueToIndex( slant, FONT_SLANT_TYPE_TO_INT, NUM_FONT_SLANT_TYPE - 1u ) );
141 FontClient::Plugin::FallbackCacheItem::FallbackCacheItem( const FontDescription& font, FontList* fallbackFonts, CharacterSetList* characterSets )
142 : fontDescription( font ),
143 fallbackFonts( fallbackFonts ),
144 characterSets( characterSets )
148 FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem( const FontDescription& fontDescription,
149 FontDescriptionId index )
150 : fontDescription( fontDescription ),
155 FontClient::Plugin::FontIdCacheItem::FontIdCacheItem( FontDescriptionId validatedFontId,
156 PointSize26Dot6 requestedPointSize,
158 : validatedFontId( validatedFontId ),
159 requestedPointSize( requestedPointSize ),
164 FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem( FT_Face ftFace,
165 const FontPath& path,
166 PointSize26Dot6 requestedPointSize,
168 const FontMetrics& metrics )
169 : mFreeTypeFace( ftFace ),
171 mRequestedPointSize( requestedPointSize ),
174 mCharacterSet( NULL ),
175 mFixedWidthPixels( 0.0f ),
176 mFixedHeightPixels( 0.0f ),
178 mIsFixedSizeBitmap( false ),
179 mHasColorTables( false )
183 FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem( FT_Face ftFace,
184 const FontPath& path,
185 PointSize26Dot6 requestedPointSize,
187 const FontMetrics& metrics,
190 bool hasColorTables )
191 : mFreeTypeFace( ftFace ),
193 mRequestedPointSize( requestedPointSize ),
196 mCharacterSet( NULL ),
197 mFixedWidthPixels( fixedWidth ),
198 mFixedHeightPixels( fixedHeight ),
200 mIsFixedSizeBitmap( true ),
201 mHasColorTables( hasColorTables )
205 FontClient::Plugin::Plugin( unsigned int horizontalDpi,
206 unsigned int verticalDpi )
207 : mFreeTypeLibrary( NULL ),
208 mDpiHorizontal( horizontalDpi ),
209 mDpiVertical( verticalDpi ),
210 mDefaultFontDescription(),
214 mValidatedFontCache(),
215 mFontDescriptionCache( 1u ),
216 mCharacterSetCache(),
218 mVectorFontCache( NULL ),
220 mDefaultFontDescriptionCached( false )
222 mCharacterSetCache.Resize( 1u );
224 int error = FT_Init_FreeType( &mFreeTypeLibrary );
225 if( FT_Err_Ok != error )
227 DALI_LOG_INFO( gLogFilter, Debug::General, "FreeType Init error: %d\n", error );
230 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
231 mVectorFontCache = new VectorFontCache( mFreeTypeLibrary );
235 FontClient::Plugin::~Plugin()
237 for( std::vector<FallbackCacheItem>::iterator it = mFallbackCache.begin(), endIt = mFallbackCache.end();
241 FallbackCacheItem& item = *it;
243 if( item.fallbackFonts )
245 delete item.fallbackFonts;
246 delete item.characterSets;
247 item.fallbackFonts = NULL;
248 item.characterSets = NULL;
252 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
253 delete mVectorFontCache;
256 FT_Done_FreeType( mFreeTypeLibrary );
259 void FontClient::Plugin::SetDpi( unsigned int horizontalDpi,
260 unsigned int verticalDpi )
262 mDpiHorizontal = horizontalDpi;
263 mDpiVertical = verticalDpi;
266 void FontClient::Plugin::ResetSystemDefaults()
268 mDefaultFontDescriptionCached = false;
271 void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, FontList& fontList, CharacterSetList& characterSetList )
273 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::SetFontList\n" );
274 DALI_LOG_INFO( gLogFilter, Debug::General, " description; family : [%s]\n", fontDescription.family.c_str() );
275 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
276 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
277 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
281 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontDescription );
283 FcResult result = FcResultMatch;
285 // Match the pattern.
286 FcFontSet* fontSet = FcFontSort( NULL /* use default configure */,
288 false /* don't trim */,
292 if( NULL != fontSet )
294 DALI_LOG_INFO( gLogFilter, Debug::General, " number of fonts found : [%d]\n", fontSet->nfont );
295 // Reserve some space to avoid reallocations.
296 fontList.reserve( fontSet->nfont );
298 for( int i = 0u; i < fontSet->nfont; ++i )
300 FcPattern* fontPattern = fontSet->fonts[i];
304 // Skip fonts with no path
305 if( GetFcString( fontPattern, FC_FILE, path ) )
307 FcCharSet* characterSet = NULL;
308 FcPatternGetCharSet( fontPattern, FC_CHARSET, 0u, &characterSet );
310 characterSetList.PushBack( characterSet );
311 fontList.push_back( FontDescription() );
312 FontDescription& newFontDescription = fontList.back();
314 newFontDescription.path = path;
319 GetFcString( fontPattern, FC_FAMILY, newFontDescription.family );
320 GetFcInt( fontPattern, FC_WIDTH, width );
321 GetFcInt( fontPattern, FC_WEIGHT, weight );
322 GetFcInt( fontPattern, FC_SLANT, slant );
323 newFontDescription.width = IntToWidthType( width );
324 newFontDescription.weight = IntToWeightType( weight );
325 newFontDescription.slant = IntToSlantType( slant );
327 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " description; family : [%s]\n", newFontDescription.family.c_str() );
328 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", newFontDescription.path.c_str() );
329 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[newFontDescription.width] );
330 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[newFontDescription.weight] );
331 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[newFontDescription.slant] );
335 FcFontSetDestroy( fontSet );
339 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " No fonts found.\n" );
342 FcPatternDestroy( fontFamilyPattern );
343 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::SetFontList\n" );
346 void FontClient::Plugin::GetDefaultFonts( FontList& defaultFonts )
348 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetDefaultFonts\n" );
350 if( mDefaultFonts.empty() )
352 FontDescription fontDescription;
353 fontDescription.family = DEFAULT_FONT_FAMILY_NAME; // todo This could be set to the Platform font
354 fontDescription.width = IntToWidthType( DEFAULT_FONT_WIDTH );
355 fontDescription.weight = IntToWeightType( DEFAULT_FONT_WEIGHT );
356 fontDescription.slant = IntToSlantType( DEFAULT_FONT_SLANT );
357 SetFontList( fontDescription, mDefaultFonts, mDefaultFontCharacterSets );
360 defaultFonts = mDefaultFonts;
362 DALI_LOG_INFO( gLogFilter, Debug::General, " number of default fonts : [%d]\n", mDefaultFonts.size() );
363 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetDefaultFonts\n" );
366 void FontClient::Plugin::GetDefaultPlatformFontDescription( FontDescription& fontDescription )
368 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetDefaultPlatformFontDescription\n");
370 if( !mDefaultFontDescriptionCached )
372 // Clear any font config stored info in the caches.
373 mDefaultFontCharacterSets.Clear();
374 mCharacterSetCache.Clear();
376 for( std::vector<FallbackCacheItem>::iterator it = mFallbackCache.begin(), endIt = mFallbackCache.end(); it != endIt; ++it )
378 FallbackCacheItem& item = *it;
380 item.characterSets->Clear();
383 for( std::vector<FontFaceCacheItem>::iterator it = mFontCache.begin(), endIt = mFontCache.end(); it != endIt; ++it )
385 FontFaceCacheItem& item = *it;
387 // Set the character set pointer as null. Will be created again the next time IsCharacterSupportedByFont()
388 item.mCharacterSet = NULL;
391 // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
392 FcInitReinitialize();
394 FcPattern* matchPattern = FcPatternCreate();
398 FcConfigSubstitute( NULL, matchPattern, FcMatchPattern );
399 FcDefaultSubstitute( matchPattern );
401 FcCharSet* characterSet = NULL;
402 MatchFontDescriptionToPattern( matchPattern, mDefaultFontDescription, &characterSet );
403 FcPatternDestroy( matchPattern );
406 // Create again the character sets as they are not valid after FcInitReinitialize()
408 for( FontList::const_iterator it = mDefaultFonts.begin(), endIt = mDefaultFonts.end(); it != endIt; ++it )
410 const FontDescription& description = *it;
412 mDefaultFontCharacterSets.PushBack( CreateCharacterSetFromDescription( description ) );
415 for( FontList::const_iterator it = mFontDescriptionCache.begin(), endIt = mFontDescriptionCache.end(); it != endIt; ++it )
417 const FontDescription& description = *it;
419 mCharacterSetCache.PushBack( CreateCharacterSetFromDescription( description ) );
422 for( std::vector<FallbackCacheItem>::iterator it = mFallbackCache.begin(), endIt = mFallbackCache.end(); it != endIt; ++it )
424 FallbackCacheItem& item = *it;
426 if( NULL != item.fallbackFonts )
428 if( NULL == item.characterSets )
430 item.characterSets = new CharacterSetList;
433 for( FontList::const_iterator flIt = item.fallbackFonts->begin(), flEndIt = item.fallbackFonts->end(); flIt != flEndIt; ++flIt )
435 const FontDescription& description = *flIt;
436 item.characterSets->PushBack( CreateCharacterSetFromDescription( description ) );
441 mDefaultFontDescriptionCached = true;
444 fontDescription.path = mDefaultFontDescription.path;
445 fontDescription.family = mDefaultFontDescription.family;
446 fontDescription.width = mDefaultFontDescription.width;
447 fontDescription.weight = mDefaultFontDescription.weight;
448 fontDescription.slant = mDefaultFontDescription.slant;
450 DALI_LOG_INFO( gLogFilter, Debug::General, " description; family : [%s]\n", fontDescription.family.c_str() );
451 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", fontDescription.path.c_str() );
452 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
453 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
454 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
455 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetDefaultPlatformFontDescription\n");
458 void FontClient::Plugin::GetSystemFonts( FontList& systemFonts )
460 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetSystemFonts\n");
462 if( mSystemFonts.empty() )
467 systemFonts = mSystemFonts;
468 DALI_LOG_INFO( gLogFilter, Debug::General, " number of system fonts : [%d]\n", mSystemFonts.size() );
469 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetSystemFonts\n");
472 void FontClient::Plugin::GetDescription( FontId id,
473 FontDescription& fontDescription ) const
475 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetDescription\n");
476 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", id );
478 for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
479 endIt = mFontIdCache.end();
483 const FontIdCacheItem& item = *it;
485 if( item.fontId == id )
487 fontDescription = *( mFontDescriptionCache.begin() + item.validatedFontId );
489 DALI_LOG_INFO( gLogFilter, Debug::General, " description; family : [%s]\n", fontDescription.family.c_str() );
490 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", fontDescription.path.c_str() );
491 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
492 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
493 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
494 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetDescription\n");
499 DALI_LOG_INFO( gLogFilter, Debug::General, " No description found for the font ID %d\n", id );
500 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetDescription\n");
503 PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id )
505 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetPointSize\n");
506 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", id );
507 const FontId index = id - 1u;
510 ( index < mFontCache.size() ) )
512 DALI_LOG_INFO( gLogFilter, Debug::General, " point size : %d\n", ( *( mFontCache.begin() + index ) ).mRequestedPointSize );
513 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetPointSize\n");
514 return ( *( mFontCache.begin() + index ) ).mRequestedPointSize;
518 DALI_LOG_INFO( gLogFilter, Debug::General, " Invalid font ID %d\n", id );
521 DALI_LOG_INFO( gLogFilter, Debug::General, " default point size : %d\n", TextAbstraction::FontClient::DEFAULT_POINT_SIZE );
522 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetPointSize\n");
523 return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
526 bool FontClient::Plugin::IsCharacterSupportedByFont( FontId fontId, Character character )
528 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::IsCharacterSupportedByFont\n");
529 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", fontId );
530 DALI_LOG_INFO( gLogFilter, Debug::General, " character : %p\n", character );
532 if( ( fontId < 1u ) || ( fontId > mFontCache.size() ) )
534 DALI_LOG_INFO( gLogFilter, Debug::General, " Invalid font id. Number of items in the cache: %d\n",mFontCache.size());
535 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::IsCharacterSupportedByFont\n");
541 bool isSupported = false;
543 FontFaceCacheItem& cacheItem = mFontCache[fontId];
545 if( NULL == cacheItem.mCharacterSet )
547 // Create again the character set.
548 // It can be null if the ResetSystemDefaults() method has been called.
550 FontDescription description;
551 description.path = cacheItem.mPath;
552 description.family = FontFamily( cacheItem.mFreeTypeFace->family_name );
553 description.weight = FontWeight::NONE;
554 description.width = FontWidth::NONE;
555 description.slant = FontSlant::NONE;
557 // Note FreeType doesn't give too much info to build a proper font style.
558 if( cacheItem.mFreeTypeFace->style_flags & FT_STYLE_FLAG_ITALIC )
560 description.slant = FontSlant::ITALIC;
562 if( cacheItem.mFreeTypeFace->style_flags & FT_STYLE_FLAG_BOLD )
564 description.weight = FontWeight::BOLD;
567 cacheItem.mCharacterSet = CreateCharacterSetFromDescription( description );
570 isSupported = FcCharSetHasChar( cacheItem.mCharacterSet, character );
572 DALI_LOG_INFO( gLogFilter, Debug::General, " is supported : %s\n", (isSupported ? "true" : "false") );
573 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::IsCharacterSupportedByFont\n");
577 FontId FontClient::Plugin::FindFontForCharacter( const FontList& fontList,
578 const CharacterSetList& characterSetList,
580 PointSize26Dot6 requestedPointSize,
583 DALI_ASSERT_DEBUG( ( fontList.size() == characterSetList.Count() ) && "FontClient::Plugin::FindFontForCharacter. Different number of fonts and character sets." );
585 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFontForCharacter\n" );
586 DALI_LOG_INFO( gLogFilter, Debug::General, " character : %p\n", character );
587 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize );
588 DALI_LOG_INFO( gLogFilter, Debug::General, " preferColor : %s\n", ( preferColor ? "true" : "false" ) );
591 bool foundColor = false;
593 DALI_LOG_INFO( gLogFilter, Debug::General, " number of fonts : %d\n", fontList.size() );
595 // Traverse the list of fonts.
596 // Check for each font if supports the character.
597 for( unsigned int index = 0u, numberOfFonts = fontList.size(); index < numberOfFonts; ++index )
599 const FontDescription& description = fontList[index];
600 const FcCharSet* const characterSet = characterSetList[index];
602 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " description; family : [%s]\n", description.family.c_str() );
603 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", description.path.c_str() );
604 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[description.width] );
605 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[description.weight] );
606 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[description.slant] );
608 bool foundInRanges = false;
609 if( NULL != characterSet )
611 foundInRanges = FcCharSetHasChar( characterSet, character );
616 fontId = GetFontId( description,
620 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " font id : %d\n", fontId );
624 if( ( fontId > 0 ) &&
625 ( fontId - 1u < mFontCache.size() ) )
627 const FontFaceCacheItem& item = mFontCache[fontId - 1u];
629 foundColor = item.mHasColorTables;
632 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " foundColor : %s\n", ( foundColor ? "true" : "false" ) );
635 // Keep going unless we prefer a different (color) font.
636 if( !preferColor || foundColor )
643 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", fontId );
644 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFontForCharacter\n" );
648 FontId FontClient::Plugin::FindDefaultFont( Character charcode,
649 PointSize26Dot6 requestedPointSize,
652 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindDefaultFont\n" );
653 DALI_LOG_INFO( gLogFilter, Debug::General, " character : %p\n", charcode );
654 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize );
655 DALI_LOG_INFO( gLogFilter, Debug::General, " preferColor : %s\n", ( preferColor ? "true" : "false" ) );
659 // Create the list of default fonts if it has not been created.
660 if( mDefaultFonts.empty() )
662 FontDescription fontDescription;
663 fontDescription.family = DEFAULT_FONT_FAMILY_NAME;
664 fontDescription.width = IntToWidthType( DEFAULT_FONT_WIDTH );
665 fontDescription.weight = IntToWeightType( DEFAULT_FONT_WEIGHT );
666 fontDescription.slant = IntToSlantType( DEFAULT_FONT_SLANT );
668 SetFontList( fontDescription, mDefaultFonts, mDefaultFontCharacterSets );
670 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " number of default fonts : %d\n", mDefaultFonts.size() );
673 // Traverse the list of default fonts.
674 // Check for each default font if supports the character.
675 fontId = FindFontForCharacter( mDefaultFonts, mDefaultFontCharacterSets, charcode, requestedPointSize, preferColor );
677 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", fontId );
678 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindDefaultFont\n" );
683 FontId FontClient::Plugin::FindFallbackFont( Character charcode,
684 const FontDescription& preferredFontDescription,
685 PointSize26Dot6 requestedPointSize,
688 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFallbackFont\n" );
689 DALI_LOG_INFO( gLogFilter, Debug::General, " character : %p\n", charcode );
690 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize );
691 DALI_LOG_INFO( gLogFilter, Debug::General, " preferColor : %s\n", ( preferColor ? "true" : "false" ) );
693 // The font id to be returned.
696 FontDescription fontDescription;
698 // Fill the font description with the preferred font description and complete with the defaults.
699 fontDescription.family = preferredFontDescription.family.empty() ? DEFAULT_FONT_FAMILY_NAME : preferredFontDescription.family;
700 fontDescription.weight = ( ( FontWeight::NONE == preferredFontDescription.weight ) ? IntToWeightType( DEFAULT_FONT_WEIGHT ) : preferredFontDescription.weight );
701 fontDescription.width = ( ( FontWidth::NONE == preferredFontDescription.width ) ? IntToWidthType( DEFAULT_FONT_WIDTH ) : preferredFontDescription.width );
702 fontDescription.slant = ( ( FontSlant::NONE == preferredFontDescription.slant ) ? IntToSlantType( DEFAULT_FONT_SLANT ) : preferredFontDescription.slant );
704 DALI_LOG_INFO( gLogFilter, Debug::General, " preferredFontDescription --> fontDescription\n" );
705 DALI_LOG_INFO( gLogFilter, Debug::General, " [%s] --> [%s]\n", preferredFontDescription.family.c_str(), fontDescription.family.c_str() );
706 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " [%s] --> [%s]\n", FontWeight::Name[preferredFontDescription.weight], FontWeight::Name[fontDescription.weight] );
707 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " [%s] --> [%s]\n", FontWidth::Name[preferredFontDescription.width], FontWidth::Name[fontDescription.width] );
708 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " [%s] --> [%s]\n", FontSlant::Name[preferredFontDescription.slant], FontSlant::Name[fontDescription.slant] );
710 // Check first if the font's description has been queried before.
711 FontList* fontList = NULL;
712 CharacterSetList* characterSetList = NULL;
714 if( !FindFallbackFontList( fontDescription, fontList, characterSetList ) )
716 fontList = new FontList;
717 characterSetList = new CharacterSetList;
719 SetFontList( fontDescription, *fontList, *characterSetList );
721 // Add the font-list to the cache.
722 mFallbackCache.push_back( FallbackCacheItem( fontDescription, fontList, characterSetList ) );
725 if( fontList && characterSetList )
727 fontId = FindFontForCharacter( *fontList, *characterSetList, charcode, requestedPointSize, preferColor );
730 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", fontId );
731 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFallbackFont\n");
735 FontId FontClient::Plugin::GetFontId( const FontPath& path,
736 PointSize26Dot6 requestedPointSize,
738 bool cacheDescription )
740 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetFontId\n" );
741 DALI_LOG_INFO( gLogFilter, Debug::General, " path : [%s]\n", path.c_str() );
742 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize );
746 if( NULL != mFreeTypeLibrary )
749 if( FindFont( path, requestedPointSize, faceIndex, foundId ) )
755 id = CreateFont( path, requestedPointSize, faceIndex, cacheDescription );
759 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", id );
760 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetFontId\n" );
765 FontId FontClient::Plugin::GetFontId( const FontDescription& fontDescription,
766 PointSize26Dot6 requestedPointSize,
767 FaceIndex faceIndex )
769 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetFontId\n" );
770 DALI_LOG_INFO( gLogFilter, Debug::General, " description; family : [%s]\n", fontDescription.family.c_str() );
771 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", fontDescription.path.c_str() );
772 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
773 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
774 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
775 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize );
777 // This method uses three vectors which caches:
778 // * Pairs of non validated font descriptions and an index to a vector with paths to font file names.
779 // * The path to font file names.
780 // * The font ids of pairs 'font point size, index to the vector with paths to font file names'.
782 // 1) Checks in the cache if the font's description has been validated before.
783 // If it was it gets an index to the vector with paths to font file names. Otherwise,
784 // retrieves using font config a path to a font file name which matches with the
785 // font's description. The path is stored in the cache.
787 // 2) Checks in the cache if the pair 'font point size, index to the vector with paths to
788 // font file names' exists. If exists, it gets the font id. If it doesn't it calls
789 // the GetFontId() method with the path to the font file name and the point size to
792 // The font id to be returned.
795 // Check first if the font's description have been validated before.
796 FontDescriptionId validatedFontId = 0u;
798 if( !FindValidatedFont( fontDescription,
801 // Use font config to validate the font's description.
802 ValidateFont( fontDescription,
806 // Check if exists a pair 'validatedFontId, requestedPointSize' in the cache.
807 if( !FindFont( validatedFontId, requestedPointSize, fontId ) )
809 // Retrieve the font file name path.
810 const FontDescription& description = *( mFontDescriptionCache.begin() + validatedFontId );
812 // Retrieve the font id. Do not cache the description as it has been already cached.
813 fontId = GetFontId( description.path,
818 mFontCache[fontId-1u].mCharacterSet = mCharacterSetCache[validatedFontId];
820 // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
821 mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
826 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", fontId );
827 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetFontId\n" );
832 void FontClient::Plugin::ValidateFont( const FontDescription& fontDescription,
833 FontDescriptionId& validatedFontId )
835 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::ValidateFont\n" );
836 DALI_LOG_INFO( gLogFilter, Debug::General, " description; family : [%s]\n", fontDescription.family.c_str() );
837 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", fontDescription.path.c_str() );
838 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
839 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
840 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
842 // Create a font pattern.
843 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontDescription );
845 FontDescription description;
847 FcCharSet* characterSet = NULL;
848 bool matched = MatchFontDescriptionToPattern( fontFamilyPattern, description, &characterSet );
849 FcPatternDestroy( fontFamilyPattern );
851 if( matched && ( NULL != characterSet ) )
853 // Set the index to the vector of paths to font file names.
854 validatedFontId = mFontDescriptionCache.size();
856 DALI_LOG_INFO( gLogFilter, Debug::General, " matched description; family : [%s]\n", description.family.c_str() );
857 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", description.path.c_str() );
858 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[description.width] );
859 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[description.weight] );
860 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[description.slant] );
861 DALI_LOG_INFO( gLogFilter, Debug::General, " validatedFontId : %d\n", validatedFontId );
863 // Add the path to the cache.
864 mFontDescriptionCache.push_back( description );
865 mCharacterSetCache.PushBack( characterSet );
867 // Cache the index and the matched font's description.
868 FontDescriptionCacheItem item( description,
871 mValidatedFontCache.push_back( item );
873 if( ( fontDescription.family != description.family ) ||
874 ( fontDescription.width != description.width ) ||
875 ( fontDescription.weight != description.weight ) ||
876 ( fontDescription.slant != description.slant ) )
878 // Cache the given font's description if it's different than the matched.
879 FontDescriptionCacheItem item( fontDescription,
882 mValidatedFontCache.push_back( item );
887 DALI_LOG_INFO( gLogFilter, Debug::General, " font validation failed for font [%s]\n", fontDescription.family.c_str() );
890 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::ValidateFont\n" );
893 void FontClient::Plugin::GetFontMetrics( FontId fontId,
894 FontMetrics& metrics )
896 if( ( fontId > 0 ) &&
897 ( fontId - 1u < mFontCache.size() ) )
899 const FontFaceCacheItem& font = mFontCache[fontId-1];
901 metrics = font.mMetrics;
903 // Adjust the metrics if the fixed-size font should be down-scaled
904 if( font.mIsFixedSizeBitmap )
906 const float desiredFixedSize = static_cast<float>( font.mRequestedPointSize ) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
908 if( desiredFixedSize > 0.f )
910 const float scaleFactor = desiredFixedSize / static_cast<float>( font.mFixedHeightPixels );
912 metrics.ascender = floorf( metrics.ascender * scaleFactor );
913 metrics.descender = floorf( metrics.descender * scaleFactor );
914 metrics.height = floorf( metrics.height * scaleFactor );
915 metrics.underlinePosition = floorf( metrics.underlinePosition * scaleFactor );
916 metrics.underlineThickness = floorf( metrics.underlineThickness * scaleFactor );
922 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::GetFontMetrics. Invalid font id : %d\n", fontId );
926 GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId,
929 GlyphIndex index = 0u;
931 if( ( fontId > 0u ) &&
932 ( fontId - 1u < mFontCache.size() ) )
934 FT_Face ftFace = mFontCache[fontId-1u].mFreeTypeFace;
936 index = FT_Get_Char_Index( ftFace, charcode );
942 bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
947 if( VECTOR_GLYPH == type )
949 return GetVectorMetrics( array, size, horizontal );
952 return GetBitmapMetrics( array, size, horizontal );
955 bool FontClient::Plugin::GetBitmapMetrics( GlyphInfo* array,
959 bool success( true );
961 for( unsigned int i=0; i<size; ++i )
963 GlyphInfo& glyph = array[i];
965 FontId fontId = glyph.fontId;
968 fontId-1 < mFontCache.size() )
970 const FontFaceCacheItem& font = mFontCache[fontId-1];
972 FT_Face ftFace = font.mFreeTypeFace;
974 #ifdef FREETYPE_BITMAP_SUPPORT
975 // Check to see if we should be loading a Fixed Size bitmap?
976 if ( font.mIsFixedSizeBitmap )
978 int error = FT_Load_Glyph( ftFace, glyph.index, FT_LOAD_COLOR );
979 if ( FT_Err_Ok == error )
981 glyph.width = font.mFixedWidthPixels;
982 glyph.height = font.mFixedHeightPixels;
983 glyph.advance = font.mFixedWidthPixels;
984 glyph.xBearing = 0.0f;
985 glyph.yBearing = font.mFixedHeightPixels;
987 // Adjust the metrics if the fixed-size font should be down-scaled
988 const float desiredFixedSize = static_cast<float>( font.mRequestedPointSize ) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
990 if( desiredFixedSize > 0.f )
992 const float scaleFactor = desiredFixedSize / static_cast<float>( font.mFixedHeightPixels );
994 glyph.width = floorf( glyph.width * scaleFactor );
995 glyph.height = floorf( glyph.height * scaleFactor );
996 glyph.advance = floorf( glyph.advance * scaleFactor );
997 glyph.xBearing = floorf( glyph.xBearing * scaleFactor );
998 glyph.yBearing = floorf( glyph.yBearing * scaleFactor );
1000 glyph.scaleFactor = scaleFactor;
1005 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::GetBitmapMetrics. FreeType Bitmap Load_Glyph error %d\n", error );
1012 int error = FT_Load_Glyph( ftFace, glyph.index, FT_LOAD_DEFAULT );
1014 if( FT_Err_Ok == error )
1016 glyph.width = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
1017 glyph.height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
1020 glyph.xBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
1021 glyph.yBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
1025 glyph.xBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
1026 glyph.yBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
1044 bool FontClient::Plugin::GetVectorMetrics( GlyphInfo* array,
1048 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
1049 bool success( true );
1051 for( unsigned int i=0; i<size; ++i )
1053 FontId fontId = array[i].fontId;
1056 fontId-1 < mFontCache.size() )
1058 FontFaceCacheItem& font = mFontCache[fontId-1];
1060 if( ! font.mVectorFontId )
1062 font.mVectorFontId = mVectorFontCache->GetFontId( font.mPath );
1065 mVectorFontCache->GetGlyphMetrics( font.mVectorFontId, array[i] );
1067 // Vector metrics are in EMs, convert to pixels
1068 const float scale = ( static_cast<float>( font.mRequestedPointSize ) * FROM_266 ) * static_cast<float>( mDpiVertical ) / POINTS_PER_INCH;
1069 array[i].width *= scale;
1070 array[i].height *= scale;
1071 array[i].xBearing *= scale;
1072 array[i].yBearing *= scale;
1073 array[i].advance *= scale;
1087 void FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth )
1089 if( ( fontId > 0 ) &&
1090 ( fontId - 1u < mFontCache.size() ) )
1092 FT_Face ftFace = mFontCache[fontId - 1u].mFreeTypeFace;
1096 #ifdef FREETYPE_BITMAP_SUPPORT
1097 // Check to see if this is fixed size bitmap
1098 if ( mFontCache[fontId - 1u].mIsFixedSizeBitmap )
1100 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
1105 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_DEFAULT );
1107 if( FT_Err_Ok == error )
1110 error = FT_Get_Glyph( ftFace->glyph, &glyph );
1112 // Convert to bitmap if necessary
1113 if ( FT_Err_Ok == error )
1115 if( glyph->format != FT_GLYPH_FORMAT_BITMAP )
1117 // Check whether we should create a bitmap for the outline
1118 if( glyph->format == FT_GLYPH_FORMAT_OUTLINE && outlineWidth > 0 )
1122 error = FT_Stroker_New(mFreeTypeLibrary, &stroker );
1124 if ( FT_Err_Ok == error )
1126 FT_Stroker_Set( stroker, outlineWidth * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 );
1127 error = FT_Glyph_StrokeBorder( &glyph, stroker, 0, 1 );
1129 if ( FT_Err_Ok == error )
1131 FT_Stroker_Done( stroker );
1135 DALI_LOG_ERROR( "FT_Glyph_StrokeBorder Failed with error: %d\n", error );
1140 DALI_LOG_ERROR( "FT_Stroker_New Failed with error: %d\n", error );
1144 error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
1145 if ( FT_Err_Ok == error )
1147 FT_BitmapGlyph bitmapGlyph = reinterpret_cast< FT_BitmapGlyph >( glyph );
1148 ConvertBitmap( data, bitmapGlyph->bitmap );
1152 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Get_Glyph Failed with error: %d\n", error );
1157 ConvertBitmap( data, ftFace->glyph->bitmap );
1160 // Created FT_Glyph object must be released with FT_Done_Glyph
1161 FT_Done_Glyph( glyph );
1166 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::CreateBitmap. FT_Load_Glyph Failed with error: %d\n", error );
1171 PixelData FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth )
1173 TextAbstraction::FontClient::GlyphBufferData data;
1175 CreateBitmap( fontId, glyphIndex, data, outlineWidth );
1177 return PixelData::New( data.buffer,
1178 data.width * data.height * Pixel::GetBytesPerPixel( data.format ),
1182 PixelData::DELETE_ARRAY );
1185 void FontClient::Plugin::CreateVectorBlob( FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight )
1190 #ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
1192 fontId-1 < mFontCache.size() )
1194 FontFaceCacheItem& font = mFontCache[fontId-1];
1196 if( ! font.mVectorFontId )
1198 font.mVectorFontId = mVectorFontCache->GetFontId( font.mPath );
1201 mVectorFontCache->GetVectorBlob( font.mVectorFontId, fontId, glyphIndex, blob, blobLength, nominalWidth, nominalHeight );
1206 const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 requestedPointSize )
1208 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::GetEllipsisGlyph\n" );
1209 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize %d.\n", requestedPointSize );
1211 // First look into the cache if there is an ellipsis glyph for the requested point size.
1212 for( Vector<EllipsisItem>::ConstIterator it = mEllipsisCache.Begin(),
1213 endIt = mEllipsisCache.End();
1217 const EllipsisItem& item = *it;
1219 if( fabsf( item.requestedPointSize - requestedPointSize ) < Math::MACHINE_EPSILON_1000 )
1221 // Use the glyph in the cache.
1223 DALI_LOG_INFO( gLogFilter, Debug::General, " glyph id %d found in the cache.\n", item.glyph.index );
1224 DALI_LOG_INFO( gLogFilter, Debug::General, " font %d.\n", item.glyph.fontId );
1225 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetEllipsisGlyph\n" );
1231 // No glyph has been found. Create one.
1232 mEllipsisCache.PushBack( EllipsisItem() );
1233 EllipsisItem& item = *( mEllipsisCache.End() - 1u );
1235 item.requestedPointSize = requestedPointSize;
1237 // Find a font for the ellipsis glyph.
1238 item.glyph.fontId = FindDefaultFont( ELLIPSIS_CHARACTER,
1242 // Set the character index to access the glyph inside the font.
1243 item.glyph.index = FT_Get_Char_Index( mFontCache[item.glyph.fontId-1].mFreeTypeFace,
1244 ELLIPSIS_CHARACTER );
1246 GetBitmapMetrics( &item.glyph, 1u, true );
1248 DALI_LOG_INFO( gLogFilter, Debug::General, " glyph id %d found in the cache.\n", item.glyph.index );
1249 DALI_LOG_INFO( gLogFilter, Debug::General, " font %d.\n", item.glyph.fontId );
1250 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::GetEllipsisGlyph\n" );
1255 bool FontClient::Plugin::IsColorGlyph( FontId fontId, GlyphIndex glyphIndex )
1257 FT_Error error = -1;
1259 #ifdef FREETYPE_BITMAP_SUPPORT
1260 if( ( fontId > 0 ) &&
1261 ( fontId - 1u < mFontCache.size() ) )
1263 const FontFaceCacheItem& item = mFontCache[fontId - 1u];
1264 FT_Face ftFace = item.mFreeTypeFace;
1266 // Check to see if this is fixed size bitmap
1267 if( item.mHasColorTables )
1269 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
1274 return FT_Err_Ok == error;
1277 void FontClient::Plugin::InitSystemFonts()
1279 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::InitSystemFonts\n" );
1281 FcFontSet* fontSet = GetFcFontSet();
1285 DALI_LOG_INFO( gLogFilter, Debug::General, " number of system fonts : %d\n", fontSet->nfont );
1287 // Reserve some space to avoid reallocations.
1288 mSystemFonts.reserve( fontSet->nfont );
1290 for( int i = 0u; i < fontSet->nfont; ++i )
1292 FcPattern* fontPattern = fontSet->fonts[i];
1296 // Skip fonts with no path
1297 if( GetFcString( fontPattern, FC_FILE, path ) )
1299 mSystemFonts.push_back( FontDescription() );
1300 FontDescription& fontDescription = mSystemFonts.back();
1302 fontDescription.path = path;
1307 GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
1308 GetFcInt( fontPattern, FC_WIDTH, width );
1309 GetFcInt( fontPattern, FC_WEIGHT, weight );
1310 GetFcInt( fontPattern, FC_SLANT, slant );
1311 fontDescription.width = IntToWidthType( width );
1312 fontDescription.weight = IntToWeightType( weight );
1313 fontDescription.slant = IntToSlantType( slant );
1315 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " description; family : [%s]\n", fontDescription.family.c_str() );
1316 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", fontDescription.path.c_str() );
1317 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
1318 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
1319 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
1323 FcFontSetDestroy( fontSet );
1325 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::InitSystemFonts\n" );
1328 bool FontClient::Plugin::MatchFontDescriptionToPattern( FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription, FcCharSet** characterSet )
1330 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::MatchFontDescriptionToPattern\n" );
1332 FcResult result = FcResultMatch;
1333 FcPattern* match = FcFontMatch( NULL /* use default configure */, pattern, &result );
1335 const bool matched = NULL != match;
1336 DALI_LOG_INFO( gLogFilter, Debug::General, " pattern matched : %s\n", ( matched ? "true" : "false" ) );
1343 GetFcString( match, FC_FILE, fontDescription.path );
1344 GetFcString( match, FC_FAMILY, fontDescription.family );
1345 GetFcInt( match, FC_WIDTH, width );
1346 GetFcInt( match, FC_WEIGHT, weight );
1347 GetFcInt( match, FC_SLANT, slant );
1348 fontDescription.width = IntToWidthType( width );
1349 fontDescription.weight = IntToWeightType( weight );
1350 fontDescription.slant = IntToSlantType( slant );
1352 // Cache the character ranges.
1353 FcPatternGetCharSet( match, FC_CHARSET, 0u, characterSet );
1355 // destroyed the matched pattern
1356 FcPatternDestroy( match );
1358 DALI_LOG_INFO( gLogFilter, Debug::General, " description; family : [%s]\n", fontDescription.family.c_str() );
1359 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", fontDescription.path.c_str() );
1360 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
1361 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
1362 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
1365 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::MatchFontDescriptionToPattern\n" );
1369 FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontDescription& fontDescription ) const
1371 // create the cached font family lookup pattern
1372 // a pattern holds a set of names, each name refers to a property of the font
1373 FcPattern* fontFamilyPattern = FcPatternCreate();
1375 if( !fontFamilyPattern )
1380 // add a property to the pattern for the font family
1381 FcPatternAddString( fontFamilyPattern, FC_FAMILY, reinterpret_cast<const FcChar8*>( fontDescription.family.c_str() ) );
1383 int width = FONT_WIDTH_TYPE_TO_INT[fontDescription.width];
1387 width = DEFAULT_FONT_WIDTH;
1390 int weight = FONT_WEIGHT_TYPE_TO_INT[fontDescription.weight];
1394 weight = DEFAULT_FONT_WEIGHT;
1397 int slant = FONT_SLANT_TYPE_TO_INT[fontDescription.slant];
1401 slant = DEFAULT_FONT_SLANT;
1404 FcPatternAddInteger( fontFamilyPattern, FC_WIDTH, width );
1405 FcPatternAddInteger( fontFamilyPattern, FC_WEIGHT, weight );
1406 FcPatternAddInteger( fontFamilyPattern, FC_SLANT, slant );
1408 // Add a property of the pattern, to say we want to match TrueType fonts
1409 FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, reinterpret_cast<const FcChar8*>( FONT_FORMAT.c_str() ) );
1411 // modify the config, with the mFontFamilyPatterm
1412 FcConfigSubstitute( NULL /* use default configure */, fontFamilyPattern, FcMatchPattern );
1414 // provide default values for unspecified properties in the font pattern
1415 // e.g. patterns without a specified style or weight are set to Medium
1416 FcDefaultSubstitute( fontFamilyPattern );
1418 return fontFamilyPattern;
1421 _FcFontSet* FontClient::Plugin::GetFcFontSet() const
1423 // create a new pattern.
1424 // a pattern holds a set of names, each name refers to a property of the font
1425 FcPattern* pattern = FcPatternCreate();
1427 // create an object set used to define which properties are to be returned in the patterns from FcFontList.
1428 FcObjectSet* objectSet = FcObjectSetCreate();
1430 // build an object set from a list of property names
1431 FcObjectSetAdd( objectSet, FC_FILE );
1432 FcObjectSetAdd( objectSet, FC_FAMILY );
1433 FcObjectSetAdd( objectSet, FC_WIDTH );
1434 FcObjectSetAdd( objectSet, FC_WEIGHT );
1435 FcObjectSetAdd( objectSet, FC_SLANT );
1437 // get a list of fonts
1438 // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
1439 FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet );
1441 // clear up the object set
1444 FcObjectSetDestroy( objectSet );
1446 // clear up the pattern
1449 FcPatternDestroy( pattern );
1455 bool FontClient::Plugin::GetFcString( const FcPattern* const pattern,
1456 const char* const n,
1457 std::string& string )
1459 FcChar8* file = NULL;
1460 const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file );
1462 if( FcResultMatch == retVal )
1464 // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
1465 string.assign( reinterpret_cast<const char*>( file ) );
1473 bool FontClient::Plugin::GetFcInt( const _FcPattern* const pattern, const char* const n, int& intVal )
1475 const FcResult retVal = FcPatternGetInteger( pattern, n, 0u, &intVal );
1477 if( FcResultMatch == retVal )
1485 FontId FontClient::Plugin::CreateFont( const FontPath& path,
1486 PointSize26Dot6 requestedPointSize,
1487 FaceIndex faceIndex,
1488 bool cacheDescription )
1490 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::CreateFont\n" );
1491 DALI_LOG_INFO( gLogFilter, Debug::General, " path : [%s]\n", path.c_str() );
1492 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize );
1496 // Create & cache new font face
1498 int error = FT_New_Face( mFreeTypeLibrary,
1503 if( FT_Err_Ok == error )
1505 // Check if a font is scalable.
1506 const bool isScalable = ( 0 != ( ftFace->face_flags & FT_FACE_FLAG_SCALABLE ) );
1507 const bool hasFixedSizedBitmaps = ( 0 != ( ftFace->face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) && ( 0 != ftFace->num_fixed_sizes );
1508 const bool hasColorTables = ( 0 != ( ftFace->face_flags & FT_FACE_FLAG_COLOR ) );
1510 DALI_LOG_INFO( gLogFilter, Debug::General, " isScalable : [%s]\n", ( isScalable ? "true" : "false" ) );
1511 DALI_LOG_INFO( gLogFilter, Debug::General, " hasFixedSizedBitmaps : [%s]\n", ( hasFixedSizedBitmaps ? "true" : "false" ) );
1512 DALI_LOG_INFO( gLogFilter, Debug::General, " hasColorTables : [%s]\n", ( hasColorTables ? "true" : "false" ) );
1514 // Check to see if the font contains fixed sizes?
1515 if( !isScalable && hasFixedSizedBitmaps )
1517 PointSize26Dot6 actualPointSize = 0u;
1518 int fixedSizeIndex = 0;
1519 for( ; fixedSizeIndex < ftFace->num_fixed_sizes; ++fixedSizeIndex )
1521 const PointSize26Dot6 fixedSize = ftFace->available_sizes[fixedSizeIndex].size;
1522 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " size index : %d, size : %d\n", fixedSizeIndex, fixedSize );
1524 if( fixedSize >= requestedPointSize )
1526 actualPointSize = fixedSize;
1531 if( 0u == actualPointSize )
1533 // The requested point size is bigger than the bigest fixed size.
1534 fixedSizeIndex = ftFace->num_fixed_sizes - 1;
1535 actualPointSize = ftFace->available_sizes[fixedSizeIndex].size;
1538 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " size index : %d, actual size : %d\n", fixedSizeIndex, actualPointSize );
1540 // Tell Freetype to use this size
1541 error = FT_Select_Size( ftFace, fixedSizeIndex );
1542 if ( FT_Err_Ok != error )
1544 DALI_LOG_INFO( gLogFilter, Debug::General, "FreeType Select_Size error: %d\n", error );
1548 float fixedWidth = static_cast< float >( ftFace->available_sizes[ fixedSizeIndex ].width );
1549 float fixedHeight = static_cast< float >( ftFace->available_sizes[ fixedSizeIndex ].height );
1551 // Indicate that the font is a fixed sized bitmap
1552 FontMetrics metrics( fixedHeight, // The ascender in pixels.
1554 fixedHeight, // The height in pixels.
1558 mFontCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics, fixedWidth, fixedHeight, hasColorTables ) );
1559 id = mFontCache.size();
1564 error = FT_Set_Char_Size( ftFace,
1570 if( FT_Err_Ok == error )
1573 FT_Size_Metrics& ftMetrics = ftFace->size->metrics;
1575 FontMetrics metrics( static_cast< float >( ftMetrics.ascender ) * FROM_266,
1576 static_cast< float >( ftMetrics.descender ) * FROM_266,
1577 static_cast< float >( ftMetrics.height ) * FROM_266,
1578 static_cast< float >( ftFace->underline_position ) * FROM_266,
1579 static_cast< float >( ftFace->underline_thickness ) * FROM_266 );
1581 mFontCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics ) );
1582 id = mFontCache.size();
1586 DALI_LOG_INFO( gLogFilter, Debug::General, " FreeType Set_Char_Size error: %d for pointSize %d\n", error, requestedPointSize );
1592 if( cacheDescription )
1594 CacheFontPath( ftFace, id, requestedPointSize, path );
1600 DALI_LOG_INFO( gLogFilter, Debug::General, " FreeType New_Face error: %d for [%s]\n", error, path.c_str() );
1603 DALI_LOG_INFO( gLogFilter, Debug::General, " font id : %d\n", id );
1604 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::CreateFont\n" );
1609 void FontClient::Plugin::ConvertBitmap( TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap srcBitmap )
1611 if( srcBitmap.width*srcBitmap.rows > 0 )
1613 switch( srcBitmap.pixel_mode )
1615 case FT_PIXEL_MODE_GRAY:
1617 if( srcBitmap.pitch == static_cast<int>( srcBitmap.width ) )
1619 const unsigned int bufferSize = srcBitmap.width * srcBitmap.rows;
1620 data.buffer = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[].
1621 data.width = srcBitmap.width;
1622 data.height = srcBitmap.rows;
1623 data.format = Pixel::L8;
1624 memcpy( data.buffer, srcBitmap.buffer, bufferSize );
1629 #ifdef FREETYPE_BITMAP_SUPPORT
1630 case FT_PIXEL_MODE_BGRA:
1632 if( srcBitmap.pitch == static_cast<int>( srcBitmap.width << 2u ) )
1634 // Set the input dimensions.
1635 const ImageDimensions inputDimensions( srcBitmap.width, srcBitmap.rows );
1637 // Set the output dimensions.
1638 // If the output dimension is not given, the input dimension is set
1639 // and won't be downscaling.
1640 data.width = ( data.width == 0 ) ? srcBitmap.width : data.width;
1641 data.height = ( data.height == 0 ) ? srcBitmap.rows : data.height;
1642 const ImageDimensions desiredDimensions( data.width, data.height );
1644 // Creates the output buffer
1645 const unsigned int bufferSize = data.width * data.height * 4u;
1646 data.buffer = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[].
1648 if( inputDimensions == desiredDimensions )
1650 // There isn't downscaling.
1651 memcpy( data.buffer, srcBitmap.buffer, bufferSize );
1655 Dali::Internal::Platform::LanczosSample4BPP( srcBitmap.buffer,
1658 desiredDimensions );
1660 data.format = Pixel::BGRA8888;
1667 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::ConvertBitmap. FontClient Unable to create Bitmap of this PixelType\n" );
1674 bool FontClient::Plugin::FindFont( const FontPath& path,
1675 PointSize26Dot6 requestedPointSize,
1676 FaceIndex faceIndex,
1677 FontId& fontId ) const
1679 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFont\n" );
1680 DALI_LOG_INFO( gLogFilter, Debug::General, " path : [%s]\n", path.c_str() );
1681 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize );
1682 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " number of fonts in the cache : %d\n", mFontCache.size() );
1685 for( std::vector<FontFaceCacheItem>::const_iterator it = mFontCache.begin(),
1686 endIt = mFontCache.end();
1690 const FontFaceCacheItem& cacheItem = *it;
1692 if( cacheItem.mRequestedPointSize == requestedPointSize &&
1693 cacheItem.mFaceIndex == faceIndex &&
1694 cacheItem.mPath == path )
1698 DALI_LOG_INFO( gLogFilter, Debug::General, " font found, id : %d\n", fontId );
1699 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFont\n" );
1705 DALI_LOG_INFO( gLogFilter, Debug::General, " font not found\n" );
1706 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFont\n" );
1711 bool FontClient::Plugin::FindValidatedFont( const FontDescription& fontDescription,
1712 FontDescriptionId& validatedFontId )
1714 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindValidatedFont\n" );
1715 DALI_LOG_INFO( gLogFilter, Debug::General, " description; family : [%s]\n", fontDescription.family.c_str() );
1716 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", fontDescription.path.c_str() );
1717 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
1718 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
1719 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
1720 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " number of validated fonts in the cache : %d\n", mValidatedFontCache.size() );
1722 validatedFontId = 0u;
1724 for( std::vector<FontDescriptionCacheItem>::const_iterator it = mValidatedFontCache.begin(),
1725 endIt = mValidatedFontCache.end();
1729 const FontDescriptionCacheItem& item = *it;
1731 if( !fontDescription.family.empty() &&
1732 ( fontDescription.family == item.fontDescription.family ) &&
1733 ( fontDescription.width == item.fontDescription.width ) &&
1734 ( fontDescription.weight == item.fontDescription.weight ) &&
1735 ( fontDescription.slant == item.fontDescription.slant ) )
1737 validatedFontId = item.index;
1739 DALI_LOG_INFO( gLogFilter, Debug::General, " validated font found, id : %d\n", validatedFontId );
1740 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindValidatedFont\n" );
1745 DALI_LOG_INFO( gLogFilter, Debug::General, " validated font not found\n" );
1746 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindValidatedFont\n" );
1750 bool FontClient::Plugin::FindFallbackFontList( const FontDescription& fontDescription,
1751 FontList*& fontList,
1752 CharacterSetList*& characterSetList )
1754 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFallbackFontList\n" );
1755 DALI_LOG_INFO( gLogFilter, Debug::General, " description; family : [%s]\n", fontDescription.family.c_str() );
1756 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " path : [%s]\n", fontDescription.path.c_str() );
1757 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " width : [%s]\n", FontWidth::Name[fontDescription.width] );
1758 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " weight : [%s]\n", FontWeight::Name[fontDescription.weight] );
1759 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " slant : [%s]\n\n", FontSlant::Name[fontDescription.slant] );
1760 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " number of fallback font lists in the cache : %d\n", mFallbackCache.size() );
1764 for( std::vector<FallbackCacheItem>::const_iterator it = mFallbackCache.begin(), endIt = mFallbackCache.end();
1768 const FallbackCacheItem& item = *it;
1770 if( !fontDescription.family.empty() &&
1771 ( fontDescription.family == item.fontDescription.family ) &&
1772 ( fontDescription.width == item.fontDescription.width ) &&
1773 ( fontDescription.weight == item.fontDescription.weight ) &&
1774 ( fontDescription.slant == item.fontDescription.slant ) )
1776 fontList = item.fallbackFonts;
1777 characterSetList = item.characterSets;
1779 DALI_LOG_INFO( gLogFilter, Debug::General, " fallback font list found.\n" );
1780 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFallbackFontList\n" );
1785 DALI_LOG_INFO( gLogFilter, Debug::General, " fallback font list not found.\n" );
1786 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFallbackFontList\n" );
1790 bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId,
1791 PointSize26Dot6 requestedPointSize,
1794 DALI_LOG_INFO( gLogFilter, Debug::General, "-->FontClient::Plugin::FindFont\n" );
1795 DALI_LOG_INFO( gLogFilter, Debug::General, " validatedFontId : %d\n", validatedFontId );
1796 DALI_LOG_INFO( gLogFilter, Debug::General, " requestedPointSize : %d\n", requestedPointSize );
1800 for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
1801 endIt = mFontIdCache.end();
1805 const FontIdCacheItem& item = *it;
1807 if( ( validatedFontId == item.validatedFontId ) &&
1808 ( requestedPointSize == item.requestedPointSize ) )
1810 fontId = item.fontId;
1812 DALI_LOG_INFO( gLogFilter, Debug::General, " font found, id : %d\n", fontId );
1813 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFont\n" );
1818 DALI_LOG_INFO( gLogFilter, Debug::General, " font not found.\n" );
1819 DALI_LOG_INFO( gLogFilter, Debug::General, "<--FontClient::Plugin::FindFont\n" );
1823 bool FontClient::Plugin::IsScalable( const FontPath& path )
1825 bool isScalable = false;
1828 int error = FT_New_Face( mFreeTypeLibrary,
1832 if( FT_Err_Ok != error )
1834 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::IsScalable. FreeType Cannot check font: %s\n", path.c_str() );
1838 isScalable = ftFace->face_flags & FT_FACE_FLAG_SCALABLE;
1844 bool FontClient::Plugin::IsScalable( const FontDescription& fontDescription )
1846 // Create a font pattern.
1847 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontDescription );
1849 FcResult result = FcResultMatch;
1851 // match the pattern
1852 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
1853 bool isScalable = false;
1857 // Get the path to the font file name.
1859 GetFcString( match, FC_FILE, path );
1860 isScalable = IsScalable( path );
1864 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::IsScalable. FreeType Cannot check font: [%s]\n", fontDescription.family.c_str() );
1866 FcPatternDestroy( fontFamilyPattern );
1867 FcPatternDestroy( match );
1871 void FontClient::Plugin::GetFixedSizes( const FontPath& path, Vector< PointSize26Dot6 >& sizes )
1873 // Empty the caller container
1877 int error = FT_New_Face( mFreeTypeLibrary,
1881 if( FT_Err_Ok != error )
1883 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::GetFixedSizes. FreeType Cannot check font path : [%s]\n", path.c_str() );
1886 // Fetch the number of fixed sizes available
1887 if ( ftFace->num_fixed_sizes && ftFace->available_sizes )
1889 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
1891 sizes.PushBack( ftFace->available_sizes[ i ].size );
1896 void FontClient::Plugin::GetFixedSizes( const FontDescription& fontDescription,
1897 Vector< PointSize26Dot6 >& sizes )
1899 // Create a font pattern.
1900 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontDescription );
1902 FcResult result = FcResultMatch;
1904 // match the pattern
1905 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
1909 // Get the path to the font file name.
1911 GetFcString( match, FC_FILE, path );
1912 GetFixedSizes( path, sizes );
1916 DALI_LOG_INFO( gLogFilter, Debug::General, "FontClient::Plugin::GetFixedSizes. FreeType Cannot check font: [%s]\n", fontDescription.family.c_str() );
1918 FcPatternDestroy( match );
1919 FcPatternDestroy( fontFamilyPattern );
1922 void FontClient::Plugin::CacheFontPath( FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path )
1924 FontDescription description;
1925 description.path = path;
1926 description.family = FontFamily( ftFace->family_name );
1927 description.weight = FontWeight::NONE;
1928 description.width = FontWidth::NONE;
1929 description.slant = FontSlant::NONE;
1931 // Note FreeType doesn't give too much info to build a proper font style.
1932 if( ftFace->style_flags & FT_STYLE_FLAG_ITALIC )
1934 description.slant = FontSlant::ITALIC;
1936 if( ftFace->style_flags & FT_STYLE_FLAG_BOLD )
1938 description.weight = FontWeight::BOLD;
1941 FontDescriptionId validatedFontId = 0u;
1942 if( !FindValidatedFont( description,
1945 // Set the index to the vector of paths to font file names.
1946 validatedFontId = mFontDescriptionCache.size();
1948 FcPattern* pattern = CreateFontFamilyPattern( description );
1950 FcResult result = FcResultMatch;
1951 FcPattern* match = FcFontMatch( NULL, pattern, &result );
1953 FcCharSet* characterSet = NULL;
1954 FcPatternGetCharSet( match, FC_CHARSET, 0u, &characterSet );
1956 FcPatternDestroy( match );
1957 FcPatternDestroy( pattern );
1959 mFontCache[id-1u].mCharacterSet = characterSet;
1961 // Add the path to the cache.
1962 mFontDescriptionCache.push_back( description );
1963 mCharacterSetCache.PushBack( characterSet );
1965 // Cache the index and the font's description.
1966 FontDescriptionCacheItem item( description,
1969 mValidatedFontCache.push_back( item );
1971 // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
1972 mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
1978 FcCharSet* FontClient::Plugin::CreateCharacterSetFromDescription( const FontDescription& description ) const
1980 FcCharSet* characterSet = NULL;
1982 FcPattern* pattern = CreateFontFamilyPattern( description );
1984 if( NULL != pattern )
1986 FcResult result = FcResultMatch;
1987 FcPattern* match = FcFontMatch( NULL, pattern, &result );
1989 FcPatternGetCharSet( match, FC_CHARSET, 0u, &characterSet );
1991 FcPatternDestroy( match );
1992 FcPatternDestroy( pattern );
1995 return characterSet;
1998 } // namespace Internal
2000 } // namespace TextAbstraction