Text - Fix for placement actor. 52/104852/3
authorVictor Cebollada <v.cebollada@samsung.com>
Wed, 14 Dec 2016 07:10:22 +0000 (07:10 +0000)
committerVíctor Cebollada <v.cebollada@samsung.com>
Fri, 16 Dec 2016 14:33:46 +0000 (06:33 -0800)
* Aligns the placement actor within the text control according with the alignment properties.

Change-Id: I62782283d13195081b56d395eecb854eb30f1df9
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
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 31d81af5de2bf1156054d330464bd951c19ce4c0..74ac7b5b9a07bd456d7a4dbdf108322d509dac90 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 80c46311a5f7db8b8edae664ceeeb1c0098cbb00..5f0885357e1ebe4f542394a8014cd99b4af5736a 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 6f04d64ff77787734ab88fe54f0eb8185ff017cf..aa2ca31f83af109288476eb0ffc07212c739f18c 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 51684a4f80108298df662e9a198812509e70af3e..fec052a95a54741cb596616ebbfe184dfca13ff0 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 123d0a4a7c2aecd910b5a123fa4677fd912482cb..2be707235c8081f6a81703eec2987226382267fd 100644 (file)
@@ -263,6 +263,7 @@ private: // Data
   Actor mRenderableActor;
   CallbackBase* mIdleCallback;
 
+  float mAlignmentOffset;
   int mRenderingBackend;
   bool mHasBeenStaged:1;
 };
index 7341032d1e87abef67cd0ae37185c75fd15d9eb6..44dc8514123a8101117c9e7ff7b6b933e25b8e6d 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 a532449098f51feaaada9a64aa23c93ffede0610..796e57f40ab317835dddc3480cd8f74e00f1bf5e 100644 (file)
@@ -274,6 +274,7 @@ private: // Data
   Actor mRenderableActor;
   CallbackBase* mIdleCallback;
 
+  float mAlignmentOffset;
   int mRenderingBackend;
   int mExceedPolicy;
   bool mHasBeenStaged:1;
index 0129388506534cdb6fe38808987390bf5fd5d6db..e4a8b533ec1e3b82ba05e4b833f39e5462a02e82 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 148ff583769e1a1443c8ff0fd459bd1729e8f8a2..17e9f58fd4436e0f52a89c17ec14f0cdf7f3dc12 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 71768ee8974a7e2a1c69dfe54717a91b3d997c99..0d1f7d4c48513ceff4a064e1a180b6b7a11d36ef 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 5ba07cee2b7c76670238a5d72a9fbcd2b347cf49..de437fb6cfb93458f11c7a061fb1130bb62dde8e 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 a6ae4b6e5dc51e7e7229889e1a0f6c67ef4ef734..2872395b30d96f9a790e994e456e2d1320ee1fbc 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 cc7c8f4ee02e7fe580d8422698cdb30cfa9c14ba..06781b83df23ca1c1b3ff0cd01a5db7134640198 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 b183524b2fa6bc1d87148cc3e2d7ad86e9680d3d..7f15b72d9ff7d5ebaa616a9298185e5cf4a31d42 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 0b7a44e35c3b15ef5958643b735317f55a829d64..9d95655b446e2d29ab0fa65f214c79e046af2b53 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 85f48ec7ee65404a3fbe1c1ca92598080d9fabd2..3a44c2f6e231480284a4749a7c95db03bcab8f19 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 714a1544d76391a44a07936db91da0a22321ac87..58def076a476730172e334ff009cdcf0ce8dcdfe 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 765dd317069ae58019719617f90078daf9baa318..e0dd85e4556742d27caf14a800d3689833f018f7 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 eaa191dfbee385d2d794c94fe91b1d1a241eb167..efa88adcefcaaf0da530ef1fd15a016ecb7f3c60 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 73334282c4d677c5e41ef06ff944043e01727cdd..88c9b42fbf46ac1ed1627414002c5dc68fcafab4 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 8ec9af1e03fc40f8b718e1e8add287561f858c71..d494d2b1da854cf1bff39397f4d21ec905b1fbb3 100644 (file)
@@ -75,6 +75,7 @@ public:
    */
   virtual Length GetGlyphs( GlyphInfo* glyphs,
                             Vector2* glyphPositions,
+                            float& minLineOffset,
                             GlyphIndex glyphIndex,
                             Length numberOfGlyphs ) const;