Fix for underlined text.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / shaper.cpp
index e70750c..5061193 100644 (file)
 #include <dali-toolkit/internal/text/shaper.h>
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/text-abstraction/shaping.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/font-run.h>
-#include <dali-toolkit/internal/text/logical-model.h>
-#include <dali-toolkit/internal/text/script.h>
-#include <dali-toolkit/internal/text/script-run.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali/devel-api/text-abstraction/shaping.h>
 
 namespace Dali
 {
@@ -48,8 +41,9 @@ void ShapeText( const Vector<Character>& text,
                 const Vector<ScriptRun>& scripts,
                 const Vector<FontRun>& fonts,
                 Vector<GlyphInfo>& glyphs,
-                Vector<CharacterIndex>& characterIndices,
-                Vector<Length>& charactersPerGlyph )
+                Vector<CharacterIndex>& glyphToCharacterMap,
+                Vector<Length>& charactersPerGlyph,
+                Vector<GlyphIndex>& newParagraphGlyphs )
 {
   const Length numberOfCharacters = text.Count();
 
@@ -74,7 +68,7 @@ void ShapeText( const Vector<Character>& text,
 
   // The text needs to be split in chunks of consecutive characters.
   // Each chunk must contain characters with the same font id and script set.
-  // A chunk of consecutive characters must not contain a LINE_MUST_BREAK, if there is one a new chunk have to be created.
+  // A chunk of consecutive characters must not contain a LINE_MUST_BREAK, if there is one a new chunk has to be created.
 
   TextAbstraction::Shaping shaping = TextAbstraction::Shaping::Get();
 
@@ -95,15 +89,15 @@ void ShapeText( const Vector<Character>& text,
 
   Length numberOfGlyphsReserved = static_cast<Length>( numberOfCharacters * 1.3f );
   glyphs.Resize( numberOfGlyphsReserved );
-  charactersPerGlyph.Resize( numberOfGlyphsReserved );
+  glyphToCharacterMap.Resize( numberOfGlyphsReserved );
 
   // The actual number of glyphs.
   Length totalNumberOfGlyphs = 0u;
 
-  const Character* textBuffer = text.Begin();
-  const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
+  const Character* const textBuffer = text.Begin();
+  const LineBreakInfo* const lineBreakInfoBuffer = lineBreakInfo.Begin();
   GlyphInfo* glyphsBuffer = glyphs.Begin();
-  Length* charactersPerGlyphBuffer = charactersPerGlyph.Begin();
+  CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
 
   // Traverse the characters and shape the text.
   for( previousIndex = 0; previousIndex < numberOfCharacters; )
@@ -121,27 +115,26 @@ void ShapeText( const Vector<Character>& text,
 
     // Check if there is a line must break.
     bool mustBreak = false;
+
+    // Check if the current index is a new paragraph character.
+    // A new paragraph character is going to be shaped in order to not to mess the conversion tables.
+    // However, the metrics need to be changed in order to not to draw a square.
+    bool isNewParagraph = false;
+
     for( CharacterIndex index = previousIndex; index < currentIndex; ++index )
     {
       mustBreak = TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index );
       if( mustBreak )
       {
-        currentIndex = index;
+        isNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + index ) );
+        currentIndex = index + 1u;
         break;
       }
     }
 
-    // Check if the current index is a white space. Do not want to shape a \n.
-    // The last character is always a must-break even if it's not a \n.
-    Length numberOfCharactersToShape = currentIndex - previousIndex;
-    if( mustBreak && !IsWhiteSpace( *( textBuffer + currentIndex ) ) )
-    {
-      ++numberOfCharactersToShape;
-    }
-
     // Shape the text for the current chunk.
     const Length numberOfGlyphs = shaping.Shape( textBuffer + previousIndex,
-                                                 numberOfCharactersToShape,
+                                                 ( currentIndex - previousIndex ), // The number of characters to shape.
                                                  currentFontId,
                                                  currentScript );
 
@@ -153,16 +146,33 @@ void ShapeText( const Vector<Character>& text,
       // Resize the vectors to get enough space.
       numberOfGlyphsReserved = static_cast<Length>( totalNumberOfGlyphs * 1.3f );
       glyphs.Resize( numberOfGlyphsReserved );
-      charactersPerGlyph.Resize( numberOfGlyphsReserved );
+      glyphToCharacterMap.Resize( numberOfGlyphsReserved );
 
       // Iterators are not valid anymore, set them again.
       glyphsBuffer = glyphs.Begin();
-      charactersPerGlyphBuffer = charactersPerGlyph.Begin();
+      glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
     }
 
     // Retrieve the glyphs and the glyph to character conversion map.
     shaping.GetGlyphs( glyphsBuffer + glyphIndex,
-                       charactersPerGlyphBuffer + glyphIndex );
+                       glyphToCharacterMapBuffer + glyphIndex );
+
+    if( isNewParagraph )
+    {
+      // Add the index of the new paragraph glyph to a vector.
+      // Their metrics will be updated in a following step.
+      newParagraphGlyphs.PushBack( totalNumberOfGlyphs - 1u );
+    }
+
+    // Update indices.
+    if( 0u != glyphIndex )
+    {
+      for( Length index = glyphIndex; index < glyphIndex + numberOfGlyphs; ++index )
+      {
+        CharacterIndex& characterIndex = *( glyphToCharacterMapBuffer + index );
+        characterIndex += previousIndex;
+      }
+    }
 
     // Update the iterators to get the next font or script run.
     if( currentIndex == fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters )
@@ -174,31 +184,27 @@ void ShapeText( const Vector<Character>& text,
       ++scriptRunIt;
     }
 
-    // Update the previous index. Jumps the \n if needed.
-    previousIndex = mustBreak ? currentIndex + 1u : currentIndex;
+    // Update the previous index.
+    previousIndex = currentIndex;
   }
 
-  characterIndices.Reserve( totalNumberOfGlyphs );
-  CharacterIndex characterIndex = 0u;
-  characterIndices.PushBack( characterIndex );
-  for( Length index = 0u, length = totalNumberOfGlyphs - 1u; index < length; ++index )
+  // Add the number of characters per glyph.
+  charactersPerGlyph.Reserve( totalNumberOfGlyphs );
+  previousIndex = 0u;
+  for( Length index = 1u; index < totalNumberOfGlyphs; ++index )
   {
-    characterIndex += *( charactersPerGlyphBuffer + index );
-    characterIndices.PushBack( characterIndex );
+    const CharacterIndex characterIndex = *( glyphToCharacterMapBuffer + index );
+
+    charactersPerGlyph.PushBack( characterIndex - previousIndex );
+
+    previousIndex = characterIndex;
   }
 
+  charactersPerGlyph.PushBack( numberOfCharacters - previousIndex );
+
   // Resize the vectors to set the right number of items.
   glyphs.Resize( totalNumberOfGlyphs );
-  // characterIndices.Resize( totalNumberOfGlyphs );
-  charactersPerGlyph.Resize( totalNumberOfGlyphs );
-}
-
-void ShapeText( const LogicalModel& logicalModel,
-                VisualModel& visualModel,
-                CharacterIndex characterIndex,
-                Length numberOfCharactersToRemove,
-                Length numberOfCharactersToInsert )
-{
+  glyphToCharacterMap.Resize( totalNumberOfGlyphs );
 }
 
 } // namespace Text