Merge "Text - Fix for placement actor." into devel/master
authorPaul Wisbey <p.wisbey@samsung.com>
Fri, 16 Dec 2016 15:10:30 +0000 (07:10 -0800)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Fri, 16 Dec 2016 15:10:30 +0000 (07:10 -0800)
21 files changed:
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.h
dali-toolkit/internal/text/rendering/text-renderer.h
dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.cpp
dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-model.h
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h

index 31d81af..74ac7b5 100644 (file)
@@ -334,11 +334,13 @@ void CreateTextModel( const std::string& text,
 
   if( options.align )
   {
+    float alignmentOffset = 0.f;
     layoutEngine.Align( textArea,
                         0u,
                         numberOfCharacters,
                         Layout::HORIZONTAL_ALIGN_BEGIN,
-                        lines );
+                        lines,
+                        alignmentOffset );
   }
 }
 
index 80c4631..5f08853 100644 (file)
@@ -482,11 +482,13 @@ bool AlignTest( const AlignData& data )
   Layout::Engine engine;
   engine.SetMetrics( metrics );
 
+  float alignmentOffset = 0.f;
   engine.Align( data.textArea,
                 data.startIndex,
                 data.numberOfCharacters,
                 data.horizontalAlignment,
-                visualModel->mLines );
+                visualModel->mLines,
+                alignmentOffset );
 
   // Compare results.
   if( data.numberOfLines != visualModel->mLines.Count() )
index 6f04d64..aa2ca31 100644 (file)
@@ -450,6 +450,17 @@ int UtcDaliToolkitTextlabelAtlasRenderP(void)
     tet_result(TET_FAIL);
   }
 
+  try
+  {
+    // Render some text with the shared atlas backend
+    label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Text::RENDERING_VECTOR_BASED );
+    application.SendNotification();
+    application.Render();
+  }
+  catch( ... )
+  {
+    tet_result(TET_FAIL);
+  }
   END_TEST;
 }
 
index 51684a4..fec052a 100644 (file)
@@ -1092,7 +1092,9 @@ void TextEditor::RenderText( Text::Controller::UpdateTextType updateTextType )
   {
     if( mRenderer )
     {
-      renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT );
+      renderableActor = mRenderer->Render( mController->GetView(),
+                                           mAlignmentOffset,
+                                           DepthIndex::TEXT );
     }
 
     if( renderableActor != mRenderableActor )
@@ -1106,7 +1108,7 @@ void TextEditor::RenderText( Text::Controller::UpdateTextType updateTextType )
   {
     const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
 
-    mRenderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
+    mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset, scrollOffset.y );
 
     // Make sure the actors are parented correctly with/without clipping
     Actor self = mStencil ? mStencil : Self();
@@ -1398,6 +1400,7 @@ void TextEditor::OnIdleSignal()
 TextEditor::TextEditor()
 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
   mIdleCallback( NULL ),
+  mAlignmentOffset( 0.f ),
   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
   mHasBeenStaged( false )
 {
index 123d0a4..2be7072 100644 (file)
@@ -263,6 +263,7 @@ private: // Data
   Actor mRenderableActor;
   CallbackBase* mIdleCallback;
 
+  float mAlignmentOffset;
   int mRenderingBackend;
   bool mHasBeenStaged:1;
 };
index 7341032..44dc851 100644 (file)
@@ -1270,7 +1270,9 @@ void TextField::RenderText( Text::Controller::UpdateTextType updateTextType )
   {
     if( mRenderer )
     {
-      renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT );
+      renderableActor = mRenderer->Render( mController->GetView(),
+                                           mAlignmentOffset,
+                                           DepthIndex::TEXT );
     }
 
     if( renderableActor != mRenderableActor )
@@ -1284,7 +1286,7 @@ void TextField::RenderText( Text::Controller::UpdateTextType updateTextType )
   {
     const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
 
-    mRenderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
+    mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset, scrollOffset.y );
 
     // Make sure the actors are parented correctly with/without clipping
     Actor self = mStencil ? mStencil : Self();
@@ -1536,7 +1538,6 @@ void TextField::EnableClipping()
     mStencil.SetParentOrigin( ParentOrigin::CENTER );
 
     // Creates a background visual. Even if the color is transparent it updates the stencil.
-    // Property::Map backgroundMap;
     mStencil.SetProperty( Toolkit::Control::Property::BACKGROUND,
                           Property::Map().Add( Toolkit::Visual::Property::TYPE, DevelVisual::COLOR ).
                           Add( ColorVisual::Property::MIX_COLOR, Color::TRANSPARENT ) );
@@ -1597,6 +1598,7 @@ void TextField::OnIdleSignal()
 TextField::TextField()
 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
   mIdleCallback( NULL ),
+  mAlignmentOffset( 0.f ),
   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
   mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP ),
   mHasBeenStaged( false )
index a532449..796e57f 100644 (file)
@@ -274,6 +274,7 @@ private: // Data
   Actor mRenderableActor;
   CallbackBase* mIdleCallback;
 
+  float mAlignmentOffset;
   int mRenderingBackend;
   int mExceedPolicy;
   bool mHasBeenStaged:1;
index 0129388..e4a8b53 100644 (file)
@@ -726,9 +726,12 @@ void TextLabel::RenderText()
   Actor self = Self();
   Actor renderableActor;
 
+  float alignmentOffset = 0.f;
   if( mRenderer )
   {
-    renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT );
+    renderableActor = mRenderer->Render( mController->GetView(),
+                                         alignmentOffset,
+                                         DepthIndex::TEXT );
   }
 
   if( renderableActor != mRenderableActor )
@@ -738,7 +741,7 @@ void TextLabel::RenderText()
     if( renderableActor )
     {
       const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
-      renderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
+      renderableActor.SetPosition( scrollOffset.x + alignmentOffset, scrollOffset.y );
 
       self.Add( renderableActor );
     }
index 148ff58..17e9f58 100644 (file)
@@ -1078,10 +1078,12 @@ struct Engine::Impl
               CharacterIndex startIndex,
               Length numberOfCharacters,
               HorizontalAlignment horizontalAlignment,
-              Vector<LineRun>& lines )
+              Vector<LineRun>& lines,
+              float& alignmentOffset )
   {
     const CharacterIndex lastCharacterPlusOne = startIndex + numberOfCharacters;
 
+    alignmentOffset = MAX_FLOAT;
     // Traverse all lines and align the glyphs.
     for( Vector<LineRun>::Iterator it = lines.Begin(), endIt = lines.End();
          it != endIt;
@@ -1106,6 +1108,9 @@ struct Engine::Impl
       CalculateHorizontalAlignment( size.width,
                                     horizontalAlignment,
                                     line );
+
+      // Updates the alignment offset.
+      alignmentOffset = std::min( alignmentOffset, line.alignmentOffset );
     }
   }
 
@@ -1267,13 +1272,15 @@ void Engine::Align( const Size& size,
                     CharacterIndex startIndex,
                     Length numberOfCharacters,
                     Layout::HorizontalAlignment horizontalAlignment,
-                    Vector<LineRun>& lines )
+                    Vector<LineRun>& lines,
+                    float& alignmentOffset )
 {
   mImpl->Align( size,
                 startIndex,
                 numberOfCharacters,
                 horizontalAlignment,
-                lines );
+                lines,
+                alignmentOffset );
 }
 
 void Engine::SetDefaultLineSpacing( float lineSpacing )
index 71768ee..0d1f7d4 100644 (file)
@@ -139,12 +139,14 @@ public:
    * @param[in] numberOfCharacters The number of characters.
    * @param[in] horizontalAlignment The horizontal alignment.
    * @param[in,out] lines The laid-out lines.
+   * @param[out] alignmentOffset The alignment offset.
    */
   void Align( const Size& size,
               CharacterIndex startIndex,
               Length numberOfCharacters,
               Layout::HorizontalAlignment horizontalAlignment,
-              Vector<LineRun>& lines );
+              Vector<LineRun>& lines,
+              float& alignmentOffset );
 
   /**
    * @brief Sets the default line spacing.
index 5ba07ce..de437fb 100644 (file)
@@ -168,7 +168,8 @@ struct AtlasRenderer::Impl
                   const Vector4& defaultColor,
                   const Vector4* const colorsBuffer,
                   const ColorIndex* const colorIndicesBuffer,
-                  int depth )
+                  int depth,
+                  float minLineOffset )
   {
     AtlasManager::AtlasSlot slot;
     std::vector< MeshRecord > meshContainer;
@@ -214,11 +215,11 @@ struct AtlasRenderer::Impl
     Vector< TextCacheEntry > newTextCache;
     const GlyphInfo* const glyphsBuffer = glyphs.Begin();
     const Vector2* const positionsBuffer = positions.Begin();
+    const Vector2 lineOffsetPosition( minLineOffset, 0.f );
 
     for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i )
     {
       const GlyphInfo& glyph = *( glyphsBuffer + i );
-
       const bool underlineGlyph = underlineEnabled || IsGlyphUnderlined( i, underlineRuns );
       thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph;
 
@@ -325,7 +326,7 @@ struct AtlasRenderer::Impl
         }
 
         // Move the origin (0,0) of the mesh to the center of the actor
-        const Vector2 position = *( positionsBuffer + i ) - halfTextSize;
+        const Vector2 position = *( positionsBuffer + i ) - halfTextSize - lineOffsetPosition;
 
         // Generate mesh data for this quad, plugging in our supplied position
         AtlasManager::Mesh2D newMesh;
@@ -735,7 +736,9 @@ Text::RendererPtr AtlasRenderer::New()
   return Text::RendererPtr( new AtlasRenderer() );
 }
 
-Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth )
+Actor AtlasRenderer::Render( Text::ViewInterface& view,
+                             float& alignmentOffset,
+                             int depth )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "Text::AtlasRenderer::Render()\n" );
 
@@ -753,6 +756,7 @@ Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth )
 
     numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
                                      positions.Begin(),
+                                     alignmentOffset,
                                      0u,
                                      numberOfGlyphs );
 
@@ -769,7 +773,8 @@ Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth )
                       defaultColor,
                       colorsBuffer,
                       colorIndicesBuffer,
-                      depth );
+                      depth,
+                      alignmentOffset );
 
     /* In the case where AddGlyphs does not create a renderable Actor for example when glyphs are all whitespace create a new Actor. */
     /* This renderable actor is used to position the text, other "decorations" can rely on there always being an Actor regardless of it is whitespace or regular text. */
index a6ae4b6..2872395 100644 (file)
@@ -44,13 +44,11 @@ public:
   static RendererPtr New();
 
   /**
-   * @brief Render the glyphs from a ViewInterface.
-   *
-   * @param[in] view The interface to a view.
-   * @param[in] depth The depth in the tree of the parent.
-   * @return The Renderable actor used to position the text.
+   * @copydoc Renderer::Render()
    */
-  virtual Actor Render( ViewInterface& view, int depth );
+  virtual Actor Render( ViewInterface& view,
+                        float& alignmentOffset,
+                        int depth );
 
 protected:
 
index cc7c8f4..06781b8 100644 (file)
@@ -51,10 +51,13 @@ public:
    * @brief Render the glyphs from a ViewInterface.
    *
    * @param[in] view The interface to a view.
+   * @param[out] alignmentOffset Offset used to internally align the placement actor.
    * @param[in] depth The depth in the tree of the parent.
    * @return The Renderable actor used to position the text.
    */
-  virtual Actor Render( ViewInterface& view, int depth ) = 0;
+  virtual Actor Render( ViewInterface& view,
+                        float& alignmentOffset,
+                        int depth ) = 0;
 
 protected:
 
index b183524..7f15b72 100644 (file)
@@ -181,7 +181,9 @@ Text::RendererPtr VectorBasedRenderer::New()
   return Text::RendererPtr( new VectorBasedRenderer() );
 }
 
-Actor VectorBasedRenderer::Render( Text::ViewInterface& view, int /*depth*/ )
+Actor VectorBasedRenderer::Render( Text::ViewInterface& view,
+                                   float& alignmentOffset,
+                                   int /*depth*/ )
 {
   UnparentAndReset( mImpl->mActor );
 
@@ -205,8 +207,10 @@ Actor VectorBasedRenderer::Render( Text::ViewInterface& view, int /*depth*/ )
 
     numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
                                      positions.Begin(),
+                                     alignmentOffset,
                                      0u,
                                      numberOfGlyphs );
+
     glyphs.Resize( numberOfGlyphs );
     positions.Resize( numberOfGlyphs );
 
@@ -218,7 +222,7 @@ Actor VectorBasedRenderer::Render( Text::ViewInterface& view, int /*depth*/ )
     Vector< unsigned short > indices;
 
     const Vector2& controlSize = view.GetControlSize();
-    float xOffset = controlSize.width  * -0.5f;
+    float xOffset = -alignmentOffset + controlSize.width * -0.5f;
     float yOffset = controlSize.height * -0.5f;
 
     if( ! mImpl->mAtlas ||
index 0b7a44e..9d95655 100644 (file)
@@ -44,13 +44,11 @@ public:
   static RendererPtr New();
 
   /**
-   * @brief Render the glyphs from a ViewInterface.
-   *
-   * @param[in] view The interface to a view.
-   * @param[in] depth The depth in the tree of the parent.
-   * @return The Renderable actor used to position the text.
+   * @copydoc Renderer::Render()
    */
-  virtual Actor Render( ViewInterface& view, int depth );
+  virtual Actor Render( ViewInterface& view,
+                        float& alignmentOffset,
+                        int depth );
 
 protected:
 
index 85f48ec..3a44c2f 100644 (file)
@@ -2668,13 +2668,13 @@ void Controller::Impl::UpdateSelectionHandle( HandleType handleType,
 
 void Controller::Impl::ClampHorizontalScroll( const Vector2& layoutSize )
 {
-  // Clamp between -space & 0.
+  // Clamp between -space & -alignment offset.
 
   if( layoutSize.width > mModel->mVisualModel->mControlSize.width )
   {
-    const float space = ( layoutSize.width - mModel->mVisualModel->mControlSize.width );
+    const float space = ( layoutSize.width - mModel->mVisualModel->mControlSize.width ) + mModel->mAlignmentOffset;
     mModel->mScrollPosition.x = ( mModel->mScrollPosition.x < -space ) ? -space : mModel->mScrollPosition.x;
-    mModel->mScrollPosition.x = ( mModel->mScrollPosition.x > 0.f ) ? 0.f : mModel->mScrollPosition.x;
+    mModel->mScrollPosition.x = ( mModel->mScrollPosition.x > -mModel->mAlignmentOffset ) ? -mModel->mAlignmentOffset : mModel->mScrollPosition.x;
 
     mEventData->mDecoratorUpdated = true;
   }
index 714a154..58def07 100644 (file)
@@ -2674,11 +2674,14 @@ bool Controller::DoRelayout( const Size& size,
     // The laid-out lines.
     Vector<LineRun>& lines = mImpl->mModel->mVisualModel->mLines;
 
+    // Need to align with the control's size as the text may contain lines
+    // starting either with left to right text or right to left.
     mImpl->mLayoutEngine.Align( size,
                                 startIndex,
                                 requestedNumberOfCharacters,
                                 mImpl->mModel->mHorizontalAlignment,
-                                lines );
+                                lines,
+                                mImpl->mModel->mAlignmentOffset );
 
     viewUpdated = true;
   }
index 765dd31..e0dd85e 100644 (file)
@@ -158,6 +158,7 @@ public:
   Vector2                     mScrollPosition;      ///< The text is offset by this position when scrolling.
   Layout::HorizontalAlignment mHorizontalAlignment; ///< The layout's horizontal alignment.
   Layout::VerticalAlignment   mVerticalAlignment;   ///< The layout's vertical alignment.
+  float                       mAlignmentOffset;     ///< The alignment offset.
   bool                        mElideEnabled:1;      ///< Whether the text's elide is enabled.
 };
 
index eaa191d..efa88ad 100644 (file)
@@ -87,6 +87,7 @@ public:
    *
    * @param[out] glyphs Pointer to a buffer where the glyphs are copied.
    * @param[out] glyphPositions Pointer to a buffer where the glyph's positions are copied.
+   * @param[out] minLineOffset The minimum line offset.
    * @param[in] glyphIndex Index to the first glyph.
    * @param[in] numberOfGlyphs Number of glyphs to be copied.
    *
@@ -94,6 +95,7 @@ public:
    */
   virtual Length GetGlyphs( GlyphInfo* glyphs,
                             Vector2* glyphPositions,
+                            float& minLineOffset,
                             GlyphIndex glyphIndex,
                             Length numberOfGlyphs ) const = 0;
 
index 7333428..88c9b42 100644 (file)
@@ -94,6 +94,7 @@ Length View::GetNumberOfGlyphs() const
 
 Length View::GetGlyphs( GlyphInfo* glyphs,
                         Vector2* glyphPositions,
+                        float& minLineOffset,
                         GlyphIndex glyphIndex,
                         Length numberOfGlyphs ) const
 {
@@ -157,6 +158,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
 
         // Add the alignment offset to the glyph's position.
 
+        minLineOffset = line->alignmentOffset;
         float penY = line->ascender;
         for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index )
         {
@@ -174,6 +176,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
             if( lineIndex < numberOfLines )
             {
               line = lineBuffer + lineIndex;
+              minLineOffset = std::min( minLineOffset, line->alignmentOffset );
 
               lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u;
 
index 8ec9af1..d494d2b 100644 (file)
@@ -75,6 +75,7 @@ public:
    */
   virtual Length GetGlyphs( GlyphInfo* glyphs,
                             Vector2* glyphPositions,
+                            float& minLineOffset,
                             GlyphIndex glyphIndex,
                             Length numberOfGlyphs ) const;