Fix for multi-language support.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / multi-language-support-impl.cpp
index 27d0ee2..c596045 100644 (file)
 #include <dali/integration-api/debug.h>
 #include <dali/public-api/adaptor-framework/singleton-service.h>
 #include <dali/public-api/text-abstraction/font-client.h>
+#include <dali/public-api/text-abstraction/script.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/public-api/text/logical-model.h>
-#include <dali-toolkit/public-api/text/font-run.h>
-#include <dali-toolkit/public-api/text/script.h>
-#include <dali-toolkit/public-api/text/script-run.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/font-run.h>
+#include <dali-toolkit/internal/text/script-run.h>
+#include <dali-toolkit/internal/text/text-io.h>
 
 namespace Dali
 {
@@ -36,6 +37,15 @@ namespace Dali
 namespace Toolkit
 {
 
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_MULTI_LANGUAGE_SUPPORT");
+#endif
+
+const Dali::Toolkit::Text::Character UTF32_A = 0x0041;
+}
+
 namespace Text
 {
 
@@ -125,13 +135,13 @@ Script GetScript( Length index,
  */
 bool IsValidForAllScripts( Character character )
 {
-  return ( IsWhiteSpace( character )         ||
-           IsZeroWidthNonJoiner( character ) ||
-           IsZeroWidthJoiner( character )    ||
-           IsZeroWidthSpace( character )     ||
-           IsLeftToRightMark( character )    ||
-           IsRightToLeftMark( character )    ||
-           IsThinSpace( character ) );
+  return ( TextAbstraction::IsWhiteSpace( character )         ||
+           TextAbstraction::IsZeroWidthNonJoiner( character ) ||
+           TextAbstraction::IsZeroWidthJoiner( character )    ||
+           TextAbstraction::IsZeroWidthSpace( character )     ||
+           TextAbstraction::IsLeftToRightMark( character )    ||
+           TextAbstraction::IsRightToLeftMark( character )    ||
+           TextAbstraction::IsThinSpace( character ) );
 }
 
 bool ValidateFontsPerScript::FindValidFont( FontId fontId ) const
@@ -285,14 +295,14 @@ void MultilanguageSupport::SetScripts( const Vector<Character>& text,
     }
 
     // Get the script of the character.
-    Script script = GetCharacterScript( character );
+    Script script = TextAbstraction::GetCharacterScript( character );
 
     // Check if it is the first character of a paragraph.
     if( firstValidScript &&
         ( TextAbstraction::UNKNOWN != script ) )
     {
       // Sets the direction of the first valid script.
-      isParagraphRTL = ( TextAbstraction::ARABIC == script );
+      isParagraphRTL = TextAbstraction::IsRightToLeftScript( script );
       firstValidScript = false;
     }
 
@@ -300,7 +310,7 @@ void MultilanguageSupport::SetScripts( const Vector<Character>& text,
     {
       // Current run needs to be stored and a new one initialized.
 
-      if( isParagraphRTL != ( TextAbstraction::ARABIC == script ) )
+      if( isParagraphRTL != TextAbstraction::IsRightToLeftScript( script ) )
       {
         // Current script has different direction than the first script of the paragraph.
         // All the previously skipped characters need to be added to the previous script before it's stored.
@@ -440,12 +450,33 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
       {
         // Check in the valid fonts cache.
         ValidateFontsPerScript* validateFontsPerScript = *( validFontsPerScriptCacheBuffer + script );
+
+        if( NULL == validateFontsPerScript )
+        {
+          validateFontsPerScript = new ValidateFontsPerScript();
+
+          mValidFontsPerScriptCache.PushBack( validateFontsPerScript );
+          validFontsPerScriptCacheBuffer = mValidFontsPerScriptCache.Begin();
+        }
+
         if( NULL != validateFontsPerScript )
         {
           if( !validateFontsPerScript->FindValidFont( fontId ) )
           {
             // Use the font client to validate the font.
-            const GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character );
+            GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character );
+
+            // Emojis are present in many monochrome fonts; prefer color by default.
+            if( TextAbstraction::EMOJI == script &&
+                0u != glyphIndex )
+            {
+              BufferImage bitmap = fontClient.CreateBitmap( fontId, glyphIndex );
+              if( bitmap &&
+                  Pixel::BGRA8888 != bitmap.GetPixelFormat() )
+              {
+                glyphIndex = 0;
+              }
+            }
 
             if( 0u == glyphIndex )
             {
@@ -462,30 +493,8 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
             }
           }
         }
-        else
-        {
-          // Use the font client to validate the font.
-          const GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character );
-
-          if( 0u == glyphIndex )
-          {
-            // Get the point size of the current font. It will be used to get a default font id.
-            pointSize = fontClient.GetPointSize( fontId );
-
-            // The font is not valid. Set to zero and a default one will be set.
-            fontId = 0u;
-          }
-          else
-          {
-            // Add the font to the valid font cache.
-            validateFontsPerScript = new ValidateFontsPerScript();
-            *( validFontsPerScriptCacheBuffer + script ) = validateFontsPerScript;
-
-            validateFontsPerScript->mValidFonts.PushBack( fontId );
-          }
-        }
       }
-    }
+    } // !isDefault
 
     // The font has not been validated. Find a default one.
     if( 0u == fontId )
@@ -496,9 +505,27 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
       // If the cache has not a default font, get one from the font client.
       if( 0u == fontId )
       {
+        // Emojis are present in many monochrome fonts; prefer color by default.
+        bool preferColor = ( TextAbstraction::EMOJI == script );
+
         // Find a default font.
-        fontId = fontClient.FindDefaultFont( character, pointSize );
+        fontId = fontClient.FindDefaultFont( character, pointSize, preferColor );
+
+        // If the system does not support a suitable font, fallback to Latin
+        if( 0u == fontId )
+        {
+          fontId = *( defaultFontPerScriptCacheBuffer + TextAbstraction::LATIN );
+        }
+        if( 0u == fontId )
+        {
+          fontId = fontClient.FindDefaultFont( UTF32_A, pointSize );
+        }
 
+#ifdef DEBUG_ENABLED
+        Dali::TextAbstraction::FontDescription description;
+        fontClient.GetDescription( fontId, description );
+        DALI_LOG_INFO( gLogFilter, Debug::Concise, "Script: %s; Selected font: %s\n", Dali::TextAbstraction::ScriptName[script], description.path.c_str() );
+#endif
         // Cache the font.
         *( defaultFontPerScriptCacheBuffer + script ) = fontId;
       }