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 * Conversion from Fractional26.6 to float
31 const float FROM_266 = 1.0f / 64.0f;
33 const std::string FONT_FORMAT( "TrueType" );
34 const std::string DEFAULT_FONT_FAMILY_NAME( "Tizen" );
35 const std::string DEFAULT_FONT_STYLE( "Regular" );
41 namespace TextAbstraction
47 FontClient::Plugin::CacheItem::CacheItem( FontId id,
49 const std::string& path,
50 PointSize26Dot6 pointSize,
52 const FontMetrics& metrics )
53 : mFreeTypeFace( ftFace ),
55 mPointSize( pointSize ),
60 FontClient::Plugin::Plugin( unsigned int horizontalDpi,
61 unsigned int verticalDpi )
62 : mFreeTypeLibrary( NULL ),
63 mDpiHorizontal( horizontalDpi ),
64 mDpiVertical( verticalDpi )
67 FontClient::Plugin::~Plugin()
69 FT_Done_FreeType( mFreeTypeLibrary );
72 void FontClient::Plugin::Initialize()
74 int error = FT_Init_FreeType( &mFreeTypeLibrary );
75 if( FT_Err_Ok != error )
77 DALI_LOG_ERROR( "FreeType Init error: %d\n", error );
81 void FontClient::Plugin::SetDpi( unsigned int horizontalDpi,
82 unsigned int verticalDpi )
84 mDpiHorizontal = horizontalDpi;
85 mDpiVertical = verticalDpi;
88 void FontClient::Plugin::GetSystemFonts( FontList& systemFonts )
90 if( mSystemFonts.empty() )
95 systemFonts = mSystemFonts;
98 void FontClient::Plugin::InitSystemFonts()
100 FcFontSet* fontSet = GetFcFontSet();
104 mSystemFonts.reserve( fontSet->nfont );
106 for( int i = 0u; i < fontSet->nfont; ++i )
108 FcPattern* fontPattern = fontSet->fonts[i];
112 // Skip fonts with no path
113 if( GetFcString( fontPattern, FC_FILE, path ) )
115 mSystemFonts.push_back( FontDescription() );
116 FontDescription& fontDescription = mSystemFonts.back();
118 fontDescription.path = path;
120 GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
121 GetFcString( fontPattern, FC_STYLE, fontDescription.style );
125 FcFontSetDestroy( fontSet );
129 _FcFontSet* FontClient::Plugin::GetFcFontSet() const
131 // create a new pattern.
132 // a pattern holds a set of names, each name refers to a property of the font
133 FcPattern* pattern = FcPatternCreate();
135 // create an object set used to define which properties are to be returned in the patterns from FcFontList.
136 FcObjectSet* objectSet = FcObjectSetCreate();
138 // build an object set from a list of property names
139 FcObjectSetAdd( objectSet, FC_FILE );
140 FcObjectSetAdd( objectSet, FC_FAMILY );
141 FcObjectSetAdd( objectSet, FC_STYLE );
143 // get a list of fonts
144 // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
145 FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet );
147 // clear up the object set
150 FcObjectSetDestroy( objectSet );
152 // clear up the pattern
155 FcPatternDestroy( pattern );
161 bool FontClient::Plugin::GetFcString( const FcPattern* pattern,
163 std::string& string )
165 FcChar8* file = NULL;
166 const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file );
168 if( FcResultMatch == retVal )
170 // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
171 string.assign( reinterpret_cast<const char*>( file ) );
179 void FontClient::Plugin::GetDescription( FontId id,
180 FontDescription& fontDescription ) const
185 PointSize26Dot6 FontClient::Plugin::GetPointSize( FontId id )
190 FontId FontClient::Plugin::FindDefaultFont( Character charcode,
191 PointSize26Dot6 pointSize )
193 // TODO - Use FcCharSetHasChar()
197 FontId FontClient::Plugin::GetFontId( const std::string& path,
198 PointSize26Dot6 pointSize,
199 FaceIndex faceIndex )
203 if( NULL != mFreeTypeLibrary )
206 if( FindFont( path, pointSize, faceIndex, foundId ) )
212 id = CreateFont( path, pointSize, faceIndex );
219 FontId FontClient::Plugin::GetFontId( const FontFamily& fontFamily,
220 const FontStyle& fontStyle,
221 PointSize26Dot6 pointSize,
222 FaceIndex faceIndex )
227 GlyphIndex FontClient::Plugin::GetGlyphIndex( FontId fontId,
230 GlyphIndex index( 0 );
233 fontId-1 < mFontCache.size() )
235 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
237 index = FT_Get_Char_Index( ftFace, charcode );
243 FontId FontClient::Plugin::CreateFont( const std::string& path,
244 PointSize26Dot6 pointSize,
245 FaceIndex faceIndex )
249 // Create & cache new font face
251 int error = FT_New_Face( mFreeTypeLibrary,
256 if( FT_Err_Ok == error )
258 error = FT_Set_Char_Size( ftFace,
264 if( FT_Err_Ok == error )
266 id = mFontCache.size() + 1;
268 FT_Size_Metrics& ftMetrics = ftFace->size->metrics;
270 FontMetrics metrics( static_cast< float >( ftMetrics.ascender ) * FROM_266,
271 static_cast< float >( ftMetrics.descender ) * FROM_266,
272 static_cast< float >( ftMetrics.height ) * FROM_266 );
274 mFontCache.push_back( CacheItem( id, ftFace, path, pointSize, faceIndex, metrics ) );
278 DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", pointSize );
283 DALI_LOG_ERROR( "FreeType New_Face error: %d for %s\n", error, path.c_str() );
289 void FontClient::Plugin::GetFontMetrics( FontId fontId,
290 FontMetrics& metrics )
293 fontId-1 < mFontCache.size() )
295 metrics = mFontCache[fontId-1].mMetrics;
299 DALI_LOG_ERROR( "Invalid font ID %d\n", fontId );
303 bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
307 bool success( true );
309 for( unsigned int i=0; i<size; ++i )
311 FontId fontId = array[i].fontId;
314 fontId-1 < mFontCache.size() )
316 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
318 int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_DEFAULT );
320 if( FT_Err_Ok == error )
322 array[i].width = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
323 array[i].height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
326 array[i].xBearing = static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
327 array[i].yBearing = static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
328 array[i].advance = static_cast< float >( ftFace->glyph->metrics.horiAdvance ) * FROM_266;
332 array[i].xBearing = static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
333 array[i].yBearing = static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
334 array[i].advance = static_cast< float >( ftFace->glyph->metrics.vertAdvance ) * FROM_266;
351 BitmapImage FontClient::Plugin::CreateBitmap( FontId fontId,
352 GlyphIndex glyphIndex )
357 fontId-1 < mFontCache.size() )
359 FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
361 FT_Error error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_DEFAULT );
362 if( FT_Err_Ok == error )
365 error = FT_Get_Glyph( ftFace->glyph, &glyph );
367 // Convert to bitmap if necessary
368 if ( FT_Err_Ok == error )
370 if( glyph->format != FT_GLYPH_FORMAT_BITMAP )
372 error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
376 DALI_LOG_ERROR( "FT_Glyph_To_Bitmap Failed with error: %d\n", error );
381 DALI_LOG_ERROR( "FT_Get_Glyph Failed with error: %d\n", error );
384 if( FT_Err_Ok == error )
386 // Access the underlying bitmap data
387 FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
388 ConvertBitmap( bitmap, bitmapGlyph->bitmap );
391 // Created FT_Glyph object must be released with FT_Done_Glyph
392 FT_Done_Glyph( glyph );
396 DALI_LOG_ERROR( "FT_Load_Glyph Failed with error: %d\n", error );
403 void FontClient::Plugin::ConvertBitmap( BitmapImage& destBitmap,
404 FT_Bitmap srcBitmap )
406 if( srcBitmap.width*srcBitmap.rows > 0 )
408 // TODO - Support all pixel modes
409 if( FT_PIXEL_MODE_GRAY == srcBitmap.pixel_mode )
411 if( srcBitmap.pitch == srcBitmap.width )
413 destBitmap = BitmapImage::New( srcBitmap.width, srcBitmap.rows, Pixel::L8 );
415 PixelBuffer* destBuffer = destBitmap.GetBuffer();
416 memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows );
422 bool FontClient::Plugin::FindFont( const std::string& path,
423 PointSize26Dot6 pointSize,
425 FontId& found ) const
427 for( unsigned int i=0; i<mFontCache.size(); ++i )
429 if( mFontCache[i].mPointSize == pointSize &&
430 mFontCache[i].mPath == path &&
431 mFontCache[i].mFaceIndex == faceIndex )
441 } // namespace Internal
443 } // namespace TextAbstraction