Underline predictive text. 73/44873/2
authorVictor Cebollada <v.cebollada@samsung.com>
Tue, 28 Jul 2015 08:43:37 +0000 (09:43 +0100)
committerPaul Wisbey <p.wisbey@samsung.com>
Thu, 30 Jul 2015 11:06:17 +0000 (04:06 -0700)
Change-Id: I4675891596c6db239e4f58a5c372ad18fd4d2194
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
17 files changed:
dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp
dali-toolkit/internal/atlas-manager/atlas-manager-impl.h
dali-toolkit/internal/atlas-manager/atlas-manager.cpp
dali-toolkit/internal/atlas-manager/atlas-manager.h
dali-toolkit/internal/text/glyph-run.h [new file with mode: 0644]
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/line-run.h
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-definitions.h
dali-toolkit/internal/text/text-io.cpp
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/text/visual-model-impl.cpp
dali-toolkit/internal/text/visual-model-impl.h

index 3e69856..bfcf1fa 100644 (file)
@@ -489,16 +489,22 @@ void AtlasManager::StitchMesh( Toolkit::AtlasManager::Mesh2D& first,
                                const Toolkit::AtlasManager::Mesh2D& second,
                                bool optimize )
 {
-  uint32_t vc = first.mVertices.Size();
+  const uint32_t verticesCount = first.mVertices.Size();
+  first.mVertices.Insert( first.mVertices.End(),
+                          second.mVertices.Begin(),
+                          second.mVertices.End() );
 
-  for ( uint32_t v = 0; v < second.mVertices.Size(); ++v )
-  {
-    first.mVertices.PushBack( second.mVertices[ v ] );
-  }
+  const uint32_t indicesCount = first.mIndices.Size();
+  first.mIndices.Insert( first.mIndices.End(),
+                         second.mIndices.Begin(),
+                         second.mIndices.End() );
 
-  for ( uint32_t i = 0; i < second.mIndices.Size(); ++i )
+  for( Vector<unsigned int>::Iterator it = first.mIndices.Begin() + indicesCount,
+         endIt = first.mIndices.End();
+       it != endIt;
+       ++it )
   {
-    first.mIndices.PushBack( second.mIndices[ i ] + vc );
+    *it += verticesCount;
   }
 
   if ( optimize )
@@ -509,41 +515,6 @@ void AtlasManager::StitchMesh( Toolkit::AtlasManager::Mesh2D& first,
   }
 }
 
-void AtlasManager::StitchMesh( const Toolkit::AtlasManager::Mesh2D& first,
-                               const Toolkit::AtlasManager::Mesh2D& second,
-                               Toolkit::AtlasManager::Mesh2D& out,
-                               bool optimize )
-{
-  uint32_t vc = first.mVertices.Size();
-
-  for ( uint32_t v = 0; v < vc; ++v )
-  {
-    out.mVertices.PushBack( first.mVertices[ v ] );
-  }
-
-  for ( uint32_t v = 0; v < second.mVertices.Size(); ++v )
-  {
-    out.mVertices.PushBack( second.mVertices[ v ] );
-  }
-
-  for ( uint32_t i = 0; i < first.mIndices.Size(); ++i )
-  {
-    out.mIndices.PushBack( first.mIndices[ i ] );
-  }
-
-  for ( uint32_t i = 0; i < second.mIndices.Size(); ++i )
-  {
-    out.mIndices.PushBack( second.mIndices[ i ] + vc );
-  }
-
-  if ( optimize )
-  {
-    Toolkit::AtlasManager::Mesh2D optimizedMesh;
-    OptimizeMesh( out, optimizedMesh );
-    out = optimizedMesh;
-  }
-}
-
 void AtlasManager::UploadImage( const BufferImage& image,
                                 const AtlasSlotDescriptor& desc )
 {
index b22f709..5b301f0 100644 (file)
@@ -122,14 +122,6 @@ public:
                    bool optimize );
 
   /**
-   * @copydoc Toolkit::AtlasManager::StitchMesh
-   */
-  void StitchMesh(  const Toolkit::AtlasManager::Mesh2D& first,
-                    const Toolkit::AtlasManager::Mesh2D& second,
-                    Toolkit::AtlasManager::Mesh2D& out,
-                    bool optimize );
-
-  /**
    * @copydoc Toolkit::AtlasManager::Remove
    */
   bool Remove( ImageId id );
@@ -249,4 +241,4 @@ inline Internal::AtlasManager& GetImplementation(Toolkit::AtlasManager& manager)
 } // namespace Dali
 
 
- #endif // __DALI_TOOLKIT_ATLAS_MANAGER_IMPL_H__
\ No newline at end of file
+ #endif // __DALI_TOOLKIT_ATLAS_MANAGER_IMPL_H__
index e6b041c..849b27d 100644 (file)
@@ -85,14 +85,6 @@ void AtlasManager::StitchMesh( Mesh2D& first,
   GetImplementation(*this).StitchMesh( first, second, optimize );
 }
 
-void AtlasManager::StitchMesh( const Mesh2D& first,
-                               const Mesh2D& second,
-                               Mesh2D& out,
-                               bool optimize )
-{
-  GetImplementation(*this).StitchMesh( first, second, out, optimize );
-}
-
 Dali::Atlas AtlasManager::GetAtlasContainer( AtlasId atlas ) const
 {
   return GetImplementation(*this).GetAtlasContainer( atlas );
index 532be6f..2c7f192 100644 (file)
@@ -313,19 +313,6 @@ public:
                    bool optimize = false );
 
   /**
-   * @brief Combine two meshes, outputting the result into a new mesh
-   *
-   * @param[in] first First mesh
-   * @param[in] second Second mesh
-   * @param[in] optimize should we optimize vertex data
-   * @param[out] out resulting mesh
-   */
-  void StitchMesh( const Mesh2D& first,
-                   const Mesh2D& second,
-                   Mesh2D& out,
-                   bool optimize = false );
-
-  /**
    * @brief Get the BufferImage containing an atlas
    *
    * @param[in] atlas AtlasId returned when atlas was created
diff --git a/dali-toolkit/internal/text/glyph-run.h b/dali-toolkit/internal/text/glyph-run.h
new file mode 100644 (file)
index 0000000..47ebfb8
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __DALI_TOOLKIT_TEXT_GLYPH_RUN_H__
+#define __DALI_TOOLKIT_TEXT_GLYPH_RUN_H__
+
+/*
+ * Copyright (c) 2015 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief A run of consecutive glyphs.
+ */
+struct GlyphRun
+{
+  GlyphIndex glyphIndex;     ///< Index to the first glyph.
+  Length     numberOfGlyphs; ///< Number of glyphs in the run.
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_GLYPH_RUN_H__
index 25ea95a..5a28904 100644 (file)
@@ -527,11 +527,11 @@ struct LayoutEngine::Impl
 
           penY -= layout.ascender - lineRun.descender;
 
-          ellipsisLayout.glyphIndex = lineRun.glyphIndex;
+          ellipsisLayout.glyphIndex = lineRun.glyphRun.glyphIndex;
         }
         else
         {
-          lineRun.glyphIndex = 0u;
+          lineRun.glyphRun.glyphIndex = 0u;
           ellipsisLayout.glyphIndex = 0u;
         }
 
@@ -540,7 +540,7 @@ struct LayoutEngine::Impl
                              currentParagraphDirection,
                              true );
 
-        lineRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs;
+        lineRun.glyphRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs;
         lineRun.characterRun.characterIndex = ellipsisLayout.characterIndex;
         lineRun.characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
         lineRun.width = ellipsisLayout.length;
@@ -553,10 +553,10 @@ struct LayoutEngine::Impl
         actualSize.width = layoutParameters.boundingBox.width;
         actualSize.height += ( lineRun.ascender + -lineRun.descender );
 
-        SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun.glyphIndex,
+        SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun.glyphRun.glyphIndex,
                            ellipsisLayout.numberOfGlyphs,
                            penY,
-                           glyphPositions.Begin() + lineRun.glyphIndex );
+                           glyphPositions.Begin() + lineRun.glyphRun.glyphIndex );
 
         if( 0u != numberOfLines )
         {
@@ -576,8 +576,8 @@ struct LayoutEngine::Impl
         const bool isLastLine = index + layout.numberOfGlyphs == layoutParameters.totalNumberOfGlyphs;
 
         LineRun lineRun;
-        lineRun.glyphIndex = index;
-        lineRun.numberOfGlyphs = layout.numberOfGlyphs;
+        lineRun.glyphRun.glyphIndex = index;
+        lineRun.glyphRun.numberOfGlyphs = layout.numberOfGlyphs;
         lineRun.characterRun.characterIndex = layout.characterIndex;
         lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
         if( isLastLine && !layoutParameters.isLastNewParagraph )
@@ -635,8 +635,8 @@ struct LayoutEngine::Impl
           mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics );
 
           LineRun lineRun;
-          lineRun.glyphIndex = 0u;
-          lineRun.numberOfGlyphs = 0u;
+          lineRun.glyphRun.glyphIndex = 0u;
+          lineRun.glyphRun.numberOfGlyphs = 0u;
           lineRun.characterRun.characterIndex = 0u;
           lineRun.characterRun.numberOfCharacters = 0u;
           lineRun.width = 0.f;
index 6909182..52df79e 100644 (file)
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/glyph-run.h>
 
 namespace Dali
 {
@@ -35,9 +36,8 @@ namespace Text
  */
 struct LineRun
 {
-  GlyphIndex         glyphIndex;      ///< The initial glyph index.
-  Length             numberOfGlyphs;  ///< The number of glyphs of the run.
-  CharacterRun       characterRun;    ///< The initial character and the number of characters.
+  GlyphRun           glyphRun;        ///< The initial glyph index and the number of glyphs of the run.
+  CharacterRun       characterRun;    ///< The initial character index and the number of characters of the run.
   float              width;           ///< The line's width.
   float              ascender;        ///< The line's ascender.
   float              descender;       ///< The line's descender.
index ce937a8..5ba6740 100644 (file)
@@ -1,4 +1,3 @@
-
 #ifndef __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
 #define __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
 
@@ -185,5 +184,4 @@ inline Internal::AtlasGlyphManager& GetImplementation(Toolkit::AtlasGlyphManager
 
 } // namespace Dali
 
-
- #endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
+#endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
index 2e94ce1..42961ce 100644 (file)
@@ -30,6 +30,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/internal/text/glyph-run.h>
 #include <dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h>
 #include <dali-toolkit/internal/text/text-view.h>
 
@@ -72,6 +73,10 @@ struct AtlasRenderer::Impl : public ConnectionTracker
     FrameBufferImage mBuffer;
   };
 
+  /**
+   * brief Struct used to generate the underline mesh.
+   * There is one Extent per line of text.
+   */
   struct Extent
   {
     Extent()
@@ -143,8 +148,30 @@ struct AtlasRenderer::Impl : public ConnectionTracker
     mQuadIndexFormat[ "indices" ] = Property::INTEGER;
   }
 
+  bool IsGlyphUnderlined( GlyphIndex index,
+                          const Vector<GlyphRun>& underlineRuns )
+  {
+    // TODO: At the moment it works because we always traverse the glyphs starting from the beginning
+    //       and there is only one glyph run! If there are more they should be ordered.
+
+    for( Vector<GlyphRun>::ConstIterator it = underlineRuns.Begin(),
+           endIt = underlineRuns.End();
+           it != endIt;
+         ++it )
+    {
+      const GlyphRun& run = *it;
+
+      if( ( run.glyphIndex <= index ) && ( index < run.glyphIndex + run.numberOfGlyphs ) )
+      {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
   void AddGlyphs( Text::ViewInterface& view,
-                  const std::vector<Vector2>& positions,
+                  const Vector<Vector2>& positions,
                   const Vector<GlyphInfo>& glyphs,
                   int depth )
   {
@@ -155,18 +182,29 @@ struct AtlasRenderer::Impl : public ConnectionTracker
     mDepth = depth;
 
     const Vector2& actorSize( view.GetControlSize() );
-    Vector2 halfActorSize( actorSize * 0.5f );
+    const Vector2 halfActorSize( actorSize * 0.5f );
     const Vector4& textColor( view.GetTextColor() );
     const Vector2& shadowOffset( view.GetShadowOffset() );
     const Vector4& shadowColor( view.GetShadowColor() );
-    bool underlineEnabled( view.IsUnderlineEnabled() );
+    const bool underlineEnabled( view.IsUnderlineEnabled() );
     const Vector4& underlineColor( view.GetUnderlineColor() );
-    float underlineHeight( view.GetUnderlineHeight() );
+    const float underlineHeight( view.GetUnderlineHeight() );
+
+    // Get the underline runs.
+    const Length numberOfUnderlineRuns = view.GetNumberOfUnderlineRuns();
+    Vector<GlyphRun> underlineRuns;
+    underlineRuns.Resize( numberOfUnderlineRuns );
+    view.GetUnderlineRuns( underlineRuns.Begin(),
+                           0u,
+                           numberOfUnderlineRuns );
+
+    bool thereAreUnderlinedGlyphs = false;
 
     float currentUnderlinePosition = ZERO;
     float currentUnderlineThickness = underlineHeight;
     uint32_t currentBlockSize = 0;
     FontId lastFontId = 0;
+    FontId lastUnderlinedFontId = 0;
     Style style = STYLE_NORMAL;
 
     if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 )
@@ -179,16 +217,20 @@ struct AtlasRenderer::Impl : public ConnectionTracker
     // Avoid emptying mTextCache (& removing references) until after incremented references for the new text
     Vector< TextCacheEntry > newTextCache;
     const GlyphInfo* const glyphsBuffer = glyphs.Begin();
+    const Vector2* const positionsBuffer = positions.Begin();
 
     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;
+
       // No operation for white space
       if ( glyph.width && glyph.height )
       {
         // Are we still using the same fontId as previous
-        if ( glyph.fontId != lastFontId )
+        if ( underlineGlyph && ( glyph.fontId != lastUnderlinedFontId ) )
         {
           // We need to fetch fresh font underline metrics
           FontMetrics fontMetrics;
@@ -221,7 +263,9 @@ struct AtlasRenderer::Impl : public ConnectionTracker
             // Move offset down by one ( EFL behavior )
             currentUnderlinePosition = ONE;
           }
-        }
+
+          lastUnderlinedFontId = glyph.fontId;
+        } // underline
 
         if ( !mGlyphManager.Cached( glyph.fontId, glyph.index, slot ) )
         {
@@ -277,7 +321,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker
         }
 
         // Move the origin (0,0) of the mesh to the center of the actor
-        Vector2 position = positions[ i ] - halfActorSize;
+        Vector2 position = *( positionsBuffer + i ) - halfActorSize;
 
         // Generate mesh data for this quad, plugging in our supplied position
         AtlasManager::Mesh2D newMesh;
@@ -293,6 +337,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker
                         extents,
                         textColor,
                         position.y + glyph.yBearing,
+                        underlineGlyph,
                         currentUnderlinePosition,
                         currentUnderlineThickness,
                         slot );
@@ -304,7 +349,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker
     RemoveText();
     mTextCache.Swap( newTextCache );
 
-    if ( underlineEnabled )
+    if( thereAreUnderlinedGlyphs )
     {
       // Check to see if any of the text needs an underline
       GenerateUnderlines( meshContainer, extents, underlineColor, textColor );
@@ -396,6 +441,7 @@ struct AtlasRenderer::Impl : public ConnectionTracker
                        Vector< Extent >& extents,
                        const Vector4& color,
                        float baseLine,
+                       bool underlineGlyph,
                        float underlinePosition,
                        float underlineThickness,
                        AtlasManager::AtlasSlot& slot )
@@ -416,14 +462,19 @@ struct AtlasRenderer::Impl : public ConnectionTracker
         {
           // Stitch the mesh to the existing mesh and adjust any extents
           mGlyphManager.StitchMesh( mIt->mMesh, newMesh );
-          AdjustExtents( extents,
-                         meshContainer,
-                         index,
-                         left,
-                         right,
-                         baseLine,
-                         underlinePosition,
-                         underlineThickness );
+
+          if( underlineGlyph )
+          {
+            AdjustExtents( extents,
+                           meshContainer,
+                           index,
+                           left,
+                           right,
+                           baseLine,
+                           underlinePosition,
+                           underlineThickness );
+          }
+
           return;
         }
       }
@@ -435,16 +486,18 @@ struct AtlasRenderer::Impl : public ConnectionTracker
       meshRecord.mColor = color;
       meshContainer.push_back( meshRecord );
 
-      // Adjust extents for this new meshrecord
-      AdjustExtents( extents,
-                     meshContainer,
-                     meshContainer.size() - 1u,
-                     left,
-                     right,
-                     baseLine,
-                     underlinePosition,
-                     underlineThickness );
-
+      if( underlineGlyph )
+      {
+        // Adjust extents for this new meshrecord
+        AdjustExtents( extents,
+                       meshContainer,
+                       meshContainer.size() - 1u,
+                       left,
+                       right,
+                       baseLine,
+                       underlinePosition,
+                       underlineThickness );
+      }
     }
   }
 
@@ -756,15 +809,15 @@ Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth )
     Vector<GlyphInfo> glyphs;
     glyphs.Resize( numberOfGlyphs );
 
-    std::vector<Vector2> positions;
-    positions.resize( numberOfGlyphs );
+    Vector<Vector2> positions;
+    positions.Resize( numberOfGlyphs );
 
     numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
-                                     &positions[0],
+                                     positions.Begin(),
                                      0u,
                                      numberOfGlyphs );
     glyphs.Resize( numberOfGlyphs );
-    positions.resize( numberOfGlyphs );
+    positions.Resize( numberOfGlyphs );
 
     mImpl->AddGlyphs( view,
                       positions,
index 9d0cf87..a843feb 100644 (file)
@@ -1198,6 +1198,9 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
                  this, text.c_str(), (COMMIT == type ? "COMMIT" : "PRE_EDIT"),
                  mImpl->mEventData->mPrimaryCursorPosition, mImpl->mEventData->mPreEditFlag, mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength );
 
+  // TODO: At the moment the underline runs are only for pre-edit.
+  mImpl->mVisualModel->mUnderlineRuns.Clear();
+
   Vector<Character> utf32Characters;
   Length characterCount( 0u );
 
@@ -1255,7 +1258,7 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
       }
       else // PRE_EDIT
       {
-        if( ! mImpl->mEventData->mPreEditFlag )
+        if( !mImpl->mEventData->mPreEditFlag )
         {
           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Entered PreEdit state" );
 
@@ -1266,6 +1269,22 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
         mImpl->mEventData->mPreEditLength = utf32Characters.Count();
         mImpl->mEventData->mPreEditFlag = true;
 
+        // Add the underline for the pre-edit text.
+        const GlyphIndex* const charactersToGlyphBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin();
+        const Length* const glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin();
+
+        const GlyphIndex glyphStart = *( charactersToGlyphBuffer + mImpl->mEventData->mPreEditStartPosition );
+        const CharacterIndex lastPreEditCharacter = mImpl->mEventData->mPreEditStartPosition + ( ( mImpl->mEventData->mPreEditLength > 0u ) ? mImpl->mEventData->mPreEditLength - 1u : 0u );
+        const Length numberOfGlyphsLastCharacter = *( glyphsPerCharacterBuffer + lastPreEditCharacter );
+        const GlyphIndex glyphEnd = *( charactersToGlyphBuffer + lastPreEditCharacter ) + ( numberOfGlyphsLastCharacter > 1u ? numberOfGlyphsLastCharacter - 1u : 0u );
+
+        GlyphRun underlineRun;
+        underlineRun.glyphIndex = glyphStart;
+        underlineRun.numberOfGlyphs = 1u + glyphEnd - glyphStart;
+
+        // TODO: At the moment the underline runs are only for pre-edit.
+        mImpl->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
+
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "mPreEditStartPosition %d mPreEditLength %d\n", mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength );
       }
     }
index f93ffd7..85888b0 100644 (file)
@@ -51,6 +51,7 @@ typedef TextAbstraction::CharacterDirection CharacterDirection; ///< The charact
 typedef uint32_t                         GlyphIndex;            ///< An index into an array of glyphs.
 typedef uint32_t                         ScriptRunIndex;        ///< An index into an array of script runs.
 typedef uint32_t                         FontRunIndex;          ///< An index into an array of font runs.
+typedef uint32_t                         UnderlineRunIndex;     ///< An index into an array of underline runs.
 typedef uint32_t                         BidirectionalRunIndex; ///< An index into an array of font runs.
 typedef uint32_t                         LineIndex;             ///< An index into an array of lines.
 
index f4bd3f2..99f8a8c 100644 (file)
@@ -93,7 +93,7 @@ std::ostream& operator<< (std::ostream& o, const Vector<LineRun>& lineRuns)
   for( unsigned int i=0; i<lineRuns.Count(); ++i )
   {
     // e.g. Print "Line 0 Glyphs: 0->9 Characters: 0->9 (10)" for a ten character run staring from beginning of the model
-    o << "Line " << i << " Glyphs: " << lineRuns[i].glyphIndex << "->" << (lineRuns[i].glyphIndex + lineRuns[i].numberOfGlyphs );
+    o << "Line " << i << " Glyphs: " << lineRuns[i].glyphRun.glyphIndex << "->" << (lineRuns[i].glyphRun.glyphIndex + lineRuns[i].glyphRun.numberOfGlyphs );
     o << " Characters: " << lineRuns[i].characterRun.characterIndex << "->" << (lineRuns[i].characterRun.characterIndex + lineRuns[i].characterRun.numberOfCharacters );
     o << " Width: " << lineRuns[i].width;
     o << " Ascender: " << lineRuns[i].ascender;
index bcc7f22..56439d2 100644 (file)
@@ -33,6 +33,8 @@ namespace Toolkit
 namespace Text
 {
 
+struct GlyphRun;
+
 /**
  * @brief Abstract interface to provide the information necessary displaying text.
  *
@@ -129,6 +131,23 @@ public:
    */
   virtual float GetUnderlineHeight() const = 0;
 
+  /**
+   * @brief Retrieves the number of underline runs.
+   *
+   * @return The number of underline runs.
+   */
+  virtual Length GetNumberOfUnderlineRuns() const = 0;
+
+  /**
+   * @brief Retrieves the underline runs.
+   *
+   * @param[out] underlineRuns Pointer to a buffer where the underline runs are copied.
+   * @param[in] index Index of the first underline run to be copied.
+   * @param[in] numberOfRuns Number of underline runs to be copied.
+   */
+  virtual void GetUnderlineRuns( GlyphRun* underlineRuns,
+                                 UnderlineRunIndex index,
+                                 Length numberOfRuns ) const = 0;
 };
 
 } // namespace Text
index 4bee1c2..ea074fa 100644 (file)
@@ -103,7 +103,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
       // Otherwise use the given number of glyphs.
       if( lastLine.ellipsis )
       {
-        numberOfLaidOutGlyphs = lastLine.glyphIndex + lastLine.numberOfGlyphs;
+        numberOfLaidOutGlyphs = lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs;
       }
       else
       {
@@ -141,7 +141,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
       LineRun* line = lineBuffer + lineIndex;
 
       // Index of the last glyph of the line.
-      GlyphIndex lastGlyphIndexOfLine = line->glyphIndex + line->numberOfGlyphs - 1u;
+      GlyphIndex lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u;
 
       // Add the alignment offset to the glyph's position.
       for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index )
@@ -156,7 +156,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
           if( lineIndex < numberOfLines )
           {
             line = lineBuffer + lineIndex;
-            lastGlyphIndexOfLine = line->glyphIndex + line->numberOfGlyphs - 1u;
+            lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u;
           }
         }
       }
@@ -317,6 +317,27 @@ float View::GetUnderlineHeight() const
   return 0.0f;
 }
 
+Length View::GetNumberOfUnderlineRuns() const
+{
+  if( mImpl->mVisualModel )
+  {
+    return mImpl->mVisualModel->mUnderlineRuns.Count();
+  }
+
+  return 0u;
+}
+
+void View::GetUnderlineRuns( GlyphRun* underlineRuns,
+                             UnderlineRunIndex index,
+                             Length numberOfRuns ) const
+{
+  if( mImpl->mVisualModel )
+  {
+    mImpl->mVisualModel->GetUnderlineRuns( underlineRuns,
+                                           index,
+                                           numberOfRuns );
+  }
+}
 
 } // namespace Text
 
index 2ab19b1..058ca9c 100644 (file)
@@ -103,6 +103,18 @@ public:
    */
   virtual float GetUnderlineHeight() const;
 
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfUnderlineRuns()
+   */
+  virtual Length GetNumberOfUnderlineRuns() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetUnderlineRuns()
+   */
+  virtual void GetUnderlineRuns( GlyphRun* underlineRuns,
+                                 UnderlineRunIndex index,
+                                 Length numberOfRuns ) const;
+
 private:
 
   // Undefined
index bb7cdde..561beee 100644 (file)
@@ -149,13 +149,13 @@ void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
   {
     const LineRun& line = *it;
 
-    if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
-        ( lastGlyphIndex > line.glyphIndex ) )
+    if( ( line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs > glyphIndex ) &&
+        ( lastGlyphIndex > line.glyphRun.glyphIndex ) )
     {
       firstLineFound = true;
       ++numberOfLines;
     }
-    else if( lastGlyphIndex <= line.glyphIndex )
+    else if( lastGlyphIndex <= line.glyphRun.glyphIndex )
     {
       // nothing else to do.
       break;
@@ -216,6 +216,15 @@ LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex )
   return index;
 }
 
+void VisualModel::GetUnderlineRuns( GlyphRun* underlineRuns,
+                                    UnderlineRunIndex index,
+                                    Length numberOfRuns ) const
+{
+  memcpy( underlineRuns,
+          mUnderlineRuns.Begin() + index,
+          numberOfRuns * sizeof( GlyphRun ) );
+}
+
 void VisualModel::SetNaturalSize( const Vector2& size  )
 {
   mNaturalSize = size;
index 32ab386..0717582 100644 (file)
@@ -152,6 +152,19 @@ public:
    */
   LineIndex GetLineOfCharacter( CharacterIndex characterIndex );
 
+  // Underline runs
+
+  /**
+   * @brief Retrieves the underline runs.
+   *
+   * @param[out] underlineRuns Pointer to a buffer where the underline runs are copied.
+   * @param[in] index Index of the first underline run to be copied.
+   * @param[in] numberOfRuns Number of underline runs to be copied.
+   */
+  void GetUnderlineRuns( GlyphRun* underlineRuns,
+                         UnderlineRunIndex index,
+                         Length numberOfRuns ) const;
+
   // Size interface
 
   /**
@@ -300,6 +313,7 @@ public:
   Vector<Length>         mGlyphsPerCharacter;   ///< For each character, the number of glyphs that are shaped.
   Vector<Vector2>        mGlyphPositions;       ///< For each glyph, the position.
   Vector<LineRun>        mLines;                ///< The laid out lines.
+  Vector<GlyphRun>       mUnderlineRuns;        ///< Runs of glyphs that are underlined.
 
   Vector2                mControlSize;           ///< The size of the UI control the decorator is adding it's decorations to.
   Vector4                mTextColor;            ///< The text color