TextModel - Remove the visual to logical conversion tables. 12/67812/5
authorVictor Cebollada <v.cebollada@samsung.com>
Mon, 25 Apr 2016 09:58:37 +0000 (10:58 +0100)
committerVictor Cebollada <v.cebollada@samsung.com>
Tue, 3 May 2016 15:04:19 +0000 (16:04 +0100)
* After the latest patches the bidirectional line info is kept.
  This info is used now to get the logical index from the visual index.
  The logical cursor position is calculated for a given logical cursor position.
  Both conversion tables (character and cursor position) have been removed.

Change-Id: Ifc79816c0044d2c2546adbbb30f4e7dc6ceb956c
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-model.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/logical-model-impl.h
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller.cpp

index 9f39bd2..83fa45c 100644 (file)
@@ -81,7 +81,6 @@ void ClearModelData( CharacterIndex characterIndex,
   logicalModel->mBidirectionalParagraphInfo.Clear();
   logicalModel->mCharacterDirections.Clear();
   logicalModel->mBidirectionalLineInfo.Clear();
-  logicalModel->mVisualToLogicalMap.Clear();
   visualModel->mGlyphs.Clear();
   visualModel->mGlyphsToCharacters.Clear();
   visualModel->mCharactersToGlyph.Clear();
@@ -321,10 +320,6 @@ void CreateTextModel( const std::string& text,
     layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin();
     layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count();
 
-    // Set the bidirectional info into the model.
-    logicalModel->SetVisualToLogicalMap( 0u,
-                                         numberOfCharacters );
-
     if( options.reorder )
     {
       // Re-layout the text. Reorder those lines with right to left characters.
index fa28d61..068a84c 100644 (file)
@@ -31,10 +31,13 @@ using namespace Text;
 
 // Tests the following functions.
 //
-// void SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
-//                             Length numberOfRuns,
-//                             CharacterIndex startIndex  )
-
+// void CreateParagraphInfo( CharacterIndex startIndex,
+//                           Length numberOfCharacters );
+// void FindParagraphs( CharacterIndex index,
+//                      Length numberOfCharacters,
+//                      Vector<ParagraphRunIndex>& paragraphs );
+// CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const;
+// CharacterIndex GetLogicalCursorIndex( CharacterIndex visualCursorIndex ) const;
 
 //////////////////////////////////////////////////////////
 
@@ -61,15 +64,24 @@ struct FindParagraphData
   unsigned int*  paragraphs;         ///< The expected paragraph info.
 };
 
-struct SetVisualToLogicalMapData
+struct GetLogicalCharacterIndexData
 {
-  std::string   description;                ///< Description of the test.
-  std::string   text;                       ///< Input text.
-  unsigned int  startIndex;                 ///< The start index from where the visual to logical conversion table is set.
-  unsigned int  numberOfCharacters;         ///< The number of characters to set.
-  Size          textArea;                   ///< The size of the area where the text is laid-out.
-  unsigned int  expectedNumberOfCharacters; ///< The expected number of characters.
-  unsigned int* visualToLogical;            ///< The expected visual to logical conversion table.
+  std::string   description;        ///< Description of the test.
+  std::string   text;               ///< Input text.
+  Size          textArea;           ///< The text area.
+  unsigned int  numberOfIndices;    ///< The number of characters to set.
+  unsigned int* visualToLogical;    ///< The expected visual to logical conversion table.
+  unsigned int* cachedBidiLine;     ///< The cached bidi line index for each character.
+};
+
+struct GetLogicalCursorIndexData
+{
+  std::string    description;        ///< Description of the test.
+  std::string    text;               ///< Input text.
+  unsigned int   numberOfIndices;    ///< The number of characters to set.
+  unsigned int*  visualCursorIndex;  ///< The given cursor visual index.
+  unsigned int*  logicalCursorIndex; ///< The expected cursor logical index
+  unsigned int*  cachedBidiLine;     ///< The cached bidi line index for each character.
 };
 
 bool CreateParagraphTest( const CreateParagraphData& data )
@@ -175,7 +187,7 @@ bool FindParagraphTest( const FindParagraphData& data )
   return true;
 }
 
-bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data )
+bool GetLogicalCharacterIndexTest( const GetLogicalCharacterIndexData& data )
 {
   std::cout << "  testing : " << data.description << std::endl;
   // Create the model.
@@ -194,32 +206,58 @@ bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data )
                    logicalModel,
                    visualModel );
 
-  // Get the visual to logical map.
-  Vector<CharacterIndex>& visualToLogicalMap = logicalModel->mVisualToLogicalMap;
-
-  // Compare the results.
-  if( data.expectedNumberOfCharacters != visualToLogicalMap.Count() )
+  for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
   {
-    std::cout << "  differetn number of characters : " << visualToLogicalMap.Count() << ", expected : " << data.expectedNumberOfCharacters << std::endl;
-    return false;
+    // Check the current cached bidi line index. (Check it before call the GetLogicalCharacterIndex() method )
+    if( data.cachedBidiLine[index] != logicalModel->mBidirectionalLineIndex )
+    {
+      std::cout << "  index : " << index << ", different cached bidi index : " << logicalModel->mBidirectionalLineIndex << ", expected : " << data.cachedBidiLine[index] << std::endl;
+      return false;
+    }
+
+    const Character logicalIndex = logicalModel->GetLogicalCharacterIndex( index );
+    if( data.visualToLogical[index] != logicalIndex )
+    {
+      std::cout << "  visual index : " << index << ", different logical index : " << logicalIndex << ", expected : " << data.visualToLogical[index] << std::endl;
+      return false;
+    }
   }
+  return true;
+}
+
+bool GetLogicalCursorIndexTest( const GetLogicalCursorIndexData& data )
+{
+  std::cout << "  testing : " << data.description << std::endl;
+  // Create the model.
+  LogicalModelPtr logicalModel = LogicalModel::New();
+  VisualModelPtr visualModel = VisualModel::New();
+  Size textArea( 300.f, 300.f );
+  Size layoutSize;
 
-  for( unsigned int index = 0u; index < data.expectedNumberOfCharacters; ++index )
+  // Create the model with the whole text.
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
+  CreateTextModel( data.text,
+                   textArea,
+                   fontDescriptions,
+                   options,
+                   layoutSize,
+                   logicalModel,
+                   visualModel );
+
+  for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
   {
-    if( data.visualToLogical[index] != visualToLogicalMap[index] )
+    if( logicalModel->mBidirectionalLineIndex != data.cachedBidiLine[index] )
     {
-      std::cout << "  different visualToLogical table : " << std::endl;
-      for( unsigned int i = 0; i < data.expectedNumberOfCharacters; ++i )
-      {
-        std::cout << visualToLogicalMap[i] << " ";
-      }
-      std::cout << std::endl;
-      std::cout << "                         expected : " << std::endl;
-      for( unsigned int i = 0; i < data.expectedNumberOfCharacters; ++i )
-      {
-        std::cout << data.visualToLogical[i] << " ";
-      }
-      std::cout << std::endl;
+      std::cout << "  test : " << index << ", different cached line index : " << logicalModel->mBidirectionalLineIndex << ", expected : " << data.cachedBidiLine[index] << std::endl;
+      return false;
+    }
+
+    const CharacterIndex logicalCursorIndex = logicalModel->GetLogicalCursorIndex( data.visualCursorIndex[index] );
+
+    if( logicalCursorIndex != data.logicalCursorIndex[index] )
+    {
+      std::cout << "  test : " << index << ", different logical cursor index : " << logicalCursorIndex << ", expected : " << data.logicalCursorIndex[index] << std::endl;
       return false;
     }
   }
@@ -233,7 +271,8 @@ bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data )
 //
 // UtcDaliCreateParagraph
 // UtcDaliFindParagraph
-// UtcDaliSetVisualToLogicalMap
+// UtcDaliGetLogicalCharacterIndex
+// UtcDaliGetLogicalCursorIndex
 //
 //////////////////////////////////////////////////////////
 
@@ -380,110 +419,304 @@ int UtcDaliFindParagraph(void)
   END_TEST;
 }
 
-int UtcDaliSetVisualToLogicalMap(void)
+int UtcDaliGetLogicalCharacterIndex(void)
 {
   tet_infoline(" UtcDaliSetVisualToLogicalMap");
 
-  unsigned int* visualToLogical01 = NULL;
-  unsigned int* visualToLogical02 = NULL;
-  unsigned int  visualToLogical03[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
-  unsigned int  visualToLogical04[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, };
-  unsigned int  visualToLogical05[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 26u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u };
-  unsigned int  visualToLogical06[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
-  unsigned int  visualToLogical07[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
-  unsigned int  visualToLogical08[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
-  unsigned int  visualToLogical09[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
-
-  struct SetVisualToLogicalMapData data[] =
+  unsigned int visualToLogical01[] = {};
+  unsigned int  cachedBidiLine01[] = {};
+  unsigned int visualToLogical02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
+  unsigned int  cachedBidiLine02[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,  0u };
+  unsigned int visualToLogical03[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+  unsigned int  cachedBidiLine03[] = {  0u,  0u,  0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u };
+
+  unsigned int visualToLogical04[] = { 0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
+  unsigned int  cachedBidiLine04[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
+                                       0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+                                       1u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u };
+
+// size 300, 300
+// LO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _  h  e  l  l  o  _  w  o  r  l  d \n
+//      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
+// VO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ل  ا  ع   ل  ا  ب  _  ا   ب  ح  ر  م  ,   _  h  e  l  l  o  _  w  o  r  l  d \n
+//      0  1  2  3  4  5  6  7  8  9 10 11 12 25 24 23 22 21 20 19 18 17 16 15 14 13 26 27 28 29 30 31 32 33 34 35 36 37 38 39
+
+// LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _  h  e  l  l  o  _  w  o  r  l  d   ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
+//     40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
+// VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م  _  ,  h  e  l  l  o  _  w  o  r  l  d   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
+//     81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 55 56 57 58 59 60 61 62 63 64 65 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
+
+// LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
+//     82 83 84 85 86 87 88 89 90 91 92 93 94 95
+// VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
+//     95 94 93 92 91 90 89 88 87 86 85 84 83 82
+
+
+// LO   h   e   l   l   o   _   w   o   r   l   d
+//     96  97  98  99 100 101 102 103 104 105 106
+// VO   h   e   l   l   o   _   w   o   r   l   d
+//     96  97  98  99 100 101 102 103 104 105 106
+
+  unsigned int visualToLogical05[] = { 0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
+  unsigned int  cachedBidiLine05[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u };
+
+// size 300, 300
+// LO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _
+//      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
+// VO   H  e  l  l  o  _  w  o  r  l  d  ,  _  م  ل  ا  ع   ل  ا  ب  _  ا   ب  ح  ر  م  ,   _
+//      0  1  2  3  4  5  6  7  8  9 10 11 12 25 24 23 22 21 20 19 18 17 16 15 14 13 26 27
+
+// LO    h  e  l  l  o  _  w  o  r  l  d \n
+//      28 29 30 31 32 33 34 35 36 37 38 39
+// VO    h  e  l  l  o  _  w  o  r  l  d \n
+//      28 29 30 31 32 33 34 35 36 37 38 39
+
+// LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _  h  e  l  l  o  _  w  o  r  l  d   ,  _
+//     40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
+// VO  _  ,  h  e  l  l  o  _  w  o  r  l  d   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
+//     67 66 55 56 57 58 59 60 61 62 63 64 65 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
+
+// LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
+//     68 69 70 71 72 73 74 75 76 77 78 79 80 81
+// VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
+//     81 80 79 78 77 76 75 74 73 72 71 70 69 68
+
+// LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
+//     82 83 84 85 86 87 88 89 90 91 92 93 94 95
+// VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
+//     95 94 93 92 91 90 89 88 87 86 85 84 83 82
+
+
+// LO   h   e   l   l   o   _   w   o   r   l   d
+//     96  97  98  99 100 101 102 103 104 105 106
+// VO   h   e   l   l   o   _   w   o   r   l   d
+//     96  97  98  99 100 101 102 103 104 105 106
+
+  unsigned int visualToLogical06[] = { 0u,  1u,  2u,  3u,  4u,  5u,  6u,  7u,  8u,  9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
+  unsigned int  cachedBidiLine06[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
+                                       0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+                                       1u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u,
+                                       2u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u,
+                                       3u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u,
+                                       4u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u, 5u,
+                                       5u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u,
+                                       6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u, 6u };
+
+// size 100, 600
+// LO   H  e  l  l  o  _  w  o  r  l  d  ,  _
+//      0  1  2  3  4  5  6  7  8  9 10 11 12
+// VO   H  e  l  l  o  _  w  o  r  l  d  ,  _
+//      0  1  2  3  4  5  6  7  8  9 10 11 12
+
+// LO    م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,   _
+//      13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
+// VO    م  ل  ا  ع   ل  ا  ب  _  ا   ب  ح  ر  م  ,   _
+//      25 24 23 22 21 20 19 18 17 16 15 14 13 26 27
+
+// LO    h  e  l  l  o  _  w  o  r  l  d \n
+//      28 29 30 31 32 33 34 35 36 37 38 39
+// VO    h  e  l  l  o  _  w  o  r  l  d \n
+//      28 29 30 31 32 33 34 35 36 37 38 39
+
+// LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  ,  _
+//     40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
+// VO   _  ,  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
+//     54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
+
+// LO   h  e  l  l  o  _  w  o  r  l  d   ,  _
+//     55 56 57 58 59 60 61 62 63 64 65 66 67
+// VO   _  ,  h  e  l  l  o  _  w  o  r  l  d
+//     67 66 55 56 57 58 59 60 61 62 63 64 65
+
+// LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
+//     68 69 70 71 72 73 74 75 76 77 78 79 80 81
+// VO  \n  م  ل  ا   ع  ل  ا  ب  _  ا   ب  ح  ر  م
+//     81 80 79 78 77 76 75 74 73 72 71 70 69 68
+
+// LO   م  ر  ح  ب   ا  _  ب  ا  ل  ع   ا  ل  م  \n
+//     82 83 84 85 86 87 88 89 90 91 92 93 94 95
+// VO  \n  م  ل  ا  ع  ل   ا  ب  _  ا   ب  ح  ر  م
+//     95 94 93 92 91 90 89 88 87 86 85 84 83 82
+
+
+// LO   h   e   l   l   o   _   w   o   r   l   d
+//     96  97  98  99 100 101 102 103 104 105 106
+// VO   h   e   l   l   o   _   w   o   r   l   d
+//     96  97  98  99 100 101 102 103 104 105 106
+
+  struct GetLogicalCharacterIndexData data[] =
   {
     {
       "Zero characters text",
       "",
+      Size( 300.f, 300.f ),
       0u,
-      0u,
-      Size( 100.f, 300.f ),
-      0u,
-      visualToLogical01
+      visualToLogical01,
+      cachedBidiLine01
     },
     {
       "Left to right text only",
       "Hello world",
-      0u,
+      Size( 300.f, 300.f ),
       11u,
-      Size( 100.f, 300.f ),
-      0u,
-      visualToLogical02
+      visualToLogical02,
+      cachedBidiLine02
     },
     {
       "Right to left text only",
       "مرحبا بالعالم",
-      0u,
-      13u,
-      Size( 100.f, 300.f ),
+      Size( 300.f, 300.f ),
       13u,
-      visualToLogical03
+      visualToLogical03,
+      cachedBidiLine03
     },
     {
       "Mix of left to right and right to left text.",
-      "Hello world, مرحبا بالعالم",
-      0u,
-      26u,
-      Size( 100.f, 300.f ),
-      26u,
-      visualToLogical04
+      "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
+      Size( 300.f, 300.f ),
+      107u,
+      visualToLogical04,
+      cachedBidiLine04
     },
     {
       "Mix of left to right and right to left text.",
-      "Hello world, \nمرحبا بالعالم",
-      0u,
-      27u,
-      Size( 100.f, 300.f ),
-      27u,
-      visualToLogical05
+      "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
+      Size( 200.f, 400.f ),
+      107u,
+      visualToLogical05,
+      cachedBidiLine05
     },
     {
       "Mix of left to right and right to left text.",
       "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
-      0u,
-      107u,
-      Size( 100.f, 300.f ),
+      Size( 100.f, 600.f ),
       107u,
-      visualToLogical06
+      visualToLogical06,
+      cachedBidiLine06
+    },
+  };
+  const unsigned int numberOfTests = 6u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !GetLogicalCharacterIndexTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliGetLogicalCursorIndex(void)
+{
+  tet_infoline(" UtcDaliGetLogicalCursorIndex");
+
+  unsigned int visualIndex01[] = { 10u };
+  unsigned int logicalIndex01[] = { 10u };
+  unsigned int bidirectionalLineIndex01[] = { 0u };
+
+  unsigned int visualIndex02[] = { 0u, 16u, 11u, 12u };
+  unsigned int logicalIndex02[] = { 0u, 16u, 11u, 12u };
+  unsigned int bidirectionalLineIndex02[] = { 0u, 0u, 0u, 0u };
+
+
+
+// LO     H  e  l  l  o  _  w  o  r  l  d  ,  _  \n
+//       0  1  2  3  4  5  6  7  8  9 10 11 12 13 14
+// VO     H  e  l  l  o  _  w  o  r  l  d  ,  _  \n
+
+// LO      ש  ל  ו  ם  _  ע  ו  ל  ם  ,  _ \n
+//       14 15 16 17 18 19 20 21 22 23 24 25 26
+// VO      \n _  ,  ם  ל  ו  ע  _  ם  ו  ל  ש
+
+// LO      h  e  l  l  o  _  w  o  r  l  d  ,  _ \n
+//       26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
+// VO      h  e  l  l  o  _  w  o  r  l  d  ,  _ \n
+
+// LO      h  e  l  l  o  _  w  o  r  l  d  ,  _  ש  ל  ו  ם  _  ע  ו  ל  ם \n
+//       40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
+// VO      h  e  l  l  o  _  w  o  r  l  d  ,  _  ם  ל  ו  ע  _  ם  ו  ל  ש \n
+
+// LO      ש  ל  ו  ם  _  ע  ו  ל  ם
+//       63 64 65 66 67 68 69 70 71 72
+// VO      ם  ל  ו  ע  _  ם  ו  ל  ש
+
+  unsigned int visualIndex03[] = { 0u, 18u, 25u, 60u, 54u, 65u, 0u, 18u, 65u, 33u };
+  unsigned int logicalIndex03[] = { 0u, 22u, 15u, 55u, 61u, 70u, 0u, 22u, 70u, 33u };
+  unsigned int bidirectionalLineIndex03[] = { 0u, 0u, 0u, 0u, 1u, 1u, 2u, 2u, 0u, 2u };
+
+
+// LO      ש  ל  ו  ם  _  ע  ו  ל  ם  ,  _ \n
+//        0  1  2  3  4  5  6  7  8  9 10 11 12
+// VO      \n ,  ם  ל  ו  ע  _  ם  ו  ל  ש
+
+// LO      h  e  l  l  o  _  w  o  r  l  d  ,  _  \n
+//       12 13 14 15 16 17 18 19 20 21 22 23 24 25  26
+// VO      h  e  l  l  o  _  w  o  r  l  d  ,  _  \n
+
+// LO      h  e  l  l  o  _  w  o  r  l  d  ,  _  ש  ל  ו  ם  _  ע  ו  ל  ם  \n
+//       26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48  49
+// VO      h  e  l  l  o  _  w  o  r  l  d  ,  _  ש  ל  ו  ם  _  ע  ו  ל  ם  \n
+
+// LO      ש  ל  ו  ם  _  ע  ו  ל  ם  ,  _  \n
+//       49 50 51 52 53 54 55 56 57 58 59 60  61
+// VO      ם  ל  ו  ע  _  ם  ו  ל  ש  ,  \n
+
+// LO      h  e  l  l  o  _  w  o  r  l  d
+//       61 62 63 64 65 66 67 68 69 70 71 72
+// VO      h  e  l  l  o  _  w  o  r  l  d
+
+
+  unsigned int visualIndex04[] = { 0u };
+  unsigned int logicalIndex04[] = { 72u };
+  unsigned int bidirectionalLineIndex04[] = { 0u };
+
+
+
+  struct GetLogicalCursorIndexData data[] =
+  {
+    {
+      "Zero characters text",
+      "",
+      1u,
+      visualIndex01,
+      logicalIndex01,
+      bidirectionalLineIndex01,
     },
     {
-      "Mix of left to right and right to left text. Updates from character index 5",
-      "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
-      5u,
-      107u,
-      Size( 100.f, 300.f ),
-      107u,
-      visualToLogical07
+      "All left to right text 01.",
+      "Hello world\ndemo",
+      4u,
+      visualIndex02,
+      logicalIndex02,
+      bidirectionalLineIndex02,
     },
     {
-      "Mix of left to right and right to left text. Updates from character index 39",
-      "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
-      39u,
-      107u,
-      Size( 100.f, 300.f ),
-      107u,
-      visualToLogical08
+      "bidirectional text 01.",
+      "Hello world, \nשלום עולם, \nhello world, \nhello world, שלום עולם\nשלום עולם",
+      10u,
+      visualIndex03,
+      logicalIndex03,
+      bidirectionalLineIndex03,
     },
     {
-      "Mix of left to right and right to left text. Updates from character index 70",
-      "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
-      70u,
-      107u,
-      Size( 100.f, 300.f ),
-      107u,
-      visualToLogical09
-    }
+      "bidirectional text 02.",
+      "שלום עולם, \nhello world, \nhello world, שלום עולם\nשלום עולם, \nhello world",
+      1u,
+      visualIndex04,
+      logicalIndex04,
+      bidirectionalLineIndex04,
+    },
   };
-  const unsigned int numberOfTests = 9u;
+  const unsigned int numberOfTests = 4u;
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
     ToolkitTestApplication application;
-    if( !SetVisualToLogicalMapTest( data[index] ) )
+    if( !GetLogicalCursorIndexTest( data[index] ) )
     {
       tet_result(TET_FAIL);
     }
index b64ae2b..0d8cf5a 100644 (file)
@@ -78,174 +78,220 @@ CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex character
   return *( mCharacterDirections.Begin() + characterIndex );
 }
 
-void LogicalModel::SetVisualToLogicalMap( CharacterIndex startIndex,
-                                          Length numberOfCharacters )
+CharacterIndex LogicalModel::GetLogicalCursorIndex( CharacterIndex visualCursorIndex )
 {
-  mVisualToLogicalMap.Resize( numberOfCharacters );
+  // The total number of characters.
+  const Length numberOfCharacters = mText.Count();
 
-  CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin();
+  const bool fetch = FetchBidirectionalLineInfo( visualCursorIndex );
+  if( !fetch )
+  {
+    // The character is not inside a bidi line.
+    return visualCursorIndex;
+  }
 
-  const BidirectionalLineInfoRun* const bidirectionalInfo = mBidirectionalLineInfo.Begin();
-  const Length numberOfRuns = mBidirectionalLineInfo.Count();
+  // The character's directions buffer.
+  const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin();
 
-  CharacterIndex lastIndex = startIndex;
-  for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex )
-  {
-    const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex );
+  // The bidirectional line info.
+  const BidirectionalLineInfoRun* const bidirectionalLineInfo = mBidirectionalLineInfo.Begin() + mBidirectionalLineIndex;
 
-    if( bidiLineInfo.characterRun.characterIndex + bidiLineInfo.characterRun.numberOfCharacters <= startIndex )
-    {
-      // Skip this paragraph. It has been already processed.
-      continue;
-    }
+  // Whether the paragraph starts with a right to left character.
+  const bool isRightToLeftParagraph = bidirectionalLineInfo->direction;
 
-    if( lastIndex < bidiLineInfo.characterRun.characterIndex )
+  CharacterIndex logicalCursorIndex = 0u;
+
+  if( 0u == visualCursorIndex )
+  {
+    if( isRightToLeftParagraph )
     {
-      // Fill with the identity.
-      for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex )
-      {
-        *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
-      }
+      logicalCursorIndex = numberOfCharacters;
     }
-
-    // Fill the conversion table of the run.
-    for( CharacterIndex index = 0u;
-         index < bidiLineInfo.characterRun.numberOfCharacters;
-         ++index, ++lastIndex )
+    else // else logical position is zero.
     {
-      *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index );
+      logicalCursorIndex = 0u;
     }
   }
-
-  // Complete with the identity if there are some left to right characters after the last right to left.
-  for( ; lastIndex < numberOfCharacters; ++lastIndex )
+  else if( numberOfCharacters == visualCursorIndex )
   {
-    *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
-  }
-
-  // Sets the visual to logical conversion map for cursor positions.
-  const Length numberOfCharactersPlusOne = numberOfCharacters + 1u;
-  mVisualToLogicalCursorMap.Resize( numberOfCharactersPlusOne );
-
-  CharacterIndex* modelVisualToLogicalCursorMap = mVisualToLogicalCursorMap.Begin();
-
-  const Length numberOfBidirectionalParagraphs = mBidirectionalParagraphInfo.Count();
-  BidirectionalParagraphInfoRun* bidirectionalParagraphInfoBuffer = mBidirectionalParagraphInfo.Begin();
-  BidirectionalParagraphInfoRun* bidirectionalParagraph = bidirectionalParagraphInfoBuffer;
-
-  const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin();
-
-  Length bidirectionalParagraphIndex = 0u;
-  bool isRightToLeftParagraph = false;
-  for( CharacterIndex index = startIndex; index < numberOfCharactersPlusOne; ++index )
-  {
-    if( bidirectionalParagraph &&
-        ( bidirectionalParagraph->characterRun.characterIndex == index ) )
+    if( isRightToLeftParagraph )
     {
-      isRightToLeftParagraph = *( modelCharacterDirections + index );
+      logicalCursorIndex = 0u;
     }
-
-    if( 0u == index )
+    else // else logical position is the number of characters.
     {
-      if( isRightToLeftParagraph )
-      {
-        *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
-      }
-      else // else logical position is zero.
-      {
-        *( modelVisualToLogicalCursorMap + index ) = 0u;
-      }
+      logicalCursorIndex = numberOfCharacters;
     }
-    else if( numberOfCharacters == index )
+  }
+  else
+  {
+    // Get the character indexed by  index - 1 and index
+    // and calculate the logical position according the directions of
+    // both characters and the direction of the paragraph.
+
+    const CharacterIndex previousVisualCursorIndex = visualCursorIndex - 1u;
+    const CharacterIndex previousLogicalCursorIndex = *( bidirectionalLineInfo->visualToLogicalMap + previousVisualCursorIndex - bidirectionalLineInfo->characterRun.characterIndex ) + bidirectionalLineInfo->characterRun.characterIndex;
+    const CharacterIndex currentLogicalCursorIndex = *( bidirectionalLineInfo->visualToLogicalMap + visualCursorIndex - bidirectionalLineInfo->characterRun.characterIndex ) + bidirectionalLineInfo->characterRun.characterIndex;
+
+    const CharacterDirection previousCharacterDirection = *( modelCharacterDirections + previousLogicalCursorIndex );
+    const CharacterDirection currentCharacterDirection = *( modelCharacterDirections + currentLogicalCursorIndex );
+
+    if( previousCharacterDirection == currentCharacterDirection )
     {
-      if( isRightToLeftParagraph )
+      // Both glyphs have the same direction.
+      if( previousCharacterDirection )
       {
-        *( modelVisualToLogicalCursorMap + index ) = 0u;
+        logicalCursorIndex = previousLogicalCursorIndex;
       }
-      else // else logical position is the number of characters.
+      else
       {
-        *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
+        logicalCursorIndex = currentLogicalCursorIndex;
       }
     }
     else
     {
-      // Get the character indexed by  index - 1 and index
-      // and calculate the logical position according the directions of
-      // both characters and the direction of the paragraph.
-
-      const CharacterIndex previousIndex = index - 1u;
-      const CharacterIndex logicalPosition0 = *( modelVisualToLogicalMapBuffer + previousIndex );
-      const CharacterIndex logicalPosition1 = *( modelVisualToLogicalMapBuffer + index );
-
-      const CharacterDirection direction0 = *( modelCharacterDirections + logicalPosition0 );
-      const CharacterDirection direction1 = *( modelCharacterDirections + logicalPosition1 );
-
-      if( direction0 == direction1 )
+      if( isRightToLeftParagraph )
       {
-        // Both glyphs have the same direction.
-        if( direction0 )
+        if( currentCharacterDirection )
         {
-          *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
+          logicalCursorIndex = currentLogicalCursorIndex + 1u;
         }
         else
         {
-          *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
+          logicalCursorIndex = previousLogicalCursorIndex;
         }
       }
       else
       {
-        if( isRightToLeftParagraph )
+        if( previousCharacterDirection )
         {
-          if( direction1 )
-          {
-            *( modelVisualToLogicalCursorMap + index ) = logicalPosition1 + 1u;
-          }
-          else
-          {
-            *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
-          }
+          logicalCursorIndex = currentLogicalCursorIndex;
         }
         else
         {
-          if( direction0 )
-          {
-            *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
-          }
-          else
-          {
-            *( modelVisualToLogicalCursorMap + index ) = logicalPosition0 + 1u;
-          }
+          logicalCursorIndex = previousLogicalCursorIndex + 1u;
         }
       }
     }
+  }
+
+  return logicalCursorIndex;
+}
 
-    if( bidirectionalParagraph &&
-        ( bidirectionalParagraph->characterRun.characterIndex + bidirectionalParagraph->characterRun.numberOfCharacters == index ) )
+CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex )
+{
+  const bool fetch = FetchBidirectionalLineInfo( visualCharacterIndex );
+  if( !fetch )
+  {
+    // The character is not inside a bidi line.
+    return visualCharacterIndex;
+  }
+
+  // The bidirectional line info.
+  const BidirectionalLineInfoRun* const bidirectionalLineInfo = mBidirectionalLineInfo.Begin() + mBidirectionalLineIndex;
+
+  return *( bidirectionalLineInfo->visualToLogicalMap + visualCharacterIndex - bidirectionalLineInfo->characterRun.characterIndex ) + bidirectionalLineInfo->characterRun.characterIndex;
+}
+
+bool LogicalModel::FetchBidirectionalLineInfo( CharacterIndex characterIndex )
+{
+  // The number of bidirectional lines.
+  const Length numberOfBidirectionalLines = mBidirectionalLineInfo.Count();
+
+  if( 0u == numberOfBidirectionalLines )
+  {
+    // If there is no bidirectional info.
+    return false;
+  }
+
+  // Find the bidi line where the character is laid-out.
+
+  const BidirectionalLineInfoRun* const bidirectionalLineInfoBuffer = mBidirectionalLineInfo.Begin();
+
+  // Check first if the character is in the previously fetched line.
+
+  BidirectionalLineRunIndex bidiLineIndex = 0u;
+  CharacterIndex lastCharacterOfRightToLeftRun = 0u;
+  if( mBidirectionalLineIndex < numberOfBidirectionalLines )
+  {
+    const BidirectionalLineInfoRun& bidiLineRun = *( bidirectionalLineInfoBuffer + mBidirectionalLineIndex );
+
+    // Whether the character index is just after the last one. i.e The cursor position after the last character.
+    const bool isLastIndex = characterIndex == mText.Count();
+
+    const CharacterIndex lastCharacterOfRunPlusOne = bidiLineRun.characterRun.characterIndex + bidiLineRun.characterRun.numberOfCharacters;
+    if( ( bidiLineRun.characterRun.characterIndex <= characterIndex ) &&
+        ( ( characterIndex < lastCharacterOfRunPlusOne ) || ( isLastIndex && ( characterIndex == lastCharacterOfRunPlusOne ) ) ) )
+    {
+      // The character is in the previously fetched bidi line.
+      return true;
+    }
+    else
     {
-      isRightToLeftParagraph = false;
-      ++bidirectionalParagraphIndex;
-      if( bidirectionalParagraphIndex < numberOfBidirectionalParagraphs )
+      // The character is not in the previously fetched line.
+
+      if( isLastIndex )
       {
-        bidirectionalParagraph = bidirectionalParagraphInfoBuffer + bidirectionalParagraphIndex;
+        // The given index is one after the last character, so it's not in a bidi line.
+        // Check if it's just after the last bidi line.
+        const BidirectionalLineRunIndex lastBidiLineIndex = numberOfBidirectionalLines - 1u;
+        const BidirectionalLineInfoRun& bidiLineRun = *( bidirectionalLineInfoBuffer + lastBidiLineIndex );
+
+        if( characterIndex == bidiLineRun.characterRun.characterIndex + bidiLineRun.characterRun.numberOfCharacters )
+        {
+          // The character is in the last bidi line.
+          mBidirectionalLineIndex = lastBidiLineIndex;
+          return true;
+        }
+      }
+
+      // Set the bidi line index from where to start the fetch.
+
+      if( characterIndex < bidiLineRun.characterRun.characterIndex )
+      {
+        // Start the fetch from the beginning.
+        bidiLineIndex = 0u;
       }
       else
       {
-        bidirectionalParagraph = NULL;
+        // Start the fetch from the next line.
+        bidiLineIndex = mBidirectionalLineIndex + 1u;
+        lastCharacterOfRightToLeftRun = lastCharacterOfRunPlusOne - 1u;
       }
     }
   }
-}
 
-CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
-{
-  if( 0u == mVisualToLogicalMap.Count() )
+  // The character has not been found in the previously fetched bidi line.
+  for( Vector<BidirectionalLineInfoRun>::ConstIterator it = bidirectionalLineInfoBuffer + bidiLineIndex,
+         endIt = mBidirectionalLineInfo.End();
+       it != endIt;
+       ++it, ++bidiLineIndex )
   {
-    // If there is no visual to logical info is because the whole text is left to right.
-    // Return the identity.
-    return visualCharacterIndex;
+    const BidirectionalLineInfoRun& bidiLineRun = *it;
+
+    if( ( lastCharacterOfRightToLeftRun < characterIndex ) && ( characterIndex < bidiLineRun.characterRun.characterIndex ) )
+    {
+      // The character is not inside a bidi line.
+      return false;
+    }
+
+    const CharacterIndex lastCharacterOfRunPlusOne = bidiLineRun.characterRun.characterIndex + bidiLineRun.characterRun.numberOfCharacters;
+    lastCharacterOfRightToLeftRun = lastCharacterOfRunPlusOne - 1u;
+    if( ( bidiLineRun.characterRun.characterIndex <= characterIndex ) &&
+        ( characterIndex < lastCharacterOfRunPlusOne ) )
+    {
+      // Bidi line found. Fetch the line.
+      mBidirectionalLineIndex = bidiLineIndex;
+      return true;
+    }
   }
 
-  return *( mVisualToLogicalMap.Begin() + visualCharacterIndex );
+  return false;
+}
+
+BidirectionalLineRunIndex LogicalModel::GetBidirectionalLineInfo() const
+{
+  return mBidirectionalLineIndex;
 }
 
 void LogicalModel::UpdateTextStyleRuns( CharacterIndex index, int numberOfCharacters )
@@ -541,6 +587,7 @@ LogicalModel::~LogicalModel()
 }
 
 LogicalModel::LogicalModel()
+: mBidirectionalLineIndex( 0u )
 {
 }
 
index 089af8e..6ff820d 100644 (file)
@@ -89,17 +89,13 @@ public:
   // Visual <--> Logical conversion tables.
 
   /**
-   * @brief Sets the visual to logical and the logical to visual map tables.
+   * @brief Retrieves the logical cursor index for the given visual cursor index.
    *
-   * Replaces any map tables previously set.
+   * @param[in] visualCursorIndex The visual cursor index.
    *
-   * @note If the number of runs is zero the bidirectional info buffer is cleared.
-   *
-   * @param[in] startIndex Character index from where the conversion tables are set.
-   * @param[in] numberOfCharacters The number of characters.
+   * @return The logical cursor index.
    */
-  void SetVisualToLogicalMap( CharacterIndex startIndex,
-                              Length numberOfCharacters );
+  CharacterIndex GetLogicalCursorIndex( CharacterIndex visualCursorIndex );
 
   /**
    * @brief Retrieves the logical character index for the given visual character index.
@@ -108,7 +104,25 @@ public:
    *
    * @return The logical character index.
    */
-  CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const;
+  CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex );
+
+  /**
+   * @brief Fetch the bidirectional line info for the given character.
+   *
+   * Call GetBidirectionalLineInfo() to retrieve the last fetched line.
+   *
+   * @param[in] characterIndex The character index.
+   *
+   * @return @e true if the given @e character is in a bidirectional line.
+   */
+  bool FetchBidirectionalLineInfo( CharacterIndex characterIndex );
+
+  /**
+   * @brief Retrieves the last fetched bidirectional line info.
+   *
+   * @return The index of the bidirectional line info.
+   */
+  BidirectionalLineRunIndex GetBidirectionalLineInfo() const;
 
   // Text style.
 
@@ -188,10 +202,10 @@ public:
   Vector<WordBreakInfo>                 mWordBreakInfo;
   Vector<ParagraphRun>                  mParagraphInfo;
   Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
-  Vector<CharacterDirection>            mCharacterDirections;        ///< For each character, whether is right to left. ( @e flase is left to right, @e true right to left ).
+  Vector<CharacterDirection>            mCharacterDirections;              ///< For each character, whether is right to left. ( @e flase is left to right, @e true right to left ).
   Vector<BidirectionalLineInfoRun>      mBidirectionalLineInfo;
-  Vector<CharacterIndex>                mVisualToLogicalMap;         ///< Bidirectional visual to logical conversion table.
-  Vector<CharacterIndex>                mVisualToLogicalCursorMap;   ///< Bidirectional visual to logical cursor conversion table.
+
+  BidirectionalLineRunIndex             mBidirectionalLineIndex;           ///< The last fetched bidirectional line info.
 };
 
 } // namespace Text
index 56820ae..813c022 100644 (file)
@@ -388,8 +388,6 @@ void Controller::Impl::ClearFullModelData( OperationsMask operations )
         bidiLineInfo.visualToLogicalMap = NULL;
       }
       mLogicalModel->mBidirectionalLineInfo.Clear();
-
-      mLogicalModel->mVisualToLogicalMap.Clear();
     }
   }
 
@@ -499,10 +497,6 @@ void Controller::Impl::ClearCharacterModelData( CharacterIndex startIndex, Chara
 
       mLogicalModel->mBidirectionalLineInfo.Erase( bidirectionalLineInfoBuffer + startRemoveIndex,
                                                    bidirectionalLineInfoBuffer + endRemoveIndex );
-
-      CharacterIndex* visualToLogicalMapBuffer = mLogicalModel->mVisualToLogicalMap.Begin();
-      mLogicalModel->mVisualToLogicalMap.Erase( visualToLogicalMapBuffer + startIndex,
-                                                visualToLogicalMapBuffer + endIndexPlusOne );
     }
   }
 }
@@ -1939,10 +1933,6 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
   const Vector<Vector2>& positions = mVisualModel->mGlyphPositions;
   const Vector2* const positionsBuffer = positions.Begin();
 
-  // Get the visual to logical conversion tables.
-  const CharacterIndex* const visualToLogicalBuffer = ( 0u != mLogicalModel->mVisualToLogicalMap.Count() ) ? mLogicalModel->mVisualToLogicalMap.Begin() : NULL;
-  const CharacterIndex* const visualToLogicalCursorBuffer = mLogicalModel->mVisualToLogicalCursorMap.Begin();
-
   // Get the character to glyph conversion table.
   const GlyphIndex* const charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin();
 
@@ -1952,9 +1942,6 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
   // Get the glyph's info buffer.
   const GlyphInfo* const glyphInfoBuffer = mVisualModel->mGlyphs.Begin();
 
-  // If the vector is void, there is no right to left characters.
-  const bool hasRightToLeftCharacters = NULL != visualToLogicalBuffer;
-
   const CharacterIndex startCharacter = line.characterRun.characterIndex;
   const CharacterIndex endCharacter   = line.characterRun.characterIndex + line.characterRun.numberOfCharacters;
   DALI_ASSERT_DEBUG( endCharacter <= mLogicalModel->mText.Count() && "Invalid line info" );
@@ -1968,7 +1955,7 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
   for( ; !matched && ( visualIndex < endCharacter ); ++visualIndex )
   {
     // The character in logical order.
-    const CharacterIndex characterLogicalOrderIndex = hasRightToLeftCharacters ? *( visualToLogicalBuffer + visualIndex ) : visualIndex;
+    const CharacterIndex characterLogicalOrderIndex = mLogicalModel->GetLogicalCharacterIndex( visualIndex );
 
     // Get the script of the character.
     const Script script = mLogicalModel->GetScript( characterLogicalOrderIndex );
@@ -1982,7 +1969,7 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
     {
       // Get the first character/glyph of the group of glyphs.
       const CharacterIndex firstVisualCharacterIndex = 1u + visualIndex - numberOfCharacters;
-      const CharacterIndex firstLogicalCharacterIndex = hasRightToLeftCharacters ? *( visualToLogicalBuffer + firstVisualCharacterIndex ) : firstVisualCharacterIndex;
+      const CharacterIndex firstLogicalCharacterIndex = mLogicalModel->GetLogicalCharacterIndex( firstVisualCharacterIndex );
       const GlyphIndex firstLogicalGlyphIndex = *( charactersToGlyphBuffer + firstLogicalCharacterIndex );
 
       // Get the metrics for the group of glyphs.
@@ -2025,7 +2012,6 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
 
   }
 
-
   // Return the logical position of the cursor in characters.
 
   if( !matched )
@@ -2033,7 +2019,7 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
     visualIndex = endCharacter;
   }
 
-  logicalIndex = hasRightToLeftCharacters ? *( visualToLogicalCursorBuffer + visualIndex ) : visualIndex;
+  logicalIndex = mLogicalModel->GetLogicalCursorIndex( visualIndex );
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "%p closest visualIndex %d logicalIndex %d\n", this, visualIndex, logicalIndex );
 
   DALI_ASSERT_DEBUG( ( logicalIndex <= mLogicalModel->mText.Count() && logicalIndex >= 0 ) && "GetClosestCursorIndex - Out of bounds index" );
index 37110dc..9180ec9 100644 (file)
@@ -1526,14 +1526,6 @@ bool Controller::DoRelayout( const Size& size,
           layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin();
           layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count();
 
-          // TODO: update the conversion map instead creating it from scratch.
-          //       Note this tables store indices to characters, so update the table means modify all the indices of the text after the last updated character.
-          //       It's better to refactor this. Store this table per line and don't update the indices.
-          //       For the cursor position probably is better to use the function instead creating a table.
-          // Set the bidirectional info into the model.
-          mImpl->mLogicalModel->SetVisualToLogicalMap( 0u,
-                                                       mImpl->mLogicalModel->mText.Count() );
-
           // Re-layout the text. Reorder those lines with right to left characters.
           mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters,
                                                          startIndex,