#include <dali/integration-api/debug.h>
#include <dali/integration-api/platform-abstraction.h>
#include <dali/internal/text-abstraction/font-client-helper.h>
+#include <platform-abstractions/portable/image-operations.h>
#include <adaptor-impl.h>
// EXTERNAL INCLUDES
// 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::CacheItem::CacheItem( FT_Face ftFace,
- const FontPath& path,
- PointSize26Dot6 requestedPointSize,
- 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 ),
mRequestedPointSize( requestedPointSize ),
{
}
-FontClient::Plugin::CacheItem::CacheItem( FT_Face ftFace,
- const FontPath& path,
- PointSize26Dot6 requestedPointSize,
- 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 ),
mRequestedPointSize( requestedPointSize ),
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::FindFontForCharacter\n");
- FontId fontId(0);
- bool foundColor(false);
+ FontId fontId = 0u;
+ bool foundColor = false;
// Traverse the list of fonts.
- // Check for each default font if supports the character.
-
+ // Check for each font if supports the character.
for( FontList::const_iterator it = fontList.begin(), endIt = fontList.end();
it != endIt;
++it )
if( preferColor )
{
- PixelData bitmap = CreateBitmap( fontId, GetGlyphIndex(fontId,charcode) );
- if( bitmap &&
- Pixel::BGRA8888 == bitmap.GetPixelFormat() )
- {
- foundColor = true;
- }
+ foundColor = IsColorGlyph( fontId, GetGlyphIndex( fontId, charcode ) );
}
- // Keep going unless we prefer a different (color) font
+ // Keep going unless we prefer a different (color) font.
if( !preferColor || foundColor )
{
FcPatternDestroy( match );
fontDescription.width = IntToWidthType( DEFAULT_FONT_WIDTH );
fontDescription.weight = IntToWeightType( DEFAULT_FONT_WEIGHT );
fontDescription.slant = IntToSlantType( DEFAULT_FONT_SLANT );
+
SetFontList( fontDescription, mDefaultFonts );
}
return fontId;
}
-FontId FontClient::Plugin::FindFallbackFont( FontId preferredFont,
- Character charcode,
+FontId FontClient::Plugin::FindFallbackFont( Character charcode,
+ const FontDescription& preferredFontDescription,
PointSize26Dot6 requestedPointSize,
bool preferColor )
{
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 )
if( ( fontId > 0 ) &&
( fontId - 1u < mFontCache.size() ) )
{
- const CacheItem& font = mFontCache[fontId-1];
+ const FontFaceCacheItem& font = mFontCache[fontId-1];
metrics = font.mMetrics;
if( fontId > 0 &&
fontId-1 < mFontCache.size() )
{
- const CacheItem& font = mFontCache[fontId-1];
+ const FontFaceCacheItem& font = mFontCache[fontId-1];
FT_Face ftFace = font.mFreeTypeFace;
if( fontId > 0 &&
fontId-1 < mFontCache.size() )
{
- CacheItem& font = mFontCache[fontId-1];
+ FontFaceCacheItem& font = mFontCache[fontId-1];
if( ! font.mVectorFontId )
{
#endif
}
-PixelData FontClient::Plugin::CreateBitmap( FontId fontId,
- GlyphIndex glyphIndex )
+void FontClient::Plugin::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data )
{
- PixelData bitmap;
-
- if( fontId > 0 &&
- fontId-1 < mFontCache.size() )
+ if( ( fontId > 0 ) &&
+ ( fontId - 1u < mFontCache.size() ) )
{
- FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
+ FT_Face ftFace = mFontCache[fontId - 1u].mFreeTypeFace;
FT_Error error;
#ifdef FREETYPE_BITMAP_SUPPORT
// Check to see if this is fixed size bitmap
- if ( mFontCache[fontId-1].mIsFixedSizeBitmap )
+ if ( mFontCache[fontId - 1u].mIsFixedSizeBitmap )
{
error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
}
if ( FT_Err_Ok == error )
{
FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
- ConvertBitmap( bitmap, bitmapGlyph->bitmap );
+ ConvertBitmap( data, bitmapGlyph->bitmap );
}
else
{
}
else
{
- ConvertBitmap( bitmap, ftFace->glyph->bitmap );
+ ConvertBitmap( data, ftFace->glyph->bitmap );
}
// Created FT_Glyph object must be released with FT_Done_Glyph
DALI_LOG_ERROR( "FT_Load_Glyph Failed with error: %d\n", error );
}
}
+}
- return bitmap;
+PixelData FontClient::Plugin::CreateBitmap( FontId fontId,
+ GlyphIndex glyphIndex )
+{
+ TextAbstraction::FontClient::GlyphBufferData data;
+
+ CreateBitmap( fontId, glyphIndex, data );
+
+ return PixelData::New( data.buffer,
+ data.width * data.height * Pixel::GetBytesPerPixel( data.format ),
+ data.width,
+ data.height,
+ data.format,
+ PixelData::DELETE_ARRAY );
}
void FontClient::Plugin::CreateVectorBlob( FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight )
if( fontId > 0 &&
fontId-1 < mFontCache.size() )
{
- CacheItem& font = mFontCache[fontId-1];
+ FontFaceCacheItem& font = mFontCache[fontId-1];
if( ! font.mVectorFontId )
{
return item.glyph;
}
+bool FontClient::Plugin::IsColorGlyph( FontId fontId, GlyphIndex glyphIndex )
+{
+ FT_Error error = -1;
+
+#ifdef FREETYPE_BITMAP_SUPPORT
+ if( ( fontId > 0 ) &&
+ ( fontId - 1u < mFontCache.size() ) )
+ {
+ const FontFaceCacheItem& item = mFontCache[fontId - 1u];
+ FT_Face ftFace = item.mFreeTypeFace;
+
+ // Check to see if this is fixed size bitmap
+ if( item.mIsFixedSizeBitmap )
+ {
+ error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_COLOR );
+ }
+ }
+#endif
+
+ return FT_Err_Ok == error;
+}
+
void FontClient::Plugin::InitSystemFonts()
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "FontClient::Plugin::InitSystemFonts \n");
fontDescription.width = IntToWidthType( width );
fontDescription.weight = IntToWeightType( weight );
fontDescription.slant = IntToSlantType( slant );
+
// destroyed the matched pattern
FcPatternDestroy( match );
ret = true;
// 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() ) );
0.0f,
0.0f );
- mFontCache.push_back( CacheItem( ftFace, path, requestedPointSize, faceIndex, metrics, fixedWidth, fixedHeight ) );
+ mFontCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics, fixedWidth, fixedHeight ) );
id = mFontCache.size();
if( cacheDescription )
static_cast< float >( ftFace->underline_position ) * FROM_266,
static_cast< float >( ftFace->underline_thickness ) * FROM_266 );
- mFontCache.push_back( CacheItem( ftFace, path, requestedPointSize, faceIndex, metrics ) );
+ mFontCache.push_back( FontFaceCacheItem( ftFace, path, requestedPointSize, faceIndex, metrics ) );
id = mFontCache.size();
if( cacheDescription )
return id;
}
-void FontClient::Plugin::ConvertBitmap( PixelData& destBitmap,
- FT_Bitmap srcBitmap )
+void FontClient::Plugin::ConvertBitmap( TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap srcBitmap )
{
if( srcBitmap.width*srcBitmap.rows > 0 )
{
{
case FT_PIXEL_MODE_GRAY:
{
- if( srcBitmap.pitch == static_cast< int >( srcBitmap.width ) )
+ if( srcBitmap.pitch == static_cast<int>( srcBitmap.width ) )
{
- 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 );
+ const unsigned int bufferSize = srcBitmap.width * srcBitmap.rows;
+ data.buffer = new unsigned char[bufferSize];
+ data.width = srcBitmap.width;
+ data.height = srcBitmap.rows;
+ data.format = Pixel::L8;
+ memcpy( data.buffer, srcBitmap.buffer, bufferSize );
}
break;
}
#ifdef FREETYPE_BITMAP_SUPPORT
case FT_PIXEL_MODE_BGRA:
{
- if ( srcBitmap.pitch == static_cast< int >( srcBitmap.width << 2 ) )
+ if( srcBitmap.pitch == static_cast<int>( srcBitmap.width << 2u ) )
{
- 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 );
+ // Set the input dimensions.
+ const ImageDimensions inputDimensions( srcBitmap.width, srcBitmap.rows );
+
+ // Set the output dimensions.
+ // If the output dimension is not given, the input dimension is set
+ // and won't be downscaling.
+ data.width = ( data.width == 0 ) ? srcBitmap.width : data.width;
+ data.height = ( data.height == 0 ) ? srcBitmap.rows : data.height;
+ const ImageDimensions desiredDimensions( data.width, data.height );
+
+ // Creates the output buffer
+ const unsigned int bufferSize = data.width * data.height * 4u;
+ data.buffer = new unsigned char[bufferSize]; // @note The caller is responsible for deallocating the bitmap data using delete[].
+
+ if( inputDimensions == desiredDimensions )
+ {
+ // There isn't downscaling.
+ memcpy( data.buffer, srcBitmap.buffer, bufferSize );
+ }
+ else
+ {
+ Dali::Internal::Platform::LanczosSample4BPP( srcBitmap.buffer,
+ inputDimensions,
+ data.buffer,
+ desiredDimensions );
+ }
+ data.format = Pixel::BGRA8888;
}
break;
}
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.mRequestedPointSize == requestedPointSize &&
cacheItem.mFaceIndex == faceIndex &&
FontDescription description;
description.path = path;
description.family = FontFamily( ftFace->family_name );
- description.weight = FontWeight::NORMAL;
- description.width = FontWidth::NORMAL;
- description.slant = FontSlant::NORMAL;
+ 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 )