* Conversion from Fractional26.6 to float
*/
const float FROM_266 = 1.0f / 64.0f;
+const float POINTS_PER_INCH = 72.f;
const std::string FONT_FORMAT( "TrueType" );
const std::string DEFAULT_FONT_FAMILY_NAME( "Tizen" );
// http://www.freedesktop.org/software/fontconfig/fontconfig-user.html
+// NONE -1 --> DEFAULT_FONT_WIDTH (NORMAL) will be used.
// ULTRA_CONDENSED 50
// EXTRA_CONDENSED 63
// CONDENSED 75
// EXPANDED 125
// EXTRA_EXPANDED 150
// ULTRA_EXPANDED 200
-const int FONT_WIDTH_TYPE_TO_INT[] = { 50, 63, 75, 87, 100, 113, 125, 150, 200 };
+const int FONT_WIDTH_TYPE_TO_INT[] = { -1, 50, 63, 75, 87, 100, 113, 125, 150, 200 };
const unsigned int NUM_FONT_WIDTH_TYPE = sizeof( FONT_WIDTH_TYPE_TO_INT ) / sizeof( int );
+// NONE -1 --> DEFAULT_FONT_WEIGHT (NORMAL) will be used.
// THIN 0
// ULTRA_LIGHT, EXTRA_LIGHT 40
// LIGHT 50
// BOLD 200
// ULTRA_BOLD, EXTRA_BOLD 205
// BLACK, HEAVY, EXTRA_BLACK 210
-const int FONT_WEIGHT_TYPE_TO_INT[] = { 0, 40, 50, 55, 75, 80, 100, 180, 200, 205, 210 };
+const int FONT_WEIGHT_TYPE_TO_INT[] = { -1, 0, 40, 50, 55, 75, 80, 100, 180, 200, 205, 210 };
const unsigned int NUM_FONT_WEIGHT_TYPE = sizeof( FONT_WEIGHT_TYPE_TO_INT ) / sizeof( int );
-// NORMAL, ROMAN 0
-// ITALIC 100
-// OBLIQUE 110
-const int FONT_SLANT_TYPE_TO_INT[] = { 0, 100, 110 };
+// NONE -1 --> DEFAULT_FONT_SLANT (NORMAL) will be used.
+// NORMAL, ROMAN 0
+// ITALIC 100
+// OBLIQUE 110
+const int FONT_SLANT_TYPE_TO_INT[] = { -1, 0, 100, 110 };
const unsigned int NUM_FONT_SLANT_TYPE = sizeof( FONT_SLANT_TYPE_TO_INT ) / sizeof( int );
} // namespace
}
FontClient::Plugin::FontIdCacheItem::FontIdCacheItem( FontDescriptionId validatedFontId,
- PointSize26Dot6 pointSize,
+ PointSize26Dot6 requestedPointSize,
FontId fontId )
: validatedFontId( validatedFontId ),
- pointSize( pointSize ),
+ requestedPointSize( requestedPointSize ),
fontId( fontId )
{
}
-FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
- const FontPath& path,
- PointSize26Dot6 pointSize,
- FaceIndex face,
- const FontMetrics& metrics )
+FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem( FT_Face ftFace,
+ const FontPath& path,
+ PointSize26Dot6 requestedPointSize,
+ FaceIndex face,
+ const FontMetrics& metrics )
: mFreeTypeFace( ftFace ),
mPath( path ),
- mPointSize( pointSize ),
+ mRequestedPointSize( requestedPointSize ),
mFaceIndex( face ),
mMetrics( metrics ),
mFixedWidthPixels( 0.0f ),
mFixedHeightPixels( 0.0f ),
+ mVectorFontId( 0 ),
mIsFixedSizeBitmap( false )
{
}
-FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
- const FontPath& path,
- PointSize26Dot6 pointSize,
- FaceIndex face,
- const FontMetrics& metrics,
- float fixedWidth,
- float fixedHeight )
+FontClient::Plugin::FontFaceCacheItem::FontFaceCacheItem( FT_Face ftFace,
+ const FontPath& path,
+ PointSize26Dot6 requestedPointSize,
+ FaceIndex face,
+ const FontMetrics& metrics,
+ float fixedWidth,
+ float fixedHeight )
: mFreeTypeFace( ftFace ),
mPath( path ),
- mPointSize( pointSize ),
+ mRequestedPointSize( requestedPointSize ),
mFaceIndex( face ),
mMetrics( metrics ),
mFixedWidthPixels( fixedWidth ),
mFixedHeightPixels( fixedHeight ),
+ mVectorFontId( 0 ),
mIsFixedSizeBitmap( true )
{
}
: mFreeTypeLibrary( NULL ),
mDpiHorizontal( horizontalDpi ),
mDpiVertical( verticalDpi ),
+ mDefaultFontDescription(),
mSystemFonts(),
mDefaultFonts(),
mFontCache(),
mValidatedFontCache(),
mFontDescriptionCache( 1u ),
mFontIdCache(),
- mEllipsisCache()
+ mVectorFontCache( NULL ),
+ mEllipsisCache(),
+ mDefaultFontDescriptionCached( false )
{
int error = FT_Init_FreeType( &mFreeTypeLibrary );
if( FT_Err_Ok != error )
{
DALI_LOG_ERROR( "FreeType Init error: %d\n", error );
}
+
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+ mVectorFontCache = new VectorFontCache( mFreeTypeLibrary );
+#endif
}
FontClient::Plugin::~Plugin()
}
}
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+ delete mVectorFontCache;
+#endif
+
FT_Done_FreeType( mFreeTypeLibrary );
}
mDpiVertical = verticalDpi;
}
+void FontClient::Plugin::ResetSystemDefaults()
+{
+ mDefaultFontDescriptionCached = false;
+}
+
void FontClient::Plugin::SetFontList( const FontDescription& fontDescription, FontList& fontList )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::SetFontList family(%s)\n", fontDescription.family.c_str() );
FcPatternDestroy( fontFamilyPattern );
}
-void FontClient::Plugin::SetDefaultFont( const FontDescription& fontDescription )
-{
- SetFontList( fontDescription, mDefaultFonts );
-}
-
void FontClient::Plugin::GetDefaultFonts( FontList& defaultFonts )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetDefaultFonts mDefaultFonts(%s)\n", ( mDefaultFonts.empty()?"empty":"valid" ) );
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetDefaultPlatformFontDescription\n");
- if ( Adaptor::IsAvailable() )
+ if( !mDefaultFontDescriptionCached )
{
- std::string weight; // todo convert weight into enum
- Dali::Internal::Adaptor::Adaptor& adaptorImpl( Dali::Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ) );
- adaptorImpl.GetPlatformAbstraction().GetDefaultFontDescription( fontDescription.family, weight );
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetDefaultPlatformFontDescription Retreived fontFamily:%s\n", fontDescription.family.c_str() );
+ FcInitReinitialize(); // FcInitBringUptoDate did not seem to reload config file as was still getting old default font.
+
+ FcPattern* matchPattern = FcPatternCreate();
+ FcConfigSubstitute(NULL, matchPattern, FcMatchPattern);
+ FcDefaultSubstitute( matchPattern );
+
+ MatchFontDescriptionToPattern( matchPattern, mDefaultFontDescription );
+ FcPatternDestroy( matchPattern );
+
+ mDefaultFontDescriptionCached = true;
}
+
+ fontDescription.path = mDefaultFontDescription.path;
+ fontDescription.family = mDefaultFontDescription.family;
+ fontDescription.width = mDefaultFontDescription.width;
+ fontDescription.weight = mDefaultFontDescription.weight;
+ fontDescription.slant = mDefaultFontDescription.slant;
}
void FontClient::Plugin::GetSystemFonts( FontList& systemFonts )
if( id > 0u &&
index < mFontCache.size() )
{
- return ( *( mFontCache.begin() + index ) ).mPointSize;
+ return ( *( mFontCache.begin() + index ) ).mRequestedPointSize;
}
else
{
FontId FontClient::Plugin::FindFontForCharacter( const FontList& fontList,
Character charcode,
- PointSize26Dot6 requestedSize,
+ PointSize26Dot6 requestedPointSize,
bool preferColor )
{
- FontId fontId(0);
- bool foundColor(false);
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindFontForCharacter\n");
- // Traverse the list of fonts.
- // Check for each default font if supports the character.
+ FontId fontId = 0u;
+ bool foundColor = false;
+ // Traverse the list of fonts.
+ // Check for each font if supports the character.
for( FontList::const_iterator it = fontList.begin(), endIt = fontList.end();
it != endIt;
++it )
GetFixedSizes( description,
fixedSizes );
+ PointSize26Dot6 actualPointSize = requestedPointSize;
+
const Vector< PointSize26Dot6 >::SizeType count = fixedSizes.Count();
+
if( 0 != count )
{
- // If the font is not scalable, pick the largest size <= requestedSize
- PointSize26Dot6 size = fixedSizes[0];
+ // If the font is not scalable, pick the largest size <= requestedPointSize
+ actualPointSize = fixedSizes[0];
for( unsigned int i=1; i<count; ++i )
{
- if( fixedSizes[i] <= requestedSize &&
- fixedSizes[i] > size )
+ if( fixedSizes[i] <= requestedPointSize &&
+ fixedSizes[i] > actualPointSize )
{
- size = fixedSizes[i];
+ actualPointSize = fixedSizes[i];
}
}
- requestedSize = size;
}
fontId = GetFontId( description,
- requestedSize,
+ requestedPointSize,
+ actualPointSize,
0u );
if( preferColor )
{
- BufferImage bitmap = CreateBitmap( fontId, GetGlyphIndex(fontId,charcode) );
+ PixelData bitmap = CreateBitmap( fontId, GetGlyphIndex(fontId,charcode) );
if( bitmap &&
Pixel::BGRA8888 == bitmap.GetPixelFormat() )
{
}
}
- // Keep going unless we prefer a different (color) font
+ // Keep going unless we prefer a different (color) font.
if( !preferColor || foundColor )
{
FcPatternDestroy( match );
}
FontId FontClient::Plugin::FindDefaultFont( Character charcode,
- PointSize26Dot6 requestedSize,
+ PointSize26Dot6 requestedPointSize,
bool preferColor )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindDefaultFont DefaultFontsList(%s)\n", (mDefaultFonts.empty()?"empty":"created") );
fontDescription.width = IntToWidthType( DEFAULT_FONT_WIDTH );
fontDescription.weight = IntToWeightType( DEFAULT_FONT_WEIGHT );
fontDescription.slant = IntToSlantType( DEFAULT_FONT_SLANT );
+
SetFontList( fontDescription, mDefaultFonts );
}
// Traverse the list of default fonts.
// Check for each default font if supports the character.
- fontId = FindFontForCharacter( mDefaultFonts, charcode, requestedSize, preferColor );
+ fontId = FindFontForCharacter( mDefaultFonts, charcode, requestedPointSize, preferColor );
return fontId;
}
-FontId FontClient::Plugin::FindFallbackFont( FontId preferredFont,
- Character charcode,
- PointSize26Dot6 requestedSize,
+FontId FontClient::Plugin::FindFallbackFont( Character charcode,
+ const FontDescription& preferredFontDescription,
+ PointSize26Dot6 requestedPointSize,
bool preferColor )
{
// The font id to be returned.
FontId fontId = 0u;
FontDescription fontDescription;
- GetDescription( preferredFont, fontDescription );
+
+ // Fill the font description with the preferred font description and complete with the defaults.
+ fontDescription.family = preferredFontDescription.family.empty() ? DEFAULT_FONT_FAMILY_NAME : preferredFontDescription.family;
+ fontDescription.weight = ( ( FontWeight::NONE == preferredFontDescription.weight ) ? IntToWeightType( DEFAULT_FONT_WEIGHT ) : preferredFontDescription.weight );
+ fontDescription.width = ( ( FontWidth::NONE == preferredFontDescription.width ) ? IntToWidthType( DEFAULT_FONT_WIDTH ) : preferredFontDescription.width );
+ fontDescription.slant = ( ( FontSlant::NONE == preferredFontDescription.slant ) ? IntToSlantType( DEFAULT_FONT_SLANT ) : preferredFontDescription.slant );
// Check first if the font's description has been queried before.
FontList* fontList( NULL );
SetFontList( fontDescription, *fontList );
// Add the font-list to the cache.
- mFallbackCache.push_back( FallbackCacheItem(fontDescription, fontList) );
+ mFallbackCache.push_back( FallbackCacheItem( fontDescription, fontList ) );
}
if( fontList )
{
- fontId = FindFontForCharacter( *fontList, charcode, requestedSize, preferColor );
+ fontId = FindFontForCharacter( *fontList, charcode, requestedPointSize, preferColor );
}
return fontId;
}
FontId FontClient::Plugin::GetFontId( const FontPath& path,
- PointSize26Dot6 pointSize,
+ PointSize26Dot6 requestedPointSize,
+ PointSize26Dot6 actualPointSize,
FaceIndex faceIndex,
bool cacheDescription )
{
if( NULL != mFreeTypeLibrary )
{
FontId foundId(0);
- if( FindFont( path, pointSize, faceIndex, foundId ) )
+ if( FindFont( path, requestedPointSize, faceIndex, foundId ) )
{
id = foundId;
}
else
{
- id = CreateFont( path, pointSize, faceIndex, cacheDescription );
+ id = CreateFont( path, requestedPointSize, actualPointSize, faceIndex, cacheDescription );
}
}
}
FontId FontClient::Plugin::GetFontId( const FontDescription& fontDescription,
- PointSize26Dot6 pointSize,
+ PointSize26Dot6 requestedPointSize,
+ PointSize26Dot6 actualPointSize,
FaceIndex faceIndex )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::GetFontId font family(%s)\n", fontDescription.family.c_str() );
validatedFontId );
}
- // Check if exists a pair 'validatedFontId, pointSize' in the cache.
- if( !FindFont( validatedFontId, pointSize, fontId ) )
+ // Check if exists a pair 'validatedFontId, requestedPointSize' in the cache.
+ if( !FindFont( validatedFontId, requestedPointSize, fontId ) )
{
// Retrieve the font file name path.
const FontDescription& description = *( mFontDescriptionCache.begin() + validatedFontId );
// Retrieve the font id. Do not cache the description as it has been already cached.
fontId = GetFontId( description.path,
- pointSize,
+ requestedPointSize,
+ actualPointSize,
faceIndex,
false );
- // Cache the pair 'validatedFontId, pointSize' to improve the following queries.
+ // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
- pointSize,
+ requestedPointSize,
fontId ) );
}
// Create a font pattern.
FcPattern* fontFamilyPattern = CreateFontFamilyPattern( fontDescription );
- FcResult result = FcResultMatch;
+ FontDescription description;
- // match the pattern
- FcPattern* match = FcFontMatch( NULL /* use default configure */, fontFamilyPattern, &result );
+ bool matched = MatchFontDescriptionToPattern( fontFamilyPattern, description );
+ FcPatternDestroy( fontFamilyPattern );
- if( match )
+ if( matched )
{
- // Get the path to the font file name.
- int width = 0;
- int weight = 0;
- int slant = 0;
- FontDescription description;
- GetFcString( match, FC_FILE, description.path );
- GetFcString( match, FC_FAMILY, description.family );
- GetFcInt( match, FC_WIDTH, width );
- GetFcInt( match, FC_WEIGHT, weight );
- GetFcInt( match, FC_SLANT, slant );
- description.width = IntToWidthType( width );
- description.weight = IntToWeightType( weight );
- description.slant = IntToSlantType( slant );
-
// Set the index to the vector of paths to font file names.
validatedFontId = mFontDescriptionCache.size();
// Add the path to the cache.
mFontDescriptionCache.push_back( description );
- // Cache the index and the font's description.
+ // Cache the index and the matched font's description.
FontDescriptionCacheItem item( description,
validatedFontId );
mValidatedFontCache.push_back( item );
- // destroyed the matched pattern
- FcPatternDestroy( match );
+ if( ( fontDescription.family != description.family ) ||
+ ( fontDescription.width != description.width ) ||
+ ( fontDescription.weight != description.weight ) ||
+ ( fontDescription.slant != description.slant ) )
+ {
+ // Cache the given font's description if it's different than the matched.
+ FontDescriptionCacheItem item( fontDescription,
+ validatedFontId );
+
+ mValidatedFontCache.push_back( item );
+ }
}
else
{
}
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::ValidateFont validatedFontId(%u) font family(%s)\n", validatedFontId, fontDescription.family.c_str() );
-
- // destroy the pattern
- FcPatternDestroy( fontFamilyPattern );
}
void FontClient::Plugin::GetFontMetrics( FontId fontId,
- FontMetrics& metrics,
- int maxFixedSize )
+ FontMetrics& metrics )
{
- if( fontId > 0 &&
- fontId-1 < mFontCache.size() )
+ if( ( fontId > 0 ) &&
+ ( fontId - 1u < mFontCache.size() ) )
{
- const CacheItem& font = mFontCache[fontId-1];
+ const FontFaceCacheItem& font = mFontCache[fontId-1];
metrics = font.mMetrics;
// Adjust the metrics if the fixed-size font should be down-scaled
- if( font.mIsFixedSizeBitmap &&
- ( maxFixedSize > 0 ) &&
- ( font.mFixedHeightPixels > maxFixedSize ) )
+ if( font.mIsFixedSizeBitmap )
{
- float scaleFactor = static_cast<float>(maxFixedSize) / static_cast<float>(font.mFixedHeightPixels);
+ const float desiredFixedSize = static_cast<float>( font.mRequestedPointSize ) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
- metrics.ascender *= scaleFactor;
- metrics.descender *= scaleFactor;
- metrics.height *= scaleFactor;
- metrics.underlinePosition *= scaleFactor;
- metrics.underlineThickness *= scaleFactor;
+ if( desiredFixedSize > 0.f )
+ {
+ const float scaleFactor = desiredFixedSize / static_cast<float>( font.mFixedHeightPixels );
+
+ metrics.ascender = floorf( metrics.ascender * scaleFactor );
+ metrics.descender = floorf( metrics.descender * scaleFactor );
+ metrics.height = floorf( metrics.height * scaleFactor );
+ metrics.underlinePosition = floorf( metrics.underlinePosition * scaleFactor );
+ metrics.underlineThickness = floorf( metrics.underlineThickness * scaleFactor );
+ }
}
}
else
bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
uint32_t size,
- bool horizontal,
- int maxFixedSize )
+ GlyphType type,
+ bool horizontal )
+{
+ if( VECTOR_GLYPH == type )
+ {
+ return GetVectorMetrics( array, size, horizontal );
+ }
+
+ return GetBitmapMetrics( array, size, horizontal );
+}
+
+bool FontClient::Plugin::GetBitmapMetrics( GlyphInfo* array,
+ uint32_t size,
+ bool horizontal )
{
bool success( true );
for( unsigned int i=0; i<size; ++i )
{
- FontId fontId = array[i].fontId;
+ GlyphInfo& glyph = array[i];
+
+ FontId fontId = glyph.fontId;
if( fontId > 0 &&
fontId-1 < mFontCache.size() )
{
- const CacheItem& font = mFontCache[fontId-1];
+ const FontFaceCacheItem& font = mFontCache[fontId-1];
FT_Face ftFace = font.mFreeTypeFace;
// Check to see if we should be loading a Fixed Size bitmap?
if ( font.mIsFixedSizeBitmap )
{
- int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_COLOR );
+ int error = FT_Load_Glyph( ftFace, glyph.index, FT_LOAD_COLOR );
if ( FT_Err_Ok == error )
{
- array[i].width = font.mFixedWidthPixels;
- array[i].height = font.mFixedHeightPixels;
- array[i].advance = font.mFixedWidthPixels;
- array[i].xBearing = 0.0f;
- array[i].yBearing = font.mFixedHeightPixels;
+ glyph.width = font.mFixedWidthPixels;
+ glyph.height = font.mFixedHeightPixels;
+ glyph.advance = font.mFixedWidthPixels;
+ glyph.xBearing = 0.0f;
+ glyph.yBearing = font.mFixedHeightPixels;
// Adjust the metrics if the fixed-size font should be down-scaled
- if( ( maxFixedSize > 0 ) &&
- ( font.mFixedHeightPixels > maxFixedSize ) )
+ const float desiredFixedSize = static_cast<float>( font.mRequestedPointSize ) * FROM_266 / POINTS_PER_INCH * mDpiVertical;
+
+ if( desiredFixedSize > 0.f )
{
- float scaleFactor = static_cast<float>(maxFixedSize) / static_cast<float>(font.mFixedHeightPixels);
+ const float scaleFactor = desiredFixedSize / static_cast<float>( font.mFixedHeightPixels );
- array[i].width *= scaleFactor;
- array[i].height *= scaleFactor;
- array[i].advance *= scaleFactor;
- array[i].xBearing *= scaleFactor;
- array[i].yBearing *= scaleFactor;
+ glyph.width = floorf( glyph.width * scaleFactor );
+ glyph.height = floorf( glyph.height * scaleFactor );
+ glyph.advance = floorf( glyph.advance * scaleFactor );
+ glyph.xBearing = floorf( glyph.xBearing * scaleFactor );
+ glyph.yBearing = floorf( glyph.yBearing * scaleFactor );
- array[i].scaleFactor = scaleFactor;
+ glyph.scaleFactor = scaleFactor;
}
}
else
else
#endif
{
- int error = FT_Load_Glyph( ftFace, array[i].index, FT_LOAD_DEFAULT );
+ int error = FT_Load_Glyph( ftFace, glyph.index, FT_LOAD_DEFAULT );
if( FT_Err_Ok == error )
{
- array[i].width = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
- array[i].height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
+ glyph.width = static_cast< float >( ftFace->glyph->metrics.width ) * FROM_266;
+ glyph.height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
if( horizontal )
{
- array[i].xBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
- array[i].yBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
+ glyph.xBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
+ glyph.yBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
}
else
{
- array[i].xBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
- array[i].yBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
+ glyph.xBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
+ glyph.yBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
}
}
else
return success;
}
-BufferImage FontClient::Plugin::CreateBitmap( FontId fontId,
+bool FontClient::Plugin::GetVectorMetrics( GlyphInfo* array,
+ uint32_t size,
+ bool horizontal )
+{
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+ bool success( true );
+
+ for( unsigned int i=0; i<size; ++i )
+ {
+ FontId fontId = array[i].fontId;
+
+ if( fontId > 0 &&
+ fontId-1 < mFontCache.size() )
+ {
+ FontFaceCacheItem& font = mFontCache[fontId-1];
+
+ if( ! font.mVectorFontId )
+ {
+ font.mVectorFontId = mVectorFontCache->GetFontId( font.mPath );
+ }
+
+ mVectorFontCache->GetGlyphMetrics( font.mVectorFontId, array[i] );
+
+ // Vector metrics are in EMs, convert to pixels
+ const float scale = ( static_cast<float>( font.mRequestedPointSize ) * FROM_266 ) * static_cast<float>( mDpiVertical ) / POINTS_PER_INCH;
+ array[i].width *= scale;
+ array[i].height *= scale;
+ array[i].xBearing *= scale;
+ array[i].yBearing *= scale;
+ array[i].advance *= scale;
+ }
+ else
+ {
+ success = false;
+ }
+ }
+
+ return success;
+#else
+ return false;
+#endif
+}
+
+PixelData FontClient::Plugin::CreateBitmap( FontId fontId,
GlyphIndex glyphIndex )
{
- BufferImage bitmap;
+ PixelData bitmap;
if( fontId > 0 &&
fontId-1 < mFontCache.size() )
return bitmap;
}
-const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 pointSize )
+void FontClient::Plugin::CreateVectorBlob( FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight )
+{
+ blob = NULL;
+ blobLength = 0;
+
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+ if( fontId > 0 &&
+ fontId-1 < mFontCache.size() )
+ {
+ FontFaceCacheItem& font = mFontCache[fontId-1];
+
+ if( ! font.mVectorFontId )
+ {
+ font.mVectorFontId = mVectorFontCache->GetFontId( font.mPath );
+ }
+
+ mVectorFontCache->GetVectorBlob( font.mVectorFontId, fontId, glyphIndex, blob, blobLength, nominalWidth, nominalHeight );
+ }
+#endif
+}
+
+const GlyphInfo& FontClient::Plugin::GetEllipsisGlyph( PointSize26Dot6 requestedPointSize )
{
// First look into the cache if there is an ellipsis glyph for the requested point size.
for( Vector<EllipsisItem>::ConstIterator it = mEllipsisCache.Begin(),
{
const EllipsisItem& item = *it;
- if( fabsf( item.size - pointSize ) < Math::MACHINE_EPSILON_1000 )
+ if( fabsf( item.requestedPointSize - requestedPointSize ) < Math::MACHINE_EPSILON_1000 )
{
// Use the glyph in the cache.
return item.glyph;
mEllipsisCache.PushBack( EllipsisItem() );
EllipsisItem& item = *( mEllipsisCache.End() - 1u );
- item.size = pointSize;
+ item.requestedPointSize = requestedPointSize;
// Find a font for the ellipsis glyph.
item.glyph.fontId = FindDefaultFont( ELLIPSIS_CHARACTER,
- pointSize,
+ requestedPointSize,
false );
// Set the character index to access the glyph inside the font.
item.glyph.index = FT_Get_Char_Index( mFontCache[item.glyph.fontId-1].mFreeTypeFace,
ELLIPSIS_CHARACTER );
- GetGlyphMetrics( &item.glyph, 1u, true, 0 );
+ GetBitmapMetrics( &item.glyph, 1u, true );
return item.glyph;
}
}
}
+bool FontClient::Plugin::MatchFontDescriptionToPattern( FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription )
+{
+ FcResult result = FcResultMatch;
+ FcPattern* match = FcFontMatch( NULL /* use default configure */, pattern, &result );
+
+ bool ret = false;
+
+ if( match )
+ {
+ int width = 0;
+ int weight = 0;
+ int slant = 0;
+ GetFcString( match, FC_FILE, fontDescription.path );
+ GetFcString( match, FC_FAMILY, fontDescription.family );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::MatchFontDescriptionToPattern matched:%s \n", fontDescription.family.c_str());
+ GetFcInt( match, FC_WIDTH, width );
+ GetFcInt( match, FC_WEIGHT, weight );
+ GetFcInt( match, FC_SLANT, slant );
+ fontDescription.width = IntToWidthType( width );
+ fontDescription.weight = IntToWeightType( weight );
+ fontDescription.slant = IntToSlantType( slant );
+
+ // destroyed the matched pattern
+ FcPatternDestroy( match );
+ ret = true;
+ }
+ return ret;
+}
+
+
FcPattern* FontClient::Plugin::CreateFontFamilyPattern( const FontDescription& fontDescription )
{
// create the cached font family lookup pattern
// add a property to the pattern for the font family
FcPatternAddString( fontFamilyPattern, FC_FAMILY, reinterpret_cast<const FcChar8*>( fontDescription.family.c_str() ) );
- FcPatternAddInteger( fontFamilyPattern, FC_WIDTH, FONT_WIDTH_TYPE_TO_INT[fontDescription.width] );
- FcPatternAddInteger( fontFamilyPattern, FC_WEIGHT, FONT_WEIGHT_TYPE_TO_INT[fontDescription.weight] );
- FcPatternAddInteger( fontFamilyPattern, FC_SLANT, FONT_SLANT_TYPE_TO_INT[fontDescription.slant] );
+ int width = FONT_WIDTH_TYPE_TO_INT[fontDescription.width];
+ if( width < 0 )
+ {
+ // Use default.
+ width = DEFAULT_FONT_WIDTH;
+ }
+
+ int weight = FONT_WEIGHT_TYPE_TO_INT[fontDescription.weight];
+ if( weight < 0 )
+ {
+ // Use default.
+ weight = DEFAULT_FONT_WEIGHT;
+ }
+
+ int slant = FONT_SLANT_TYPE_TO_INT[fontDescription.slant];
+ if( slant < 0 )
+ {
+ // Use default.
+ slant = DEFAULT_FONT_SLANT;
+ }
+
+ FcPatternAddInteger( fontFamilyPattern, FC_WIDTH, width );
+ FcPatternAddInteger( fontFamilyPattern, FC_WEIGHT, weight );
+ FcPatternAddInteger( fontFamilyPattern, FC_SLANT, slant );
// Add a property of the pattern, to say we want to match TrueType fonts
FcPatternAddString( fontFamilyPattern , FC_FONTFORMAT, reinterpret_cast<const FcChar8*>( FONT_FORMAT.c_str() ) );
}
FontId FontClient::Plugin::CreateFont( const FontPath& path,
- PointSize26Dot6 pointSize,
+ PointSize26Dot6 requestedPointSize,
+ PointSize26Dot6 actualPointSize,
FaceIndex faceIndex,
bool cacheDescription )
{
// Ensure this size is available
for ( int i = 0; i < ftFace->num_fixed_sizes; ++i )
{
- if ( static_cast<FT_Pos>(pointSize) == ftFace->available_sizes[ i ].size )
+ if ( static_cast<FT_Pos>( actualPointSize ) == ftFace->available_sizes[ i ].size )
{
// Tell Freetype to use this size
error = FT_Select_Size( ftFace, i );
0.0f,
0.0f );
- mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics, fixedWidth, fixedHeight ) );
+ mFontCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics, fixedWidth, fixedHeight ) );
id = mFontCache.size();
if( cacheDescription )
{
- FontDescription description;
- description.path = path;
- description.family = FontFamily( ftFace->family_name );
-
- // Note FreeType doesn't give too much info to build a proper font style.
- if( ftFace->style_flags & FT_STYLE_FLAG_ITALIC )
- {
- description.slant = FontSlant::ITALIC;
- }
- if( ftFace->style_flags & FT_STYLE_FLAG_BOLD )
- {
- description.weight = FontWeight::BOLD;
- }
-
- mFontDescriptionCache.push_back( description );
+ CacheFontPath( ftFace, id, requestedPointSize, path );
}
+
return id;
}
}
sizes << ftFace->available_sizes[ i ].size;
}
DALI_LOG_ERROR( "FreeType Font: %s, does not contain Bitmaps of size: %d. Available sizes are: %s\n",
- path.c_str(), pointSize, sizes.str().c_str() );
+ path.c_str(), actualPointSize, sizes.str().c_str() );
}
else
{
error = FT_Set_Char_Size( ftFace,
- 0,
- pointSize,
- mDpiHorizontal,
- mDpiVertical );
+ 0,
+ actualPointSize,
+ mDpiHorizontal,
+ mDpiVertical );
if( FT_Err_Ok == error )
{
static_cast< float >( ftFace->underline_position ) * FROM_266,
static_cast< float >( ftFace->underline_thickness ) * FROM_266 );
- mFontCache.push_back( CacheItem( ftFace, path, pointSize, faceIndex, metrics ) );
+ mFontCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics ) );
id = mFontCache.size();
if( cacheDescription )
{
- FontDescription description;
- description.path = path;
- description.family = FontFamily( ftFace->family_name );
-
- // Note FreeType doesn't give too much info to build a proper font style.
- if( ftFace->style_flags & FT_STYLE_FLAG_ITALIC )
- {
- description.slant = FontSlant::ITALIC;
- }
- if( ftFace->style_flags & FT_STYLE_FLAG_BOLD )
- {
- description.weight = FontWeight::BOLD;
- }
-
- mFontDescriptionCache.push_back( description );
+ CacheFontPath( ftFace, id, requestedPointSize, path );
}
}
else
{
- DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", error, pointSize );
+ DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", error, actualPointSize );
}
}
}
return id;
}
-void FontClient::Plugin::ConvertBitmap( BufferImage& destBitmap,
+void FontClient::Plugin::ConvertBitmap( PixelData& destBitmap,
FT_Bitmap srcBitmap )
{
if( srcBitmap.width*srcBitmap.rows > 0 )
{
if( srcBitmap.pitch == static_cast< int >( srcBitmap.width ) )
{
- destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::L8 );
-
- PixelBuffer* destBuffer = destBitmap.GetBuffer();
- if( destBuffer )
- {
- memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows );
- }
- else
- {
- DALI_LOG_ERROR( "GetBuffer returns null\n" );
- }
+ unsigned int bufferSize( srcBitmap.width * srcBitmap.rows );
+ unsigned char* buffer = new unsigned char[bufferSize];
+ memcpy( buffer, srcBitmap.buffer,bufferSize );
+ destBitmap = PixelData::New( buffer, bufferSize, srcBitmap.width, srcBitmap.rows, Pixel::L8, PixelData::DELETE_ARRAY );
}
break;
}
{
if ( srcBitmap.pitch == static_cast< int >( srcBitmap.width << 2 ) )
{
- destBitmap = BufferImage::New( srcBitmap.width, srcBitmap.rows, Pixel::BGRA8888 );
-
- PixelBuffer* destBuffer = destBitmap.GetBuffer();
- if( destBuffer )
- {
- memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows*4 );
- }
- else
- {
- DALI_LOG_ERROR( "GetBuffer returns null\n" );
- }
+ unsigned int bufferSize( srcBitmap.width * srcBitmap.rows * 4 );
+ unsigned char* buffer = new unsigned char[bufferSize];
+ memcpy( buffer, srcBitmap.buffer,bufferSize );
+ destBitmap = PixelData::New( buffer, bufferSize, srcBitmap.width, srcBitmap.rows, Pixel::BGRA8888, PixelData::DELETE_ARRAY );
}
break;
}
}
bool FontClient::Plugin::FindFont( const FontPath& path,
- PointSize26Dot6 pointSize,
+ PointSize26Dot6 requestedPointSize,
FaceIndex faceIndex,
FontId& fontId ) const
{
fontId = 0u;
- for( std::vector<CacheItem>::const_iterator it = mFontCache.begin(),
+ for( std::vector<FontFaceCacheItem>::const_iterator it = mFontCache.begin(),
endIt = mFontCache.end();
it != endIt;
++it, ++fontId )
{
- const CacheItem& cacheItem = *it;
+ const FontFaceCacheItem& cacheItem = *it;
- if( cacheItem.mPointSize == pointSize &&
+ if( cacheItem.mRequestedPointSize == requestedPointSize &&
cacheItem.mFaceIndex == faceIndex &&
cacheItem.mPath == path )
{
}
bool FontClient::Plugin::FindFont( FontDescriptionId validatedFontId,
- PointSize26Dot6 pointSize,
+ PointSize26Dot6 requestedPointSize,
FontId& fontId )
{
fontId = 0u;
const FontIdCacheItem& item = *it;
if( ( validatedFontId == item.validatedFontId ) &&
- ( pointSize == item.pointSize ) )
+ ( requestedPointSize == item.requestedPointSize ) )
{
fontId = item.fontId;
return true;
FcPatternDestroy( fontFamilyPattern );
}
+void FontClient::Plugin::CacheFontPath( FT_Face ftFace, FontId id, PointSize26Dot6 requestedPointSize, const FontPath& path )
+{
+ FontDescription description;
+ description.path = path;
+ description.family = FontFamily( ftFace->family_name );
+ description.weight = FontWeight::NONE;
+ description.width = FontWidth::NONE;
+ description.slant = FontSlant::NONE;
+
+ // Note FreeType doesn't give too much info to build a proper font style.
+ if( ftFace->style_flags & FT_STYLE_FLAG_ITALIC )
+ {
+ description.slant = FontSlant::ITALIC;
+ }
+ if( ftFace->style_flags & FT_STYLE_FLAG_BOLD )
+ {
+ description.weight = FontWeight::BOLD;
+ }
+
+ FontDescriptionId validatedFontId = 0u;
+ if( !FindValidatedFont( description,
+ validatedFontId ) )
+ {
+ // Set the index to the vector of paths to font file names.
+ validatedFontId = mFontDescriptionCache.size();
+
+ // Add the path to the cache.
+ mFontDescriptionCache.push_back( description );
+
+ // Cache the index and the font's description.
+ FontDescriptionCacheItem item( description,
+ validatedFontId );
+
+ mValidatedFontCache.push_back( item );
+
+ // Cache the pair 'validatedFontId, requestedPointSize' to improve the following queries.
+ mFontIdCache.push_back( FontIdCacheItem( validatedFontId,
+ requestedPointSize,
+ id ) );
+ }
+}
+
} // namespace Internal
} // namespace TextAbstraction