Multi-language support implementation. 84/34984/11
authorVictor Cebollada <v.cebollada@samsung.com>
Wed, 4 Feb 2015 09:42:49 +0000 (09:42 +0000)
committerPaul Wisbey <p.wisbey@samsung.com>
Fri, 13 Feb 2015 14:41:59 +0000 (06:41 -0800)
Change-Id: Ia6dee3e9e85f1a7ff2043eebbe3680967bf2fafc
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
base/dali-toolkit/internal/file.list
base/dali-toolkit/internal/text/multi-language-support-impl.cpp [new file with mode: 0644]
base/dali-toolkit/internal/text/multi-language-support-impl.h [new file with mode: 0644]
base/dali-toolkit/public-api/file.list
base/dali-toolkit/public-api/text/multi-language-support.cpp
base/dali-toolkit/public-api/text/multi-language-support.h
base/dali-toolkit/public-api/text/script.cpp

index a6cb7ca..621ffbc 100644 (file)
@@ -38,6 +38,7 @@ toolkit_base_src_files = \
    $(toolkit_base_src_dir)/focus-manager/keyboard-focus-manager-impl.cpp \
    $(toolkit_base_src_dir)/focus-manager/keyinput-focus-manager-impl.cpp \
    $(toolkit_base_src_dir)/styling/style-manager-impl.cpp \
    $(toolkit_base_src_dir)/focus-manager/keyboard-focus-manager-impl.cpp \
    $(toolkit_base_src_dir)/focus-manager/keyinput-focus-manager-impl.cpp \
    $(toolkit_base_src_dir)/styling/style-manager-impl.cpp \
+   $(toolkit_base_src_dir)/text/multi-language-support-impl.cpp \
    $(toolkit_base_src_dir)/builder/builder-impl.cpp \
    $(toolkit_base_src_dir)/builder/builder-animations.cpp \
    $(toolkit_base_src_dir)/builder/builder-set-property.cpp \
    $(toolkit_base_src_dir)/builder/builder-impl.cpp \
    $(toolkit_base_src_dir)/builder/builder-animations.cpp \
    $(toolkit_base_src_dir)/builder/builder-set-property.cpp \
diff --git a/base/dali-toolkit/internal/text/multi-language-support-impl.cpp b/base/dali-toolkit/internal/text/multi-language-support-impl.cpp
new file mode 100644 (file)
index 0000000..4143b03
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/multi-language-support-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/singleton-service.h>
+#include <dali-toolkit/public-api/text/logical-model.h>
+#include <dali-toolkit/public-api/text/font-run.h>
+#include <dali-toolkit/public-api/text/script.h>
+#include <dali-toolkit/public-api/text/script-run.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Retrieves the font Id from the font run for a given character's @p index.
+ *
+ * If the character's index exceeds the current font run it increases the iterator to get the next one.
+ *
+ * @param[in] index The character's index.
+ * @param[in,out] fontRunIt Iterator to the current font run.
+ * @param[in] fontRunEndIt Iterator to one after the last font run.
+ *
+ * @return The font id.
+ */
+FontId GetFontId( Length index,
+                  Vector<FontRun>::ConstIterator& fontRunIt,
+                  const Vector<FontRun>::ConstIterator& fontRunEndIt )
+{
+  FontId fontId = 0u;
+
+  if( fontRunIt != fontRunEndIt )
+  {
+    const FontRun& fontRun = *fontRunIt;
+
+    if( ( index >= fontRun.characterRun.characterIndex ) &&
+        ( index < fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) )
+    {
+      fontId = fontRun.fontId;
+    }
+
+    if( index == fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters )
+    {
+      // All the characters of the current run have been traversed. Get the next one for the next iteration.
+      ++fontRunIt;
+    }
+  }
+
+  return fontId;
+}
+
+/**
+ * @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 == 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(),
+         endIt = mValidFonts.End();
+       it != endIt;
+       ++it )
+  {
+    if( fontId == *it )
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+MultilanguageSupport::MultilanguageSupport()
+: mDefaultFontPerScriptCache(),
+  mValidFontsPerScriptCache()
+{
+  // Initializes the default font cache to zero (invalid font).
+  // Reserves space to cache the default fonts and access them with the script as an index.
+  mDefaultFontPerScriptCache.Resize( TextAbstraction::UNKNOWN, 0u );
+
+  // Initializes the valid fonts cache to NULL (no valid fonts).
+  // Reserves space to cache the valid fonts and access them with the script as an index.
+  mValidFontsPerScriptCache.Resize( TextAbstraction::UNKNOWN, NULL );
+}
+
+MultilanguageSupport::~MultilanguageSupport()
+{
+  // Destroy the valid fonts per script cache.
+
+  for( Vector<ValidateFontsPerScript*>::Iterator it = mValidFontsPerScriptCache.Begin(),
+         endIt = mValidFontsPerScriptCache.End();
+       it != endIt;
+       ++it )
+  {
+    delete *it;
+  }
+}
+
+Text::MultilanguageSupport MultilanguageSupport::Get()
+{
+  Text::MultilanguageSupport multilanguageSupportHandle;
+
+  SingletonService service( SingletonService::Get() );
+  if( service )
+  {
+    // Check whether the singleton is already created
+    Dali::BaseHandle handle = service.GetSingleton( typeid( Text::MultilanguageSupport ) );
+    if( handle )
+    {
+      // If so, downcast the handle
+      MultilanguageSupport* impl = dynamic_cast< Internal::MultilanguageSupport* >( handle.GetObjectPtr() );
+      multilanguageSupportHandle = Text::MultilanguageSupport( impl );
+    }
+    else // create and register the object
+    {
+      multilanguageSupportHandle = Text::MultilanguageSupport( new MultilanguageSupport );
+      service.Register( typeid( multilanguageSupportHandle ), multilanguageSupportHandle );
+    }
+  }
+
+  return multilanguageSupportHandle;
+}
+
+void MultilanguageSupport::SetScripts( LogicalModel& model )
+{
+  // 1) Retrieve the text from the model.
+  const Length numberOfCharacters = model.GetNumberOfCharacters();
+
+  if( 0u == numberOfCharacters )
+  {
+    // Nothing to do if there are no characters.
+    return;
+  }
+
+  Vector<Character> text;
+  text.Resize( numberOfCharacters );
+
+  model.GetText( 0u,
+                 text.Begin(),
+                 numberOfCharacters );
+
+  // 2) Traverse all characters and set the scripts.
+
+  // Stores the current script run.
+  ScriptRun currentScriptRun;
+  currentScriptRun.characterRun.characterIndex = 0u;
+  currentScriptRun.characterRun.numberOfCharacters = 0u;
+  currentScriptRun.script = TextAbstraction::UNKNOWN;
+
+  // Temporary stores the script runs.
+  std::vector<ScriptRun> scriptRuns;
+  scriptRuns.reserve( numberOfCharacters << 2u ); // To reduce the number of reallocations.
+
+  for( Vector<Character>::ConstIterator it = text.Begin(),
+         endIt = text.End();
+       it != endIt;
+       ++it )
+  {
+    const Character character = *it;
+
+    Script script = GetCharacterScript( character );
+
+    if( TextAbstraction::UNKNOWN == script )
+    {
+      script = TextAbstraction::LATIN;
+      DALI_ASSERT_DEBUG( !"MultilanguageSupport::SetScripts. Unkown script!" );
+    }
+
+    if( script != currentScriptRun.script )
+    {
+      // Current run needs to be stored and a new one initialized.
+
+      if( 0u != currentScriptRun.characterRun.numberOfCharacters )
+      {
+        // Store the script run.
+        scriptRuns.push_back( currentScriptRun );
+      }
+
+      // Initialize the new one.
+      currentScriptRun.characterRun.characterIndex = currentScriptRun.characterRun.characterIndex + currentScriptRun.characterRun.numberOfCharacters;
+      currentScriptRun.characterRun.numberOfCharacters = 0u;
+      currentScriptRun.script = script;
+    }
+
+    // Add one more character to the run.
+    ++currentScriptRun.characterRun.numberOfCharacters;
+  }
+
+  if( 0u != currentScriptRun.characterRun.numberOfCharacters )
+  {
+    // Store the last run.
+    scriptRuns.push_back( currentScriptRun );
+  }
+
+  // 3) Set the script runs into the model.
+
+  model.SetScripts( &scriptRuns[0u],
+                    scriptRuns.size() );
+}
+
+void MultilanguageSupport::ValidateFonts( LogicalModel& model )
+{
+  // 1) Retrieve the text from the model.
+  const Length numberOfCharacters = model.GetNumberOfCharacters();
+
+  if( 0u == numberOfCharacters )
+  {
+    // Nothing to do if there are no characters.
+    return;
+  }
+
+  Vector<Character> text;
+  text.Resize( numberOfCharacters );
+
+  Character* textBuffer = text.Begin();
+  model.GetText( 0u,
+                 textBuffer,
+                 numberOfCharacters );
+
+  // 2) Retrieve any font previously set.
+
+  const Length numberOfFontRuns = model.GetNumberOfFontRuns( 0u, numberOfCharacters );
+
+  Vector<FontRun> fontRuns;
+  fontRuns.Reserve( numberOfFontRuns );
+
+  FontRun* fontRunsBuffer = fontRuns.Begin();
+  model.GetFontRuns( fontRunsBuffer,
+                     0u,
+                     numberOfCharacters );
+
+  // 3) Retrieve the scripts from the model.
+
+  const Length numberOfScriptRuns = model.GetNumberOfScriptRuns( 0u, numberOfCharacters );
+
+  Vector<ScriptRun> scriptRuns;
+  scriptRuns.Reserve( numberOfScriptRuns );
+
+  ScriptRun* scriptRunsBuffer = scriptRuns.Begin();
+  model.GetScriptRuns( scriptRunsBuffer,
+                       0u,
+                       numberOfCharacters );
+
+  // 4) Traverse the characters and validate/set the fonts.
+
+  // Get the caches.
+  FontId* defaultFontPerScriptCacheBuffer = mDefaultFontPerScriptCache.Begin();
+  ValidateFontsPerScript** validFontsPerScriptCacheBuffer = mValidFontsPerScriptCache.Begin();
+
+  // Stores the validated font runs.
+  Vector<FontRun> validatedFontRuns;
+  validatedFontRuns.Reserve( numberOfFontRuns );
+
+  // Initializes a validated font run.
+  FontRun currentFontRun;
+  currentFontRun.characterRun.characterIndex = 0u;
+  currentFontRun.characterRun.numberOfCharacters = 0u;
+  currentFontRun.fontId = 0u;
+  currentFontRun.isDefault = false;
+
+  // Get the font client.
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+
+  // Iterators of the font and script runs.
+  Vector<FontRun>::ConstIterator fontRunIt = fontRuns.Begin();
+  Vector<FontRun>::ConstIterator fontRunEndIt = fontRuns.End();
+  Vector<ScriptRun>::ConstIterator scriptRunIt = scriptRuns.Begin();
+  Vector<ScriptRun>::ConstIterator scriptRunEndIt = scriptRuns.End();
+
+  for( Length index = 0u; index < numberOfCharacters; ++index )
+  {
+    // Get the character.
+    const Character character = *( textBuffer + index );
+
+    // Get the font for the character.
+    FontId fontId = GetFontId( index,
+                               fontRunIt,
+                               fontRunEndIt );
+
+    // Get the script for the character.
+    Script script = GetScript( index,
+                               scriptRunIt,
+                               scriptRunEndIt );
+
+    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.
+    const bool isDefault = ( 0u == fontId );
+
+    // The default font point size.
+    PointSize26Dot6 pointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
+
+    if( !isDefault )
+    {
+      // Validate if the font set by the user supports the character.
+
+      // Check first in the caches.
+
+      // The user may have set the default font. Check it. Otherwise check in the valid fonts cache.
+      if( fontId != *( defaultFontPerScriptCacheBuffer + script ) )
+      {
+        // Check in the valid fonts cache.
+        ValidateFontsPerScript* validateFontsPerScript = *( validFontsPerScriptCacheBuffer + script );
+        if( NULL != validateFontsPerScript )
+        {
+          if( !validateFontsPerScript->FindValidFont( fontId ) )
+          {
+            // Use the font client to validate the font.
+            const GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character );
+
+            if( 0u == glyphIndex )
+            {
+              // Get the point size of the current font. It will be used to get a default font id.
+              pointSize = fontClient.GetPointSize( fontId );
+
+              // The font is not valid. Set to zero and a default one will be set.
+              fontId = 0u;
+            }
+            else
+            {
+              // Add the font to the valid font cache.
+              validateFontsPerScript->mValidFonts.PushBack( fontId );
+            }
+          }
+        }
+        else
+        {
+          // Use the font client to validate the font.
+          const GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character );
+
+          if( 0u == glyphIndex )
+          {
+            // Get the point size of the current font. It will be used to get a default font id.
+            pointSize = fontClient.GetPointSize( fontId );
+
+            // The font is not valid. Set to zero and a default one will be set.
+            fontId = 0u;
+          }
+          else
+          {
+            // Add the font to the valid font cache.
+            validateFontsPerScript = new ValidateFontsPerScript();
+            *( validFontsPerScriptCacheBuffer + script ) = validateFontsPerScript;
+
+            validateFontsPerScript->mValidFonts.PushBack( fontId );
+          }
+        }
+      }
+    }
+
+    // The font has not been validated. Find a default one.
+    if( 0u == fontId )
+    {
+      // The character has no font assigned. Get a default one from the cache
+      fontId = *( defaultFontPerScriptCacheBuffer + script );
+
+      // If the cache has not a default font, get one from the font client.
+      if( 0u == fontId )
+      {
+        // Find a default font.
+        fontId = fontClient.FindDefaultFont( character, pointSize );
+
+        // Cache the font.
+        *( defaultFontPerScriptCacheBuffer + script ) = fontId;
+      }
+    }
+
+    // The font is now validated.
+
+    if( ( fontId != currentFontRun.fontId ) ||
+        ( isDefault != currentFontRun.isDefault ) )
+    {
+      // Current run needs to be stored and a new one initialized.
+
+      if( 0u != currentFontRun.characterRun.numberOfCharacters )
+      {
+        // Store the font run.
+        validatedFontRuns.PushBack( currentFontRun );
+      }
+
+      // Initialize the new one.
+      currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters;
+      currentFontRun.characterRun.numberOfCharacters = 0u;
+      currentFontRun.fontId = fontId;
+      currentFontRun.isDefault = isDefault;
+    }
+
+    // Add one more character to the run.
+    ++currentFontRun.characterRun.numberOfCharacters;
+  }
+
+  if( 0u != currentFontRun.characterRun.numberOfCharacters )
+  {
+    // Store the last run.
+    validatedFontRuns.PushBack( currentFontRun );
+  }
+
+  // 5) Sets the validated font runs to the model.
+  model.SetFonts( validatedFontRuns.Begin(),
+                  validatedFontRuns.Count() );
+}
+
+} // namespace Internal
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/base/dali-toolkit/internal/text/multi-language-support-impl.h b/base/dali-toolkit/internal/text/multi-language-support-impl.h
new file mode 100644 (file)
index 0000000..f527031
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__
+#define __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__
+
+/*
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/text/multi-language-support.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/base-object.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Stores valid font ids per script.
+ */
+struct ValidateFontsPerScript
+{
+  /**
+   * Default constructor.
+   */
+  ValidateFontsPerScript()
+  : mValidFonts()
+  {}
+
+  /**
+   * Default destructor.
+   */
+  ~ValidateFontsPerScript()
+  {}
+
+  /**
+   * @brief Whether the given @p fontId is in the vector of valid fonts.
+   *
+   * @param[in] fontId The font id.
+   *
+   * @return @e true if the font is in the vector of valid fonts.
+   */
+  bool FindValidFont( FontId fontId ) const;
+
+  Vector<FontId> mValidFonts;
+};
+
+/**
+ * @brief Multi-language support implementation. @see Text::MultilanguageSupport.
+ */
+class MultilanguageSupport : public BaseObject
+{
+public:
+
+  /**
+   * Constructor
+   */
+  MultilanguageSupport();
+
+  /**
+   * Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~MultilanguageSupport();
+
+  /**
+   * @copydoc Dali::MultilanguageSupport::Get()
+   */
+  static Text::MultilanguageSupport Get();
+
+  /**
+   * @copydoc Dali::MultilanguageSupport::SetScripts()
+   */
+  void SetScripts( LogicalModel& model );
+
+  /**
+   * @copydoc Dali::MultilanguageSupport::ValidateFonts()
+   */
+  void ValidateFonts( LogicalModel& model );
+
+private:
+  Vector<FontId>                  mDefaultFontPerScriptCache; ///< Caches the default font for a script.
+  Vector<ValidateFontsPerScript*> mValidFontsPerScriptCache;  ///< Caches valid fonts for a script.
+};
+
+} // namespace Internal
+
+inline static Internal::MultilanguageSupport& GetImplementation( MultilanguageSupport& multilanguageSupport )
+{
+  DALI_ASSERT_ALWAYS( multilanguageSupport && "multi-language handle is empty" );
+  BaseObject& handle = multilanguageSupport.GetBaseObject();
+  return static_cast<Internal::MultilanguageSupport&>( handle );
+}
+
+inline static const Internal::MultilanguageSupport& GetImplementation( const MultilanguageSupport& multilanguageSupport )
+{
+  DALI_ASSERT_ALWAYS( multilanguageSupport && "multi-language handle is empty" );
+  const BaseObject& handle = multilanguageSupport.GetBaseObject();
+  return static_cast<const Internal::MultilanguageSupport&>( handle );
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__
index 5755eba..7ab17c8 100755 (executable)
@@ -41,6 +41,7 @@ public_api_base_src_files = \
   $(public_api_base_src_dir)/text/character-set-conversion.cpp \
   $(public_api_base_src_dir)/text/logical-model.cpp \
   $(public_api_base_src_dir)/text/multi-language-support.cpp \
   $(public_api_base_src_dir)/text/character-set-conversion.cpp \
   $(public_api_base_src_dir)/text/logical-model.cpp \
   $(public_api_base_src_dir)/text/multi-language-support.cpp \
+  $(public_api_base_src_dir)/text/script.cpp \
   $(public_api_base_src_dir)/text/segmentation.cpp \
   $(public_api_base_src_dir)/text/text-controller.cpp \
   $(public_api_base_src_dir)/text/text-view.cpp \
   $(public_api_base_src_dir)/text/segmentation.cpp \
   $(public_api_base_src_dir)/text/text-controller.cpp \
   $(public_api_base_src_dir)/text/text-view.cpp \
@@ -131,6 +132,7 @@ public_api_base_text_header_files = \
   $(public_api_base_src_dir)/text/logical-model.h \
   $(public_api_base_src_dir)/text/multi-language-support.h \
   $(public_api_base_src_dir)/text/script.h \
   $(public_api_base_src_dir)/text/logical-model.h \
   $(public_api_base_src_dir)/text/multi-language-support.h \
   $(public_api_base_src_dir)/text/script.h \
+  $(public_api_base_src_dir)/text/script-run.h \
   $(public_api_base_src_dir)/text/segmentation.h \
   $(public_api_base_src_dir)/text/text-controller.h \
   $(public_api_base_src_dir)/text/text-definitions.h \
   $(public_api_base_src_dir)/text/segmentation.h \
   $(public_api_base_src_dir)/text/text-controller.h \
   $(public_api_base_src_dir)/text/text-definitions.h \
index a017d12..1eb6805 100644 (file)
@@ -18,6 +18,9 @@
 // FILE HEADER
 #include <dali-toolkit/public-api/text/multi-language-support.h>
 
 // FILE HEADER
 #include <dali-toolkit/public-api/text/multi-language-support.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/multi-language-support-impl.h>
+
 namespace Dali
 {
 
 namespace Dali
 {
 
@@ -36,20 +39,23 @@ MultilanguageSupport::~MultilanguageSupport()
 }
 
 MultilanguageSupport::MultilanguageSupport( Internal::MultilanguageSupport* implementation )
 }
 
 MultilanguageSupport::MultilanguageSupport( Internal::MultilanguageSupport* implementation )
+: BaseHandle( implementation )
 {
 }
 
 MultilanguageSupport MultilanguageSupport::Get()
 {
 {
 }
 
 MultilanguageSupport MultilanguageSupport::Get()
 {
-  return MultilanguageSupport();
+  return Internal::MultilanguageSupport::Get();
 }
 
 void MultilanguageSupport::SetScripts( LogicalModel& model )
 {
 }
 
 void MultilanguageSupport::SetScripts( LogicalModel& model )
 {
+  GetImplementation( *this ).SetScripts( model );
 }
 
 void MultilanguageSupport::ValidateFonts( LogicalModel& model )
 {
 }
 
 void MultilanguageSupport::ValidateFonts( LogicalModel& model )
 {
+  GetImplementation( *this ).ValidateFonts( model );
 }
 
 } // namespace Text
 }
 
 } // namespace Text
index a1e4c99..dbd2552 100644 (file)
@@ -64,7 +64,7 @@ public:
   /**
    * @brief This constructor is used by MultilanguageSupport::Get().
    *
   /**
    * @brief This constructor is used by MultilanguageSupport::Get().
    *
-   * @param[in] implementation A pointer to the internal multilanguage support object.
+   * @param[in] implementation A pointer to the internal multi-language support object.
    */
   explicit DALI_INTERNAL MultilanguageSupport( Internal::MultilanguageSupport* implementation );
 
    */
   explicit DALI_INTERNAL MultilanguageSupport( Internal::MultilanguageSupport* implementation );
 
@@ -80,6 +80,8 @@ public:
    *
    * Any script info previously set is removed.
    *
    *
    * Any script info previously set is removed.
    *
+   * Scripts are used to validate and set default fonts and to shape the text in further steps.
+   *
    * @pre The @p model needs to have a text set.
    *
    * @param[in,out] model The text's logical model.
    * @pre The @p model needs to have a text set.
    *
    * @param[in,out] model The text's logical model.
@@ -89,8 +91,15 @@ public:
   /**
    * @brief Validates the character's font of the whole text.
    *
   /**
    * @brief Validates the character's font of the whole text.
    *
-   * It may update fonts set by the mark-up processor.
-   * It sets default fonts based on the script to those characters without a font set.
+   * It may update fonts set by application developers.
+   *
+   * This method ensures all characters are going to be rendered using an appropriate font. Provided a valid font
+   * exists in the platform.
+   *
+   * For those characters with no font set, it sets a default one.
+   *
+   * If a font has been set by the application developer, this method checks if the font supports the character.
+   * If it doesn't, this method replaces it by a default one.
    *
    * @pre The @p model needs to have a text set.
    * @pre The @p model needs to have the scripts set.
    *
    * @pre The @p model needs to have a text set.
    * @pre The @p model needs to have the scripts set.
index a001f94..8860a14 100644 (file)
@@ -29,6 +29,338 @@ namespace Text
 
 Script GetCharacterScript( Character character )
 {
 
 Script GetCharacterScript( Character character )
 {
+  // Latin script:
+  // 0x0000 - 0x007f C0 Controls and Basic Latin
+  // 0x0080 - 0x00ff C1 Controls and Latin-1 Supplement
+  // 0x0100 - 0x017f Latin Extended-A
+  // 0x0180 - 0x024f Latin Extended-B
+  // 0x0250 - 0x02af IPA Extensions
+  // 0x02b0 - 0x02ff Spacing Modifier Letters
+  // 0x1d00 - 0x1d7f Phonetic Extensions
+  // 0x1d80 - 0x1dbf Phonetic Extensions Supplement
+  // 0x1e00 - 0x1eff Latin Extended Additional
+  // 0x2070 - 0x209f Superscripts and Subscripts
+  // 0x2100 - 0x214f Letterlike symbols
+  // 0x2150 - 0x218f Number Forms
+  // 0x2c60 - 0x2c7f Latin Extended-C
+  // 0xa720 - 0xa7ff Latin Extended-D
+  // 0xab30 - 0xab6f Latin Extended-E
+  // 0xfb00 - 0xfb4f Alphabetic Presentation Forms
+  // 0xff00 - 0xffef Halfwidth and Fullwidth Forms
+
+  // Brahmic scripts:
+  // 0x0900 - 0x097f Devanagari
+  // 0x0980 - 0x09ff Bengali
+  // 0x0a00 - 0x0a7f Gurmukhi
+  // 0x0a80 - 0x0aff Gujarati
+  // 0x0b00 - 0x0b7f Oriya
+  // 0x0b80 - 0x0bff Tamil
+  // 0x0c00 - 0x0c7f Telugu
+  // 0x0c80 - 0x0cff Kannada
+  // 0x0d00 - 0x0d7f Malayalam
+
+  // Sinhala script.
+  // 0x0d80 - 0x0dff Sinhala
+
+  // Arabic script.
+  // 0x0600 - 0x06ff Arabic
+  // 0x0750 - 0x077f Arabic Supplement
+  // 0x08A0 - 0x08ff Arabic Extended-A
+  // 0xfb50 - 0xfdff Arabic Presentation Forms-A
+  // 0xfe70 - 0xfeff Arabic Presentation Forms-B
+  // 0x1ee00 - 0x1eeff Arabic Mathematical Alphabetic Symbols
+
+  // CJK and Vietnamese script.
+  // 0x2E80 - 0x2eff CJK Radicals Supplement
+  // 0x3000 - 0x303f CJK Symbols and Punctuation
+  // 0x3200 - 0x32ff Enclosed CJK Letters and Months
+  // 0x3400 - 0x4dbf CJK Unified Ideographs Extension A
+  // 0x4e00 - 0x62ff CJK Unified Ideographs
+  // 0x6300 - 0x77ff CJK Unified Ideographs
+  // 0x7800 - 0x8cff CJK Unified Ideographs
+  // 0x8d00 - 0x9fff CJK Unified Ideographs
+  // 0x20000 - 0x215ff CJK Unified Ideographs Extension B
+  // 0x21600 - 0x230ff CJK Unified Ideographs Extension B
+  // 0x23100 - 0x245ff CJK Unified Ideographs Extension B
+  // 0x24600 - 0x260ff CJK Unified Ideographs Extension B
+  // 0x26100 - 0x275ff CJK Unified Ideographs Extension B
+  // 0x27600 - 0x290ff CJK Unified Ideographs Extension B
+  // 0x29100 - 0x2a6df CJK Unified Ideographs Extension B
+  // 2a700-2b73f. CJK Unified Ideographs Extension C
+  // 2b740-2b81f. CJK Unified Ideographs Extension D
+
+  // Hangul script
+  // 0x1100 - 0x11ff Hangul jamo
+  // 0x3130 - 0x318f Hangul Compatibility Jamo
+  // 0xa960 - 0xa97f Hangul Jamo Extended-A
+  // 0xac00 - 0xd7af Hangul Syllables
+  // 0xd7b0 - 0xd7ff Hangul Jamo Extended-B
+
+  // Khmer script
+  // 0x1780 - 0x17ff Khmer
+  // 0x19e0 - 0x19ff Khmer Symbols
+
+  // Lao script
+  // 0x0e80 - 0x0eff Lao
+
+  // Thai script
+  // 0x0e00 - 0x0e7f Thai
+
+  // Burmese script
+  // 0x1000 - 0x104f Myanmar
+
+
+  if( character <= 0x0cff )
+  {
+    if( character <= 0x09ff )
+    {
+      if( character <= 0x077f )
+      {
+        if( character <= 0x02ff )
+        {
+          return TextAbstraction::LATIN;
+        }
+        if( ( 0x0600 <= character ) && ( character <= 0x06ff ) )
+        {
+          return TextAbstraction::ARABIC;
+        }
+        if( ( 0x0750 <= character ) && ( character <= 0x077f ) )
+        {
+          return TextAbstraction::ARABIC;
+        }
+      }
+      else // > 0x077f
+      {
+        if( ( 0x08A0 <= character ) && ( character <= 0x08ff ) )
+        {
+          return TextAbstraction::ARABIC;
+        }
+        if( ( 0x0900 <= character ) && ( character <= 0x097f ) )
+        {
+          return TextAbstraction::DEVANAGARI;
+        }
+        if( ( 0x0980 <= character ) && ( character <= 0x09ff ) )
+        {
+          return TextAbstraction::BENGALI;
+        }
+      }
+    }
+    else // > 0x09ff
+    {
+      if( character <= 0x0b7f )
+      {
+        if( ( 0x0a00 <= character ) && ( character <= 0x0a7f ) )
+        {
+          return TextAbstraction::GURMUKHI;
+        }
+        if( ( 0x0a80 <= character ) && ( character <= 0x0aff ) )
+        {
+          return TextAbstraction::GUJARATI;
+        }
+        if( ( 0x0b00 <= character ) && ( character <= 0x0b7f ) )
+        {
+          return TextAbstraction::ORIYA;
+        }
+      }
+      else // > 0x0b7f
+      {
+        if( ( 0x0b80 <= character ) && ( character <= 0x0bff ) )
+        {
+          return TextAbstraction::TAMIL;
+        }
+        if( ( 0x0c00 <= character ) && ( character <= 0x0c7f ) )
+        {
+          return TextAbstraction::TELUGU;
+        }
+        if( ( 0x0c80 <= character ) && ( character <= 0x0cff ) )
+        {
+          return TextAbstraction::KANNADA;
+        }
+      }
+    }
+  }
+  else // > 0x0cff
+  {
+    if( character <= 0x2c7f )
+    {
+      if( character <= 0x1eff )
+      {
+        if( ( 0x0d00 <= character ) && ( character <= 0x0d7f ) )
+        {
+          return TextAbstraction::MALAYALAM;
+        }
+        if( ( 0x0d80 <= character ) && ( character <= 0x0dff ) )
+        {
+          return TextAbstraction::SINHALA;
+        }
+        if( ( 0x0e00 <= character ) && ( character <= 0x0e7f ) )
+        {
+          return TextAbstraction::THAI;
+        }
+        if( ( 0x0e80 <= character ) && ( character <= 0x0eff ) )
+        {
+          return TextAbstraction::LAO;
+        }
+        if( ( 0x1000 <= character ) && ( character <= 0x104f ) )
+        {
+          return TextAbstraction::BURMESE;
+        }
+        if( ( 0x1100 <= character ) && ( character <= 0x11ff ) )
+        {
+          return TextAbstraction::HANGUL;
+        }
+        if( ( 0x1780 <= character ) && ( character <= 0x17ff ) )
+        {
+          return TextAbstraction::KHMER;
+        }
+        if( ( 0x19e0 <= character ) && ( character <= 0x19ff ) )
+        {
+          return TextAbstraction::KHMER;
+        }
+        if( ( 0x1d00 <= character ) && ( character <= 0x1eff ) )
+        {
+          return TextAbstraction::LATIN;
+        }
+      }
+      else // > 0x1eff
+      {
+        if( ( 0x2070 <= character ) && ( character <= 0x209f ) )
+        {
+          return TextAbstraction::LATIN;
+        }
+        if( ( 0x2100 <= character ) && ( character <= 0x218f ) )
+        {
+          return TextAbstraction::LATIN;
+        }
+        if( ( 0x2c60 <= character ) && ( character <= 0x2c7f ) )
+        {
+          return TextAbstraction::LATIN;
+        }
+      }
+    }
+    else // > 0x2c7f
+    {
+      if( character <= 0xfdff )
+      {
+        if( ( 0x2e80 <= character ) && ( character <= 0x2eff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x3000 <= character ) && ( character <= 0x303f ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x3130 <= character ) && ( character <= 0x318f ) )
+        {
+          return TextAbstraction::HANGUL;
+        }
+        if( ( 0x3200 <= character ) && ( character <= 0x32ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x3400 <= character ) && ( character <= 0x4dbf ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x4e00 <= character ) && ( character <= 0x62ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x6300 <= character ) && ( character <= 0x77ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x7800 <= character ) && ( character <= 0x8cff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x8d00 <= character ) && ( character <= 0x9fff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0xa720 <= character ) && ( character <= 0xa7ff ) )
+        {
+          return TextAbstraction::LATIN;
+        }
+        if( ( 0xa960 <= character ) && ( character <= 0xa97f ) )
+        {
+          return TextAbstraction::HANGUL;
+        }
+        if( ( 0xab30 <= character ) && ( character <= 0xab6f ) )
+        {
+          return TextAbstraction::LATIN;
+        }
+        if( ( 0xac00 <= character ) && ( character <= 0xd7af ) )
+        {
+          return TextAbstraction::HANGUL;
+        }
+        if( ( 0xd7b0 <= character ) && ( character <= 0xd7ff ) )
+        {
+          return TextAbstraction::HANGUL;
+        }
+        if( ( 0xfb00 <= character ) && ( character <= 0xfb4f ) )
+        {
+          return TextAbstraction::LATIN;
+        }
+        if( ( 0xfb50 <= character ) && ( character <= 0xfdff ) )
+        {
+          return TextAbstraction::ARABIC;
+        }
+      }
+      else // > 0xfdff
+      {
+        if( ( 0xfe70 <= character ) && ( character <= 0xfeff ) )
+        {
+          return TextAbstraction::ARABIC;
+        }
+        if( ( 0xff00 <= character ) && ( character <= 0xffef ) )
+        {
+          return TextAbstraction::LATIN;
+        }
+        if( ( 0x1ee00 <= character ) && ( character <= 0x1eeff ) )
+        {
+          return TextAbstraction::ARABIC;
+        }
+        if( ( 0x20000 <= character ) && ( character <= 0x215ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x21600 <= character ) && ( character <= 0x230ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x23100 <= character ) && ( character <= 0x245ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x24600 <= character ) && ( character <= 0x260ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x26100 <= character ) && ( character <= 0x275ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x27600 <= character ) && ( character <= 0x290ff ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x29100 <= character ) && ( character <= 0x2a6df ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x2a700 <= character ) && ( character <= 0x2b73f ) )
+        {
+          return TextAbstraction::CJK;
+        }
+        if( ( 0x2b740 <= character ) && ( character <= 0x2b81f ) )
+        {
+          return TextAbstraction::CJK;
+        }
+      }
+    }
+  }
+
   return TextAbstraction::UNKNOWN;
 }
 
   return TextAbstraction::UNKNOWN;
 }