Check supported by font and find fallback font for common script.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / multi-language-support-impl.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 7570e04..4b6eee2
@@ -436,16 +436,20 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
   Vector<ScriptRun>::ConstIterator scriptRunEndIt = scripts.End();
   bool isNewParagraphCharacter = false;
 
-  FontId currentFontId = 0u;
-  FontId previousFontId = 0u;
   bool isPreviousEmojiScript = false;
 
+  // Description of fallback font which is selected at current iteration.
+  TextAbstraction::FontDescription selectedFontDescription;
+
   CharacterIndex lastCharacter = startIndex + numberOfCharacters;
   for( Length index = startIndex; index < lastCharacter; ++index )
   {
     // Get the current character.
     const Character character = *( textBuffer + index );
+    bool needSoftwareBoldening = false;
+    bool needSoftwareItalic = false;
 
+    // new description for current character
     TextAbstraction::FontDescription currentFontDescription;
     TextAbstraction::PointSize26Dot6 currentFontPointSize = defaultFontPointSize;
     bool isDefaultFont = true;
@@ -459,7 +463,6 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 
     // Get the font for the current character.
     FontId fontId = fontClient.GetFontId( currentFontDescription, currentFontPointSize );
-    currentFontId = fontId;
 
     // Get the script for the current character.
     Script script = GetScript( index,
@@ -547,133 +550,107 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
       //      supports the 'white space'. However, that font may not support the DEVANAGARI script.
       isCommonScript = TextAbstraction::IsCommonScript( character );
 
-      if( isCommonScript )
+      // Check in the valid fonts cache.
+      ValidateFontsPerScript* validateFontsPerScript = *( validFontsPerScriptCacheBuffer + script );
+
+      if( NULL != validateFontsPerScript )
       {
-        if( isValidCachedDefaultFont &&
-            ( isDefaultFont || ( currentFontId == previousFontId ) ) &&
-            !isEmojiScript )
+        // This cache stores valid fonts set by the user.
+        isValidFont = validateFontsPerScript->IsValidFont( fontId );
+
+        // It may happen that a validated font for a script doesn't have all the glyphs for that script.
+        // i.e a font validated for the CJK script may contain glyphs for the chinese language but not for the Japanese.
+        if( isValidFont )
         {
-          // At this point the character common for all scripts has no font assigned.
-          // If there is a valid previously cached default font for it, use that one.
-          fontId = cachedDefaultFontId;
+          // Checks if the current character is supported by the font is needed.
+          isValidFont = fontClient.IsCharacterSupportedByFont( fontId, character );
         }
       }
-      else
+
+      if( !isValidFont ) // (2)
       {
-        // Check in the valid fonts cache.
-        ValidateFontsPerScript* validateFontsPerScript = *( validFontsPerScriptCacheBuffer + script );
+        // The selected font is not stored in any cache.
+
+        // Checks if the current character is supported by the selected font.
+        isValidFont = fontClient.IsCharacterSupportedByFont( fontId, character );
 
-        if( NULL != validateFontsPerScript )
+        // Emojis are present in many monochrome fonts; prefer color by default.
+        if( isValidFont &&
+            isEmojiScript )
         {
-          // This cache stores valid fonts set by the user.
-          isValidFont = validateFontsPerScript->IsValidFont( fontId );
+          const GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character );
 
-          // It may happen that a validated font for a script doesn't have all the glyphs for that script.
-          // i.e a font validated for the CJK script may contain glyphs for the chinese language but not for the Japanese.
-          if( isValidFont )
+          // For color emojis, the font is valid if the glyph is a color glyph (the bitmap is RGBA).
+          isValidFont = fontClient.IsColorGlyph( fontId, glyphIndex );
+        }
+
+        // If there is a valid font, cache it.
+        if( isValidFont && !isCommonScript )
+        {
+          if( NULL == validateFontsPerScript )
           {
-            // Checks if the current character is supported by the font is needed.
-            isValidFont = fontClient.IsCharacterSupportedByFont( fontId, character );
+            validateFontsPerScript = new ValidateFontsPerScript();
+
+            *( validFontsPerScriptCacheBuffer + script ) = validateFontsPerScript;
           }
+
+          validateFontsPerScript->mValidFonts.PushBack( fontId );
         }
 
-        if( !isValidFont ) // (2)
+        if( !isValidFont && ( fontId != cachedDefaultFontId ) && ( !TextAbstraction::IsNewParagraph( character ) )) // (3)
         {
-          // The selected font is not stored in any cache.
+          // The selected font by the user or the platform's default font has failed to validate the character.
 
-          // Checks if the current character is supported by the selected font.
-          isValidFont = fontClient.IsCharacterSupportedByFont( fontId, character );
-
-          // Emojis are present in many monochrome fonts; prefer color by default.
-          if( isValidFont &&
-              isEmojiScript )
+          // Checks if the previously discarted cached default font supports the character.
+          bool isValidCachedFont = false;
+          if( isValidCachedDefaultFont )
           {
-            const GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character );
-
-            // For color emojis, the font is valid if the glyph is a color glyph (the bitmap is RGBA).
-            isValidFont = fontClient.IsColorGlyph( fontId, glyphIndex );
+            isValidCachedFont = fontClient.IsCharacterSupportedByFont( cachedDefaultFontId, character );
           }
 
-          // If there is a valid font, cache it.
-          if( isValidFont )
+          if( isValidCachedFont )
           {
-            if( NULL == validateFontsPerScript )
-            {
-              validateFontsPerScript = new ValidateFontsPerScript();
+            // Use the cached default font for the script if there is one.
+            fontId = cachedDefaultFontId;
+          }
+          else
+          {
+            // There is no valid cached default font for the script.
 
-              *( validFontsPerScriptCacheBuffer + script ) = validateFontsPerScript;
-            }
+            DefaultFonts* defaultFontsPerScript = NULL;
 
-            validateFontsPerScript->mValidFonts.PushBack( fontId );
-          }
+            // Emojis are present in many monochrome fonts; prefer color by default.
+            const bool preferColor = ( TextAbstraction::EMOJI == script );
 
-          if( !isValidFont && ( fontId != cachedDefaultFontId ) ) // (3)
-          {
-            // The selected font by the user or the platform's default font has failed to validate the character.
+            // Find a fallback-font.
+            fontId = fontClient.FindFallbackFont( character,
+                                                  currentFontDescription,
+                                                  currentFontPointSize,
+                                                  preferColor );
 
-            // Checks if the previously discarted cached default font supports the character.
-            bool isValidCachedFont = false;
-            if( isValidCachedDefaultFont )
+            if( 0u == fontId )
             {
-              isValidCachedFont = fontClient.IsCharacterSupportedByFont( cachedDefaultFontId, character );
+              fontId = fontClient.FindDefaultFont( UTF32_A, currentFontPointSize );
             }
 
-            if( isValidCachedFont )
+            if ( !isCommonScript && (script != TextAbstraction::UNKNOWN) )
             {
-              // Use the cached default font for the script if there is one.
-              fontId = cachedDefaultFontId;
-            }
-            else
-            {
-              // There is no valid cached default font for the script.
-
-              DefaultFonts* defaultFontsPerScript = NULL;
-
-              // Emojis are present in many monochrome fonts; prefer color by default.
-              const bool preferColor = ( TextAbstraction::EMOJI == script );
-
-              // Find a fallback-font.
-              fontId = fontClient.FindFallbackFont( character,
-                                                    currentFontDescription,
-                                                    currentFontPointSize,
-                                                    preferColor );
-
-              if( 0u == fontId )
-              {
-                // If the system does not support a suitable font, fallback to Latin
-                defaultFontsPerScript = *( defaultFontPerScriptCacheBuffer + TextAbstraction::LATIN );
-                if( NULL != defaultFontsPerScript )
-                {
-                  fontId = defaultFontsPerScript->FindFont( fontClient,
-                                                            currentFontDescription,
-                                                            currentFontPointSize );
-                }
-              }
-
-              if( 0u == fontId )
+              // Cache the font if it is not an unknown script
+              if( NULL == defaultFontsPerScript )
               {
-                fontId = fontClient.FindDefaultFont( UTF32_A, currentFontPointSize );
-              }
+                defaultFontsPerScript = *( defaultFontPerScriptCacheBuffer + script );
 
-              if ( script != TextAbstraction::UNKNOWN )
-              {
-                // Cache the font if it is not an unknown script
                 if( NULL == defaultFontsPerScript )
                 {
-                  defaultFontsPerScript = *( defaultFontPerScriptCacheBuffer + script );
-
-                  if( NULL == defaultFontsPerScript )
-                  {
-                    defaultFontsPerScript = new DefaultFonts();
-                    *( defaultFontPerScriptCacheBuffer + script ) = defaultFontsPerScript;
-                  }
+                  defaultFontsPerScript = new DefaultFonts();
+                  *( defaultFontPerScriptCacheBuffer + script ) = defaultFontsPerScript;
                 }
-                defaultFontsPerScript->Cache( currentFontDescription, fontId );
               }
+              defaultFontsPerScript->Cache( currentFontDescription, fontId );
             }
-          } // !isValidFont (3)
-        } // !isValidFont (2)
-      } // !isCommonScript
+          }
+        } // !isValidFont (3)
+      } // !isValidFont (2)
     } // !isValidFont (1)
 
 #ifdef DEBUG_ENABLED
@@ -689,9 +666,22 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
     }
 #endif
 
+    if( fontId != currentFontRun.fontId )
+    {
+      fontClient.GetDescription(fontId,selectedFontDescription);
+    }
+
+    // Developer sets bold to character but selected font cannot support it
+    needSoftwareBoldening = ( currentFontDescription.weight >= TextAbstraction::FontWeight::BOLD ) && ( selectedFontDescription.weight < TextAbstraction::FontWeight::BOLD );
+
+    // Developer sets italic to character but selected font cannot support it
+    needSoftwareItalic = ( currentFontDescription.slant == TextAbstraction::FontSlant::ITALIC ) && ( selectedFontDescription.slant < TextAbstraction::FontSlant::ITALIC );
+
     // The font is now validated.
     if( ( fontId != currentFontRun.fontId ) ||
-        isNewParagraphCharacter )
+        isNewParagraphCharacter ||
+        // If font id is same as previous but style is diffrent, initialize new one
+        ( ( fontId == currentFontRun.fontId ) && ( ( needSoftwareBoldening != currentFontRun.softwareBold ) || ( needSoftwareItalic != currentFontRun.softwareItalic ) ) ) )
     {
       // Current run needs to be stored and a new one initialized.
 
@@ -706,6 +696,8 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
       currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters;
       currentFontRun.characterRun.numberOfCharacters = 0u;
       currentFontRun.fontId = fontId;
+      currentFontRun.softwareItalic = needSoftwareItalic;
+      currentFontRun.softwareBold = needSoftwareBoldening;
     }
 
     // Add one more character to the run.
@@ -713,7 +705,6 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 
     // Whether the current character is a new paragraph character.
     isNewParagraphCharacter = TextAbstraction::IsNewParagraph( character );
-    previousFontId = currentFontId;
     isPreviousEmojiScript = isEmojiScript;
   } // end traverse characters.