Merge "Reduce Popup layers, parent to same actor as other decorations" into new_text
authorPaul Wisbey <p.wisbey@samsung.com>
Thu, 12 Mar 2015 16:37:05 +0000 (09:37 -0700)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Thu, 12 Mar 2015 16:37:05 +0000 (09:37 -0700)
20 files changed:
dali-toolkit/internal/text/bidirectional-line-info-run.h
dali-toolkit/internal/text/bidirectional-support.cpp
dali-toolkit/internal/text/bidirectional-support.h
dali-toolkit/internal/text/character-set-conversion.h
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/layouts/layout-parameters.h
dali-toolkit/internal/text/logical-model.cpp
dali-toolkit/internal/text/logical-model.h
dali-toolkit/internal/text/multi-language-support-impl.h
dali-toolkit/internal/text/multi-language-support.h
dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp
dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.cpp
dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h
dali-toolkit/internal/text/segmentation.h
dali-toolkit/internal/text/shaper.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/visual-model.cpp
dali-toolkit/internal/text/visual-model.h

index 90c8514..9aeea2a 100644 (file)
@@ -37,7 +37,6 @@ struct BidirectionalLineInfoRun
 {
   CharacterRun    characterRun;       ///< The initial character index within the whole text and the number of characters of the run.
   CharacterIndex* visualToLogicalMap; ///< Pointer to the visual to logical map table.
-  CharacterIndex* logicalToVisualMap; ///< Pointer to the logical to visual map table.
 };
 
 } // namespace Text
index 5cf1ffb..14fb1a7 100644 (file)
@@ -18,6 +18,9 @@
 // FILE HEADER
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 
+// EXTERNAL INCLUDES
+#include <dali/public-api/text-abstraction/bidirectional-support.h>
+
 namespace Dali
 {
 
@@ -27,10 +30,135 @@ namespace Toolkit
 namespace Text
 {
 
+namespace
+{
+
+/**
+ * @brief Get the lines of a paragraph.
+ *
+ * @param[in] paragraphInfo The paragraph.
+ * @param[in] lines The lines.
+ * @param[in] lineIndex Index pointing the first line to be checked.
+ * @param[out] firstLine Index to the first line of the paragraph.
+ * @param[out] numberOfLines The number of lines.
+ */
+void GetLines( const BidirectionalParagraphInfoRun& paragraphInfo,
+               const Vector<LineRun>& lines,
+               unsigned int lineIndex,
+               unsigned int& firstLine,
+               unsigned int& numberOfLines )
+{
+  firstLine = lineIndex;
+  numberOfLines = 0u;
+
+  const CharacterIndex lastCharacterIndex = paragraphInfo.characterRun.characterIndex + paragraphInfo.characterRun.numberOfCharacters;
+  bool firstLineFound = false;
+
+  for( Vector<LineRun>::ConstIterator it = lines.Begin() + lineIndex,
+         endIt = lines.End();
+       it != endIt;
+       ++it )
+  {
+    const LineRun& line = *it;
+
+    if( ( line.characterRun.characterIndex + line.characterRun.numberOfCharacters > paragraphInfo.characterRun.characterIndex ) &&
+        ( lastCharacterIndex > line.characterRun.characterIndex ) )
+    {
+      firstLineFound = true;
+      ++numberOfLines;
+    }
+    else if( lastCharacterIndex <= line.characterRun.characterIndex )
+    {
+      // nothing else to do.
+      break;
+    }
+
+    if( !firstLineFound )
+    {
+      ++firstLine;
+    }
+  }
+}
+
+} // namespace
+
 void SetBidirectionalInfo( const Vector<Character>& text,
+                           const Vector<ScriptRun>& scripts,
                            const Vector<LineBreakInfo>& lineBreakInfo,
                            Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo )
 {
+  // Traverse the script runs. If there is one with a right to left script, create the bidirectional info for the paragraph containing that script is needed.
+  // From the bidirectional point of view, a paragraph is the piece of text between two LINE_MUST_BREAK.
+
+  // Index pointing the first character of the current paragraph.
+  CharacterIndex paragraphCharacterIndex = 0u;
+
+  // Pointer to the text buffer.
+  const Character* textBuffer = text.Begin();
+
+  // Pointer to the line break info buffer.
+  const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
+
+  // The number of characters.
+  const Length numberOfCharacters = text.Count();
+
+  // Handle to the bidirectional info module in text-abstraction.
+  TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
+
+  for( Vector<ScriptRun>::ConstIterator it = scripts.Begin(),
+         endIt = scripts.End();
+       it != endIt;
+       ++it )
+  {
+    const ScriptRun& scriptRun = *it;
+    const CharacterIndex lastScriptRunIndex = scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters;
+
+    if( TextAbstraction::IsRightToLeftScript( scriptRun.script ) && // The script is right to left.
+        ( lastScriptRunIndex > paragraphCharacterIndex ) )          // It isn't part of a previous paragraph.
+    {
+      // Find the paragraphs which contains this script run.
+      // Consider:
+      //  1) Different paragraphs may contain this script run.
+      //  ------||------------------- rtl sr ------------------------||-------------------
+      //  --||----- p -----||------------------ p -------------||-------- p ------||------
+      //
+      //  2) The paragraph which contains this script run may contain other right to left script runs.
+      //  -----||--- rtl sr ---||---- ltr sr ----||---------- rtl sr -----------||--------
+      //  -----||---------------------------------- p -----------------------------------|
+
+      while( lastScriptRunIndex > paragraphCharacterIndex )
+      {
+        // There is a paragraph which contains the current script.
+
+        Length index = paragraphCharacterIndex;
+        while( ( index < numberOfCharacters ) && ( paragraphCharacterIndex < lastScriptRunIndex ) )
+        {
+          if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ) )
+          {
+            if( index >= scriptRun.characterRun.characterIndex )
+            {
+              // The Bidirectional run must have the same number of characters than the paragraph.
+              BidirectionalParagraphInfoRun bidirectionalRun;
+              bidirectionalRun.characterRun.characterIndex = paragraphCharacterIndex;
+              bidirectionalRun.characterRun.numberOfCharacters = ( index - paragraphCharacterIndex ) + 1u; // The must break character is part of the paragrah.
+
+              // Create the bidirectional info for the whole paragraph and store the index to the table with this info in the run.
+              bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo( textBuffer + bidirectionalRun.characterRun.characterIndex,
+                                                                                         bidirectionalRun.characterRun.numberOfCharacters );
+
+              bidirectionalInfo.PushBack( bidirectionalRun );
+            }
+
+            // Update the character index of the next paragraph.
+            paragraphCharacterIndex = index + 1u;
+          }
+          ++index;
+        }
+
+        // The last character is always a must-break, so there is no need to check if there is characters left.
+      }
+    }
+  }
 }
 
 void ReplaceBidirectionalInfo( LogicalModel& model,
@@ -41,9 +169,63 @@ void ReplaceBidirectionalInfo( LogicalModel& model,
 }
 
 void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
-                   const Vector<CharacterRun>& lineRuns,
+                   const Vector<LineRun>& lineRuns,
                    Vector<BidirectionalLineInfoRun>& lineInfoRuns )
 {
+  // Handle to the bidirectional info module in text-abstraction.
+  TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
+
+  // Keep an index to the first line to be checked if it's contained inside the paragraph.
+  // Avoids check the lines from the beginning for each paragraph.
+  unsigned int lineIndex = 0u;
+
+  for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = bidirectionalInfo.Begin(),
+         endIt = bidirectionalInfo.End();
+       it != endIt;
+       ++it )
+  {
+    const BidirectionalParagraphInfoRun& paragraphInfo = *it;
+
+    // Get the lines for this paragraph.
+    unsigned int firstLine = 0u;
+    unsigned int numberOfLines = 0u;
+
+    // Get an index to the first line and the number of lines of the current paragraph.
+    GetLines( paragraphInfo,
+              lineRuns,
+              lineIndex,
+              firstLine,
+              numberOfLines );
+
+    lineIndex = firstLine + numberOfLines;
+
+    // Traverse the lines and reorder them
+    for( Vector<LineRun>::ConstIterator lineIt = lineRuns.Begin() + firstLine,
+           endLineIt = lineRuns.Begin() + firstLine + numberOfLines;
+           lineIt != endLineIt;
+         ++lineIt )
+    {
+      const LineRun& line = *lineIt;
+
+      // Creates a bidirectional info for the line run.
+      BidirectionalLineInfoRun lineInfoRun;
+      lineInfoRun.characterRun.characterIndex = line.characterRun.characterIndex;
+      lineInfoRun.characterRun.numberOfCharacters = line.characterRun.numberOfCharacters;
+
+      // Allocate space for the conversion maps.
+      // The memory is freed after the visual to logical to visual conversion tables are built in the logical model.
+      lineInfoRun.visualToLogicalMap = reinterpret_cast<CharacterIndex*>( malloc( line.characterRun.numberOfCharacters * sizeof( CharacterIndex ) ) );
+
+      // Reorders the line.
+      bidirectionalSupport.Reorder( paragraphInfo.bidirectionalInfoIndex,
+                                    line.characterRun.characterIndex,
+                                    line.characterRun.numberOfCharacters,
+                                    lineInfoRun.visualToLogicalMap );
+
+      // Push the run into the vector.
+      lineInfoRuns.PushBack( lineInfoRun );
+    }
+  }
 }
 
 void ReorderLines( LogicalModel& logicalModel,
index a54bc19..4bdd5e3 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
+// EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
 #include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
+#include <dali-toolkit/internal/text/line-run.h>
+#include <dali-toolkit/internal/text/script-run.h>
 
 namespace Dali
 {
@@ -39,10 +43,12 @@ class VisualModel;
  * Sets the bidirectional info into the logical model.
  *
  * @param[in] text Vector of UTF-32 characters.
+ * @param[in] scripts Vector containing the script runs for the whole text.
  * @param[in] lineBreakInfo The line break info.
  * @param[out] bidirectionalInfo Vector with the bidirectional infor for each paragraph.
  */
 void SetBidirectionalInfo( const Vector<Character>& text,
+                           const Vector<ScriptRun>& scripts,
                            const Vector<LineBreakInfo>& lineBreakInfo,
                            Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo );
 
@@ -79,7 +85,7 @@ void ReplaceBidirectionalInfo( LogicalModel& model,
  * @param[out] lineInfoRuns line runs with the visual to logical and logical to visual conversion maps.
  */
 void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
-                   const Vector<CharacterRun>& lineRuns,
+                   const Vector<LineRun>& lineRuns,
                    Vector<BidirectionalLineInfoRun>& lineInfoRuns );
 
 /**
index 1e49357..2fca983 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
-
 // EXTERNAL INCLUDES
 #include <stdint.h>
 
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
 namespace Dali
 {
 
index 9544a66..86ddbb4 100644 (file)
@@ -24,6 +24,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
 
 namespace Dali
 {
@@ -293,7 +294,43 @@ struct LayoutEngine::Impl
     return update;
   }
 
-  // TODO - Rewrite this to handle bidi
+  void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
+                                 Vector<Vector2>& glyphPositions )
+  {
+    for( Length lineIndex = 0u; lineIndex < layoutParameters.numberOfBidirectionalInfoRuns; ++lineIndex )
+    {
+      const BidirectionalLineInfoRun& bidiLine = *( layoutParameters.lineBidirectionalInfoRunsBuffer +lineIndex  );
+
+      float penX = 0.f;
+
+      Vector2* glyphPositionsBuffer = glyphPositions.Begin();
+
+      for( CharacterIndex characterLogicalIndex = 0u;
+           characterLogicalIndex < bidiLine.characterRun.numberOfCharacters;
+           ++characterLogicalIndex )
+      {
+        // Convert the character in the logical order into the character in the visual order.
+        const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *( bidiLine.visualToLogicalMap + characterLogicalIndex );
+
+        // Get the number of glyphs of the character.
+        const Length numberOfGlyphs = *( layoutParameters.glyphsPerCharacterBuffer + characterVisualIndex );
+
+        for( GlyphIndex index = 0u; index < numberOfGlyphs; ++index )
+        {
+          // Convert the character in the visual order into the glyph in the visual order.
+          GlyphIndex glyphIndex = 1u + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex + index ) - numberOfGlyphs;
+
+          const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + glyphIndex );
+          Vector2& position = *( glyphPositionsBuffer + glyphIndex );
+
+          position.x = penX + glyph.xBearing;
+
+          penX += glyph.advance;
+        }
+      }
+    }
+  }
+
   bool SingleLineLayout( const LayoutParameters& layoutParameters,
                          Vector<Vector2>& glyphPositions,
                          Vector<LineRun>& lines,
@@ -339,7 +376,6 @@ struct LayoutEngine::Impl
     return true;
   }
 
-  // TODO - Rewrite this to handle bidi
   bool MultiLineLayout( const LayoutParameters& layoutParameters,
                         Vector<Vector2>& glyphPositions,
                         Vector<LineRun>& lines,
@@ -443,6 +479,13 @@ bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters,
                             actualSize );
 }
 
+void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
+                                             Vector<Vector2>& glyphPositions )
+{
+  mImpl->ReLayoutRightToLeftLines( layoutParameters,
+                                   glyphPositions );
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index 59977c2..cdcd156 100644 (file)
  *
  */
 
-// INTERNAL INCLUDE
-#include <dali-toolkit/internal/text/line-run.h>
-
 // EXTERNAL INCLUDE
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/math/vector2.h>
 
+// INTERNAL INCLUDE
+#include <dali-toolkit/internal/text/line-run.h>
+
 namespace Dali
 {
 
@@ -90,6 +90,17 @@ public:
                    Vector<LineRun>& lines,
                    Size& actualSize );
 
+  /**
+   * Re-lays out those lines with right to left characters.
+   *
+   * It doesn't change the phisical position of the glyphs in the model but sets their new position.
+   *
+   * @param[in] layoutParameters The parameters needed to layout the text.
+   * @param[in,out] glyphPositions The positions of all the glyphs.
+   */
+  void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
+                                 Vector<Vector2>& glyphPositions );
+
 private:
 
   // Undefined
index 9fa4dde..808e1ae 100644 (file)
@@ -33,6 +33,8 @@ namespace Toolkit
 namespace Text
 {
 
+struct BidirectionalLineInfoRun;
+
 /**
  * @brief Struct used to pass parameters.
  */
@@ -62,7 +64,11 @@ struct LayoutParameters
     totalNumberOfGlyphs( totalNumberOfGlyphs ),
     glyphsBuffer( glyphsBuffer ),
     glyphsToCharactersBuffer( glyphsToCharactersBuffer ),
-    charactersPerGlyphBuffer( charactersPerGlyphBuffer )
+    charactersPerGlyphBuffer( charactersPerGlyphBuffer ),
+    charactersToGlyphsBuffer( NULL ),
+    glyphsPerCharacterBuffer( NULL ),
+    lineBidirectionalInfoRunsBuffer( NULL ),
+    numberOfBidirectionalInfoRuns( 0u )
   {}
 
   Vector2                     boundingBox;
@@ -72,6 +78,10 @@ struct LayoutParameters
   const GlyphInfo* const      glyphsBuffer;
   const CharacterIndex* const glyphsToCharactersBuffer;
   const Length* const         charactersPerGlyphBuffer;
+  GlyphIndex*                 charactersToGlyphsBuffer;        ///< The character to glyph conversion table.
+  Length*                     glyphsPerCharacterBuffer;        ///< The number of glyphs per character.
+  BidirectionalLineInfoRun*   lineBidirectionalInfoRunsBuffer; ///< Bidirectional conversion tables per line.
+  Length                      numberOfBidirectionalInfoRuns;   ///< The number of lines with bidirectional info.
 };
 
 } // namespace Text
index 01b03fd..b91b285 100644 (file)
 // CLASS HEADER
 #include <dali-toolkit/internal/text/logical-model.h>
 
+// EXTERNAL INCLUDES
+#include <memory.h>
+
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
 #include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
 #include <dali-toolkit/internal/text/font-run.h>
 #include <dali-toolkit/internal/text/script-run.h>
 
-// EXTERNAL INCLUDES
-#include <memory.h>
-
 namespace Dali
 {
 
@@ -35,14 +35,35 @@ namespace Toolkit
 
 namespace Text
 {
+/**
+ * @brief caches some temporary values of the GetNumberOfScriptRuns( characterIndex, numberOfCharacters )
+ * operation and the GetNumberOfFontRuns( characterIndex, numberOfCharacters ) as they are going to be
+ * used in the GetScriptRuns() and the GetFontRuns() calls.
+ */
+struct GetRunCache
+{
+  CharacterIndex characterIndex;     ///< The character index.
+  Length         numberOfCharacters; ///< The number of characters.
+  Length         firstRun;           ///< Index to the first run.
+  Length         numberOfRuns;       ///< The number of runs.
+};
 
 struct LogicalModel::Impl
 {
-  Vector<Character>     mText;
-  Vector<ScriptRun>     mScriptRuns;
-  Vector<FontRun>       mFontRuns;
-  Vector<LineBreakInfo> mLineBreakInfo;
-  Vector<WordBreakInfo> mWordBreakInfo;
+  Vector<Character>                     mText;
+  Vector<ScriptRun>                     mScriptRuns;
+  Vector<FontRun>                       mFontRuns;
+  Vector<LineBreakInfo>                 mLineBreakInfo;
+  Vector<WordBreakInfo>                 mWordBreakInfo;
+  Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
+
+  Vector<BidirectionalLineInfoRun>      mBidirectionalLineInfo;
+  Vector<CharacterIndex>                mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table.
+  Vector<CharacterIndex>                mVisualToLogicalMap; ///< Bidirectional visual to logical conversion table.
+
+  GetRunCache                           mGetScriptCache;             ///< Caches the GetNumberOfScriptRuns( characterIndex, numberOfCharacters ) operation.
+  GetRunCache                           mGetFontCache;               ///< Caches the GetNumberOfFontRuns( characterIndex, numberOfCharacters ) operation.
+  GetRunCache                           mGetBidirectionalCache;      ///< Caches the GetNumberOfBidirectionalInfoRuns( characterIndex, numberOfCharacters ) operation.
 };
 
 LogicalModelPtr LogicalModel::New()
@@ -71,8 +92,8 @@ Length LogicalModel::GetNumberOfCharacters() const
   return mImpl->mText.Count();
 }
 
-void LogicalModel::GetText( CharacterIndex characterIndex,
-                            Character* text,
+void LogicalModel::GetText( Character* text,
+                            CharacterIndex characterIndex,
                             Length numberOfCharacters ) const
 {
   Vector<Character>& modelText = mImpl->mText;
@@ -98,65 +119,82 @@ void LogicalModel::SetScripts( const ScriptRun* const scripts,
     scriptRuns.Resize( numberOfRuns );
     memcpy( scriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) );
   }
+
+  mImpl->mGetScriptCache.characterIndex = 0u;
+  mImpl->mGetScriptCache.numberOfCharacters = 0u;
+  mImpl->mGetScriptCache.firstRun = 0u;
+  mImpl->mGetScriptCache.numberOfRuns = 0u;
 }
 
 Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
                                             Length numberOfCharacters ) const
 {
-  if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
+  GetRunCache& scriptCache = mImpl->mGetScriptCache;
+
+  // Set the character index and the number of characters into the cache.
+  scriptCache.characterIndex = characterIndex;
+  scriptCache.numberOfCharacters = numberOfCharacters;
+
+  if( ( 0u == characterIndex ) &&
+      ( mImpl->mText.Count() == numberOfCharacters ) )
   {
-    return mImpl->mScriptRuns.Count();
+    scriptCache.firstRun = 0u;
+    scriptCache.numberOfRuns = mImpl->mScriptRuns.Count();
+    return scriptCache.numberOfRuns;
   }
 
-  const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
-  Length numberOfScriptRuns = 0u;
-  bool firstIndexFound = false;
+  // Initialize the number of scripts and the index to the first script.
+  scriptCache.firstRun = 0u;
+  scriptCache.numberOfRuns = 0;
+  bool firstScriptFound = false;
 
-  for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
+  const Vector<ScriptRun>& modelScripts = mImpl->mScriptRuns;
+  const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters;
+
+  // Traverse the scripts and count those scripts within the range of characters.
+  for( Vector<ScriptRun>::ConstIterator it = modelScripts.Begin(),
+         endIt = modelScripts.End();
+       it != endIt;
+       ++it )
   {
-    const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
+    const ScriptRun& script = *it;
 
-    if( !firstIndexFound &&
-        ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
+    if( ( script.characterRun.characterIndex + script.characterRun.numberOfCharacters > characterIndex ) &&
+        ( lastCharacterIndex > script.characterRun.characterIndex ) )
     {
-      // The character index is within this script run.
-      // Starts the counter of script runs.
-      firstIndexFound = true;
+      firstScriptFound = true;
+      ++scriptCache.numberOfRuns;
+    }
+    else if( lastCharacterIndex <= script.characterRun.characterIndex )
+    {
+      // nothing else to do.
+      break;
     }
 
-    if( firstIndexFound )
+    if( !firstScriptFound )
     {
-      ++numberOfScriptRuns;
-      if( scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters > charcterEndIndex )
-      {
-        // This script run exceeds the given range. The number of scripts can be returned.
-        return numberOfScriptRuns;
-      }
+      ++scriptCache.firstRun;
     }
   }
 
-  return numberOfScriptRuns;
+  return scriptCache.numberOfRuns;
 }
 
 void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
                                   CharacterIndex characterIndex,
                                   Length numberOfCharacters ) const
 {
-  // A better implementation can cache the first script run and the number of then when the GetNumberOfScriptRuns() is called.
-
-  Length numberOfScriptRuns = GetNumberOfScriptRuns( characterIndex,
-                                                     numberOfCharacters );
+  const Vector<ScriptRun>& modelScripts = mImpl->mScriptRuns;
+  GetRunCache& scriptCache = mImpl->mGetScriptCache;
 
-  for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
+  if( ( characterIndex != scriptCache.characterIndex ) ||
+      ( numberOfCharacters != scriptCache.numberOfCharacters ) )
   {
-    const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
-
-    if( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters )
-    {
-      memcpy( scriptRuns, scriptRun, sizeof( ScriptRun ) * numberOfScriptRuns );
-      return;
-    }
+    GetNumberOfScriptRuns( characterIndex,
+                           numberOfCharacters );
   }
+
+  memcpy( scriptRuns, modelScripts.Begin() + scriptCache.firstRun, scriptCache.numberOfRuns * sizeof( ScriptRun ) );
 }
 
 Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
@@ -191,65 +229,82 @@ void LogicalModel::SetFonts( const FontRun* const fonts,
     fontRuns.Resize( numberOfRuns );
     memcpy( fontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) );
   }
+
+  mImpl->mGetFontCache.characterIndex = 0u;
+  mImpl->mGetFontCache.numberOfCharacters = 0u;
+  mImpl->mGetFontCache.firstRun = 0u;
+  mImpl->mGetFontCache.numberOfRuns = 0u;
 }
 
 Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
                                           Length numberOfCharacters ) const
 {
-  if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
+  GetRunCache& fontCache = mImpl->mGetFontCache;
+
+  // Set the character index and the number of characters into the cache.
+  fontCache.characterIndex = characterIndex;
+  fontCache.numberOfCharacters = numberOfCharacters;
+
+  if( ( 0u == characterIndex ) &&
+      ( mImpl->mText.Count() == numberOfCharacters ) )
   {
-    return mImpl->mFontRuns.Count();
+    fontCache.firstRun = 0u;
+    fontCache.numberOfRuns = mImpl->mFontRuns.Count();
+    return fontCache.numberOfRuns;
   }
 
-  const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
-  Length numberOfFontRuns = 0u;
-  bool firstIndexFound = false;
+  // Initialize the number of fonts and the index to the first font.
+  fontCache.firstRun = 0u;
+  fontCache.numberOfRuns = 0;
+  bool firstFontFound = false;
 
-  for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
+  const Vector<FontRun>& modelFonts = mImpl->mFontRuns;
+  const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters;
+
+  // Traverse the fonts and count those fonts within the range of characters.
+  for( Vector<FontRun>::ConstIterator it = modelFonts.Begin(),
+         endIt = modelFonts.End();
+       it != endIt;
+       ++it )
   {
-    const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
+    const FontRun& font = *it;
 
-    if( !firstIndexFound &&
-        ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
+    if( ( font.characterRun.characterIndex + font.characterRun.numberOfCharacters > characterIndex ) &&
+        ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) )
+    {
+      firstFontFound = true;
+      ++fontCache.numberOfRuns;
+    }
+    else if( lastCharacterIndex <= font.characterRun.characterIndex )
     {
-      // The character index is within this font run.
-      // Starts the counter of font runs.
-      firstIndexFound = true;
+      // nothing else to do.
+      break;
     }
 
-    if( firstIndexFound )
+    if( !firstFontFound )
     {
-      ++numberOfFontRuns;
-      if( fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters > charcterEndIndex )
-      {
-        // This font run exceeds the given range. The number of fonts can be returned.
-        return numberOfFontRuns;
-      }
+      ++fontCache.firstRun;
     }
   }
 
-  return numberOfFontRuns;
+  return fontCache.numberOfRuns;
 }
 
 void LogicalModel::GetFontRuns( FontRun* fontRuns,
                                 CharacterIndex characterIndex,
                                 Length numberOfCharacters ) const
 {
-  // A better implementation can cache the first font run and the number of then when the GetNumberOfFontRuns() is called.
-
-  Length numberOfFontRuns = GetNumberOfFontRuns( characterIndex,
-                                                 numberOfCharacters );
+  const Vector<FontRun>& modelFonts = mImpl->mFontRuns;
+  GetRunCache& fontCache = mImpl->mGetFontCache;
 
-  for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
+  if( ( characterIndex != fontCache.characterIndex ) ||
+      ( numberOfCharacters != fontCache.numberOfCharacters ) )
   {
-    const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
-
-    if( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters )
-    {
-      memcpy( fontRuns, fontRun, sizeof( FontRun ) * numberOfFontRuns );
-      return;
-    }
+    GetNumberOfFontRuns( characterIndex,
+                         numberOfCharacters );
   }
+
+  memcpy( fontRuns, modelFonts.Begin() + fontCache.firstRun, fontCache.numberOfRuns * sizeof( FontRun ) );
 }
 
 FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const
@@ -327,12 +382,87 @@ WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) co
 void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
                                          Length numberOfRuns )
 {
+  Vector<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
+
+  if( 0u == numberOfRuns )
+  {
+    modelBidirectionalParagraphInfo.Clear();
+  }
+  else
+  {
+    modelBidirectionalParagraphInfo.Resize( numberOfRuns );
+    memcpy( modelBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) );
+  }
+
+  mImpl->mGetBidirectionalCache.characterIndex = 0u;
+  mImpl->mGetBidirectionalCache.numberOfCharacters = 0u;
+  mImpl->mGetBidirectionalCache.firstRun = 0u;
+  mImpl->mGetBidirectionalCache.numberOfRuns = 0u;
 }
 
 Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
                                                        Length numberOfCharacters ) const
 {
-  return 0u;
+  GetRunCache& bidiCache = mImpl->mGetBidirectionalCache;
+
+  // Set the character index and the number of characters into the cache.
+  bidiCache.characterIndex = characterIndex;
+  bidiCache.numberOfCharacters = numberOfCharacters;
+
+  if( ( 0u == characterIndex ) &&
+      ( mImpl->mText.Count() == numberOfCharacters ) )
+  {
+    bidiCache.firstRun = 0u;
+    bidiCache.numberOfRuns = mImpl->mBidirectionalParagraphInfo.Count();
+    return bidiCache.numberOfRuns;
+  }
+
+  // Initialize the number of bidi paragraphs and the index to the first paragraph.
+  bidiCache.firstRun = 0u;
+  bidiCache.numberOfRuns = 0;
+  bool firstParagraphFound = false;
+
+  const Vector<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
+
+  // Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters.
+  for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = modelBidirectionalParagraphInfo.Begin(),
+         endIt = modelBidirectionalParagraphInfo.End();
+       it != endIt;
+       ++it )
+  {
+    const BidirectionalParagraphInfoRun& bidi = *it;
+
+    if( ( bidi.characterRun.characterIndex + bidi.characterRun.numberOfCharacters > characterIndex ) &&
+        ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) )
+    {
+      firstParagraphFound = true;
+      ++bidiCache.numberOfRuns;
+    }
+
+    if( !firstParagraphFound )
+    {
+      ++bidiCache.firstRun;
+    }
+  }
+
+  return bidiCache.numberOfRuns;
+}
+
+void LogicalModel::GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo,
+                                         CharacterIndex characterIndex,
+                                         Length numberOfCharacters ) const
+{
+  const Vector<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
+  GetRunCache& bidiCache = mImpl->mGetBidirectionalCache;
+
+  if( ( characterIndex != bidiCache.characterIndex ) ||
+      ( numberOfCharacters != bidiCache.numberOfCharacters ) )
+  {
+    GetNumberOfBidirectionalInfoRuns( characterIndex,
+                                      numberOfCharacters );
+  }
+
+  memcpy( bidirectionalInfo, modelBidirectionalParagraphInfo.Begin() + bidiCache.firstRun, bidiCache.numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) );
 }
 
 void LogicalModel::GetCharacterDirections( CharacterDirection* directions,
@@ -349,28 +479,96 @@ CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex character
 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
                                           Length numberOfRuns )
 {
+  Vector<CharacterIndex>& modelVisualToLogicalMap = mImpl->mVisualToLogicalMap;
+  Vector<CharacterIndex>& modelLogicalToVisualMap = mImpl->mLogicalToVisualMap;
+
+  if( 0u == numberOfRuns )
+  {
+    modelVisualToLogicalMap.Clear();
+    modelLogicalToVisualMap.Clear();
+  }
+  else
+  {
+    const Length numberOfCharacters = mImpl->mText.Count();
+    modelVisualToLogicalMap.Resize( numberOfCharacters );
+    modelLogicalToVisualMap.Resize( numberOfCharacters );
+
+    CharacterIndex* modelVisualToLogicalMapBuffer = modelVisualToLogicalMap.Begin();
+    CharacterIndex* modelLogicalToVisualMapBuffer = modelLogicalToVisualMap.Begin();
+
+    CharacterIndex lastIndex = 0u;
+    for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex )
+    {
+      const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex );
+
+      if( lastIndex < bidiLineInfo.characterRun.characterIndex )
+      {
+        // Fill with the identity.
+        for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex )
+        {
+          *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
+        }
+      }
+
+      // Fill the conversion table of the run.
+      for( CharacterIndex index = 0u;
+           index < bidiLineInfo.characterRun.numberOfCharacters;
+           ++index, ++lastIndex )
+      {
+        *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index );
+      }
+    }
+
+    // Complete with the identity if there are some left to right characters after the last right to left.
+    for( ; lastIndex < numberOfCharacters; ++lastIndex )
+    {
+      *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
+    }
+
+    // Sets the logical to visual conversion map.
+    for( CharacterIndex index = 0u; index < numberOfCharacters; ++index )
+    {
+      *( modelLogicalToVisualMapBuffer + *( modelVisualToLogicalMapBuffer + index ) ) = index;
+    }
+  }
 }
 
 CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const
 {
-  return 0u;
+  if( 0u == mImpl->mLogicalToVisualMap.Count() )
+  {
+    // If there is no logical to visual info is because the whole text is left to right.
+    // Return the identity.
+    return logicalCharacterIndex;
+  }
+
+  return *( mImpl->mLogicalToVisualMap.Begin() + logicalCharacterIndex );
 }
 
 CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
 {
-  return 0u;
+  if( 0u == mImpl->mVisualToLogicalMap.Count() )
+  {
+    // If there is no visual to logical info is because the whole text is left to right.
+    // Return the identity.
+    return visualCharacterIndex;
+  }
+
+  return *( mImpl->mVisualToLogicalMap.Begin() + visualCharacterIndex );
 }
 
 void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap,
                                           CharacterIndex characterIndex,
                                           Length numberOfCharacters ) const
 {
+  memcpy( logicalToVisualMap, mImpl->mLogicalToVisualMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) );
 }
 
 void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap,
                                           CharacterIndex characterIndex,
                                           Length numberOfCharacters ) const
 {
+  memcpy( visualToLogicalMap, mImpl->mVisualToLogicalMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) );
 }
 
 LogicalModel::~LogicalModel()
index 5d14098..8e3f5df 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
+// EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/public-api/object/ref-object.h>
+
+// INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/text-definitions.h>
 
 namespace Dali
@@ -81,12 +83,12 @@ public:
    * @brief Retrieves characters from the text in the given buffer.
    *
    * @pre The size of the @p text buffer needs to be big enough to copy the @p numberOfCharacters.
-   * @param[in] characterIndex The index to the first character to copy.
    * @param[out] text Pointer to a buffer where the text is copied.
+   * @param[in] characterIndex The index to the first character to copy.
    * @param[in] numberOfCharacters The number of characters to be copied.
    */
-  void GetText( CharacterIndex characterIndex,
-                Character* text,
+  void GetText( Character* text,
+                CharacterIndex characterIndex,
                 Length numberOfCharacters ) const;
 
   /**
@@ -332,6 +334,21 @@ public:
                                            Length numberOfCharacters ) const;
 
   /**
+   * Retrieves the bidirectional paragraph info runs for the given range of characters.
+   *
+   * The @p bidirectionalInfo buffer needs to be big enough to copy the number of bidirectional
+   * paragraph info runs.
+   * Call GetNumberOfBidirectionalInfoRuns() to retrieve the number of bidirectional runs.
+   *
+   * @param[out] bidirectionalInfo Pointer to a buffer where the bidirectional info runs are copied.
+   * @param[in] characterIndex Index to the first character.
+   * @param[in] numberOfCharacters The number of characters.
+   */
+  void GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo,
+                             CharacterIndex characterIndex,
+                             Length numberOfCharacters ) const;
+
+  /**
    * Retrieves the direction of the characters.
    *
    * It sets @c true for right to left characters and @c false for left to right.
index bcf0a6b..0f7e177 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/multi-language-support.h>
-
 // EXTERNAL INCLUDES
 #include <dali/public-api/object/base-object.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/multi-language-support.h>
+
 namespace Dali
 {
 
index b0873d9..b70f672 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
+// EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/object/base-handle.h>
+
+// INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/font-run.h>
 #include <dali-toolkit/internal/text/script-run.h>
 
index 31ab53f..dc6ec3e 100644 (file)
@@ -369,7 +369,7 @@ RenderableActor BasicRenderer::Render( Text::ViewInterface& view )
       actorBGRA8888 = MeshActor::New( mImpl->CreateMesh( glyphs, positions, Pixel::BGRA8888, mImpl->mAtlasBGRA8888 ) );
       actorBGRA8888.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
 
-      ShaderEffect shader = BGRAShader::New();
+      ShaderEffect shader = BgraShader::New();
       actorBGRA8888.SetShaderEffect( shader );
     }
 
index 70e3c67..16293c6 100644 (file)
@@ -34,7 +34,7 @@ namespace Text
 /**
  * @brief A BGRA shader for rendering glyphs.
  */
-namespace BGRAShader
+namespace BgraShader
 {
 
 /**
index 27fb85d..949b1c9 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
+// EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/text-definitions.h>
 
 namespace Dali
index c1ccfb5..d423cc5 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
+// EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/font-run.h>
 #include <dali-toolkit/internal/text/script-run.h>
 
index c3bec4f..4395e1b 100644 (file)
 // CLASS HEADER
 #include <dali-toolkit/internal/text/text-controller.h>
 
+// EXTERNAL INCLUDES
+#include <limits>
+#include <vector>
+#include <dali/public-api/adaptor-framework/key.h>
+#include <dali/public-api/text-abstraction/font-client.h>
+
 // INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 #include <dali-toolkit/internal/text/text-view.h>
 #include <dali-toolkit/internal/text/visual-model.h>
 
-// EXTERNAL INCLUDES
-#include <limits>
-#include <vector>
-#include <dali/public-api/adaptor-framework/key.h>
-#include <dali/public-api/text-abstraction/font-client.h>
-
 using std::vector;
 
 namespace
@@ -434,6 +435,18 @@ void Controller::SetText( const std::string& text )
   // The natural size needs to be re-calculated.
   mImpl->mRecalculateNaturalSize = true;
 
+  // Reset buffers.
+  mImpl->mLogicalModel->SetText( NULL, 0u );
+  mImpl->mLogicalModel->SetScripts( NULL, 0u );
+  mImpl->mLogicalModel->SetFonts( NULL, 0u );
+  mImpl->mLogicalModel->SetLineBreakInfo( NULL, 0u );
+  mImpl->mLogicalModel->SetWordBreakInfo( NULL, 0u );
+  mImpl->mLogicalModel->SetBidirectionalInfo( NULL, 0u );
+  mImpl->mLogicalModel->SetVisualToLogicalMap( NULL, 0u );
+  mImpl->mVisualModel->SetGlyphs( NULL, NULL, NULL, 0u );
+  mImpl->mVisualModel->SetGlyphPositions( NULL, 0u );
+  mImpl->mVisualModel->SetLines( NULL, 0u );
+
   if( mImpl->mTextInput )
   {
     // Cancel previously queued events
@@ -687,6 +700,68 @@ bool Controller::DoRelayout( const Vector2& size,
     }
   }
 
+  Vector<BidirectionalParagraphInfoRun> bidirectionalInfo;
+  if( BIDI_INFO & operations )
+  {
+    // Some vectors with data needed to get the paragraph's bidirectional info may be void
+    // after the first time the text has been laid out.
+    // Fill the vectors again.
+
+    const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
+
+    if( 0u == utf32Characters.Count() )
+    {
+      utf32Characters.Resize( numberOfCharacters );
+
+      mImpl->mLogicalModel->GetText( utf32Characters.Begin(),
+                                     0u,
+                                     numberOfCharacters );
+    }
+
+    if( 0u == lineBreakInfo.Count() )
+    {
+      lineBreakInfo.Resize( numberOfCharacters );
+
+      mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
+                                              0u,
+                                              numberOfCharacters );
+    }
+
+    if( 0u == scripts.Count() )
+    {
+      scripts.Resize( mImpl->mLogicalModel->GetNumberOfScriptRuns( 0u,
+                                                                   numberOfCharacters ) );
+      mImpl->mLogicalModel->GetScriptRuns( scripts.Begin(),
+                                           0u,
+                                           numberOfCharacters );
+    }
+
+    // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's
+    // bidirectional info.
+
+    Length numberOfParagraphs = 0u;
+
+    const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
+    for( Length index = 0u; index < characterCount; ++index )
+    {
+      if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) )
+      {
+        ++numberOfParagraphs;
+      }
+    }
+
+    bidirectionalInfo.Reserve( numberOfParagraphs );
+
+    // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
+    SetBidirectionalInfo( utf32Characters,
+                          scripts,
+                          lineBreakInfo,
+                          bidirectionalInfo );
+
+    mImpl->mLogicalModel->SetBidirectionalInfo( bidirectionalInfo.Begin(),
+                                                bidirectionalInfo.Count() );
+  }
+
   Vector<GlyphInfo> glyphs;
   Vector<CharacterIndex> glyphsToCharactersMap;
   Vector<Length> charactersPerGlyph;
@@ -719,34 +794,48 @@ bool Controller::DoRelayout( const Vector2& size,
 
   if( LAYOUT & operations )
   {
+    // Some vectors with data needed to layout and reorder may be void
+    // after the first time the text has been laid out.
+    // Fill the vectors again.
+
     const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
+    numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
 
-    if( 0u == numberOfGlyphs )
+    if( 0u == lineBreakInfo.Count() )
     {
-      numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
-
       lineBreakInfo.Resize( numberOfCharacters );
-      wordBreakInfo.Resize( numberOfCharacters );
-      glyphs.Resize( numberOfGlyphs );
-      glyphsToCharactersMap.Resize( numberOfGlyphs );
-      charactersPerGlyph.Resize( numberOfGlyphs );
-
       mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
                                               0u,
                                               numberOfCharacters );
+    }
 
+    if( 0u == wordBreakInfo.Count() )
+    {
+      wordBreakInfo.Resize( numberOfCharacters );
       mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(),
                                               0u,
                                               numberOfCharacters );
+    }
 
+    if( 0u == glyphs.Count() )
+    {
+      glyphs.Resize( numberOfGlyphs );
       mImpl->mVisualModel->GetGlyphs( glyphs.Begin(),
                                       0u,
                                       numberOfGlyphs );
+    }
 
+    if( 0u == glyphsToCharactersMap.Count() )
+    {
+      glyphsToCharactersMap.Resize( numberOfGlyphs );
       mImpl->mVisualModel->GetGlyphToCharacterMap( glyphsToCharactersMap.Begin(),
                                                    0u,
                                                    numberOfGlyphs );
+    }
 
+    if( 0u == charactersPerGlyph.Count() )
+    {
+      charactersPerGlyph.Resize( numberOfGlyphs );
       mImpl->mVisualModel->GetCharactersPerGlyphMap( charactersPerGlyph.Begin(),
                                                      0u,
                                                      numberOfGlyphs );
@@ -780,6 +869,76 @@ bool Controller::DoRelayout( const Vector2& size,
 
     if( viewUpdated )
     {
+      // Reorder the lines
+      if( REORDER & operations )
+      {
+        const Length numberOfBidiParagraphs = mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters );
+
+        if( 0u == bidirectionalInfo.Count() )
+        {
+          bidirectionalInfo.Resize( numberOfBidiParagraphs );
+          mImpl->mLogicalModel->GetBidirectionalInfo( bidirectionalInfo.Begin(),
+                                                      0u,
+                                                      numberOfCharacters );
+        }
+
+        // Check first if there are paragraphs with bidirectional info.
+        if( 0u != bidirectionalInfo.Count() )
+        {
+          // Get the lines
+          const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines();
+
+          // Reorder the lines.
+          Vector<BidirectionalLineInfoRun> lineBidirectionalInfoRuns;
+          lineBidirectionalInfoRuns.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
+          ReorderLines( bidirectionalInfo,
+                        lines,
+                        lineBidirectionalInfoRuns );
+
+          // Set the bidirectional info into the model.
+          const Length numberOfBidirectionalInfoRuns = lineBidirectionalInfoRuns.Count();
+          mImpl->mLogicalModel->SetVisualToLogicalMap( lineBidirectionalInfoRuns.Begin(),
+                                                       numberOfBidirectionalInfoRuns );
+
+          // Set the bidirectional info per line into the layout parameters.
+          layoutParameters.lineBidirectionalInfoRunsBuffer = lineBidirectionalInfoRuns.Begin();
+          layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns;
+
+          // Get the character to glyph conversion table and set into the layout.
+          Vector<GlyphIndex> characterToGlyphMap;
+          characterToGlyphMap.Resize( numberOfCharacters );
+
+          layoutParameters.charactersToGlyphsBuffer = characterToGlyphMap.Begin();
+          mImpl->mVisualModel->GetCharacterToGlyphMap( layoutParameters.charactersToGlyphsBuffer,
+                                                       0u,
+                                                       numberOfCharacters );
+
+          // Get the glyphs per character table and set into the layout.
+          Vector<Length> glyphsPerCharacter;
+          glyphsPerCharacter.Resize( numberOfCharacters );
+
+          layoutParameters.glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
+          mImpl->mVisualModel->GetGlyphsPerCharacterMap( layoutParameters.glyphsPerCharacterBuffer,
+                                                         0u,
+                                                         numberOfCharacters );
+
+          // Re-layout the text. Reorder those lines with right to left characters.
+          mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters,
+                                                         glyphPositions );
+
+          // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+          for( Vector<BidirectionalLineInfoRun>::Iterator it = lineBidirectionalInfoRuns.Begin(),
+                 endIt = lineBidirectionalInfoRuns.End();
+               it != endIt;
+               ++it )
+          {
+            BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+            free( bidiLineInfo.visualToLogicalMap );
+          }
+        }
+      }
+
       // Sets the positions into the model.
       if( UPDATE_POSITIONS & operations )
       {
index b061330..5ffa531 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/decorator/text-decorator.h>
-#include <dali-toolkit/internal/text/text-control-interface.h>
-#include <dali-toolkit/internal/text/text-view.h>
-
 // EXTERNAL INCLUDES
+#include <string>
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/public-api/events/key-event.h>
 #include <dali/public-api/math/vector3.h>
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/object/ref-object.h>
-#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/decorator/text-decorator.h>
+#include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/text/text-view.h>
 
 namespace Dali
 {
@@ -70,15 +70,16 @@ private:
     VALIDATE_FONTS     = 0x0004,
     GET_LINE_BREAKS    = 0x0008,
     GET_WORD_BREAKS    = 0x0010,
-    SHAPE_TEXT         = 0x0020,
-    GET_GLYPH_METRICS  = 0x0040,
-    LAYOUT             = 0x0080,
-    UPDATE_ACTUAL_SIZE = 0x0100,
-    UPDATE_POSITIONS   = 0x0200,
-    UPDATE_LINES       = 0x0400,
-    REORDER            = 0x0800,
-    ALIGNMENT          = 0x1000,
-    RENDER             = 0x2000,
+    BIDI_INFO          = 0x0020,
+    SHAPE_TEXT         = 0x0040,
+    GET_GLYPH_METRICS  = 0x0080,
+    LAYOUT             = 0x0100,
+    UPDATE_ACTUAL_SIZE = 0x0200,
+    UPDATE_POSITIONS   = 0x0400,
+    UPDATE_LINES       = 0x0800,
+    REORDER            = 0x1000,
+    ALIGNMENT          = 0x2000,
+    RENDER             = 0x4000,
     ALL_OPERATIONS     = 0xFFFF
   };
 
index 9daa2d1..55d8797 100644 (file)
 
 // EXTERNAL INCLUDES
 #include <memory.h>
-
-// INTERNAL INCLUDES
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/math/vector2.h>
+
+// INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/line-run.h>
 
 namespace Dali
@@ -53,6 +53,7 @@ struct VisualModel::Impl
   Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
   Vector<GlyphIndex>     mCharactersToGlyph;  ///< For each character, the index of the first glyph.
   Vector<Length>         mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
+  Vector<Length>         mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
   Vector<Vector2>        mGlyphPositions;     ///< For each glyph, the position.
   Vector<LineRun>        mLines;              ///< The laid out lines.
 
@@ -74,8 +75,9 @@ void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
 {
   Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
   Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
-  Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
   Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
+  Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
+  Vector<Length>& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter;
 
   if( 0u == numberOfGlyphs )
   {
@@ -83,6 +85,7 @@ void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
     modelGlyphsToCharacters.Clear();
     modelCharactersToGlyph.Clear();
     modelCharactersPerGlyph.Clear();
+    modelGlyphsPerCharacter.Clear();
   }
   else
   {
@@ -106,11 +109,17 @@ void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
       // Build the characters to glyph conversion table.
 
       // 1) Reserve some space for the characters to avoid reallocations.
-      modelCharactersToGlyph.Reserve( static_cast<Length> ( static_cast<float>( numberOfGlyphs ) * 1.3f ) );
+      const Length numberOfCharacters = static_cast<Length> ( static_cast<float>( numberOfGlyphs ) * 1.3f );
+      modelCharactersToGlyph.Reserve( numberOfCharacters );
+      modelGlyphsPerCharacter.Reserve( numberOfCharacters );
+
+      // 2) Traverse the glyphs and set the glyph indices and the glyphs per character.
 
-      // 2) Traverse the glyphs and set the glyph indices.
+      // The number of 'characters per glyph' equal to zero.
+      Length zeroCharactersPerGlyph = 0u;
+
+      // Index to the glyph.
       GlyphIndex glyphIndex = 0u;
-      Length totalNumberOfCharacters = 0u;
       for( Vector<Length>::ConstIterator it = modelCharactersPerGlyph.Begin(),
              endIt = modelCharactersPerGlyph.End();
            it != endIt;
@@ -118,10 +127,29 @@ void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
       {
         const Length numberOfCharacters = *it;
 
-        for( Length index = 0u; index < numberOfCharacters; ++index, ++totalNumberOfCharacters )
+        // Set the glyph indices.
+        for( Length index = 0u; index < numberOfCharacters; ++index )
         {
           modelCharactersToGlyph.PushBack( glyphIndex );
         }
+
+        // Set the glyphs per character.
+        if( 0u == numberOfCharacters )
+        {
+          ++zeroCharactersPerGlyph;
+        }
+        else
+        {
+          const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharacters - 1u );
+          for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
+          {
+            modelGlyphsPerCharacter.PushBack( 0u );
+          }
+
+          modelGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph );
+
+          zeroCharactersPerGlyph = 0u;
+        }
       }
     }
   }
@@ -168,6 +196,14 @@ void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
   memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
 }
 
+void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
+                                          GlyphIndex glyphIndex,
+                                          Length numberOfGlyphs ) const
+{
+  const Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
+  memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
+}
+
 void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
                                             GlyphIndex glyphIndex,
                                             Length numberOfGlyphs ) const
@@ -176,12 +212,12 @@ void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
   memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
 }
 
-void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
-                                          GlyphIndex glyphIndex,
-                                          Length numberOfGlyphs ) const
+void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
+                                            CharacterIndex characterIndex,
+                                            Length numberOfCharacters ) const
 {
-  const Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
-  memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
+  const Vector<Length>& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter;
+  memcpy( glyphsPerCharacter, modelGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) );
 }
 
 void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
@@ -284,7 +320,7 @@ Length VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
   const Vector<LineRun>& modelLines = mImpl->mLines;
   const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
 
-  // Traverse the lines and cound those lines within the range of glyphs.
+  // Traverse the lines and count those lines within the range of glyphs.
   for( Vector<LineRun>::ConstIterator it = modelLines.Begin(),
          endIt = modelLines.End();
        it != endIt;
index 9593fd8..1a7120a 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
+// EXTERNAL INCLUDES
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/public-api/object/ref-object.h>
+
+// INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/text-definitions.h>
 
 namespace Dali
@@ -146,6 +148,19 @@ public:
                                Length numberOfCharacters ) const;
 
   /**
+   * Retrieves the whole or part of the glyph to character conversion map.
+   *
+   * The size of the buffer needs to be big enough to copy the @p numberOfGlyphs.
+   *
+   * @param[out] glyphToCharacter Pointer to a buffer where the conversion map is copied.
+   * @param[in] glyphIndex Index to the first glyph.
+   * @param[in] numberOfGlyphs The number of glyphs.
+   */
+  void GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
+                               GlyphIndex glyphIndex,
+                               Length numberOfGlyphs ) const;
+
+  /**
    * Retrieves for each glyph the number of characters the glyph represents.
    *
    * @param[out] charactersPerGlyph Pointer to a buffer where the number of characters for each glyph are copied.
@@ -157,17 +172,15 @@ public:
                                  Length numberOfGlyphs ) const;
 
   /**
-   * Retrieves the whole or part of the glyph to character conversion map.
+   * Retrieves for each character the number of glyphs the character is shaped.
    *
-   * The size of the buffer needs to be big enough to copy the @p numberOfGlyphs.
-   *
-   * @param[out] glyphToCharacter Pointer to a buffer where the conversion map is copied.
-   * @param[in] glyphIndex Index to the first glyph.
-   * @param[in] numberOfGlyphs The number of glyphs.
+   * @param[out] glyphsPerCharacter Pointer to a buffer where the number of glyphs for each character are copied.
+   * @param[in] characterIndex Index to the first character.
+   * @param[in] numberOfCharacters The number of characters.
    */
-  void GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
-                               GlyphIndex glyphIndex,
-                               Length numberOfGlyphs ) const;
+  void GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
+                                 CharacterIndex characterIndex,
+                                 Length numberOfCharacters ) const;
 
   // Position interface