TextModel - Create the text language info for a given range of characters inside... 75/60675/5
authorVictor Cebollada <v.cebollada@samsung.com>
Fri, 12 Feb 2016 09:11:31 +0000 (09:11 +0000)
committerVictor Cebollada <v.cebollada@samsung.com>
Wed, 2 Mar 2016 14:47:59 +0000 (14:47 +0000)
Change-Id: I48fdb5f7fda20f2f3c45566160b5e7d739f8afb9
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
21 files changed:
automated-tests/resources/fonts/dejavu/DejaVuSans.ttf [new file with mode: 0644]
automated-tests/resources/fonts/dejavu/DejaVuSerif-Bold.ttf [new file with mode: 0644]
automated-tests/resources/fonts/dejavu/DejaVuSerif-Italic.ttf [new file with mode: 0644]
automated-tests/resources/fonts/dejavu/DejaVuSerif.ttf [new file with mode: 0644]
automated-tests/resources/fonts/dejavu/LICENSE [new file with mode: 0644]
automated-tests/resources/fonts/tizen/TizenColorEmoji.ttf [new file with mode: 0644]
automated-tests/resources/fonts/tizen/TizenSansArabicRegular.ttf [new file with mode: 0644]
automated-tests/resources/fonts/tizen/TizenSansHebrewRegular.ttf [new file with mode: 0644]
automated-tests/resources/fonts/tizen/TizenSansHindiRegular.ttf [new file with mode: 0644]
automated-tests/resources/fonts/tizen/TizenSansRegular.ttf [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/multi-language-helper-functions.cpp [new file with mode: 0644]
dali-toolkit/internal/text/multi-language-helper-functions.h [new file with mode: 0644]
dali-toolkit/internal/text/multi-language-support-impl.cpp
dali-toolkit/internal/text/multi-language-support-impl.h
dali-toolkit/internal/text/multi-language-support.cpp
dali-toolkit/internal/text/multi-language-support.h
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-run-container.h [moved from dali-toolkit/internal/text/text-style-run-container.h with 64% similarity]

diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf
new file mode 100644 (file)
index 0000000..5267218
Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf differ
diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSerif-Bold.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSerif-Bold.ttf
new file mode 100644 (file)
index 0000000..d683eb2
Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSerif-Bold.ttf differ
diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSerif-Italic.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSerif-Italic.ttf
new file mode 100644 (file)
index 0000000..45b508b
Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSerif-Italic.ttf differ
diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSerif.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSerif.ttf
new file mode 100644 (file)
index 0000000..39dd394
Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSerif.ttf differ
diff --git a/automated-tests/resources/fonts/dejavu/LICENSE b/automated-tests/resources/fonts/dejavu/LICENSE
new file mode 100644 (file)
index 0000000..254e2cc
--- /dev/null
@@ -0,0 +1,99 @@
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
+
+Bitstream Vera Fonts Copyright
+------------------------------
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated
+documentation files (the "Font Software"), to reproduce and distribute the
+Font Software, including without limitation the rights to use, copy, merge,
+publish, distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright and trademark notices and this permission notice shall
+be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional glyphs or characters may be added to the Fonts, only if the fonts
+are renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream
+Vera" names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome
+Foundation, and Bitstream Inc., shall not be used in advertising or
+otherwise to promote the sale, use or other dealings in this Font Software
+without prior written authorization from the Gnome Foundation or Bitstream
+Inc., respectively. For further information, contact: fonts at gnome dot
+org. 
+
+Arev Fonts Copyright
+------------------------------
+
+Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the fonts accompanying this license ("Fonts") and
+associated documentation files (the "Font Software"), to reproduce
+and distribute the modifications to the Bitstream Vera Font Software,
+including without limitation the rights to use, copy, merge, publish,
+distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright and trademark notices and this permission notice
+shall be included in all copies of one or more of the Font Software
+typefaces.
+
+The Font Software may be modified, altered, or added to, and in
+particular the designs of glyphs or characters in the Fonts may be
+modified and additional glyphs or characters may be added to the
+Fonts, only if the fonts are renamed to names not containing either
+the words "Tavmjong Bah" or the word "Arev".
+
+This License becomes null and void to the extent applicable to Fonts
+or Font Software that has been modified and is distributed under the 
+"Tavmjong Bah Arev" names.
+
+The Font Software may be sold as part of a larger software package but
+no copy of one or more of the Font Software typefaces may be sold by
+itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
+TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the name of Tavmjong Bah shall not
+be used in advertising or otherwise to promote the sale, use or other
+dealings in this Font Software without prior written authorization
+from Tavmjong Bah. For further information, contact: tavmjong @ free
+. fr.
+
+$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
diff --git a/automated-tests/resources/fonts/tizen/TizenColorEmoji.ttf b/automated-tests/resources/fonts/tizen/TizenColorEmoji.ttf
new file mode 100644 (file)
index 0000000..25234ea
Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenColorEmoji.ttf differ
diff --git a/automated-tests/resources/fonts/tizen/TizenSansArabicRegular.ttf b/automated-tests/resources/fonts/tizen/TizenSansArabicRegular.ttf
new file mode 100644 (file)
index 0000000..55fc232
Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenSansArabicRegular.ttf differ
diff --git a/automated-tests/resources/fonts/tizen/TizenSansHebrewRegular.ttf b/automated-tests/resources/fonts/tizen/TizenSansHebrewRegular.ttf
new file mode 100644 (file)
index 0000000..b9a25d7
Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenSansHebrewRegular.ttf differ
diff --git a/automated-tests/resources/fonts/tizen/TizenSansHindiRegular.ttf b/automated-tests/resources/fonts/tizen/TizenSansHindiRegular.ttf
new file mode 100644 (file)
index 0000000..d451f59
Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenSansHindiRegular.ttf differ
diff --git a/automated-tests/resources/fonts/tizen/TizenSansRegular.ttf b/automated-tests/resources/fonts/tizen/TizenSansRegular.ttf
new file mode 100644 (file)
index 0000000..00863b6
Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenSansRegular.ttf differ
index 11a2af7..f602e8a 100644 (file)
  */
 
 #include <iostream>
  */
 
 #include <iostream>
-
 #include <stdlib.h>
 #include <stdlib.h>
+#include <unistd.h>
+
+#include <dali/devel-api/text-abstraction/font-client.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/segmentation.h>
-#include <dali-toolkit/internal/text/multi-language-support.h>
 #include <dali-toolkit/internal/text/logical-model-impl.h>
 #include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/multi-language-helper-functions.h>
+#include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 
-
 using namespace Dali;
 using namespace Toolkit;
 using namespace Text;
 
 // Tests the following functions with different scripts.
 using namespace Dali;
 using namespace Toolkit;
 using namespace Text;
 
 // Tests the following functions with different scripts.
+//
+// void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
+//                             Vector<FontId>& fontIds,
+//                             const TextAbstraction::FontDescription& defaultFontDescription,
+//                             TextAbstraction::PointSize26Dot6 defaultPointSize,
+//                             CharacterIndex startIndex,
+//                             Length numberOfCharacters );
+//
+// Script GetScript( Length index,
+//                   Vector<ScriptRun>::ConstIterator& scriptRunIt,
+//                   const Vector<ScriptRun>::ConstIterator& scriptRunEndIt );
+//
 // Constructor, destructor and MultilanguageSupport::Get()
 // Constructor, destructor and MultilanguageSupport::Get()
-// void MultilanguageSupport::SetScripts( const Vector<Character>& text, const Vector<LineBreakInfo>& lineBreakInfo, Vector<ScriptRun>& scripts );
+//
+// void MultilanguageSupport::SetScripts( const Vector<Character>& text,
+//                                        CharacterIndex startIndex,
+//                                        Length numberOfCharacters,
+//                                        Vector<ScriptRun>& scripts );
+//
 // void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 //                                           const Vector<ScriptRun>& scripts,
 //                                           const Vector<FontDescriptionRun>& fontDescriptions,
 //                                           FontId defaultFontId,
 // void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 //                                           const Vector<ScriptRun>& scripts,
 //                                           const Vector<FontDescriptionRun>& fontDescriptions,
 //                                           FontId defaultFontId,
+//                                           CharacterIndex startIndex,
+//                                           Length numberOfCharacters,
 //                                           Vector<FontRun>& fonts );
 
 //////////////////////////////////////////////////////////
 //                                           Vector<FontRun>& fonts );
 
 //////////////////////////////////////////////////////////
@@ -44,21 +66,86 @@ using namespace Text;
 namespace
 {
 
 namespace
 {
 
+const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
+const unsigned int EMOJI_FONT_SIZE = 3968u;
+const unsigned int NON_DEFAULT_FONT_SIZE = 40u;
+
+struct MergeFontDescriptionsData
+{
+  std::string description;                                 ///< Description of the experiment.
+  Vector<FontDescriptionRun> fontDescriptionRuns;          ///< The font description runs.
+  TextAbstraction::FontDescription defaultFontDescription; ///< The default font description.
+  TextAbstraction::PointSize26Dot6 defaultPointSize;       ///< The default point size.
+  unsigned int startIndex;                                 ///< The start index.
+  unsigned int numberOfCharacters;                         ///< The number of characters.
+  Vector<FontId> expectedFontIds;                          ///< The expected font ids.
+};
+
 struct ScriptsData
 {
 struct ScriptsData
 {
-  std::string description;      ///< Description of the experiment.
-  std::string text;             ///< Input text.
-  Vector<ScriptRun> scriptRuns; ///< Expected script runs.
+  std::string description;         ///< Description of the experiment.
+  std::string text;                ///< Input text.
+  unsigned int index;              ///< The index of the first character to update the script.
+  unsigned int numberOfCharacters; ///< The numbers of characters to update the script.
+  Vector<ScriptRun> scriptRuns;    ///< Expected script runs.
 };
 
 struct ValidateFontsData
 {
 };
 
 struct ValidateFontsData
 {
-  std::string description;  ///< Description of the experiment.
-  std::string text;         ///< Input text.
+  std::string                description;         ///< Description of the experiment.
+  std::string                text;                ///< Input text.
+  std::string                defaultFont;         ///< The default font.
+  unsigned int               defaultFontSize;     ///< The default font size.
+  unsigned int               index;               ///< The index of the first character to update the script.
+  unsigned int               numberOfCharacters;  ///< The numbers of characters to update the script.
+  Vector<FontDescriptionRun> fontDescriptionRuns; ///< The font description runs.
+  Vector<FontRun>            fontRuns;            ///< The expected font runs.
 };
 
 //////////////////////////////////////////////////////////
 
 };
 
 //////////////////////////////////////////////////////////
 
+bool MergeFontDescriptionsTest( const MergeFontDescriptionsData& data )
+{
+  Vector<FontId> fontIds;
+  fontIds.Resize( data.startIndex + data.numberOfCharacters, 0u );
+
+  MergeFontDescriptions( data.fontDescriptionRuns,
+                         fontIds,
+                         data.defaultFontDescription,
+                         data.defaultPointSize,
+                         data.startIndex,
+                         data.numberOfCharacters );
+
+  if( fontIds.Count() != data.expectedFontIds.Count() )
+  {
+    std::cout << data.description << " Different number of font ids : " << fontIds.Count() << ", expected : " << data.expectedFontIds.Count() << std::endl;
+    return false;
+  }
+
+  for( unsigned int index = 0u; index < fontIds.Count(); ++index )
+  {
+    if( fontIds[index] != data.expectedFontIds[index] )
+    {
+      std::cout << data.description << " Different font id at index : " << index << ", font id : " << fontIds[index] << ", expected : " << data.expectedFontIds[index] << std::endl;
+      std::cout << "           font ids : ";
+      for( unsigned int i=0;i<fontIds.Count();++i)
+      {
+        std::cout << fontIds[i] << " ";
+      }
+      std::cout << std::endl;
+      std::cout << "  expected font ids : ";
+      for( unsigned int i=0;i<data.expectedFontIds.Count();++i)
+      {
+        std::cout << data.expectedFontIds[i] << " ";
+      }
+      std::cout << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
 bool ScriptsTest( const ScriptsData& data )
 {
   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
 bool ScriptsTest( const ScriptsData& data )
 {
   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
@@ -75,9 +162,25 @@ bool ScriptsTest( const ScriptsData& data )
   // 2) Set the script info.
   Vector<ScriptRun> scripts;
   multilanguageSupport.SetScripts( utf32,
   // 2) Set the script info.
   Vector<ScriptRun> scripts;
   multilanguageSupport.SetScripts( utf32,
+                                   0u,
+                                   numberOfCharacters,
                                    scripts );
 
                                    scripts );
 
-  // 3) Compare the results.
+  if( ( 0u != data.index ) ||
+      ( numberOfCharacters != data.numberOfCharacters ) )
+  {
+    // 3) Clear the scripts.
+    ClearCharacterRuns( data.index,
+                        data.index + data.numberOfCharacters - 1u,
+                        scripts );
+
+    multilanguageSupport.SetScripts( utf32,
+                                     data.index,
+                                     data.numberOfCharacters,
+                                     scripts );
+  }
+
+  // 4) Compare the results.
 
   tet_printf( "Testing %s\n", data.description.c_str() );
   if( scripts.Count() != data.scriptRuns.Count() )
 
   tet_printf( "Testing %s\n", data.description.c_str() );
   if( scripts.Count() != data.scriptRuns.Count() )
@@ -116,6 +219,7 @@ bool ScriptsTest( const ScriptsData& data )
 bool ValidateFontTest( const ValidateFontsData& data )
 {
   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
 bool ValidateFontTest( const ValidateFontsData& data )
 {
   MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
 
   // 1) Convert to utf32
   Vector<Character> utf32;
 
   // 1) Convert to utf32
   Vector<Character> utf32;
@@ -129,24 +233,351 @@ bool ValidateFontTest( const ValidateFontsData& data )
   // 2) Set the script info.
   Vector<ScriptRun> scripts;
   multilanguageSupport.SetScripts( utf32,
   // 2) Set the script info.
   Vector<ScriptRun> scripts;
   multilanguageSupport.SetScripts( utf32,
+                                   0u,
+                                   numberOfCharacters,
                                    scripts );
 
                                    scripts );
 
+  char* pathNamePtr = get_current_dir_name();
+  const std::string pathName( pathNamePtr );
+  free( pathNamePtr );
+
+  // Get the default font id.
+  const FontId defaultFontId = fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + data.defaultFont,
+                                                     data.defaultFontSize );
+
   // To be completed ...
   // To be completed ...
-  Vector<FontDescriptionRun> fontDescriptions;
-  FontId defaultFontId = 0u;
-  Vector<FontRun> fonts;
+  Vector<FontRun> fontRuns;
 
 
-  // 3) Validate the fonts
+  // 3) Validate the fonts.
   multilanguageSupport.ValidateFonts( utf32,
                                       scripts,
   multilanguageSupport.ValidateFonts( utf32,
                                       scripts,
-                                      fontDescriptions,
+                                      data.fontDescriptionRuns,
                                       defaultFontId,
                                       defaultFontId,
-                                      fonts );
+                                      0u,
+                                      numberOfCharacters,
+                                      fontRuns );
+
+  if( ( 0u != data.index ) ||
+      ( numberOfCharacters != data.numberOfCharacters ) )
+  {
+    // 4) Clear the fonts.
+    ClearCharacterRuns( data.index,
+                        data.index + data.numberOfCharacters - 1u,
+                        fontRuns );
+
+    multilanguageSupport.ValidateFonts( utf32,
+                                        scripts,
+                                        data.fontDescriptionRuns,
+                                        defaultFontId,
+                                        data.index,
+                                        data.numberOfCharacters,
+                                        fontRuns );
+  }
+
+  // 5) Compare the results.
+  if( data.fontRuns.Count() != fontRuns.Count() )
+  {
+    std::cout << "  Different number of font runs : " << fontRuns.Count() << ", expected : " << data.fontRuns.Count() << std::endl;
+    return false;
+  }
+
+
+  for( unsigned int index = 0; index < data.fontRuns.Count(); ++index )
+  {
+    const FontRun& run = fontRuns[index];
+    const FontRun& expectedRun = data.fontRuns[index];
+
+    if( run.characterRun.characterIndex != expectedRun.characterRun.characterIndex )
+    {
+      std::cout << "  character run : " << index << ", index : " << run.characterRun.characterIndex << ", expected : " << expectedRun.characterRun.characterIndex << std::endl;
+      return false;
+    }
+    if( run.characterRun.numberOfCharacters != expectedRun.characterRun.numberOfCharacters )
+    {
+      std::cout << "  character run : " << index << ", num chars : " << run.characterRun.numberOfCharacters << ", expected : " << expectedRun.characterRun.numberOfCharacters << std::endl;
+      return false;
+    }
+    if( run.fontId != expectedRun.fontId )
+    {
+      std::cout << "  character run : " << index << ", font : " << run.fontId << ", expected : " << expectedRun.fontId << std::endl;
+      return false;
+    }
+  }
+
   return true;
 }
 
 } // namespace
 
   return true;
 }
 
 } // namespace
 
+int UtcDaliTextGetScript(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextGetScript");
+
+  Script script = TextAbstraction::LATIN;
+
+  // Text with no scripts.
+  Vector<ScriptRun> scriptRuns;
+  Vector<ScriptRun>::ConstIterator scriptRunIt = scriptRuns.Begin();
+  script = GetScript( 0u,
+                      scriptRunIt,
+                      scriptRuns.End() );
+
+  DALI_TEST_CHECK( TextAbstraction::UNKNOWN == script );
+
+  const unsigned int numberOfCharacters = 7u;
+  // Add scripts.
+  ScriptRun scriptRun01 =
+  {
+    {
+      0u,
+      2u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun02 =
+  {
+    {
+      2u,
+      2u,
+    },
+    TextAbstraction::HEBREW
+  };
+  ScriptRun scriptRun03 =
+  {
+    {
+      4u,
+      2u,
+    },
+    TextAbstraction::ARABIC
+  };
+  scriptRuns.PushBack( scriptRun01 );
+  scriptRuns.PushBack( scriptRun02 );
+  scriptRuns.PushBack( scriptRun03 );
+
+  // Expected results
+  TextAbstraction::Script expectedScripts[]=
+  {
+    TextAbstraction::LATIN,
+    TextAbstraction::LATIN,
+    TextAbstraction::HEBREW,
+    TextAbstraction::HEBREW,
+    TextAbstraction::ARABIC,
+    TextAbstraction::ARABIC,
+    TextAbstraction::UNKNOWN
+  };
+
+  scriptRunIt = scriptRuns.Begin();
+  for( unsigned int index = 0u; index < numberOfCharacters; ++index )
+  {
+    script = GetScript( index,
+                        scriptRunIt,
+                        scriptRuns.End() );
+
+    DALI_TEST_CHECK( expectedScripts[index] == script );
+  }
+  DALI_TEST_CHECK( scriptRunIt == scriptRuns.End() );
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextMergeFontDescriptions(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextMergeFontDescriptions");
+
+  // Load some fonts.
+
+  char* pathNamePtr = get_current_dir_name();
+  const std::string pathName( pathNamePtr );
+  free( pathNamePtr );
+
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif.ttf", NON_DEFAULT_FONT_SIZE );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif-Bold.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif-Italic.ttf" );
+
+  // To test the font width as GetFontId() with the font file path can't cache the width property.
+  TextAbstraction::FontDescription widthDescription;
+  widthDescription.path = "";
+  widthDescription.family = "DejaVu Serif";
+  widthDescription.weight = TextAbstraction::FontWeight::NORMAL;
+  widthDescription.width = TextAbstraction::FontWidth::EXPANDED;
+  widthDescription.slant = TextAbstraction::FontSlant::NORMAL;
+  fontClient.GetFontId( widthDescription );
+
+  // Test.
+
+  TextAbstraction::FontDescription defaultFontDescription01;
+  Vector<FontDescriptionRun> fontDescriptionRuns01;
+  Vector<FontId> expectedFontIds01;
+
+  TextAbstraction::FontDescription defaultFontDescription02;
+  Vector<FontDescriptionRun> fontDescriptionRuns02;
+  Vector<FontId> expectedFontIds02;
+  expectedFontIds02.PushBack( 0u );
+  expectedFontIds02.PushBack( 0u );
+
+  TextAbstraction::FontDescription defaultFontDescription03;
+  defaultFontDescription03.family = "DejaVu Serif";
+  Vector<FontDescriptionRun> fontDescriptionRuns03;
+
+  FontDescriptionRun fontDescription0301 =
+  {
+    {
+      0u,
+      2u
+    },
+    const_cast<char*>( "DejaVu Sans" ),
+    11u,
+    TextAbstraction::FontWeight::NORMAL,
+    TextAbstraction::FontWidth::NORMAL,
+    TextAbstraction::FontSlant::NORMAL,
+    TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+    true,
+    false,
+    false,
+    false,
+    false
+  };
+  FontDescriptionRun fontDescription0302 =
+  {
+    {
+      2u,
+      2u
+    },
+    NULL,
+    0u,
+    TextAbstraction::FontWeight::NORMAL,
+    TextAbstraction::FontWidth::NORMAL,
+    TextAbstraction::FontSlant::ITALIC,
+    TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+    false,
+    false,
+    false,
+    true,
+    false
+  };
+  FontDescriptionRun fontDescription0303 =
+  {
+    {
+      4u,
+      2u
+    },
+    NULL,
+    0u,
+    TextAbstraction::FontWeight::BOLD,
+    TextAbstraction::FontWidth::NORMAL,
+    TextAbstraction::FontSlant::NORMAL,
+    TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+    false,
+    true,
+    false,
+    false,
+    false
+  };
+  FontDescriptionRun fontDescription0304 =
+  {
+    {
+      6u,
+      2u
+    },
+    NULL,
+    0u,
+    TextAbstraction::FontWeight::NORMAL,
+    TextAbstraction::FontWidth::NORMAL,
+    TextAbstraction::FontSlant::NORMAL,
+    NON_DEFAULT_FONT_SIZE,
+    false,
+    false,
+    false,
+    false,
+    true
+  };
+  FontDescriptionRun fontDescription0305 =
+  {
+    {
+      8u,
+      2u
+    },
+    NULL,
+    0u,
+    TextAbstraction::FontWeight::NORMAL,
+    TextAbstraction::FontWidth::EXPANDED,
+    TextAbstraction::FontSlant::NORMAL,
+    TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+    false,
+    false,
+    true,
+    false,
+    false
+  };
+
+  fontDescriptionRuns03.PushBack( fontDescription0301 );
+  fontDescriptionRuns03.PushBack( fontDescription0302 );
+  fontDescriptionRuns03.PushBack( fontDescription0303 );
+  fontDescriptionRuns03.PushBack( fontDescription0304 );
+  fontDescriptionRuns03.PushBack( fontDescription0305 );
+
+  Vector<FontId> expectedFontIds03;
+  expectedFontIds03.PushBack( 1u );
+  expectedFontIds03.PushBack( 1u );
+  expectedFontIds03.PushBack( 5u );
+  expectedFontIds03.PushBack( 5u );
+  expectedFontIds03.PushBack( 4u );
+  expectedFontIds03.PushBack( 4u );
+  expectedFontIds03.PushBack( 3u );
+  expectedFontIds03.PushBack( 3u );
+  expectedFontIds03.PushBack( 6u );
+  expectedFontIds03.PushBack( 6u );
+
+  const MergeFontDescriptionsData data[] =
+  {
+    {
+      "void text.",
+      fontDescriptionRuns01,
+      defaultFontDescription01,
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      0u,
+      expectedFontIds01
+    },
+    {
+      "No description runs.",
+      fontDescriptionRuns02,
+      defaultFontDescription02,
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      2u,
+      expectedFontIds02
+    },
+    {
+      "Some description runs.",
+      fontDescriptionRuns03,
+      defaultFontDescription03,
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      10u,
+      expectedFontIds03
+    }
+  };
+  const unsigned int numberOfTests = 3u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    if( !MergeFontDescriptionsTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
 int UtcDaliTextMultiLanguageConstructor(void)
 {
   ToolkitTestApplication application;
 int UtcDaliTextMultiLanguageConstructor(void)
 {
   ToolkitTestApplication application;
@@ -442,7 +873,15 @@ int UtcDaliTextMultiLanguageSetScripts(void)
   {
     {
       163u,
   {
     {
       163u,
-      35u,
+      18u,
+    },
+    TextAbstraction::HANGUL
+  };
+  ScriptRun scriptRun1011 =
+  {
+    {
+      181u,
+      17u,
     },
     TextAbstraction::HANGUL
   };
     },
     TextAbstraction::HANGUL
   };
@@ -457,6 +896,7 @@ int UtcDaliTextMultiLanguageSetScripts(void)
   scriptRuns10.PushBack( scriptRun1008 );
   scriptRuns10.PushBack( scriptRun1009 );
   scriptRuns10.PushBack( scriptRun1010 );
   scriptRuns10.PushBack( scriptRun1008 );
   scriptRuns10.PushBack( scriptRun1009 );
   scriptRuns10.PushBack( scriptRun1010 );
+  scriptRuns10.PushBack( scriptRun1011 );
 
   // Paragraphs with no scripts mixed with paragraphs with scripts.
   Vector<ScriptRun> scriptRuns11;
 
   // Paragraphs with no scripts mixed with paragraphs with scripts.
   Vector<ScriptRun> scriptRuns11;
@@ -464,20 +904,83 @@ int UtcDaliTextMultiLanguageSetScripts(void)
   {
     {
       0u,
   {
     {
       0u,
-      31u,
+      3u,
     },
     TextAbstraction::LATIN
   };
   ScriptRun scriptRun1101 =
   {
     {
     },
     TextAbstraction::LATIN
   };
   ScriptRun scriptRun1101 =
   {
     {
+      3u,
+      3u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1102 =
+  {
+    {
+      6u,
+      19u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1103 =
+  {
+    {
+      25u,
+      3u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1104 =
+  {
+    {
+      28u,
+      3u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1105 =
+  {
+    {
       31u,
       31u,
-      21u,
+      15u,
     },
     TextAbstraction::HEBREW
   };
     },
     TextAbstraction::HEBREW
   };
+  ScriptRun scriptRun1106 =
+  {
+    {
+      46u,
+      2u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1107 =
+  {
+    {
+      48u,
+      2u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1108 =
+  {
+    {
+      50u,
+      2u,
+    },
+    TextAbstraction::LATIN
+  };
   scriptRuns11.PushBack( scriptRun1100 );
   scriptRuns11.PushBack( scriptRun1101 );
   scriptRuns11.PushBack( scriptRun1100 );
   scriptRuns11.PushBack( scriptRun1101 );
+  scriptRuns11.PushBack( scriptRun1102 );
+  scriptRuns11.PushBack( scriptRun1103 );
+  scriptRuns11.PushBack( scriptRun1104 );
+  scriptRuns11.PushBack( scriptRun1105 );
+  scriptRuns11.PushBack( scriptRun1106 );
+  scriptRuns11.PushBack( scriptRun1107 );
+  scriptRuns11.PushBack( scriptRun1108 );
 
   // Paragraphs with no scripts.
   Vector<ScriptRun> scriptRuns12;
 
   // Paragraphs with no scripts.
   Vector<ScriptRun> scriptRuns12;
@@ -485,62 +988,148 @@ int UtcDaliTextMultiLanguageSetScripts(void)
   {
     {
       0u,
   {
     {
       0u,
-      11u,
+      3u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1201 =
+  {
+    {
+      3u,
+      3u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1202 =
+  {
+    {
+      6u,
+      3u,
+    },
+    TextAbstraction::LATIN
+  };
+  ScriptRun scriptRun1203 =
+  {
+    {
+      9u,
+      2u,
     },
     TextAbstraction::LATIN
   };
   scriptRuns12.PushBack( scriptRun1200 );
     },
     TextAbstraction::LATIN
   };
   scriptRuns12.PushBack( scriptRun1200 );
+  scriptRuns12.PushBack( scriptRun1201 );
+  scriptRuns12.PushBack( scriptRun1202 );
+  scriptRuns12.PushBack( scriptRun1203 );
+
+  Vector<ScriptRun> scriptRuns13;
+  ScriptRun scriptRun1301 =
+  {
+    {
+      0u,
+      4u,
+    },
+    TextAbstraction::LATIN // An unknown script is transformed to LATIN
+  };
+  scriptRuns13.PushBack( scriptRun1301 );
 
   const ScriptsData data[] =
   {
     {
       "void text",
       "",
 
   const ScriptsData data[] =
   {
     {
       "void text",
       "",
+      0u,
+      0u,
       scriptRuns00,
     },
     {
       "Easy latin script",
       "Hello world",
       scriptRuns00,
     },
     {
       "Easy latin script",
       "Hello world",
+      0u,
+      11u,
       scriptRuns01,
     },
     {
       "Mix of LTR '\\n'and RTL",
       "Hello world\nمرحبا بالعالم",
       scriptRuns01,
     },
     {
       "Mix of LTR '\\n'and RTL",
       "Hello world\nمرحبا بالعالم",
+      0u,
+      25u,
+      scriptRuns02,
+    },
+    {
+      "Update mix of LTR '\\n'and RTL. Update LTR",
+      "Hello world\nمرحبا بالعالم",
+      0u,
+      12u,
+      scriptRuns02,
+    },
+    {
+      "Update mix of LTR '\\n'and RTL. Update RTL",
+      "Hello world\nمرحبا بالعالم",
+      12u,
+      13u,
       scriptRuns02,
     },
     {
       "Mix of RTL '\\n'and LTR",
       "مرحبا بالعالم\nHello world",
       scriptRuns02,
     },
     {
       "Mix of RTL '\\n'and LTR",
       "مرحبا بالعالم\nHello world",
+      0u,
+      25u,
+      scriptRuns03,
+    },
+    {
+      "Update mix of RTL '\\n'and LTR. Update RTL",
+      "مرحبا بالعالم\nHello world",
+      0u,
+      14u,
+      scriptRuns03,
+    },
+    {
+      "Update mix of RTL '\\n'and LTR. Update LTR",
+      "مرحبا بالعالم\nHello world",
+      14u,
+      11u,
       scriptRuns03,
     },
     {
       "White spaces. At the beginning of the text.",
       "    Hello world.",
       scriptRuns03,
     },
     {
       "White spaces. At the beginning of the text.",
       "    Hello world.",
+      0u,
+      16u,
       scriptRuns04,
     },
     {
       "White spaces. At the end of the text.",
       "Hello world.    ",
       scriptRuns04,
     },
     {
       "White spaces. At the end of the text.",
       "Hello world.    ",
+      0u,
+      16u,
       scriptRuns05,
     },
     {
       "White spaces. At the middle of the text.",
       "Hello     world.",
       scriptRuns05,
     },
     {
       "White spaces. At the middle of the text.",
       "Hello     world.",
+      0u,
+      16u,
       scriptRuns06,
     },
     {
       "White spaces between different scripts.",
       "  Hel   세계   ",
       scriptRuns06,
     },
     {
       "White spaces between different scripts.",
       "  Hel   세계   ",
+      0u,
+      13u,
       scriptRuns07,
     },
     {
       "White spaces between different scripts and differetn directions. Starting LTR.",
       "  Hello   world   مرحبا  بالعالم     안녕하세요   세계   ",
       scriptRuns07,
     },
     {
       "White spaces between different scripts and differetn directions. Starting LTR.",
       "  Hello   world   مرحبا  بالعالم     안녕하세요   세계   ",
+      0u,
+      50u,
       scriptRuns08,
     },
     {
       "White spaces between different scripts and differetn directions. Starting RTL.",
       "   مرحبا  بالعالم    Hello   world   안녕하세요   세계   مرحبا  بالعالم   ",
       scriptRuns08,
     },
     {
       "White spaces between different scripts and differetn directions. Starting RTL.",
       "   مرحبا  بالعالم    Hello   world   안녕하세요   세계   مرحبا  بالعالم   ",
+      0u,
+      67u,
       scriptRuns09
     },
     {
       scriptRuns09
     },
     {
@@ -550,20 +1139,87 @@ int UtcDaliTextMultiLanguageSetScripts(void)
       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
       "   안녕하세요   세계   ",
       "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
       " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
       "   안녕하세요   세계   ",
+      0u,
+      198u,
+      scriptRuns10
+    },
+    {
+      "Update paragraphs with different directions. Update initial paragraphs.",
+      "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
+      " Hello   world   안녕하세요   세계   \n "
+      "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
+      " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
+      "   안녕하세요   세계   ",
+      0u,
+      81u,
+      scriptRuns10
+    },
+    {
+      "Update paragraphs with different directions. Update middle paragraphs.",
+      "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
+      " Hello   world   안녕하세요   세계   \n "
+      "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
+      " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
+      "   안녕하세요   세계   ",
+      49u,
+      80u,
+      scriptRuns10
+    },
+    {
+      "Update paragraphs with different directions. Update final paragraphs.",
+      "   مرحبا  بالعالم   שלום עולם   مرحبا  بالعالم  \n "
+      " Hello   world   안녕하세요   세계   \n "
+      "  مرحبا  بالعالم  Hello   world    שלום עולם  \n  "
+      " Hello   world    مرحبا  بالعالم    안녕하세요   세계   \n "
+      "   안녕하세요   세계   ",
+      129u,
+      69u,
       scriptRuns10
     },
     {
       "Paragraphs with no scripts mixed with paragraphs with scripts.",
       "  \n  \n   Hello   world  \n  \n  \n   שלום עולם  \n \n \n  ",
       scriptRuns10
     },
     {
       "Paragraphs with no scripts mixed with paragraphs with scripts.",
       "  \n  \n   Hello   world  \n  \n  \n   שלום עולם  \n \n \n  ",
+      0u,
+      52u,
       scriptRuns11
     },
     {
       "Paragraphs with no scripts.",
       "  \n  \n  \n  ",
       scriptRuns11
     },
     {
       "Paragraphs with no scripts.",
       "  \n  \n  \n  ",
+      0u,
+      11u,
       scriptRuns12
       scriptRuns12
+    },
+    {
+      "Update paragraphs with no scripts. Update initial paragraphs.",
+      "  \n  \n  \n  ",
+      0u,
+      3u,
+      scriptRuns12
+    },
+    {
+      "Update paragraphs with no scripts. Update middle paragraphs.",
+      "  \n  \n  \n  ",
+      3u,
+      6u,
+      scriptRuns12
+    },
+    {
+      "Update paragraphs with no scripts. Update final paragraphs.",
+      "  \n  \n  \n  ",
+      9u,
+      2u,
+      scriptRuns12
+    },
+    {
+      "Unknown scripts.",
+      "ᚩᚯᚱᚸ", // Runic script not currentlu supported.
+      0u,
+      4u,
+      scriptRuns13
     }
   };
     }
   };
-  const unsigned int numberOfTests = 13u;
+  const unsigned int numberOfTests = 24u;
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
@@ -582,18 +1238,296 @@ int UtcDaliTextMultiLanguageValidateFonts01(void)
   ToolkitTestApplication application;
   tet_infoline(" UtcDaliTextMultiLanguageValidateFonts");
 
   ToolkitTestApplication application;
   tet_infoline(" UtcDaliTextMultiLanguageValidateFonts");
 
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+
+  char* pathNamePtr = get_current_dir_name();
+  const std::string pathName( pathNamePtr );
+  free( pathNamePtr );
+
+  // Load some fonts.
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenColorEmoji.ttf", EMOJI_FONT_SIZE );
+
+  // Font id 1 --> TizenSansArabicRegular.ttf
+  // Font id 2 --> TizenSansHebrewRegular.ttf
+  // Font id 3 --> TizenColorEmoji.ttf
+  // Font id 4 --> (default)
+
+  Vector<FontRun> fontRuns01;
+  Vector<FontDescriptionRun> fontDescriptions01;
+
+  FontRun fontRun0201 =
+  {
+    {
+      0u,
+      11u
+    },
+    4u
+  };
+  Vector<FontRun> fontRuns02;
+  fontRuns02.PushBack( fontRun0201 );
+
+  FontDescriptionRun fontDescription0201 =
+  {
+    {
+      0u,
+      11u
+    },
+    const_cast<char*>( "TizenSans" ),
+    9u,
+    TextAbstraction::FontWeight::NORMAL,
+    TextAbstraction::FontWidth::NORMAL,
+    TextAbstraction::FontSlant::NORMAL,
+    0u,
+    true,
+    false,
+    false,
+    false,
+    false
+  };
+  Vector<FontDescriptionRun> fontDescriptions02;
+  fontDescriptions02.PushBack( fontDescription0201 );
+
+  FontRun fontRun0301 =
+  {
+    {
+      0u,
+      12u
+    },
+    4u
+  };
+  FontRun fontRun0302 =
+  {
+    {
+      12u,
+      12u
+    },
+    4u
+  };
+  FontRun fontRun0303 =
+  {
+    {
+      24u,
+      4u
+    },
+    4u
+  };
+  Vector<FontRun> fontRuns03;
+  fontRuns03.PushBack( fontRun0301 );
+  fontRuns03.PushBack( fontRun0302 );
+  fontRuns03.PushBack( fontRun0303 );
+
+  Vector<FontDescriptionRun> fontDescriptions03;
+
+  FontRun fontRun0701 =
+  {
+    {
+      0u,
+      4u
+    },
+    2u
+  };
+  FontRun fontRun0702 =
+  {
+    {
+      4u,
+      1u
+    },
+    4u
+  };
+  FontRun fontRun0703 =
+  {
+    {
+      5u,
+      4u
+    },
+    2u
+  };
+  Vector<FontRun> fontRuns07;
+  fontRuns07.PushBack( fontRun0701 );
+  fontRuns07.PushBack( fontRun0702 );
+  fontRuns07.PushBack( fontRun0703 );
+
+  FontDescriptionRun fontDescription0701 =
+  {
+    {
+      0u,
+      4u
+    },
+    const_cast<char*>( "TizenSansHebrew" ),
+    15u,
+    TextAbstraction::FontWeight::NORMAL,
+    TextAbstraction::FontWidth::NORMAL,
+    TextAbstraction::FontSlant::NORMAL,
+    0u,
+    true,
+    false,
+    false,
+    false,
+    false
+  };
+  FontDescriptionRun fontDescription0702 =
+  {
+    {
+      5u,
+      4u
+    },
+    const_cast<char*>( "TizenSansHebrew" ),
+    15u,
+    TextAbstraction::FontWeight::NORMAL,
+    TextAbstraction::FontWidth::NORMAL,
+    TextAbstraction::FontSlant::NORMAL,
+    0u,
+    true,
+    false,
+    false,
+    false,
+    false
+  };
+  Vector<FontDescriptionRun> fontDescriptions07;
+  fontDescriptions07.PushBack( fontDescription0701 );
+  fontDescriptions07.PushBack( fontDescription0702 );
+
+  FontRun fontRun0801 =
+  {
+    {
+      0u,
+      9u
+    },
+    2u
+  };
+  Vector<FontRun> fontRuns08;
+  fontRuns08.PushBack( fontRun0801 );
+
+  Vector<FontDescriptionRun> fontDescriptions08;
+
+  FontRun fontRun0901 =
+  {
+    {
+      0u,
+      4u
+    },
+    3u
+  };
+  Vector<FontRun> fontRuns09;
+  fontRuns09.PushBack( fontRun0901 );
+
+  Vector<FontDescriptionRun> fontDescriptions09;
+  FontDescriptionRun fontDescription0901 =
+  {
+    {
+      0u,
+      4u
+    },
+    const_cast<char*>( "TizenColorEmoji" ),
+    15u,
+    TextAbstraction::FontWeight::NORMAL,
+    TextAbstraction::FontWidth::NORMAL,
+    TextAbstraction::FontSlant::NORMAL,
+    EMOJI_FONT_SIZE,
+    true,
+    false,
+    false,
+    false,
+    true
+  };
+  fontDescriptions09.PushBack( fontDescription0901 );
+
   const ValidateFontsData data[] =
   {
     {
   const ValidateFontsData data[] =
   {
     {
-      "void text",
+      "void text.",
       "",
       "",
+      "/tizen/TizenSansRegular.ttf",
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      0u,
+      fontDescriptions01,
+      fontRuns01
     },
     {
     },
     {
-      "Easy latin script",
+      "Easy latin script.",
       "Hello world",
       "Hello world",
+      "/tizen/TizenSansRegular.ttf",
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      11u,
+      fontDescriptions02,
+      fontRuns02
+    },
+    {
+      "Different paragraphs.",
+      "Hello world\nhello world\ndemo",
+      "/tizen/TizenSansRegular.ttf",
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      28u,
+      fontDescriptions03,
+      fontRuns03
+    },
+    {
+      "Different paragraphs. Update the initial paragraph.",
+      "Hello world\nhello world\ndemo",
+      "/tizen/TizenSansRegular.ttf",
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      12u,
+      fontDescriptions03,
+      fontRuns03
+    },
+    {
+      "Different paragraphs. Update the middle paragraph.",
+      "Hello world\nhello world\ndemo",
+      "/tizen/TizenSansRegular.ttf",
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      12u,
+      12u,
+      fontDescriptions03,
+      fontRuns03
+    },
+    {
+      "Different paragraphs. Update the final paragraph.",
+      "Hello world\nhello world\ndemo",
+      "/tizen/TizenSansRegular.ttf",
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      24u,
+      4u,
+      fontDescriptions03,
+      fontRuns03
+    },
+    {
+      "Hebrew text. Default font: latin",
+      "שלום עולם",
+      "/tizen/TizenSansRegular.ttf",
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      9u,
+      fontDescriptions07,
+      fontRuns07
+    },
+    {
+      "Hebrew text. Default font: hebrew",
+      "שלום עולם",
+      "/tizen/TizenSansHebrewRegular.ttf",
+      TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+      0u,
+      9u,
+      fontDescriptions08,
+      fontRuns08
+    },
+    {
+      "Emojis",
+      "\xF0\x9F\x98\x81\xF0\x9F\x98\x82\xF0\x9F\x98\x83\xF0\x9F\x98\x84",
+      "/tizen/TizenColorEmoji.ttf",
+      EMOJI_FONT_SIZE,
+      0u,
+      4u,
+      fontDescriptions09,
+      fontRuns09
     },
   };
     },
   };
-  const unsigned int numberOfTests = 2u;
+  const unsigned int numberOfTests = 9u;
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
index 96501dd..1e037b1 100644 (file)
@@ -102,6 +102,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/text/visual-model-impl.cpp \
    $(toolkit_src_dir)/text/decorator/text-decorator.cpp \
    $(toolkit_src_dir)/text/layouts/layout-engine.cpp \
    $(toolkit_src_dir)/text/visual-model-impl.cpp \
    $(toolkit_src_dir)/text/decorator/text-decorator.cpp \
    $(toolkit_src_dir)/text/layouts/layout-engine.cpp \
+   $(toolkit_src_dir)/text/multi-language-helper-functions.cpp \
    $(toolkit_src_dir)/text/multi-language-support-impl.cpp \
    $(toolkit_src_dir)/text/rendering/text-backend.cpp \
    $(toolkit_src_dir)/text/rendering/text-renderer.cpp \
    $(toolkit_src_dir)/text/multi-language-support-impl.cpp \
    $(toolkit_src_dir)/text/rendering/text-backend.cpp \
    $(toolkit_src_dir)/text/rendering/text-renderer.cpp \
index d4a9d94..822f9f8 100644 (file)
@@ -20,7 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/input-style.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/input-style.h>
-#include <dali-toolkit/internal/text/text-style-run-container.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
 
 namespace Dali
 {
 
 namespace Dali
 {
diff --git a/dali-toolkit/internal/text/multi-language-helper-functions.cpp b/dali-toolkit/internal/text/multi-language-helper-functions.cpp
new file mode 100644 (file)
index 0000000..a5feaef
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/multi-language-helper-functions.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/font-client.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
+                            Vector<FontId>& fontIds,
+                            const TextAbstraction::FontDescription& defaultFontDescription,
+                            TextAbstraction::PointSize26Dot6 defaultPointSize,
+                            CharacterIndex startIndex,
+                            Length numberOfCharacters )
+{
+  // Get the handle to the font client.
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+
+  // Pointer to the font id buffer.
+  FontId* fontIdsBuffer = fontIds.Begin();
+
+  // Traverse all the characters.
+  for( CharacterIndex index = startIndex; index < numberOfCharacters; ++index )
+  {
+    // The default font description and font point size.
+    TextAbstraction::FontDescription fontDescription = defaultFontDescription;
+    TextAbstraction::PointSize26Dot6 fontSize = defaultPointSize;
+    bool defaultFont = true;
+
+    // Traverse all the font descriptions.
+    for( Vector<FontDescriptionRun>::ConstIterator it = fontDescriptions.Begin(),
+           endIt = fontDescriptions.End();
+         it != endIt;
+         ++it )
+    {
+      // Check whether the character's font is modified by the current font description.
+      const FontDescriptionRun& fontRun = *it;
+      if( ( index >= fontRun.characterRun.characterIndex ) &&
+          ( index < fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) )
+      {
+        if( fontRun.familyDefined )
+        {
+          fontDescription.family = std::string( fontRun.familyName, fontRun.familyLength );
+          defaultFont = false;
+        }
+        if( fontRun.weightDefined )
+        {
+          fontDescription.weight = fontRun.weight;
+          defaultFont = false;
+        }
+        if( fontRun.widthDefined )
+        {
+          fontDescription.width = fontRun.width;
+          defaultFont = false;
+        }
+        if( fontRun.slantDefined )
+        {
+          fontDescription.slant = fontRun.slant;
+          defaultFont = false;
+        }
+        if( fontRun.sizeDefined )
+        {
+          fontSize = fontRun.size;
+          defaultFont = false;
+        }
+      }
+    }
+
+    // Get the font id if is not the default font.
+    if( !defaultFont )
+    {
+      *( fontIdsBuffer + index - startIndex ) = fontClient.GetFontId( fontDescription, fontSize );
+    }
+  }
+}
+
+Script GetScript( Length index,
+                  Vector<ScriptRun>::ConstIterator& scriptRunIt,
+                  const Vector<ScriptRun>::ConstIterator& scriptRunEndIt )
+{
+  Script script = TextAbstraction::UNKNOWN;
+
+  while( scriptRunIt != scriptRunEndIt )
+  {
+    const ScriptRun& scriptRun = *scriptRunIt;
+
+    if( index >= scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters )
+    {
+      ++scriptRunIt;
+    }
+    else if( index >= scriptRun.characterRun.characterIndex )
+    {
+      script = scriptRun.script;
+
+      if( index + 1u == scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters )
+      {
+        // All the characters of the current run have been traversed. Get the next one for the next iteration.
+        ++scriptRunIt;
+      }
+
+      break;
+    }
+  }
+
+  return script;
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/multi-language-helper-functions.h b/dali-toolkit/internal/text/multi-language-helper-functions.h
new file mode 100644 (file)
index 0000000..b73da2f
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_HELPER_FUNCTIONS_H__
+#define __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_HELPER_FUNCTIONS_H__
+
+/*
+ * Copyright (c) 2016 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/script-run.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Merges the font descriptions to retrieve the font Id for each character.
+ *
+ * @param[in] fontDescriptions The font descriptions.
+ * @param[out] fontIds The font id for each character.
+ * @param[in] defaultFontDescription The default font description.
+ * @param[in] defaultPointSize The default font size.
+ * @param[in] startIndex The character from where the fonts are merged.
+ * @param[in] numberOfCharacters The number of characters to set the font.
+ */
+void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
+                            Vector<FontId>& fontIds,
+                            const TextAbstraction::FontDescription& defaultFontDescription,
+                            TextAbstraction::PointSize26Dot6 defaultPointSize,
+                            CharacterIndex startIndex,
+                            Length numberOfCharacters );
+
+/**
+ * @brief Retrieves the script Id from the script run for a given character's @p index.
+ *
+ * If the character's index exceeds the current script run it increases the iterator to get the next one.
+ *
+ * @param[in] index The character's index.
+ * @param[in,out] scriptRunIt Iterator to the current script run.
+ * @param[in] scriptRunEndIt Iterator to one after the last script run.
+ *
+ * @return The script.
+ */
+Script GetScript( Length index,
+                  Vector<ScriptRun>::ConstIterator& scriptRunIt,
+                  const Vector<ScriptRun>::ConstIterator& scriptRunEndIt );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_HELPER_FUNCTIONS_H__
index f37bdc2..81598d9 100644 (file)
@@ -23,6 +23,9 @@
 #include <dali/devel-api/adaptor-framework/singleton-service.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
 
 #include <dali/devel-api/adaptor-framework/singleton-service.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/multi-language-helper-functions.h>
+
 namespace Dali
 {
 
 namespace Dali
 {
 
@@ -44,118 +47,6 @@ namespace Text
 namespace Internal
 {
 
 namespace Internal
 {
 
-/**
- * @brief Merges the font descriptions to retrieve the font Id for each character.
- *
- * @param[in] fontDescriptions The font descriptions.
- * @param[out] fontIds The font id for each character.
- * @param[in] defaultFontDescription The default font description.
- * @param[in] defaultPointSize The default font size.
- */
-void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
-                            Vector<FontId>& fontIds,
-                            const TextAbstraction::FontDescription& defaultFontDescription,
-                            TextAbstraction::PointSize26Dot6 defaultPointSize )
-{
-  // Get the handle to the font client.
-  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
-
-  // Pointer to the font id buffer.
-  FontId* fontIdsBuffer = fontIds.Begin();
-
-  // Traverse all the characters.
-  const Length numberOfCharacters = fontIds.Count();
-  for( CharacterIndex index = 0u; index < numberOfCharacters; ++index )
-  {
-    // The default font description and font point size.
-    TextAbstraction::FontDescription fontDescription = defaultFontDescription;
-    TextAbstraction::PointSize26Dot6 fontSize = defaultPointSize;
-    bool defaultFont = true;
-
-    // Traverse all the font descriptions.
-    for( Vector<FontDescriptionRun>::ConstIterator it = fontDescriptions.Begin(),
-           endIt = fontDescriptions.End();
-         it != endIt;
-         ++it )
-    {
-      // Check whether the character's font is modified by the current font description.
-      const FontDescriptionRun& fontRun = *it;
-      if( ( index >= fontRun.characterRun.characterIndex ) &&
-          ( index < fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) )
-      {
-        if( fontRun.familyDefined )
-        {
-          fontDescription.family = std::string( fontRun.familyName, fontRun.familyLength );
-          defaultFont = false;
-        }
-        if( fontRun.weightDefined )
-        {
-          fontDescription.weight = fontRun.weight;
-          defaultFont = false;
-        }
-        if( fontRun.widthDefined )
-        {
-          fontDescription.width = fontRun.width;
-          defaultFont = false;
-        }
-        if( fontRun.slantDefined )
-        {
-          fontDescription.slant = fontRun.slant;
-          defaultFont = false;
-        }
-        if( fontRun.sizeDefined )
-        {
-          fontSize = fontRun.size;
-          defaultFont = false;
-        }
-      }
-    }
-
-    // Get the font id if is not the default font.
-    if( !defaultFont )
-    {
-      *( fontIdsBuffer + index ) = fontClient.GetFontId( fontDescription, fontSize );
-    }
-  }
-}
-
-/**
- * @brief Retrieves the script Id from the script run for a given character's @p index.
- *
- * If the character's index exceeds the current script run it increases the iterator to get the next one.
- *
- * @param[in] index The character's index.
- * @param[in,out] scriptRunIt Iterator to the current font run.
- * @param[in] scriptRunEndIt Iterator to one after the last script run.
- *
- * @return The script.
- */
-Script GetScript( Length index,
-                  Vector<ScriptRun>::ConstIterator& scriptRunIt,
-                  const Vector<ScriptRun>::ConstIterator& scriptRunEndIt )
-{
-  Script script = TextAbstraction::UNKNOWN;
-
-  if( scriptRunIt != scriptRunEndIt )
-  {
-    const ScriptRun& scriptRun = *scriptRunIt;
-
-    if( ( index >= scriptRun.characterRun.characterIndex ) &&
-        ( index < scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ) )
-    {
-      script = scriptRun.script;
-    }
-
-    if( index + 1u == scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters )
-    {
-      // All the characters of the current run have been traversed. Get the next one for the next iteration.
-      ++scriptRunIt;
-    }
-  }
-
-  return script;
-}
-
 bool ValidateFontsPerScript::FindValidFont( FontId fontId ) const
 {
   for( Vector<FontId>::ConstIterator it = mValidFonts.Begin(),
 bool ValidateFontsPerScript::FindValidFont( FontId fontId ) const
 {
   for( Vector<FontId>::ConstIterator it = mValidFonts.Begin(),
@@ -224,24 +115,42 @@ Text::MultilanguageSupport MultilanguageSupport::Get()
 }
 
 void MultilanguageSupport::SetScripts( const Vector<Character>& text,
 }
 
 void MultilanguageSupport::SetScripts( const Vector<Character>& text,
+                                       CharacterIndex startIndex,
+                                       Length numberOfCharacters,
                                        Vector<ScriptRun>& scripts )
 {
                                        Vector<ScriptRun>& scripts )
 {
-  const Length numberOfCharacters = text.Count();
-
   if( 0u == numberOfCharacters )
   {
     // Nothing to do if there are no characters.
     return;
   }
 
   if( 0u == numberOfCharacters )
   {
     // Nothing to do if there are no characters.
     return;
   }
 
+  // Find the first index where to insert the script.
+  ScriptRunIndex scriptIndex = 0u;
+  if( 0u != startIndex )
+  {
+    for( Vector<ScriptRun>::ConstIterator it = scripts.Begin(),
+           endIt = scripts.End();
+         it != endIt;
+         ++it, ++scriptIndex )
+    {
+      const ScriptRun& run = *it;
+      if( startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+      {
+        // Run found.
+        break;
+      }
+    }
+  }
+
   // Stores the current script run.
   ScriptRun currentScriptRun;
   // Stores the current script run.
   ScriptRun currentScriptRun;
-  currentScriptRun.characterRun.characterIndex = 0u;
+  currentScriptRun.characterRun.characterIndex = startIndex;
   currentScriptRun.characterRun.numberOfCharacters = 0u;
   currentScriptRun.script = TextAbstraction::UNKNOWN;
 
   // Reserve some space to reduce the number of reallocations.
   currentScriptRun.characterRun.numberOfCharacters = 0u;
   currentScriptRun.script = TextAbstraction::UNKNOWN;
 
   // Reserve some space to reduce the number of reallocations.
-  scripts.Reserve( numberOfCharacters << 2u );
+  scripts.Reserve( text.Count() << 2u );
 
   // Whether the first valid script needs to be set.
   bool isFirstScriptToBeSet = true;
 
   // Whether the first valid script needs to be set.
   bool isFirstScriptToBeSet = true;
@@ -256,7 +165,8 @@ void MultilanguageSupport::SetScripts( const Vector<Character>& text,
   const Character* const textBuffer = text.Begin();
 
   // Traverse all characters and set the scripts.
   const Character* const textBuffer = text.Begin();
 
   // Traverse all characters and set the scripts.
-  for( Length index = 0u; index < numberOfCharacters; ++index )
+  const Length lastCharacter = startIndex + numberOfCharacters;
+  for( Length index = startIndex; index < lastCharacter; ++index )
   {
     Character character = *( textBuffer + index );
 
   {
     Character character = *( textBuffer + index );
 
@@ -272,7 +182,7 @@ void MultilanguageSupport::SetScripts( const Vector<Character>& text,
     //   script of the first character of the paragraph with a defined script.
 
     // Skip those characters valid for many scripts like white spaces or '\n'.
     //   script of the first character of the paragraph with a defined script.
 
     // Skip those characters valid for many scripts like white spaces or '\n'.
-    bool endOfText = index == numberOfCharacters;
+    bool endOfText = index == lastCharacter;
     while( !endOfText &&
            ( TextAbstraction::COMMON == script ) )
     {
     while( !endOfText &&
            ( TextAbstraction::COMMON == script ) )
     {
@@ -287,17 +197,27 @@ void MultilanguageSupport::SetScripts( const Vector<Character>& text,
         // the same direction than the first script of the paragraph.
         isFirstScriptToBeSet = true;
 
         // the same direction than the first script of the paragraph.
         isFirstScriptToBeSet = true;
 
-        // Characters common to all scripts at the end of the paragraph are added to the last script (if the last one is not unknown).
-        if( TextAbstraction::UNKNOWN != currentScriptRun.script )
+        // Characters common to all scripts at the end of the paragraph are added to the last script.
+        currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters;
+
+        // Store the script run.
+        if( TextAbstraction::UNKNOWN == currentScriptRun.script )
         {
         {
-          currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters;
-          numberOfAllScriptCharacters = 0u;
+          currentScriptRun.script = TextAbstraction::LATIN;
         }
         }
-      }
+        scripts.Insert( scripts.Begin() + scriptIndex, currentScriptRun );
+        ++scriptIndex;
+
+        // Initialize the new one.
+        currentScriptRun.characterRun.characterIndex = currentScriptRun.characterRun.characterIndex + currentScriptRun.characterRun.numberOfCharacters;
+        currentScriptRun.characterRun.numberOfCharacters = 0u;
+        currentScriptRun.script = TextAbstraction::UNKNOWN;
+        numberOfAllScriptCharacters = 0u;
+     }
 
       // Get the next character.
       ++index;
 
       // Get the next character.
       ++index;
-      endOfText = index == numberOfCharacters;
+      endOfText = index == lastCharacter;
       if( !endOfText )
       {
         character = *( textBuffer + index );
       if( !endOfText )
       {
         character = *( textBuffer + index );
@@ -347,7 +267,8 @@ void MultilanguageSupport::SetScripts( const Vector<Character>& text,
       if( 0u != currentScriptRun.characterRun.numberOfCharacters )
       {
         // Store the script run.
       if( 0u != currentScriptRun.characterRun.numberOfCharacters )
       {
         // Store the script run.
-        scripts.PushBack( currentScriptRun );
+        scripts.Insert( scripts.Begin() + scriptIndex, currentScriptRun );
+        ++scriptIndex;
       }
 
       // Initialize the new one.
       }
 
       // Initialize the new one.
@@ -373,29 +294,46 @@ void MultilanguageSupport::SetScripts( const Vector<Character>& text,
   // Add remaining characters into the last script.
   currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters;
 
   // Add remaining characters into the last script.
   currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters;
 
-  DALI_ASSERT_DEBUG( ( 0u != currentScriptRun.characterRun.numberOfCharacters ) && "MultilanguageSupport::SetScripts() Trying to insert a script run with zero characters." );
-
-  if( TextAbstraction::UNKNOWN == currentScriptRun.script )
+  if( 0u != currentScriptRun.characterRun.numberOfCharacters )
   {
   {
-    // There are only white spaces in the last script. Set the latin script.
-    currentScriptRun.script = TextAbstraction::LATIN;
+    if( TextAbstraction::UNKNOWN == currentScriptRun.script )
+    {
+      // There are only white spaces in the last script. Set the latin script.
+      currentScriptRun.script = TextAbstraction::LATIN;
+    }
+
+    // Store the last run.
+    scripts.Insert( scripts.Begin() + scriptIndex, currentScriptRun );
+    ++scriptIndex;
   }
 
   }
 
-  // Store the last run.
-  scripts.PushBack( currentScriptRun );
+  if( scriptIndex < scripts.Count() )
+  {
+    // Update the indices of the next script runs.
+    const ScriptRun& run = *( scripts.Begin() + scriptIndex - 1u );
+    CharacterIndex nextCharacterIndex = run.characterRun.characterIndex + run.characterRun.numberOfCharacters;
+
+    for( Vector<ScriptRun>::Iterator it = scripts.Begin() + scriptIndex,
+           endIt = scripts.End();
+         it != endIt;
+         ++it )
+    {
+      ScriptRun& run = *it;
+      run.characterRun.characterIndex = nextCharacterIndex;
+      nextCharacterIndex += run.characterRun.numberOfCharacters;
+    }
+  }
 }
 
 void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
                                           const Vector<ScriptRun>& scripts,
                                           const Vector<FontDescriptionRun>& fontDescriptions,
                                           FontId defaultFontId,
 }
 
 void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
                                           const Vector<ScriptRun>& scripts,
                                           const Vector<FontDescriptionRun>& fontDescriptions,
                                           FontId defaultFontId,
+                                          CharacterIndex startIndex,
+                                          Length numberOfCharacters,
                                           Vector<FontRun>& fonts )
 {
                                           Vector<FontRun>& fonts )
 {
-  // Clear any previously validated font.
-  fonts.Clear();
-
   DALI_LOG_INFO( gLogFilter, Debug::General, "-->MultilanguageSupport::ValidateFonts\n" );
   DALI_LOG_INFO( gLogFilter, Debug::General, "-->MultilanguageSupport::ValidateFonts\n" );
-  const Length numberOfCharacters = text.Count();
 
   if( 0u == numberOfCharacters )
   {
 
   if( 0u == numberOfCharacters )
   {
@@ -404,6 +342,24 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
     return;
   }
 
     return;
   }
 
+  // Find the first index where to insert the font run.
+  FontRunIndex fontIndex = 0u;
+  if( 0u != startIndex )
+  {
+    for( Vector<FontRun>::ConstIterator it = fonts.Begin(),
+           endIt = fonts.End();
+         it != endIt;
+         ++it, ++fontIndex )
+    {
+      const FontRun& run = *it;
+      if( startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+      {
+        // Run found.
+        break;
+      }
+    }
+  }
+
   // Traverse the characters and validate/set the fonts.
 
   // Get the caches.
   // Traverse the characters and validate/set the fonts.
 
   // Get the caches.
@@ -415,7 +371,7 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 
   // Initializes a validated font run.
   FontRun currentFontRun;
 
   // Initializes a validated font run.
   FontRun currentFontRun;
-  currentFontRun.characterRun.characterIndex = 0u;
+  currentFontRun.characterRun.characterIndex = startIndex;
   currentFontRun.characterRun.numberOfCharacters = 0u;
   currentFontRun.fontId = 0u;
 
   currentFontRun.characterRun.numberOfCharacters = 0u;
   currentFontRun.fontId = 0u;
 
@@ -437,20 +393,24 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
   MergeFontDescriptions( fontDescriptions,
                          fontIds,
                          defaultFontDescription,
   MergeFontDescriptions( fontDescriptions,
                          fontIds,
                          defaultFontDescription,
-                         defaultPointSize );
+                         defaultPointSize,
+                         startIndex,
+                         numberOfCharacters );
 
   const Character* const textBuffer = text.Begin();
   const FontId* const fontIdsBuffer = fontIds.Begin();
   Vector<ScriptRun>::ConstIterator scriptRunIt = scripts.Begin();
   Vector<ScriptRun>::ConstIterator scriptRunEndIt = scripts.End();
 
   const Character* const textBuffer = text.Begin();
   const FontId* const fontIdsBuffer = fontIds.Begin();
   Vector<ScriptRun>::ConstIterator scriptRunIt = scripts.Begin();
   Vector<ScriptRun>::ConstIterator scriptRunEndIt = scripts.End();
+  bool isNewParagraphCharacter = false;
 
 
-  for( Length index = 0u; index < numberOfCharacters; ++index )
+  CharacterIndex lastCharacter = startIndex + numberOfCharacters;
+  for( Length index = startIndex; index < lastCharacter; ++index )
   {
     // Get the character.
     const Character character = *( textBuffer + index );
 
     // Get the font for the character.
   {
     // Get the character.
     const Character character = *( textBuffer + index );
 
     // Get the font for the character.
-    FontId fontId = *( fontIdsBuffer + index );
+    FontId fontId = *( fontIdsBuffer + index - startIndex );
 
     // Get the script for the character.
     Script script = GetScript( index,
 
     // Get the script for the character.
     Script script = GetScript( index,
@@ -471,12 +431,6 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
     }
 #endif
 
     }
 #endif
 
-    if( TextAbstraction::UNKNOWN == script )
-    {
-      DALI_LOG_WARNING( "MultilanguageSupport::ValidateFonts. Unknown script!" );
-      script = TextAbstraction::LATIN;
-    }
-
     // Whether the font being validated is a default one not set by the user.
     FontId preferredFont = fontId;
 
     // Whether the font being validated is a default one not set by the user.
     FontId preferredFont = fontId;
 
@@ -594,15 +548,16 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 #endif
 
     // The font is now validated.
 #endif
 
     // The font is now validated.
-
-    if( fontId != currentFontRun.fontId )
+    if( ( fontId != currentFontRun.fontId ) ||
+        isNewParagraphCharacter )
     {
       // Current run needs to be stored and a new one initialized.
 
       if( 0u != currentFontRun.characterRun.numberOfCharacters )
       {
         // Store the font run.
     {
       // Current run needs to be stored and a new one initialized.
 
       if( 0u != currentFontRun.characterRun.numberOfCharacters )
       {
         // Store the font run.
-        fonts.PushBack( currentFontRun );
+        fonts.Insert( fonts.Begin() + fontIndex, currentFontRun );
+        ++fontIndex;
       }
 
       // Initialize the new one.
       }
 
       // Initialize the new one.
@@ -613,13 +568,36 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 
     // Add one more character to the run.
     ++currentFontRun.characterRun.numberOfCharacters;
 
     // Add one more character to the run.
     ++currentFontRun.characterRun.numberOfCharacters;
+
+    // Whether the current character is a new paragraph character.
+    isNewParagraphCharacter = TextAbstraction::IsNewParagraph( character );
   }
 
   if( 0u != currentFontRun.characterRun.numberOfCharacters )
   {
     // Store the last run.
   }
 
   if( 0u != currentFontRun.characterRun.numberOfCharacters )
   {
     // Store the last run.
-    fonts.PushBack( currentFontRun );
+    fonts.Insert( fonts.Begin() + fontIndex, currentFontRun );
+    ++fontIndex;
+  }
+
+  if( fontIndex < fonts.Count() )
+  {
+    // Update the indices of the next font runs.
+    const FontRun& run = *( fonts.Begin() + fontIndex - 1u );
+    CharacterIndex nextCharacterIndex = run.characterRun.characterIndex + run.characterRun.numberOfCharacters;
+
+    for( Vector<FontRun>::Iterator it = fonts.Begin() + fontIndex,
+           endIt = fonts.End();
+         it != endIt;
+         ++it )
+    {
+      FontRun& run = *it;
+
+      run.characterRun.characterIndex = nextCharacterIndex;
+      nextCharacterIndex += run.characterRun.numberOfCharacters;
+    }
   }
   }
+
   DALI_LOG_INFO( gLogFilter, Debug::General, "<--MultilanguageSupport::ValidateFonts\n" );
 }
 
   DALI_LOG_INFO( gLogFilter, Debug::General, "<--MultilanguageSupport::ValidateFonts\n" );
 }
 
index e6105ac..781aed5 100644 (file)
@@ -94,6 +94,8 @@ public:
    * @copydoc Dali::MultilanguageSupport::SetScripts()
    */
   void SetScripts( const Vector<Character>& text,
    * @copydoc Dali::MultilanguageSupport::SetScripts()
    */
   void SetScripts( const Vector<Character>& text,
+                   CharacterIndex startIndex,
+                   Length numberOfCharacters,
                    Vector<ScriptRun>& scripts );
 
   /**
                    Vector<ScriptRun>& scripts );
 
   /**
@@ -103,6 +105,8 @@ public:
                       const Vector<ScriptRun>& scripts,
                       const Vector<FontDescriptionRun>& fontDescriptions,
                       FontId defaultFontId,
                       const Vector<ScriptRun>& scripts,
                       const Vector<FontDescriptionRun>& fontDescriptions,
                       FontId defaultFontId,
+                      CharacterIndex startIndex,
+                      Length numberOfCharacters,
                       Vector<FontRun>& fonts );
 
 private:
                       Vector<FontRun>& fonts );
 
 private:
index 87e594d..e612054 100644 (file)
@@ -49,9 +49,13 @@ MultilanguageSupport MultilanguageSupport::Get()
 }
 
 void MultilanguageSupport::SetScripts( const Vector<Character>& text,
 }
 
 void MultilanguageSupport::SetScripts( const Vector<Character>& text,
+                                       CharacterIndex startIndex,
+                                       Length numberOfCharacters,
                                        Vector<ScriptRun>& scripts )
 {
   GetImplementation( *this ).SetScripts( text,
                                        Vector<ScriptRun>& scripts )
 {
   GetImplementation( *this ).SetScripts( text,
+                                         startIndex,
+                                         numberOfCharacters,
                                          scripts );
 }
 
                                          scripts );
 }
 
@@ -59,12 +63,16 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
                                           const Vector<ScriptRun>& scripts,
                                           const Vector<FontDescriptionRun>& fontDescriptions,
                                           FontId defaultFontId,
                                           const Vector<ScriptRun>& scripts,
                                           const Vector<FontDescriptionRun>& fontDescriptions,
                                           FontId defaultFontId,
+                                          CharacterIndex startIndex,
+                                          Length numberOfCharacters,
                                           Vector<FontRun>& fonts )
 {
   GetImplementation( *this ).ValidateFonts( text,
                                             scripts,
                                             fontDescriptions,
                                             defaultFontId,
                                           Vector<FontRun>& fonts )
 {
   GetImplementation( *this ).ValidateFonts( text,
                                             scripts,
                                             fontDescriptions,
                                             defaultFontId,
+                                            startIndex,
+                                            numberOfCharacters,
                                             fonts );
 }
 
                                             fonts );
 }
 
index bcbb130..d4fd1c7 100644 (file)
@@ -90,9 +90,13 @@ public:
    *   script of the first character of the paragraph with a defined script.
    *
    * @param[in] text Vector of UTF-32 characters.
    *   script of the first character of the paragraph with a defined script.
    *
    * @param[in] text Vector of UTF-32 characters.
+   * @param[in] startIndex The character from where the script info is set.
+   * @param[in] numberOfCharacters The number of characters to set the script.
    * @param[out] scripts Vector containing the script runs for the whole text.
    */
   void SetScripts( const Vector<Character>& text,
    * @param[out] scripts Vector containing the script runs for the whole text.
    */
   void SetScripts( const Vector<Character>& text,
+                   CharacterIndex startIndex,
+                   Length numberOfCharacters,
                    Vector<ScriptRun>& scripts );
 
   /**
                    Vector<ScriptRun>& scripts );
 
   /**
@@ -110,12 +114,16 @@ public:
    * @param[in] scripts Vector containing the script runs for the whole text.
    * @param[in] fontDescriptions The fonts set by the application developers.
    * @param[in] defaultFontId The default font's id.
    * @param[in] scripts Vector containing the script runs for the whole text.
    * @param[in] fontDescriptions The fonts set by the application developers.
    * @param[in] defaultFontId The default font's id.
+   * @param[in] startIndex The character from where the font info is set.
+   * @param[in] numberOfCharacters The number of characters to set the font.
    * @param[out] fonts The validated fonts.
    */
   void ValidateFonts( const Vector<Character>& text,
                       const Vector<ScriptRun>& scripts,
                       const Vector<FontDescriptionRun>& fontDescriptions,
                       FontId defaultFontId,
    * @param[out] fonts The validated fonts.
    */
   void ValidateFonts( const Vector<Character>& text,
                       const Vector<ScriptRun>& scripts,
                       const Vector<FontDescriptionRun>& fontDescriptions,
                       FontId defaultFontId,
+                      CharacterIndex startIndex,
+                      Length numberOfCharacters,
                       Vector<FontRun>& fonts );
 };
 
                       Vector<FontRun>& fonts );
 };
 
index 4ac12b7..2a76cb2 100644 (file)
@@ -367,6 +367,8 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     {
       // Retrieves the scripts used in the text.
       multilanguageSupport.SetScripts( utf32Characters,
     {
       // Retrieves the scripts used in the text.
       multilanguageSupport.SetScripts( utf32Characters,
+                                       startIndex,
+                                       requestedNumberOfCharacters,
                                        scripts );
     }
 
                                        scripts );
     }
 
@@ -384,6 +386,8 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                                           scripts,
                                           fontDescriptionRuns,
                                           defaultFontId,
                                           scripts,
                                           fontDescriptionRuns,
                                           defaultFontId,
+                                          startIndex,
+                                          requestedNumberOfCharacters,
                                           validFonts );
     }
   }
                                           validFonts );
     }
   }
@@ -31,6 +31,97 @@ namespace Text
 {
 
 /**
 {
 
 /**
+ * @brief Clears the runs starting from the given character index.
+ *
+ * @param[in] startIndex The starting character index used to remove runs.
+ * @param[in] endIndex The ending character index used to remove runs.
+ * @param[in,out] runs The text's runs.
+ * @param[out] startRemoveIndex The index to the first run to be removed.
+ * @param[out] endRemoveIndex The index to the last run to be removed.
+ */
+template< typename T >
+void ClearCharacterRuns( CharacterIndex startIndex,
+                         CharacterIndex endIndex,
+                         Vector<T>& runs,
+                         uint32_t& startRemoveIndex,
+                         uint32_t& endRemoveIndex )
+{
+  T* runsBuffer = runs.Begin();
+
+  const Length length = runs.Count();
+  for( Length index = 0u; index < length; ++index )
+  {
+    T* run = ( runsBuffer + index );
+
+    if( ( run->characterRun.characterIndex <= endIndex ) &&
+        ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
+    {
+      // Run found.
+
+      // Set the index to the first run to be removed.
+      startRemoveIndex = index;
+      break;
+    }
+  }
+
+  for( Length index = startRemoveIndex; index < length; ++index )
+  {
+    T* run = ( runsBuffer + index );
+
+    if( ( run->characterRun.characterIndex <= endIndex ) &&
+        ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
+    {
+      // Update the index to the last run to be removed.
+      endRemoveIndex = index + 1u;
+    }
+    else
+    {
+      // Run found. Nothing else to do.
+      break;
+    }
+  }
+
+  // The number of characters to remove.
+  const Length numberOfCharactersRemoved = 1u + endIndex - startIndex;
+
+  // Update the character index of the next runs.
+  for( Length index = 0u; index < length; ++index )
+  {
+    T* run = ( runsBuffer + index );
+
+    if( run->characterRun.characterIndex > startIndex )
+    {
+      run->characterRun.characterIndex -= numberOfCharactersRemoved;
+    }
+  }
+}
+
+/**
+ * @brief Clears the runs starting from the given character index.
+ *
+ * @param[in] startIndex The starting character index used to remove runs.
+ * @param[in] endIndex The ending character index used to remove runs.
+ * @param[in,out] runs The text's runs.
+ */
+template< typename T >
+void ClearCharacterRuns( CharacterIndex startIndex,
+                         CharacterIndex endIndex,
+                         Vector<T>& runs )
+{
+  uint32_t startRemoveIndex = runs.Count();
+  uint32_t endRemoveIndex = startRemoveIndex;
+  ClearCharacterRuns( startIndex,
+                      endIndex,
+                      runs,
+                      startRemoveIndex,
+                      endRemoveIndex );
+
+  // Remove all remaining runs.
+  T* runBuffer = runs.Begin();
+  runs.Erase( runBuffer + startRemoveIndex, runBuffer + endRemoveIndex );
+}
+
+/**
  * @brief Updates the number of characters and the character index of the text's style runs.
  *
  * If the @p numberOfCharacters is a negative value, it means the number of characters that are removed starting from the @p index.
  * @brief Updates the number of characters and the character index of the text's style runs.
  *
  * If the @p numberOfCharacters is a negative value, it means the number of characters that are removed starting from the @p index.