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/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" );
40 const uint32_t ELLIPSIS_CHARACTER = 0x2026;
48 namespace TextAbstraction
54 const bool FONT_FIXED_SIZE_BITMAP( true );
56 FontClient::Plugin::FontDescriptionCacheItem::FontDescriptionCacheItem( const FontFamily& fontFamily,
57 const FontStyle& fontStyle,
58 FontDescriptionId index )
59 : fontFamily( fontFamily ),
60 fontStyle( fontStyle ),
65 FontClient::Plugin::FontIdCacheItem::FontIdCacheItem( FontDescriptionId validatedFontId,
66 PointSize26Dot6 pointSize,
68 : validatedFontId( validatedFontId ),
69 pointSize( pointSize ),
74 FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
76 PointSize26Dot6 pointSize,
78 const FontMetrics& metrics )
79 : mFreeTypeFace( ftFace ),
81 mPointSize( pointSize ),
84 mFixedWidthPixels( 0.0f ),
85 mFixedHeightPixels( 0.0f ),
86 mIsFixedSizeBitmap( false )
90 FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
92 PointSize26Dot6 pointSize,
94 const FontMetrics& metrics,
97 : mFreeTypeFace( ftFace ),
99 mPointSize( pointSize ),
102 mFixedWidthPixels( fixedWidth ),
103 mFixedHeightPixels( fixedHeight ),
104 mIsFixedSizeBitmap( true )
108 FontClient::Plugin::Plugin( unsigned int horizontalDpi,
109 unsigned int verticalDpi )
110 : mFreeTypeLibrary( NULL ),
111 mDpiHorizontal( horizontalDpi ),
112 mDpiVertical( verticalDpi ),
116 mValidatedFontCache(),
117 mFontDescriptionCache( 1u ),
121 int error = FT_Init_FreeType( &mFreeTypeLibrary );
122 if( FT_Err_Ok != error )
124 DALI_LOG_ERROR( "FreeType Init error: %d\n", error );
128 FontClient::Plugin::~Plugin()
130 FT_Done_FreeType( mFreeTypeLibrary );
133 void FontClient::Plugin::SetDpi( unsigned int horizontalDpi,
134 unsigned int verticalDpi )
136 mDpiHorizontal = horizontalDpi;
137 mDpiVertical = verticalDpi;
140 void FontClient::Plugin::SetDefaultFontFamily( const FontFamily& fontFamilyName,
141 const FontStyle& fontStyle )
143 mDefaultFonts.clear();
145 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamilyName,
148 FcResult result = FcResultMatch;
150 // Match the pattern.
151 FcFontSet* fontSet = FcFontSort( NULL /* use default configure */,
153 false /* don't trim */,
157 if( NULL != fontSet )
159 // Reserve some space to avoid reallocations.
160 mDefaultFonts.reserve( fontSet->nfont );
162 for( int i = 0u; i < fontSet->nfont; ++i )
164 FcPattern* fontPattern = fontSet->fonts[i];
168 // Skip fonts with no path
169 if( GetFcString( fontPattern, FC_FILE, path ) )
171 mDefaultFonts.push_back( FontDescription() );
172 FontDescription& fontDescription = mDefaultFonts.back();
174 fontDescription.path = path;
176 GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
177 GetFcString( fontPattern, FC_STYLE, fontDescription.style );
181 FcFontSetDestroy( fontSet );
184 FcPatternDestroy( fontFamilyPattern );
187 void FontClient::Plugin::GetDefaultFonts( FontList& defaultFonts )
189 if( mDefaultFonts.empty() )
191 SetDefaultFontFamily( DEFAULT_FONT_FAMILY_NAME,
192 DEFAULT_FONT_STYLE );
195 defaultFonts = mDefaultFonts;
198 void FontClient::Plugin::GetSystemFonts( FontList& systemFonts )
200 if( mSystemFonts.empty() )
205 systemFonts = mSystemFonts;
208 void FontClient::Plugin::GetDescription( FontId id,
209 FontDescription& fontDescription ) const
211 for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
212 endIt = mFontIdCache.end();
216 const FontIdCacheItem& item = *it;
218 if( item.fontId == id )
220 fontDescription = *( mFontDescriptionCache.begin() + item.validatedFontId );
225 DALI_LOG_ERROR( "FontClient::Plugin::GetDescription. No description found for the font ID %d\n", id );
228 PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id )
230 const FontId index = id - 1u;
233 index < mFontCache.size() )
235 return ( *( mFontCache.begin() + index ) ).mPointSize;
239 DALI_LOG_ERROR( "FontClient::Plugin::GetPointSize. Invalid font ID %d\n", id );
242 return TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
245 FontId FontClient::Plugin::FindDefaultFont( Character charcode,
246 PointSize26Dot6 requestedSize,
250 bool foundColor(false);
252 // Create the list of default fonts if it has not been created.
253 if( mDefaultFonts.empty() )
255 SetDefaultFontFamily( DEFAULT_FONT_FAMILY_NAME,
256 DEFAULT_FONT_STYLE );
259 // Traverse the list of default fonts.
260 // Check for each default font if supports the character.
262 for( FontList::const_iterator it = mDefaultFonts.begin(), endIt = mDefaultFonts.end();
266 const FontDescription& description = *it;
268 FcPattern* pattern = CreateFontFamilyPattern( description.family,
271 FcResult result = FcResultMatch;
272 FcPattern* match = FcFontMatch( NULL /* use default configure */, pattern, &result );
274 FcCharSet* charSet = NULL;
275 FcPatternGetCharSet( match, FC_CHARSET, 0u, &charSet );
277 if( FcCharSetHasChar( charSet, charcode ) )
279 Vector< PointSize26Dot6 > fixedSizes;
280 GetFixedSizes( description.family,
284 const Vector< PointSize26Dot6 >::SizeType count = fixedSizes.Count();
287 // If the font is not scalable, pick the largest size <= requestedSize
288 PointSize26Dot6 size = fixedSizes[0];
289 for( unsigned int i=1; i<count; ++i )
291 if( fixedSizes[i] <= requestedSize &&
292 fixedSizes[i] > size )
294 size = fixedSizes[i];
297 requestedSize = size;
300 fontId = GetFontId( description.family,
307 BufferImage bitmap = CreateBitmap( fontId, GetGlyphIndex(fontId,charcode) );
309 Pixel::BGRA8888 == bitmap.GetPixelFormat() )
315 // Keep going unless we prefer a different (color) font
316 if( !preferColor || foundColor )
318 FcPatternDestroy( match );
319 FcPatternDestroy( pattern );
324 FcPatternDestroy( match );
325 FcPatternDestroy( pattern );
330 FontId FontClient::Plugin::GetFontId( const FontPath& path,
331 PointSize26Dot6 pointSize,
333 bool cacheDescription )
337 if( NULL != mFreeTypeLibrary )
340 if( FindFont( path, pointSize, faceIndex, foundId ) )
346 id = CreateFont( path, pointSize, faceIndex, cacheDescription );
353 FontId FontClient::Plugin::GetFontId( const FontFamily& fontFamily,
354 const FontStyle& fontStyle,
355 PointSize26Dot6 pointSize,
356 FaceIndex faceIndex )
358 // This method uses three vectors which caches:
359 // * Pairs of non validated 'fontFamily, fontStyle' and an index to a vector with paths to font file names.
360 // * The path to font file names.
361 // * The font ids of pairs 'font point size, index to the vector with paths to font file names'.
363 // 1) Checks in the cache if the pair 'fontFamily, fontStyle' has been validated before.
364 // If it was it gets an index to the vector with paths to font file names. Otherwise,
365 // retrieves using font config a path to a font file name which matches with the pair
366 // 'fontFamily, fontStyle'. The path is stored in the chache.
368 // 2) Checks in the cache if the pair 'font point size, index to the vector with paths to
369 // fon file names' exists. If exists, it gets the font id. If it doesn't it calls
370 // the GetFontId() method with the path to the font file name and the point size to
373 // The font id to be returned.
376 // Check first if the pair font family and style have been validated before.
377 FontDescriptionId validatedFontId = 0u;
379 if( !FindValidatedFont( fontFamily,
383 // Use font config to validate the font family name and font style.
384 ValidateFont( fontFamily, fontStyle, validatedFontId );
387 // Check if exists a pair 'validatedFontId, pointSize' in the cache.
388 if( !FindFont( validatedFontId, pointSize, fontId ) )
390 // Retrieve the font file name path.
391 const FontDescription& description = *( mFontDescriptionCache.begin() + validatedFontId );
393 // Retrieve the font id. Do not cache the description as it has been already cached.
394 fontId = GetFontId( description.path,
399 // Cache the pair 'validatedFontId, pointSize' to improve the following queries.
400 mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
408 void FontClient::Plugin::ValidateFont( const FontFamily& fontFamily,
409 const FontStyle& fontStyle,
410 FontDescriptionId& validatedFontId )
412 // Create a font pattern.
413 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
416 FcResult result = FcResultMatch;
419 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
423 // Get the path to the font file name.
424 FontDescription description;
425 GetFcString( match, FC_FILE, description.path );
426 GetFcString( match, FC_FAMILY, description.family );
427 GetFcString( match, FC_STYLE, description.style );
429 // Set the index to the vector of paths to font file names.
430 validatedFontId = mFontDescriptionCache.size();
432 // Add the path to the cache.
433 mFontDescriptionCache.push_back( description );
435 // Cache the index and the pair font family name, font style.
436 FontDescriptionCacheItem item( fontFamily, fontStyle, validatedFontId );
437 mValidatedFontCache.push_back( item );
439 // destroyed the matched pattern
440 FcPatternDestroy( match );
444 DALI_LOG_ERROR( "FontClient::Plugin::ValidateFont failed for font %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
447 // destroy the pattern
448 FcPatternDestroy( fontFamilyPattern );
451 void FontClient::Plugin::GetFontMetrics( FontId fontId,
452 FontMetrics& metrics,
456 fontId-1 < mFontCache.size() )
458 const CacheItem& font = mFontCache[fontId-1];
460 metrics = font.mMetrics;
462 // Adjust the metrics if the fixed-size font should be down-scaled
463 if( font.mIsFixedSizeBitmap &&
464 ( maxFixedSize > 0 ) &&
465 ( font.mFixedHeightPixels > maxFixedSize ) )
467 float scaleFactor = static_cast<float>(maxFixedSize) / static_cast<float>(font.mFixedHeightPixels);
469 metrics.ascender *= scaleFactor;
470 metrics.descender *= scaleFactor;
471 metrics.height *= scaleFactor;
472 metrics.underlinePosition *= scaleFactor;
473 metrics.underlineThickness *= scaleFactor;
478 DALI_LOG_ERROR( "Invalid font ID %d\n", fontId );
482 GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId,
485 GlyphIndex index( 0 );
488 fontId-1 < mFontCache.size() )
490 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
492 index = FT_Get_Char_Index( ftFace, charcode );
498 bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
503 bool success( true );
505 for( unsigned int i=0; i<size; ++i )
507 FontId fontId = array[i].fontId;
510 fontId-1 < mFontCache.size() )
512 const CacheItem& font = mFontCache[fontId-1];
514 FT_Face ftFace = font.mFreeTypeFace;
516 #ifdef FREETYPE_BITMAP_SUPPORT
517 // Check to see if we should be loading a Fixed Size bitmap?
518 if ( font.mIsFixedSizeBitmap )
520 int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_COLOR );
521 if ( FT_Err_Ok == error )
523 array[i].width = font.mFixedWidthPixels;
524 array[i].height = font.mFixedHeightPixels;
525 array[i].advance = font.mFixedWidthPixels;
526 array[i].xBearing = 0.0f;
527 array[i].yBearing = font.mFixedHeightPixels;
529 // Adjust the metrics if the fixed-size font should be down-scaled
530 if( ( maxFixedSize > 0 ) &&
531 ( font.mFixedHeightPixels > maxFixedSize ) )
533 float scaleFactor = static_cast<float>(maxFixedSize) / static_cast<float>(font.mFixedHeightPixels);
535 array[i].width *= scaleFactor;
536 array[i].height *= scaleFactor;
537 array[i].advance *= scaleFactor;
538 array[i].xBearing *= scaleFactor;
539 array[i].yBearing *= scaleFactor;
541 array[i].scaleFactor = scaleFactor;
546 DALI_LOG_ERROR( "FreeType Bitmap Load_Glyph error %d\n", error );
553 int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_DEFAULT );
555 if( FT_Err_Ok == error )
557 array[i].width = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
558 array[i].height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
561 array[i].xBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
562 array[i].yBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
566 array[i].xBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
567 array[i].yBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
585 BufferImage FontClient::Plugin::CreateBitmap( FontId fontId,
586 GlyphIndex glyphIndex )
591 fontId-1 < mFontCache.size() )
593 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
597 #ifdef FREETYPE_BITMAP_SUPPORT
598 // Check to see if this is fixed size bitmap
599 if ( mFontCache[fontId-1].mIsFixedSizeBitmap )
601 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
606 error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_DEFAULT );
608 if( FT_Err_Ok == error )
611 error = FT_Get_Glyph( ftFace->glyph, &glyph );
613 // Convert to bitmap if necessary
614 if ( FT_Err_Ok == error )
616 if( glyph->format != FT_GLYPH_FORMAT_BITMAP )
618 error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
619 if ( FT_Err_Ok == error )
621 FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
622 ConvertBitmap( bitmap, bitmapGlyph->bitmap );
626 DALI_LOG_ERROR( "FT_Get_Glyph Failed with error: %d\n", error );
631 ConvertBitmap( bitmap, ftFace->glyph->bitmap );
634 // Created FT_Glyph object must be released with FT_Done_Glyph
635 FT_Done_Glyph( glyph );
640 DALI_LOG_ERROR( "FT_Load_Glyph Failed with error: %d\n", error );
647 const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 pointSize )
649 // First look into the cache if there is an ellipsis glyph for the requested point size.
650 for( Vector<EllipsisItem>::ConstIterator it = mEllipsisCache.Begin(),
651 endIt = mEllipsisCache.End();
655 const EllipsisItem& item = *it;
657 if( fabsf( item.size - pointSize ) < Math::MACHINE_EPSILON_1000 )
659 // Use the glyph in the cache.
664 // No glyph has been found. Create one.
665 mEllipsisCache.PushBack( EllipsisItem() );
666 EllipsisItem& item = *( mEllipsisCache.End() - 1u );
668 item.size = pointSize;
670 // Find a font for the ellipsis glyph.
671 item.glyph.fontId = FindDefaultFont( ELLIPSIS_CHARACTER,
675 // Set the character index to access the glyph inside the font.
676 item.glyph.index = FT_Get_Char_Index( mFontCache[item.glyph.fontId-1].mFreeTypeFace,
677 ELLIPSIS_CHARACTER );
679 GetGlyphMetrics( &item.glyph, 1u, true, 0 );
684 void FontClient::Plugin::InitSystemFonts()
686 FcFontSet* fontSet = GetFcFontSet();
690 // Reserve some space to avoid reallocations.
691 mSystemFonts.reserve( fontSet->nfont );
693 for( int i = 0u; i < fontSet->nfont; ++i )
695 FcPattern* fontPattern = fontSet->fonts[i];
699 // Skip fonts with no path
700 if( GetFcString( fontPattern, FC_FILE, path ) )
702 mSystemFonts.push_back( FontDescription() );
703 FontDescription& fontDescription = mSystemFonts.back();
705 fontDescription.path = path;
707 GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
708 GetFcString( fontPattern, FC_STYLE, fontDescription.style );
712 FcFontSetDestroy( fontSet );
716 FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontFamily& fontFamily,
717 const FontStyle& fontStyle )
719 // create the cached font family lookup pattern
720 // a pattern holds a set of names, each name refers to a property of the font
721 FcPattern* fontFamilyPattern = FcPatternCreate();
723 // add a property to the pattern for the font family
724 FcPatternAddString( fontFamilyPattern, FC_FAMILY, reinterpret_cast<const FcChar8*>( fontFamily.c_str() ) );
726 // add a property to the pattern for the font family
727 FcPatternAddString( fontFamilyPattern, FC_STYLE, reinterpret_cast<const FcChar8*>( fontStyle.c_str() ) );
729 // Add a property of the pattern, to say we want to match TrueType fonts
730 FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, reinterpret_cast<const FcChar8*>( FONT_FORMAT.c_str() ) );
732 // modify the config, with the mFontFamilyPatterm
733 FcConfigSubstitute( NULL /* use default configure */, fontFamilyPattern, FcMatchPattern );
735 // provide default values for unspecified properties in the font pattern
736 // e.g. patterns without a specified style or weight are set to Medium
737 FcDefaultSubstitute( fontFamilyPattern );
739 return fontFamilyPattern;
742 _FcFontSet* FontClient::Plugin::GetFcFontSet() const
744 // create a new pattern.
745 // a pattern holds a set of names, each name refers to a property of the font
746 FcPattern* pattern = FcPatternCreate();
748 // create an object set used to define which properties are to be returned in the patterns from FcFontList.
749 FcObjectSet* objectSet = FcObjectSetCreate();
751 // build an object set from a list of property names
752 FcObjectSetAdd( objectSet, FC_FILE );
753 FcObjectSetAdd( objectSet, FC_FAMILY );
754 FcObjectSetAdd( objectSet, FC_STYLE );
756 // get a list of fonts
757 // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
758 FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet );
760 // clear up the object set
763 FcObjectSetDestroy( objectSet );
765 // clear up the pattern
768 FcPatternDestroy( pattern );
774 bool FontClient::Plugin::GetFcString( const FcPattern* const pattern,
776 std::string& string )
778 FcChar8* file = NULL;
779 const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file );
781 if( FcResultMatch == retVal )
783 // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
784 string.assign( reinterpret_cast<const char*>( file ) );
792 FontId FontClient::Plugin::CreateFont( const FontPath& path,
793 PointSize26Dot6 pointSize,
795 bool cacheDescription )
799 // Create & cache new font face
801 int error = FT_New_Face( mFreeTypeLibrary,
806 if( FT_Err_Ok == error )
808 // Check to see if the font contains fixed sizes?
809 if ( ftFace->num_fixed_sizes && ftFace->available_sizes )
811 // Ensure this size is available
812 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
814 if ( static_cast<FT_Pos>(pointSize) == ftFace->available_sizes[ i ].size )
816 // Tell Freetype to use this size
817 error = FT_Select_Size( ftFace, i );
818 if ( FT_Err_Ok != error )
820 DALI_LOG_ERROR( "FreeType Select_Size error: %d\n", error );
824 float fixedWidth = static_cast< float >( ftFace->available_sizes[ i ].width );
825 float fixedHeight = static_cast< float >( ftFace->available_sizes[ i ].height );
827 // Indicate that the font is a fixed sized bitmap
828 FontMetrics metrics( fixedHeight, // The ascender in pixels.
830 fixedHeight, // The height in pixels.
834 mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics, fixedWidth, fixedHeight ) );
835 id = mFontCache.size();
837 if( cacheDescription )
839 FontDescription description;
840 description.path = path;
841 description.family = FontFamily( ftFace->family_name );
842 description.style = FontStyle( ftFace->style_name );
844 mFontDescriptionCache.push_back( description );
851 // Can't find this size
852 std::stringstream sizes;
853 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
859 sizes << ftFace->available_sizes[ i ].size;
861 DALI_LOG_ERROR( "FreeType Font: %s, does not contain Bitmaps of size: %d. Available sizes are: %s\n",
862 path.c_str(), pointSize, sizes.str().c_str() );
866 error = FT_Set_Char_Size( ftFace,
872 if( FT_Err_Ok == error )
875 FT_Size_Metrics& ftMetrics = ftFace->size->metrics;
877 FontMetrics metrics( static_cast< float >( ftMetrics.ascender ) * FROM_266,
878 static_cast< float >( ftMetrics.descender ) * FROM_266,
879 static_cast< float >( ftMetrics.height ) * FROM_266,
880 static_cast< float >( ftFace->underline_position ) * FROM_266,
881 static_cast< float >( ftFace->underline_thickness ) * FROM_266 );
883 mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics ) );
884 id = mFontCache.size();
886 if( cacheDescription )
888 FontDescription description;
889 description.path = path;
890 description.family = FontFamily( ftFace->family_name );
891 description.style = FontStyle( ftFace->style_name );
893 mFontDescriptionCache.push_back( description );
898 DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", error, pointSize );
904 DALI_LOG_ERROR( "FreeType New_Face error: %d for %s\n", error, path.c_str() );
910 void FontClient::Plugin::ConvertBitmap( BufferImage& destBitmap,
911 FT_Bitmap srcBitmap )
913 if( srcBitmap.width*srcBitmap.rows > 0 )
915 switch( srcBitmap.pixel_mode )
917 case FT_PIXEL_MODE_GRAY:
919 if( srcBitmap.pitch == static_cast< int >( srcBitmap.width ) )
921 destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::L8 );
923 PixelBuffer* destBuffer = destBitmap.GetBuffer();
926 memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows );
930 DALI_LOG_ERROR( "GetBuffer returns null\n" );
936 #ifdef FREETYPE_BITMAP_SUPPORT
937 case FT_PIXEL_MODE_BGRA:
939 if ( srcBitmap.pitch == static_cast< int >( srcBitmap.width << 2 ) )
941 destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::BGRA8888 );
943 PixelBuffer* destBuffer = destBitmap.GetBuffer();
946 memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows*4 );
950 DALI_LOG_ERROR( "GetBuffer returns null\n" );
958 DALI_LOG_ERROR( "FontClient Unable to create Bitmap of this PixelType\n" );
965 bool FontClient::Plugin::FindFont( const FontPath& path,
966 PointSize26Dot6 pointSize,
968 FontId& fontId ) const
971 for( std::vector<CacheItem>::const_iterator it = mFontCache.begin(),
972 endIt = mFontCache.end();
976 const CacheItem& cacheItem = *it;
978 if( cacheItem.mPointSize == pointSize &&
979 cacheItem.mFaceIndex == faceIndex &&
980 cacheItem.mPath == path )
990 bool FontClient::Plugin::FindValidatedFont( const FontFamily& fontFamily,
991 const FontStyle& fontStyle,
992 FontDescriptionId& validatedFontId )
994 validatedFontId = 0u;
996 for( std::vector<FontDescriptionCacheItem>::const_iterator it = mValidatedFontCache.begin(),
997 endIt = mValidatedFontCache.end();
1001 const FontDescriptionCacheItem& item = *it;
1003 if( ( fontFamily == item.fontFamily ) &&
1004 ( fontStyle == item.fontStyle ) )
1006 validatedFontId = item.index;
1015 bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId,
1016 PointSize26Dot6 pointSize,
1021 for( std::vector<FontIdCacheItem>::const_iterator it = mFontIdCache.begin(),
1022 endIt = mFontIdCache.end();
1026 const FontIdCacheItem& item = *it;
1028 if( ( validatedFontId == item.validatedFontId ) &&
1029 ( pointSize == item.pointSize ) )
1031 fontId = item.fontId;
1039 bool FontClient::Plugin::IsScalable( const FontPath& path )
1042 int error = FT_New_Face( mFreeTypeLibrary,
1046 if( FT_Err_Ok != error )
1048 DALI_LOG_ERROR( "FreeType Cannot check font: %s\n", path.c_str() );
1050 return ( ftFace->num_fixed_sizes == 0 );
1053 bool FontClient::Plugin::IsScalable( const FontFamily& fontFamily, const FontStyle& fontStyle )
1055 // Create a font pattern.
1056 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
1059 FcResult result = FcResultMatch;
1061 // match the pattern
1062 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
1063 bool isScalable = true;
1067 // Get the path to the font file name.
1069 GetFcString( match, FC_FILE, path );
1070 isScalable = IsScalable( path );
1074 DALI_LOG_ERROR( "FreeType Cannot check font: %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
1076 FcPatternDestroy( fontFamilyPattern );
1077 FcPatternDestroy( match );
1081 void FontClient::Plugin::GetFixedSizes( const FontPath& path, Vector< PointSize26Dot6 >& sizes )
1083 // Empty the caller container
1087 int error = FT_New_Face( mFreeTypeLibrary,
1091 if( FT_Err_Ok != error )
1093 DALI_LOG_ERROR( "FreeType Cannot check font: %s\n", path.c_str() );
1096 // Fetch the number of fixed sizes available
1097 if ( ftFace->num_fixed_sizes && ftFace->available_sizes )
1099 for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
1101 sizes.PushBack( ftFace->available_sizes[ i ].size );
1106 void FontClient::Plugin::GetFixedSizes( const FontFamily& fontFamily,
1107 const FontStyle& fontStyle,
1108 Vector< PointSize26Dot6 >& sizes )
1110 // Create a font pattern.
1111 FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontFamily,
1114 FcResult result = FcResultMatch;
1116 // match the pattern
1117 FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
1121 // Get the path to the font file name.
1123 GetFcString( match, FC_FILE, path );
1124 GetFixedSizes( path, sizes );
1128 DALI_LOG_ERROR( "FreeType Cannot check font: %s %s\n", fontFamily.c_str(), fontStyle.c_str() );
1130 FcPatternDestroy( match );
1131 FcPatternDestroy( fontFamilyPattern );
1134 } // namespace Internal
1136 } // namespace TextAbstraction