TextModel - Create paragraph info for a given range of characters inside a text.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-impl.cpp
index 4ac12b7..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;
@@ -367,6 +373,8 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     {
       // Retrieves the scripts used in the text.
       multilanguageSupport.SetScripts( utf32Characters,
+                                       startIndex,
+                                       requestedNumberOfCharacters,
                                        scripts );
     }
 
@@ -384,6 +392,8 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                                           scripts,
                                           fontDescriptionRuns,
                                           defaultFontId,
+                                          startIndex,
+                                          requestedNumberOfCharacters,
                                           validFonts );
     }
   }
@@ -412,15 +422,18 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     SetBidirectionalInfo( utf32Characters,
                           scripts,
                           lineBreakInfo,
+                          startIndex,
+                          requestedNumberOfCharacters,
                           bidirectionalInfo );
 
     if( 0u != bidirectionalInfo.Count() )
     {
       // Only set the character directions if there is right to left characters.
       Vector<CharacterDirection>& directions = mLogicalModel->mCharacterDirections;
-      directions.Resize( numberOfCharacters );
-
       GetCharactersDirection( bidirectionalInfo,
+                              numberOfCharacters,
+                              startIndex,
+                              requestedNumberOfCharacters,
                               directions );
 
       // This paragraph has right to left text. Some characters may need to be mirrored.
@@ -429,6 +442,8 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
       textMirrored = GetMirroredText( utf32Characters,
                                       directions,
                                       bidirectionalInfo,
+                                      startIndex,
+                                      requestedNumberOfCharacters,
                                       mirroredUtf32Characters );
     }
     else
@@ -444,6 +459,7 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
   Vector<GlyphIndex> newParagraphGlyphs;
   newParagraphGlyphs.Reserve( numberOfParagraphs );
 
+  GlyphIndex startGlyphIndex = 0u;
   if( SHAPE_TEXT & operations )
   {
     const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
@@ -452,21 +468,24 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                lineBreakInfo,
                scripts,
                validFonts,
+               startIndex,
+               startGlyphIndex,
+               requestedNumberOfCharacters,
                glyphs,
                glyphsToCharactersMap,
                charactersPerGlyph,
                newParagraphGlyphs );
 
     // Create the 'number of glyphs' per character and the glyph to character conversion tables.
-    mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters );
-    mVisualModel->CreateCharacterToGlyphTable( numberOfCharacters );
+    mVisualModel->CreateGlyphsPerCharacterTable( startIndex, numberOfCharacters );
+    mVisualModel->CreateCharacterToGlyphTable( startIndex, numberOfCharacters );
   }
 
   const Length numberOfGlyphs = glyphs.Count();
 
   if( GET_GLYPH_METRICS & operations )
   {
-    GlyphInfo* glyphsBuffer = glyphs.Begin();
+    GlyphInfo* glyphsBuffer = glyphs.Begin() + startGlyphIndex;
     mMetrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
 
     // Update the width and advance of all new paragraph characters.
@@ -665,7 +684,7 @@ void Controller::Impl::OnPanEvent( const Event& event )
   if( Gesture::Started    == state ||
       Gesture::Continuing == state )
   {
-    const Vector2& actualSize = mVisualModel->GetActualSize();
+    const Vector2& actualSize = mVisualModel->GetLayoutSize();
     const Vector2 currentScroll = mEventData->mScrollPosition;
 
     if( mEventData->mHorizontalScrollingEnabled )
@@ -820,7 +839,7 @@ void Controller::Impl::OnHandleEvent( const Event& event )
   else if( HANDLE_SCROLLING == state )
   {
     const float xSpeed = event.p2.mFloat;
-    const Vector2& actualSize = mVisualModel->GetActualSize();
+    const Vector2& actualSize = mVisualModel->GetLayoutSize();
     const Vector2 currentScrollPosition = mEventData->mScrollPosition;
 
     mEventData->mScrollPosition.x += xSpeed;
@@ -1891,6 +1910,25 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
     cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + ( isCurrentRightToLeft ? 0.f : glyphMetrics.advance );
     cursorInfo.secondaryPosition.y = cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight - line.descender - ( glyphMetrics.fontHeight - glyphMetrics.ascender );
   }
+
+  if( LayoutEngine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() )
+  {
+    // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control.
+
+    // Note the white spaces laid-out at the end of the line might exceed the boundaries of the control.
+    // The reason is a wrapped line must not start with a white space so they are laid-out at the end of the line.
+
+    if( 0.f > cursorInfo.primaryPosition.x )
+    {
+      cursorInfo.primaryPosition.x = 0.f;
+    }
+
+    const float edgeWidth = mVisualModel->mControlSize.width - static_cast<float>( mEventData->mDecorator->GetCursorWidth() );
+    if( cursorInfo.primaryPosition.x > edgeWidth )
+    {
+      cursorInfo.primaryPosition.x = edgeWidth;
+    }
+  }
 }
 
 CharacterIndex Controller::Impl::CalculateNewCursorIndex( CharacterIndex index ) const
@@ -2061,17 +2099,18 @@ void Controller::Impl::ScrollToMakePositionVisible( const Vector2& position )
   const float positionEnd = position.x + ( mEventData->mDecorator ? mEventData->mDecorator->GetCursorWidth() : 0.f );
 
   // Transform the position to decorator coords.
-  const float offset = mEventData->mScrollPosition.x + mAlignmentOffset.x;
+  const float alignment = IsShowingRealText() ? mAlignmentOffset.x : 0.f;
+  const float offset = mEventData->mScrollPosition.x + alignment;
   const float decoratorPositionBegin = position.x + offset;
   const float decoratorPositionEnd = positionEnd + offset;
 
   if( decoratorPositionBegin < 0.f )
   {
-    mEventData->mScrollPosition.x = -position.x - mAlignmentOffset.x;
+    mEventData->mScrollPosition.x = -position.x - alignment;
   }
   else if( decoratorPositionEnd > mVisualModel->mControlSize.width )
   {
-    mEventData->mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd - mAlignmentOffset.x;
+    mEventData->mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd - alignment;
   }
 }
 
@@ -2083,7 +2122,7 @@ void Controller::Impl::ScrollTextToMatchCursor( const CursorInfo& cursorInfo )
   // Calculate the offset to match the cursor position before the character was deleted.
   mEventData->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x - mAlignmentOffset.x;
 
-  ClampHorizontalScroll( mVisualModel->GetActualSize() );
+  ClampHorizontalScroll( mVisualModel->GetLayoutSize() );
 }
 
 void Controller::Impl::RequestRelayout()