Retrieve outline glyph from freetype
[platform/core/uifw/dali-adaptor.git] / text / dali / internal / text-abstraction / font-client-impl.cpp
index bdd0f9e..4ab90bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
-// CLASS  HEADER
-#include "font-client-impl.h"
+// CLASS HEADER
+#include <dali/internal/text-abstraction/font-client-impl.h>
 
 // EXTERNAL INCLUDES
-#include <vector>
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_GLYPH_H
-#include <fontconfig/fontconfig.h>
-#include <dali/integration-api/debug.h>
+#ifndef DALI_PROFILE_UBUNTU
+#include <vconf.h>
+#endif
 
 // INTERNAL INCLUDES
-#include <singleton-service-impl.h>
-
-/**
- * Conversion from Fractional26.6 to float
- */
-namespace
-{
-const float FROM_266 = 1.0f / 64.0f;
-}
+#include <singleton-service.h>
+#include <dali/internal/text-abstraction/font-client-plugin-impl.h>
 
 namespace Dali
 {
@@ -46,493 +36,249 @@ namespace TextAbstraction
 namespace Internal
 {
 
-struct FontClient::Plugin
+FontClient::FontClient()
+: mPlugin( NULL ),
+  mDpiHorizontal( 0 ),
+  mDpiVertical( 0 )
 {
-  struct CacheItem
-  {
-    CacheItem( FontId id, FT_Face ftFace, const std::string& path, PointSize26Dot6 pointSize, FaceIndex face, const FontMetrics& metrics )
-    : mFreeTypeFace( ftFace ),
-      mPath( path ),
-      mPointSize( pointSize ),
-      mFaceIndex( face ),
-      mMetrics( metrics )
-    {
-    }
-
-    FT_Face mFreeTypeFace;
-    std::string mPath;
-    PointSize26Dot6 mPointSize;
-    FaceIndex mFaceIndex;
-    FontMetrics mMetrics;
-  };
-
-  Plugin( unsigned int horizontalDpi, unsigned int verticalDpi )
-  : mFreeTypeLibrary( NULL ),
-    mDpiHorizontal( horizontalDpi ),
-    mDpiVertical( verticalDpi )
-  {
-  }
-
-  ~Plugin()
-  {
-    FT_Done_FreeType( mFreeTypeLibrary );
-  }
-
-  void Initialize()
-  {
-    int error = FT_Init_FreeType( &mFreeTypeLibrary );
-    if( FT_Err_Ok != error )
-    {
-      DALI_LOG_ERROR( "FreeType Init error: %d\n", error );
-    }
-  }
-
-  void SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi )
-  {
-    mDpiHorizontal = horizontalDpi;
-    mDpiVertical = verticalDpi;
-  }
-
-  void GetSystemFonts( FontList& systemFonts )
-  {
-    if( mSystemFonts.empty() )
-    {
-      InitSystemFonts();
-    }
-
-    systemFonts = mSystemFonts;
-  }
-
-  void InitSystemFonts()
-  {
-    FcFontSet* fontSet = GetFcFontSet();
-
-    if( fontSet )
-    {
-      mSystemFonts.reserve( fontSet->nfont );
-
-      for( int i = 0u; i < fontSet->nfont; ++i )
-      {
-        FcPattern* fontPattern = fontSet->fonts[i];
-
-        std::string path;
-
-        // Skip fonts with no path
-        if( GetFcString( fontPattern, FC_FILE, path ) )
-        {
-          mSystemFonts.push_back( FontDescription() );
-          FontDescription& fontDescription = mSystemFonts.back();
-
-          fontDescription.path = path;
+}
 
-          GetFcString( fontPattern, FC_FAMILY, fontDescription.family );
-          GetFcString( fontPattern, FC_STYLE, fontDescription.style );
-        }
-      }
+FontClient::~FontClient()
+{
+  delete mPlugin;
+}
 
-      FcFontSetDestroy( fontSet );
-    }
-  }
+Dali::TextAbstraction::FontClient FontClient::Get()
+{
+  Dali::TextAbstraction::FontClient fontClientHandle;
 
-  _FcFontSet* GetFcFontSet() const
+  Dali::SingletonService service( SingletonService::Get() );
+  if ( service )
   {
-    // create a new pattern.
-    // a pattern holds a set of names, each name refers to a property of the font
-    FcPattern* pattern = FcPatternCreate();
-
-    // create an object set used to define which properties are to be returned in the patterns from FcFontList.
-    FcObjectSet* objectSet = FcObjectSetCreate();
-
-    // build an object set from a list of property names
-    FcObjectSetAdd( objectSet, FC_FILE );
-    FcObjectSetAdd( objectSet, FC_FAMILY );
-    FcObjectSetAdd( objectSet, FC_STYLE );
-
-    // get a list of fonts
-    // creates patterns from those fonts containing only the objects in objectSet and returns the set of unique such patterns
-    FcFontSet* fontset = FcFontList( NULL /* the default configuration is checked to be up to date, and used */, pattern, objectSet );
-
-    // clear up the object set
-    if( objectSet )
+    // Check whether the singleton is already created
+    Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::TextAbstraction::FontClient ) );
+    if(handle)
     {
-      FcObjectSetDestroy( objectSet );
+      // If so, downcast the handle
+      FontClient* impl = dynamic_cast< Dali::TextAbstraction::Internal::FontClient* >( handle.GetObjectPtr() );
+      fontClientHandle = Dali::TextAbstraction::FontClient( impl );
     }
-    // clear up the pattern
-    if( pattern )
+    else // create and register the object
     {
-      FcPatternDestroy( pattern );
+      fontClientHandle = Dali::TextAbstraction::FontClient( new FontClient );
+      service.Register( typeid( fontClientHandle ), fontClientHandle );
     }
-
-    return fontset;
   }
 
-  bool GetFcString( const FcPattern* pattern, const char* n, std::string& string )
-  {
-    FcChar8* file = NULL;
-    const FcResult retVal = FcPatternGetString( pattern, n, 0u, &file );
-
-    if( FcResultMatch == retVal )
-    {
-      // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
-      string.assign( reinterpret_cast<const char*>( file ) );
-
-      return true;
-    }
+  return fontClientHandle;
+}
 
-    return false;
-  }
+void FontClient::SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi  )
+{
+  mDpiHorizontal = horizontalDpi;
+  mDpiVertical = verticalDpi;
 
-  bool FindSystemFont( Character charcode, FontDescription& systemFont )
+  // Allow DPI to be set without loading plugin
+  if( mPlugin )
   {
-    // TODO - Use FcCharSetHasChar()
-
-    return false;
+    mPlugin->SetDpi( horizontalDpi, verticalDpi  );
   }
+}
 
-  FontId GetFontId( const std::string& path, PointSize26Dot6 pointSize, FaceIndex faceIndex )
-  {
-    FontId id( 0 );
-
-    if( NULL != mFreeTypeLibrary )
-    {
-      FontId foundId(0);
-      if( FindFont( path, pointSize, faceIndex, foundId ) )
-      {
-        id = foundId;
-      }
-      else
-      {
-        id = CreateFont( path, pointSize, faceIndex );
-      }
-    }
+void FontClient::GetDpi( unsigned int& horizontalDpi, unsigned int& verticalDpi )
+{
+  horizontalDpi = mDpiHorizontal;
+  verticalDpi = mDpiVertical;
+}
 
-    return id;
-  }
+int FontClient::GetDefaultFontSize()
+{
+  int fontSize( -1 );
 
-  GlyphIndex GetGlyphIndex( FontId fontId, Character charcode )
-  {
-    GlyphIndex index( 0 );
+#ifndef DALI_PROFILE_UBUNTU
+  vconf_get_int( VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, &fontSize );
+#endif // DALI_PROFILE_UBUNTU
 
-    if( fontId > 0 &&
-        fontId-1 < mFontCache.size() )
-    {
-      FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
+  return fontSize;
+}
 
-      index = FT_Get_Char_Index( ftFace, charcode );
-    }
+void FontClient::ResetSystemDefaults()
+{
+  CreatePlugin();
 
-    return index;
-  }
+  mPlugin->ResetSystemDefaults();
+}
 
-  FontId CreateFont( const std::string& path, PointSize26Dot6 pointSize, FaceIndex faceIndex )
-  {
-    FontId id( 0 );
+void FontClient::GetDefaultFonts( FontList& defaultFonts )
+{
+  CreatePlugin();
 
-    // Create & cache new font face
-    FT_Face ftFace;
-    int error = FT_New_Face( mFreeTypeLibrary,
-                             path.c_str(),
-                             0,
-                             &ftFace );
+  mPlugin->GetDefaultFonts( defaultFonts );
+}
 
-    if( FT_Err_Ok == error )
-    {
-      error = FT_Set_Char_Size( ftFace,
-                                0,
-                                pointSize,
-                                mDpiHorizontal,
-                                mDpiVertical );
-
-      if( FT_Err_Ok == error )
-      {
-        id = mFontCache.size() + 1;
-
-        FT_Size_Metrics& ftMetrics = ftFace->size->metrics;
-
-        FontMetrics metrics( static_cast< float >( ftMetrics.ascender  ) * FROM_266,
-                             static_cast< float >( ftMetrics.descender ) * FROM_266,
-                             static_cast< float >( ftMetrics.height    ) * FROM_266 );
-
-        mFontCache.push_back( CacheItem( id, ftFace, path, pointSize, faceIndex, metrics ) );
-      }
-      else
-      {
-        DALI_LOG_ERROR( "FreeType Set_Char_Size error: %d for pointSize %d\n", pointSize );
-      }
-    }
-    else
-    {
-      DALI_LOG_ERROR( "FreeType New_Face error: %d for %s\n", error, path.c_str() );
-    }
+void FontClient::GetDefaultPlatformFontDescription( FontDescription& fontDescription )
+{
+  CreatePlugin();
 
-    return id;
-  }
+  mPlugin->GetDefaultPlatformFontDescription( fontDescription );
+}
 
-  FontId FindDefaultFont( Character charcode )
-  {
-    // TODO - Return cached results based on script
-    return FontId(0);
-  }
+void FontClient::GetDescription( FontId id, FontDescription& fontDescription )
+{
+  CreatePlugin();
 
-  void GetFontMetrics( FontId fontId, FontMetrics& metrics )
-  {
-    if( fontId > 0 &&
-        fontId-1 < mFontCache.size() )
-    {
-      metrics = mFontCache[fontId-1].mMetrics;
-    }
-    else
-    {
-      DALI_LOG_ERROR( "Invalid font ID %d\n", fontId );
-    }
-  }
+  mPlugin->GetDescription( id, fontDescription );
+}
 
-  bool GetGlyphMetrics( GlyphInfo* array, uint32_t size, bool horizontal )
-  {
-    bool success( true );
+PointSize26Dot6 FontClient::GetPointSize( FontId id )
+{
+  CreatePlugin();
 
-    for( unsigned int i=0; i<size; ++i )
-    {
-      FontId fontId = array[i].fontId;
-
-      if( fontId > 0 &&
-          fontId-1 < mFontCache.size() )
-      {
-        FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
-
-        int error = FT_Load_Glyph( ftFace, array[i].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 ;
-          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;
-            array[i].advance  = static_cast< float >( ftFace->glyph->metrics.horiAdvance ) * 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;
-            array[i].advance  = static_cast< float >( ftFace->glyph->metrics.vertAdvance ) * FROM_266;
-          }
-        }
-        else
-        {
-          success = false;
-        }
-      }
-      else
-      {
-        success = false;
-      }
-    }
+  return mPlugin->GetPointSize( id );
+}
 
-    return success;
-  }
+bool FontClient::IsCharacterSupportedByFont( FontId fontId, Character character )
+{
+  CreatePlugin();
 
-  BitmapImage CreateBitmap( FontId fontId, GlyphIndex glyphIndex )
-  {
-    BitmapImage bitmap;
+  return mPlugin->IsCharacterSupportedByFont( fontId, character );
+}
 
-    if( fontId > 0 &&
-        fontId-1 < mFontCache.size() )
-    {
-      FT_Face ftFace = mFontCache[fontId-1].mFreeTypeFace;
-
-      FT_Error error = FT_Load_Glyph( ftFace, glyphIndex, FT_LOAD_DEFAULT );
-      if( FT_Err_Ok == error )
-      {
-        FT_Glyph glyph;
-        error = FT_Get_Glyph( ftFace->glyph, &glyph );
-
-        // Convert to bitmap if necessary
-        if ( FT_Err_Ok == error )
-        {
-          if( glyph->format != FT_GLYPH_FORMAT_BITMAP )
-          {
-            error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
-          }
-          else
-          {
-            DALI_LOG_ERROR( "FT_Glyph_To_Bitmap Failed with error: %d\n", error );
-          }
-        }
-        else
-        {
-          DALI_LOG_ERROR( "FT_Get_Glyph Failed with error: %d\n", error );
-        }
-
-        if( FT_Err_Ok == error )
-        {
-          // Access the underlying bitmap data
-          FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
-          ConvertBitmap( bitmap, bitmapGlyph->bitmap );
-        }
-
-        // Created FT_Glyph object must be released with FT_Done_Glyph
-        FT_Done_Glyph( glyph );
-      }
-      else
-      {
-        DALI_LOG_ERROR( "FT_Load_Glyph Failed with error: %d\n", error );
-      }
-    }
+void FontClient::GetSystemFonts( FontList& systemFonts )
+{
+  CreatePlugin();
 
-    return bitmap;
-  }
+  mPlugin->GetSystemFonts( systemFonts );
+}
 
-  void ConvertBitmap( BitmapImage& destBitmap, FT_Bitmap srcBitmap )
-  {
-    if( srcBitmap.width*srcBitmap.rows > 0 )
-    {
-      // TODO - Support all pixel modes
-      if( FT_PIXEL_MODE_GRAY == srcBitmap.pixel_mode )
-      {
-        if( srcBitmap.pitch == srcBitmap.width )
-        {
-          destBitmap = BitmapImage::New( srcBitmap.width, srcBitmap.rows, Pixel::L8 );
-
-          PixelBuffer* destBuffer = destBitmap.GetBuffer();
-          memcpy( destBuffer, srcBitmap.buffer, srcBitmap.width*srcBitmap.rows );
-        }
-      }
-    }
-  }
+FontId FontClient::FindDefaultFont( Character charcode,
+                                    PointSize26Dot6 requestedPointSize,
+                                    bool preferColor )
+{
+  CreatePlugin();
 
-private:
+  return mPlugin->FindDefaultFont( charcode,
+                                   requestedPointSize,
+                                   preferColor );
+}
 
-  bool FindFont( const std::string& path, PointSize26Dot6 pointSize, FaceIndex faceIndex, FontId& found ) const
-  {
-    for( unsigned int i=0; i<mFontCache.size(); ++i )
-    {
-      if( mFontCache[i].mPointSize == pointSize &&
-          mFontCache[i].mPath == path &&
-          mFontCache[i].mFaceIndex == faceIndex )
-      {
-        found = i + 1;
-        return true;
-      }
-    }
+FontId FontClient::FindFallbackFont( Character charcode,
+                                     const FontDescription& preferredFontDescription,
+                                     PointSize26Dot6 requestedPointSize,
+                                     bool preferColor )
+{
+  CreatePlugin();
 
-    return false;
-  }
+  return mPlugin->FindFallbackFont( charcode,
+                                    preferredFontDescription,
+                                    requestedPointSize,
+                                    preferColor );
+}
 
-  FT_Library mFreeTypeLibrary;
+bool FontClient::IsScalable( const FontPath& path )
+{
+  CreatePlugin();
 
-  FontList mSystemFonts;
+  return mPlugin->IsScalable( path );
+}
 
-  std::vector<CacheItem> mFontCache;
+bool FontClient::IsScalable( const FontDescription& fontDescription )
+{
+  CreatePlugin();
 
-  unsigned int mDpiHorizontal;
-  unsigned int mDpiVertical;
-};
+  return mPlugin->IsScalable( fontDescription );
+}
 
-FontClient::FontClient()
-: mPlugin( NULL ),
-  mDpiHorizontal( 0 ),
-  mDpiVertical( 0 )
+void FontClient::GetFixedSizes( const FontPath& path, Dali::Vector< PointSize26Dot6>& sizes )
 {
+  CreatePlugin();
+
+  mPlugin->GetFixedSizes( path, sizes );
 }
 
-FontClient::~FontClient()
+void FontClient::GetFixedSizes( const FontDescription& fontDescription,
+                                Dali::Vector< PointSize26Dot6 >& sizes )
 {
-  delete mPlugin;
+  CreatePlugin();
+
+  mPlugin->GetFixedSizes( fontDescription, sizes );
 }
 
-Dali::TextAbstraction::FontClient FontClient::Get()
+FontId FontClient::GetFontId( const FontPath& path, PointSize26Dot6 requestedPointSize, FaceIndex faceIndex )
 {
-  Dali::TextAbstraction::FontClient fontClientHandle;
-
-  Dali::SingletonService service( SingletonService::Get() );
-  if ( service )
-  {
-    // Check whether the singleton is already created
-    Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::TextAbstraction::FontClient ) );
-    if(handle)
-    {
-      // If so, downcast the handle
-      FontClient* impl = dynamic_cast< Dali::TextAbstraction::Internal::FontClient* >( handle.GetObjectPtr() );
-      fontClientHandle = Dali::TextAbstraction::FontClient( impl );
-    }
-    else // create and register the object
-    {
-      fontClientHandle = Dali::TextAbstraction::FontClient( new FontClient );
-      service.Register( typeid( fontClientHandle ), fontClientHandle );
-    }
-  }
+  CreatePlugin();
 
-  return fontClientHandle;
+  return mPlugin->GetFontId( path,
+                             requestedPointSize,
+                             faceIndex,
+                             true );
 }
 
-void FontClient::SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi  )
+FontId FontClient::GetFontId( const FontDescription& fontDescription,
+                              PointSize26Dot6 requestedPointSize,
+                              FaceIndex faceIndex )
 {
-  mDpiHorizontal = horizontalDpi;
-  mDpiVertical = verticalDpi;
+  CreatePlugin();
 
-  // Allow DPI to be set without loading plugin
-  if( mPlugin )
-  {
-    mPlugin->SetDpi( horizontalDpi, verticalDpi  );
-  }
+  return mPlugin->GetFontId( fontDescription,
+                             requestedPointSize,
+                             faceIndex );
 }
 
-void FontClient::GetSystemFonts( FontList& systemFonts )
+void FontClient::GetFontMetrics( FontId fontId, FontMetrics& metrics )
 {
   CreatePlugin();
 
-  mPlugin->GetSystemFonts( systemFonts );
+  return mPlugin->GetFontMetrics( fontId, metrics );
 }
 
-bool FontClient::FindSystemFont( Character charcode, FontDescription& systemFont )
+GlyphIndex FontClient::GetGlyphIndex( FontId fontId, Character charcode )
 {
   CreatePlugin();
 
-  return mPlugin->FindSystemFont( charcode, systemFont );
+  return mPlugin->GetGlyphIndex( fontId, charcode );
 }
 
-FontId FontClient::GetFontId( const FontPath& path, PointSize26Dot6 pointSize, FaceIndex faceIndex )
+bool FontClient::GetGlyphMetrics( GlyphInfo* array, uint32_t size, GlyphType type, bool horizontal )
 {
   CreatePlugin();
 
-  return mPlugin->GetFontId( path, pointSize, faceIndex );
+  return mPlugin->GetGlyphMetrics( array, size, type, horizontal );
 }
 
-FontId FontClient::FindDefaultFont( Character charcode )
+void FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth )
 {
   CreatePlugin();
 
-  return mPlugin->FindDefaultFont( charcode );
+  mPlugin->CreateBitmap( fontId, glyphIndex, data, outlineWidth );
 }
 
-void FontClient::GetFontMetrics( FontId fontId, FontMetrics& metrics )
+PixelData FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth )
 {
   CreatePlugin();
 
-  return mPlugin->GetFontMetrics( fontId, metrics );
+  return mPlugin->CreateBitmap( fontId, glyphIndex, outlineWidth );
 }
 
-GlyphIndex FontClient::GetGlyphIndex( FontId fontId, Character charcode )
+void FontClient::CreateVectorBlob( FontId fontId, GlyphIndex glyphIndex, VectorBlob*& blob, unsigned int& blobLength, unsigned int& nominalWidth, unsigned int& nominalHeight )
 {
   CreatePlugin();
 
-  return mPlugin->GetGlyphIndex( fontId, charcode );
+  return mPlugin->CreateVectorBlob( fontId, glyphIndex, blob, blobLength, nominalWidth, nominalHeight );
 }
 
-bool FontClient::GetGlyphMetrics( GlyphInfo* array, uint32_t size, bool horizontal )
+const GlyphInfo& FontClient::GetEllipsisGlyph( PointSize26Dot6 requestedPointSize )
 {
   CreatePlugin();
 
-  return mPlugin->GetGlyphMetrics( array, size, horizontal );
+  return mPlugin->GetEllipsisGlyph( requestedPointSize );
 }
 
-BitmapImage FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex )
+bool FontClient::IsColorGlyph( FontId fontId, GlyphIndex glyphIndex )
 {
   CreatePlugin();
 
-  return mPlugin->CreateBitmap( fontId, glyphIndex );
+  return mPlugin->IsColorGlyph( fontId, glyphIndex );
 }
 
 void FontClient::CreatePlugin()
@@ -540,12 +286,11 @@ void FontClient::CreatePlugin()
   if( !mPlugin )
   {
     mPlugin = new Plugin( mDpiHorizontal, mDpiVertical );
-    mPlugin->Initialize();
   }
 }
 
 } // namespace Internal
 
-} // namespace FontClient
+} // namespace TextAbstraction
 
 } // namespace Dali