TextModel - Create paragraph info for a given range of characters inside a text. 69/65469/2
authorVictor Cebollada <v.cebollada@samsung.com>
Mon, 21 Mar 2016 08:42:21 +0000 (08:42 +0000)
committerVictor Cebollada <v.cebollada@samsung.com>
Mon, 11 Apr 2016 08:21:13 +0000 (09:21 +0100)
Change-Id: Ie6d241502e78a99a5be3343bf4da2761e6547d4c
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Segmentation.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/logical-model-impl.h
dali-toolkit/internal/text/paragraph-run.h [new file with mode: 0644]
dali-toolkit/internal/text/segmentation.cpp
dali-toolkit/internal/text/segmentation.h
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-definitions.h

index 9ec9930..fa28d61 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include <toolkit-text-model.h>
 
@@ -39,6 +40,26 @@ using namespace Text;
 
 namespace
 {
+struct CreateParagraphData
+{
+  std::string    description;                    ///< Description of the test.
+  std::string    text;                           ///< Input text.
+  CharacterIndex index;                          ///< The first character index.
+  Length         numberOfCharacters;             ///< The number of characters.
+  unsigned int   numberOfParagraphs;             ///< The expected number of paragraphs.
+  unsigned int*  indices;                        ///< The expected paragraph info indices.
+  unsigned int*  numberOfCharactersPerParagraph; ///< The expected number of characters of each paragraph.
+};
+
+struct FindParagraphData
+{
+  std::string    description;        ///< Description of the test.
+  std::string    text;               ///< Input text.
+  CharacterIndex index;              ///< The first character index.
+  Length         numberOfCharacters; ///< The number of characters.
+  unsigned int   numberOfParagraphs; ///< The expected number of paragraphs.
+  unsigned int*  paragraphs;         ///< The expected paragraph info.
+};
 
 struct SetVisualToLogicalMapData
 {
@@ -51,6 +72,109 @@ struct SetVisualToLogicalMapData
   unsigned int* visualToLogical;            ///< The expected visual to logical conversion table.
 };
 
+bool CreateParagraphTest( const CreateParagraphData& data )
+{
+  // 1) Create the model.
+  LogicalModelPtr logicalModel = LogicalModel::New();
+  VisualModelPtr visualModel = VisualModel::New();
+  Size textArea(100.f, 60.f);
+  Size layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  LayoutOptions options;
+  CreateTextModel( data.text,
+                   textArea,
+                   fontDescriptionRuns,
+                   options,
+                   layoutSize,
+                   logicalModel,
+                   visualModel );
+
+  // 2) Clear the paragraphs.
+  Vector<ParagraphRun>& paragraphs = logicalModel->mParagraphInfo;
+  ClearCharacterRuns( data.index,
+                      data.index + data.numberOfCharacters - 1u,
+                      paragraphs );
+
+  // 3) Call the LogicalModel::CreateParagraphInfo() method
+  logicalModel->CreateParagraphInfo( data.index,
+                                     data.numberOfCharacters );
+
+  // 4) Compare the results.
+  if( data.numberOfParagraphs != paragraphs.Count() )
+  {
+    std::cout << "  Different number of paragraphs : " << paragraphs.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
+    return false;
+  }
+
+  unsigned int index = 0u;
+  for( Vector<ParagraphRun>::ConstIterator it = paragraphs.Begin(),
+         endIt = paragraphs.End();
+       it != endIt;
+       ++it, ++index )
+  {
+    const ParagraphRun& paragraph( *it );
+
+    if( data.indices[index] != paragraph.characterRun.characterIndex )
+    {
+      std::cout << "  Different character index for paragraph : " << index << ", " << paragraph.characterRun.characterIndex << ", expected : " << data.indices[index] << std::endl;
+      return false;
+    }
+    if( data.numberOfCharactersPerParagraph[index] != paragraph.characterRun.numberOfCharacters )
+    {
+      std::cout << "  Different number of characters for paragraph : " << index << ", " << paragraph.characterRun.numberOfCharacters << ", expected : " << data.numberOfCharactersPerParagraph[index] << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool FindParagraphTest( const FindParagraphData& data )
+{
+  // 1) Create the model.
+  LogicalModelPtr logicalModel = LogicalModel::New();
+  VisualModelPtr visualModel = VisualModel::New();
+  Size textArea(100.f, 60.f);
+  Size layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  LayoutOptions options;
+  CreateTextModel( data.text,
+                   textArea,
+                   fontDescriptionRuns,
+                   options,
+                   layoutSize,
+                   logicalModel,
+                   visualModel );
+
+  // 2) Find the paragraphs.
+  Vector<ParagraphRunIndex> paragraphs;
+  logicalModel->FindParagraphs( data.index, data.numberOfCharacters, paragraphs );
+
+  // 3) compare the results.
+  if( data.numberOfParagraphs != paragraphs.Count() )
+  {
+    return false;
+  }
+
+  unsigned int index = 0u;
+  for( Vector<ParagraphRunIndex>::ConstIterator it = paragraphs.Begin(),
+         endIt = paragraphs.End();
+       it != endIt;
+       ++it, ++index )
+  {
+    const ParagraphRunIndex paragraphIndex = *it;
+
+    if( paragraphIndex != data.paragraphs[index] )
+    {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data )
 {
   std::cout << "  testing : " << data.description << std::endl;
@@ -106,10 +230,158 @@ bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data )
 } // namespace
 
 //////////////////////////////////////////////////////////
+//
+// UtcDaliCreateParagraph
+// UtcDaliFindParagraph
+// UtcDaliSetVisualToLogicalMap
+//
+//////////////////////////////////////////////////////////
 
-int UtcDaliSetVisualToLogicalMap(void)
+int UtcDaliCreateParagraph(void)
 {
   ToolkitTestApplication application;
+  tet_infoline(" UtcDaliCreateParagraph");
+
+  unsigned int paragraphsIndices01[] = { 0u };
+  unsigned int paragraphsNumberOfCharacters01[] = { 0u };
+  unsigned int paragraphsIndices02[] = { 0u, 12u, 17u };
+  unsigned int paragraphsNumberOfCharacters02[] = { 12u, 5u, 1u };
+  unsigned int paragraphsIndices03[] = { 0u, 12u, 17u, 34u };
+  unsigned int paragraphsNumberOfCharacters03[] = { 12u, 5u, 17u ,1u };
+
+  struct CreateParagraphData data[] =
+  {
+    {
+      "Zero characters",
+      "",
+      0u,
+      0u,
+      0u,
+      paragraphsIndices01,
+      paragraphsNumberOfCharacters01,
+    },
+    {
+      "Some paragraphs",
+      "Hello world\ndemo\n\n",
+      0u,
+      18u,
+      3u,
+      paragraphsIndices02,
+      paragraphsNumberOfCharacters02,
+    },
+    {
+      "Some paragraphs. Update the initial paragraphs.",
+      "Hello world\ndemo\nhello world demo\n\n",
+      0u,
+      17u,
+      4u,
+      paragraphsIndices03,
+      paragraphsNumberOfCharacters03,
+    },
+    {
+      "Some paragraphs. Update the mid paragraphs.",
+      "Hello world\ndemo\nhello world demo\n\n",
+      12u,
+      5u,
+      4u,
+      paragraphsIndices03,
+      paragraphsNumberOfCharacters03,
+    },
+    {
+      "Some paragraphs. Update the final paragraphs.",
+      "Hello world\ndemo\nhello world demo\n\n",
+      17u,
+      18u,
+      4u,
+      paragraphsIndices03,
+      paragraphsNumberOfCharacters03,
+    },
+  };
+  const unsigned int numberOfTests = 5u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    // ToolkitTestApplication application;
+    if( !CreateParagraphTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliFindParagraph(void)
+{
+  tet_infoline(" UtcDaliFindParagraph");
+
+  unsigned int paragraphs01[] = {};
+  unsigned int paragraphs02[] = { 0u, 1u, 2u };
+  unsigned int paragraphs03[] = { 0u };
+  unsigned int paragraphs04[] = { 1u };
+  unsigned int paragraphs05[] = { 0u, 1u, 2u };
+
+  struct FindParagraphData data[] =
+  {
+    {
+      "Zero characters",
+      "",
+      0u,
+      100u,
+      0u,
+      paragraphs01,
+    },
+    {
+      "Some paragraphs",
+      "Hello world\ndemo\n\n",
+      0u,
+      18u,
+      3u,
+      paragraphs02
+    },
+    {
+      "Some paragraphs",
+      "Hello world\ndemo\n\n",
+      0u,
+      12u,
+      1u,
+      paragraphs03
+    },
+    {
+      "Some paragraphs",
+      "Hello world\ndemo\n\n",
+      12u,
+      5u,
+      1u,
+      paragraphs04
+    },
+    {
+      "Some paragraphs",
+      "Hello world\ndemo\n\n",
+      3u,
+      15u,
+      3u,
+      paragraphs05
+    },
+  };
+  const unsigned int numberOfTests = 5u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !FindParagraphTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliSetVisualToLogicalMap(void)
+{
   tet_infoline(" UtcDaliSetVisualToLogicalMap");
 
   unsigned int* visualToLogical01 = NULL;
@@ -210,6 +482,7 @@ int UtcDaliSetVisualToLogicalMap(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !SetVisualToLogicalMapTest( data[index] ) )
     {
       tet_result(TET_FAIL);
index 0023240..5366164 100644 (file)
@@ -62,13 +62,31 @@ bool LineBreakInfoTest( const BreakInfoData& data )
 
   utf32.Resize( numberOfCharacters );
 
-  // 2) Set the line break info.
+  // 2) Set the line break info for the whole text.
   Vector<LineBreakInfo> lineBreakInfo;
   lineBreakInfo.Resize( numberOfCharacters );
 
-  SetLineBreakInfo( utf32, lineBreakInfo );
+  SetLineBreakInfo( utf32,
+                    0u,
+                    numberOfCharacters,
+                    lineBreakInfo );
+
+  // 3) Update the word text info if it's requested for part of the text.
+  if( ( 0u != data.index ) &&
+      ( numberOfCharacters != data.numberOfCharacters ) )
+  {
+    // Clear part of the line break info.
+    lineBreakInfo.Erase( lineBreakInfo.Begin() + data.index,
+                         lineBreakInfo.Begin() + data.index + data.numberOfCharacters );
 
-  // 3) compare the results
+    // Update the word line info.
+    SetLineBreakInfo( utf32,
+                      data.index,
+                      data.numberOfCharacters,
+                      lineBreakInfo );
+  }
+
+  // 4) compare the results
   std::ostringstream breakInfo;
 
   for( unsigned int index = 0u; index < numberOfCharacters; ++index )
@@ -78,8 +96,11 @@ bool LineBreakInfoTest( const BreakInfoData& data )
 
   if( data.breakInfo != breakInfo.str() )
   {
-    std::cout << "  expected : [" << data.breakInfo << "]" << std::endl;
-    std::cout << "       got : [" << breakInfo.str() << "]" << std::endl;
+    std::cout << "                text : [" << data.text << "]" << std::endl;
+    std::cout << "               index : " <<  data.index << std::endl;
+    std::cout << "  numberOfCharacters : " <<  data.numberOfCharacters << std::endl;
+    std::cout << "            expected : [" << data.breakInfo << "]" << std::endl;
+    std::cout << "                 got : [" << breakInfo.str() << "]" << std::endl;
     return false;
   }
 
@@ -149,7 +170,6 @@ bool WordBreakInfoTest( const BreakInfoData& data )
 
 int UtcDaliTextSegnemtationSetLineBreakInfo(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliTextSegnemtationSetLineBreakInfo");
 
   struct BreakInfoData data[] =
@@ -177,6 +197,51 @@ int UtcDaliTextSegnemtationSetLineBreakInfo(void)
       "222222122222221221222212212221222222122222222220",
     },
     {
+      "Latin script. Update initial paragraphs.",
+      "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+      "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+      "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+      "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+      "Quidam corpora at duo. An eos possim scripserit?",
+      0u,
+      141u,
+      "22222122222122222122212222212222212222222222122122221222221222222222122122220"
+      "2221221222212222222122222222221222222122222222122222222122212220"
+      "221222122222122222221222222222122212222221222222212220"
+      "22122222212222222122222222222122221222122222122222222222122222222222212220"
+      "222222122222221221222212212221222222122222222220",
+    },
+    {
+      "Latin script. Update mid paragraphs.",
+      "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+      "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+      "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+      "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+      "Quidam corpora at duo. An eos possim scripserit?",
+      141u,
+      128u,
+      "22222122222122222122212222212222212222222222122122221222221222222222122122220"
+      "2221221222212222222122222222221222222122222222122222222122212220"
+      "221222122222122222221222222222122212222221222222212220"
+      "22122222212222222122222222222122221222122222122222222222122222222222212220"
+      "222222122222221221222212212221222222122222222220",
+    },
+    {
+      "Latin script. Update final paragraphs.",
+      "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+      "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+      "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+      "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+      "Quidam corpora at duo. An eos possim scripserit?",
+      195u,
+      122u,
+      "22222122222122222122212222212222212222222222122122221222221222222222122122220"
+      "2221221222212222222122222222221222222122222222122222222122212220"
+      "221222122222122222221222222222122212222221222222212220"
+      "22122222212222222122222222222122221222122222122222222222122222222222212220"
+      "222222122222221221222212212221222222122222222220",
+    },
+    {
       "Japanese script",
       "韓国側は北朝鮮当局を通じて米ドルで賃金を支払う。\n"
       "国際社会から様々な経済制裁を受ける北朝鮮にとっては出稼ぎ労働などと並んで重要な外貨稼ぎの手段となっている。\n"
@@ -199,10 +264,11 @@ int UtcDaliTextSegnemtationSetLineBreakInfo(void)
       "21111112112111111111111211121111111111120",
     }
   };
-  const unsigned int numberOfTests = 4u;
+  const unsigned int numberOfTests = 7u;
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !LineBreakInfoTest( data[index] ) )
     {
       tet_result(TET_FAIL);
@@ -215,7 +281,6 @@ int UtcDaliTextSegnemtationSetLineBreakInfo(void)
 
 int UtcDaliTextSegnemtationSetWordBreakInfo(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliTextSegnemtationSetWordBreakInfo");
 
   struct BreakInfoData data[] =
@@ -380,6 +445,7 @@ int UtcDaliTextSegnemtationSetWordBreakInfo(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !WordBreakInfoTest( data[index] ) )
     {
       tet_result(TET_FAIL);
index 5bde6be..f07cfdc 100644 (file)
@@ -116,7 +116,10 @@ void CreateTextModel( const std::string& text,
   Vector<LineBreakInfo>& lineBreakInfo = logicalModel->mLineBreakInfo;
   lineBreakInfo.Resize( numberOfCharacters );
 
-  SetLineBreakInfo( utf32Characters, lineBreakInfo );
+  SetLineBreakInfo( utf32Characters,
+                    0u,
+                    numberOfCharacters,
+                    lineBreakInfo );
 
   if( 0u == numberOfCharacters )
   {
@@ -184,6 +187,10 @@ void CreateTextModel( const std::string& text,
                         numberOfCharacters,
                         bidirectionalInfo );
 
+  // Create the paragraph info.
+  logicalModel->CreateParagraphInfo( 0u,
+                                     numberOfCharacters );
+
   // 6) Set character directions.
   Vector<CharacterDirection>& characterDirections = logicalModel->mCharacterDirections;
   if( 0u != bidirectionalInfo.Count() )
index 8af3e91..239a2f8 100644 (file)
@@ -420,6 +420,131 @@ void LogicalModel::ClearFontDescriptionRuns()
   FreeFontFamilyNames( mFontDescriptionRuns );
 }
 
+void LogicalModel::CreateParagraphInfo( CharacterIndex startIndex,
+                                        Length numberOfCharacters )
+{
+  const Length totalNumberOfCharacters = mLineBreakInfo.Count();
+
+  // Count the number of LINE_MUST_BREAK to reserve some space for the vector of paragraph's info.
+  Vector<CharacterIndex> paragraphs;
+  paragraphs.Reserve( numberOfCharacters );
+  const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = mLineBreakInfo.Begin();
+  const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters;
+  for( Length index = startIndex; index < lastCharacterIndexPlusOne; ++index )
+  {
+    if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ) )
+    {
+      paragraphs.PushBack( index );
+    }
+  }
+
+  // Whether the current paragraphs are updated or set from scratch.
+  const bool updateCurrentParagraphs = numberOfCharacters < totalNumberOfCharacters;
+
+  // Reserve space for current paragraphs plus new ones.
+  const Length numberOfNewParagraphs = paragraphs.Count();
+  const Length totalNumberOfParagraphs = mParagraphInfo.Count() + numberOfNewParagraphs;
+  mParagraphInfo.Resize( totalNumberOfParagraphs );
+
+  ParagraphRun* paragraphInfoBuffer = NULL;
+  Vector<ParagraphRun> newParagraphs;
+
+  if( updateCurrentParagraphs )
+  {
+    newParagraphs.Resize( numberOfNewParagraphs );
+    paragraphInfoBuffer = newParagraphs.Begin();
+  }
+  else
+  {
+    paragraphInfoBuffer = mParagraphInfo.Begin();
+  }
+
+  // Find where to insert the new paragraphs.
+  ParagraphRunIndex paragraphIndex = 0u;
+  CharacterIndex firstIndex = startIndex;
+
+  if( updateCurrentParagraphs )
+  {
+    for( Vector<ParagraphRun>::ConstIterator it = mParagraphInfo.Begin(),
+           endIt = mParagraphInfo.Begin() + totalNumberOfParagraphs - numberOfNewParagraphs;
+         it != endIt;
+         ++it )
+    {
+      const ParagraphRun& paragraph( *it );
+
+      if( startIndex < paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters )
+      {
+        firstIndex = paragraph.characterRun.characterIndex;
+        break;
+      }
+
+      ++paragraphIndex;
+    }
+  }
+
+  // Create the paragraph info.
+  ParagraphRunIndex newParagraphIndex = 0u;
+  for( Vector<CharacterIndex>::ConstIterator it = paragraphs.Begin(),
+         endIt = paragraphs.End();
+       it != endIt;
+       ++it, ++newParagraphIndex )
+  {
+    const CharacterIndex index = *it;
+
+    ParagraphRun& paragraph = *( paragraphInfoBuffer + newParagraphIndex );
+    paragraph.characterRun.characterIndex = firstIndex;
+    paragraph.characterRun.numberOfCharacters = 1u + index - firstIndex;
+
+    firstIndex += paragraph.characterRun.numberOfCharacters;
+  }
+
+
+  // Insert the new paragraphs.
+  if( updateCurrentParagraphs )
+  {
+    mParagraphInfo.Insert( mParagraphInfo.Begin() + paragraphIndex,
+                           newParagraphs.Begin(),
+                           newParagraphs.End() );
+
+    mParagraphInfo.Resize( totalNumberOfParagraphs );
+
+    // Update the next paragraph indices.
+    for( Vector<ParagraphRun>::Iterator it = mParagraphInfo.Begin() + paragraphIndex + newParagraphs.Count(),
+           endIt = mParagraphInfo.End();
+         it != endIt;
+         ++it )
+    {
+      ParagraphRun& paragraph( *it );
+
+      paragraph.characterRun.characterIndex += numberOfCharacters;
+    }
+  }
+}
+
+void LogicalModel::FindParagraphs( CharacterIndex index,
+                                   Length numberOfCharacters,
+                                   Vector<ParagraphRunIndex>& paragraphs )
+{
+  // Reserve som space for the paragraph indices.
+  paragraphs.Reserve( mParagraphInfo.Count() );
+
+  // Traverse the paragraphs to find which ones contain the given characters.
+  ParagraphRunIndex paragraphIndex = 0u;
+  for( Vector<ParagraphRun>::ConstIterator it = mParagraphInfo.Begin(),
+         endIt = mParagraphInfo.End();
+       it != endIt;
+       ++it, ++paragraphIndex )
+  {
+    const ParagraphRun& paragraph( *it );
+
+    if( ( paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters > index ) &&
+        ( paragraph.characterRun.characterIndex < index + numberOfCharacters ) )
+    {
+      paragraphs.PushBack( paragraphIndex );
+    }
+  }
+}
+
 LogicalModel::~LogicalModel()
 {
   ClearFontDescriptionRuns();
index 7085d79..e41f0fa 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/font-run.h>
 #include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/paragraph-run.h>
 #include <dali-toolkit/internal/text/script-run.h>
 
 namespace Dali
@@ -136,6 +137,30 @@ public:
    */
   void ClearFontDescriptionRuns();
 
+  // Paragraphs
+
+  /**
+   * @brief Creates the paragraph info.
+   *
+   * @pre The line break info must be set.
+   *
+   * @param[in] startIndex The character from where the paragraph info is set.
+   * @param[in] numberOfCharacters The number of characters.
+   */
+  void CreateParagraphInfo( CharacterIndex startIndex,
+                            Length numberOfCharacters );
+
+  /**
+   * @brief Find the paragraphs which contains the given characters.
+   *
+   * @param[in] index The first character's index of the run.
+   * @param[in] numberOfCharacters The number of characters of the run.
+   * @param[out] paragraphs Indices to the paragraphs which contain the characters.
+   */
+  void FindParagraphs( CharacterIndex index,
+                       Length numberOfCharacters,
+                       Vector<ParagraphRunIndex>& paragraphs );
+
 protected:
 
   /**
@@ -165,6 +190,7 @@ public:
   Vector<FontDescriptionRun>            mFontDescriptionRuns;
   Vector<LineBreakInfo>                 mLineBreakInfo;
   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<BidirectionalLineInfoRun>      mBidirectionalLineInfo;
diff --git a/dali-toolkit/internal/text/paragraph-run.h b/dali-toolkit/internal/text/paragraph-run.h
new file mode 100644 (file)
index 0000000..7a90363
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __DALI_TOOLKIT_TEXT_PARAGRAPH_RUN_H__
+#define __DALI_TOOLKIT_TEXT_PARAGRAPH_RUN_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector2.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief ParagraphRun
+ *
+ * In terms of the bidirectional algorithm, a 'paragraph' is understood as a run of characters between Paragraph Separators or appropriate Newline Functions.
+ * A 'paragraph' may also be determined by higher-level protocols like a mark-up tag.
+ */
+struct ParagraphRun
+{
+  CharacterRun  characterRun; ///< The initial character index within the whole text and the number of characters of the run.
+  Size          layoutSize;   ///< The size of the paragraph when is laid-out.
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_PARAGRAPH_RUN_H__
index 5e590b5..61afef1 100644 (file)
@@ -50,21 +50,51 @@ namespace Text
 {
 
 void SetLineBreakInfo( const Vector<Character>& text,
+                       CharacterIndex startIndex,
+                       Length numberOfCharacters,
                        Vector<LineBreakInfo>& lineBreakInfo )
 {
-  const Length numberOfCharacters = text.Count();
+  const Length totalNumberOfCharacters = text.Count();
 
-  if( 0u == numberOfCharacters )
+  if( 0u == totalNumberOfCharacters )
   {
     // Nothing to do if there are no characters.
     return;
   }
 
   // Retrieve the line break info.
-  lineBreakInfo.Resize( numberOfCharacters );
-  TextAbstraction::Segmentation::Get().GetLineBreakPositions( text.Begin(),
+  lineBreakInfo.Resize( totalNumberOfCharacters );
+
+  // Whether the current buffer is being updated or is set from scratch.
+  const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
+
+  LineBreakInfo* lineBreakInfoBuffer = NULL;
+  Vector<LineBreakInfo> newLineBreakInfo;
+
+  if( updateCurrentBuffer )
+  {
+    newLineBreakInfo.Resize( numberOfCharacters );
+    lineBreakInfoBuffer = newLineBreakInfo.Begin();
+  }
+  else
+  {
+    lineBreakInfoBuffer = lineBreakInfo.Begin();
+  }
+
+  // Retrieve the line break info.
+  TextAbstraction::Segmentation::Get().GetLineBreakPositions( text.Begin() + startIndex,
                                                               numberOfCharacters,
-                                                              lineBreakInfo.Begin() );
+                                                              lineBreakInfoBuffer );
+
+  // If the line break info is updated, it needs to be inserted in the model.
+  if( updateCurrentBuffer )
+  {
+    lineBreakInfo.Insert( lineBreakInfo.Begin() + startIndex,
+                          newLineBreakInfo.Begin(),
+                          newLineBreakInfo.End() );
+    lineBreakInfo.Resize( totalNumberOfCharacters );
+  }
+
 #ifdef DEBUG_ENABLED
   if( gLogFilter->IsEnabledFor(Debug::Verbose) )
   {
index 61ddcc7..e23065a 100644 (file)
@@ -45,9 +45,13 @@ class LogicalModel;
  *  - 2 is a LINE_NO_BREAK.    Text can't be broken into a new line.
  *
  * @param[in] text Vector of UTF-32 characters.
+ * @param[in] startIndex The character from where the break info is set.
+ * @param[in] numberOfCharacters The number of characters.
  * @param[out] lineBreakInfo The line break info
  */
 void SetLineBreakInfo( const Vector<Character>& text,
+                       CharacterIndex startIndex,
+                       Length numberOfCharacters,
                        Vector<LineBreakInfo>& lineBreakInfo );
 
 /**
index d681730..78bd7e9 100644 (file)
@@ -336,7 +336,13 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     lineBreakInfo.Resize( numberOfCharacters, TextAbstraction::LINE_NO_BREAK );
 
     SetLineBreakInfo( utf32Characters,
+                      startIndex,
+                      requestedNumberOfCharacters,
                       lineBreakInfo );
+
+    // Create the paragraph info.
+    mLogicalModel->CreateParagraphInfo( startIndex,
+                                        requestedNumberOfCharacters );
   }
 
   Vector<WordBreakInfo>& wordBreakInfo = mLogicalModel->mWordBreakInfo;
index 4879090..0e9fb3f 100644 (file)
@@ -59,6 +59,7 @@ typedef uint32_t                         UnderlineRunIndex;         ///< An inde
 typedef uint32_t                         BidirectionalRunIndex;     ///< An index into an array of bidirectional info.
 typedef uint32_t                         BidirectionalLineRunIndex; ///< An index into an array of bidirectional line info.
 typedef uint32_t                         LineIndex;                 ///< An index into an array of lines.
+typedef uint32_t                         ParagraphRunIndex;         ///< An index into an array of paragraphs.
 
 } // namespace Text