Fixing Bug: Caret is too big with LineSpacing 81/264281/15
authorSara Samara <sara.samara@samsung.com>
Wed, 15 Sep 2021 10:29:23 +0000 (13:29 +0300)
committerabdullah <abdullahhasan10@gmail.com>
Wed, 15 Dec 2021 15:53:31 +0000 (17:53 +0200)
***********************************************************
Description

When using LineSpacing or MinLineSize the caret size is too big and does not look good.

The primary cursor height was obtaining its height from the line height (which includes the line spacing).
I've modified it to obtain the height from the default font height.

Please use the code below to test the issue and its fix.
***********************************************************

using namespace Dali;
using namespace Dali::Toolkit;

class SimpleApp : public ConnectionTracker
{
public:
  SimpleApp(Application& application)
  : mApplication(application)
  {
    mApplication.InitSignal().Connect(this, &SimpleApp::Create);
  }

  void Create(Application& application)
  {
    Window window = application.GetWindow();
    window.SetBackgroundColor(Vector4(0.04f, 0.345f, 0.392f, 1.0f));

    mEditor = TextEditor::New();
    mEditor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
    mEditor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
    mEditor.SetProperty(Actor::Property::POSITION, Vector3(0.f, 0.0f, 0.f));
    mEditor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 100.0f));
    mEditor.SetProperty(TextEditor::Property::TEXT, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n");
    mEditor.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
    mEditor.SetProperty(TextEditor::Property::POINT_SIZE, 40.0f);
    mEditor.SetBackgroundColor(Color::WHITE);
    mEditor.SetProperty( DevelTextEditor::Property::MIN_LINE_SIZE, 50.f );

    window.Add(mEditor);
  }

   bool OnButtonClicked(Button button)
  {
    if(button == mButton)
    {
      Vector3 originalSize = mEditor.GetNaturalSize();
    }
    return true;
  }

private:
  Application &mApplication;
  TextEditor mEditor;
  PushButton mButton;
  TextField mField;
};

int DALI_EXPORT_API main(int argc, char** argv)
{
  Application application = Application::New(&argc, &argv);
  SimpleApp test(application);
  application.MainLoop();

  return 0;
}

Change-Id: I8d8accbef03b69ba4e77f4f891bae08e37f93a00

15 files changed:
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h
automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Hyphen-Wrapping.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
dali-toolkit/internal/text/cursor-helper-functions.cpp
dali-toolkit/internal/text/cursor-helper-functions.h
dali-toolkit/internal/text/glyph-metrics-helper.cpp
dali-toolkit/internal/text/glyph-metrics-helper.h
dali-toolkit/internal/text/text-controller-impl.cpp

index 701977d80d9473f07dd19e4cf68192a9bf198385..cc0288cedbc9a6f23fe88fa9db4377b95df82a94 100755 (executable)
@@ -104,7 +104,8 @@ void CreateTextModel( const std::string& text,
                       bool markupProcessorEnabled,
                       LineWrap::Mode wrapMode,
                       bool ellipsisEnabled,
-                      DevelText::EllipsisPosition::Type ellipsisPosition)
+                      DevelText::EllipsisPosition::Type ellipsisPosition,
+                      float lineSpacing)
 {
   textModel = Model::New(); ///< Pointer to the text's model.
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
@@ -327,6 +328,7 @@ void CreateTextModel( const std::string& text,
   Layout::Engine layoutEngine;
   layoutEngine.SetMetrics( metrics );
   layoutEngine.SetLayout( Layout::Engine::MULTI_LINE_BOX );
+  layoutEngine.SetDefaultLineSpacing(lineSpacing);
 
   // Set the layout parameters.
   textModel->mHorizontalAlignment = Text::HorizontalAlignment::BEGIN;
index 0b9f5926c6428964267df7a5aca06dcf288330ac..389d72d0d89de8fd90778f2870a0ee9d3a02db25 100644 (file)
@@ -59,6 +59,7 @@ struct LayoutOptions
  * @param[in] wrapMode Line wrap mode.
  * @param[in] ellipsisEnabled Whether the ellipsis layout option is enabled.
  * @param[in] ellipsisPosition Where is the location the text elide.
+ * @param[in] lineSpacing The height of the line in points.
  */
 void CreateTextModel( const std::string& text,
                       const Size& textArea,
@@ -70,7 +71,8 @@ void CreateTextModel( const std::string& text,
                       bool markupProcessorEnabled,
                       LineWrap::Mode wrapMode,
                       bool ellipsisEnabled,
-                      DevelText::EllipsisPosition::Type ellipsisPosition);
+                      DevelText::EllipsisPosition::Type ellipsisPosition,
+                      float lineSpacing);
 
 /**
  * @brief Configures the text @p controller similarly to the one configured by the text-label.
index 84ecd2de01aa990e270dad08bf03fd79148d84d8..9f1d5da63e7644c52d8fbcd75e9cd9d6e6877830 100644 (file)
@@ -114,7 +114,8 @@ bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -202,7 +203,8 @@ bool GetMirroredTextTest( const GetMirroredTextData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -281,7 +283,8 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
                    data.markupProcessorEnabled,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index a95b7079dfca3c0e4df2c6199a734f786dc69499..8b15ad30b070c1cc11ab3c27e3cc62f46cf894e5 100755 (executable)
@@ -121,7 +121,8 @@ bool CreateParagraphTest( const CreateParagraphData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -186,7 +187,8 @@ bool FindParagraphTest( const FindParagraphData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -240,7 +242,8 @@ bool FetchBidirectionalLineInfoTest( const FetchBidirectionalLineInfoData& data
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -289,7 +292,8 @@ bool GetLogicalCharacterIndexTest( const GetLogicalCharacterIndexData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -355,7 +359,8 @@ bool GetLogicalCursorIndexTest( const GetLogicalCursorIndexData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index 768e58becfc2612a322126a50e08287fabfba191..920a826af8636dd766e359400b471510247a5be3 100755 (executable)
@@ -16,8 +16,8 @@
  */
 
 #include <iostream>
-
 #include <stdlib.h>
+#include <unistd.h>
 
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/internal/text/cursor-helper-functions.h>
@@ -46,6 +46,8 @@ using namespace Text;
 
 namespace
 {
+  const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
+  const unsigned int DEFAULT_FONT_SIZE = 1152u;
 
 struct GetClosestLineData
 {
@@ -92,6 +94,15 @@ struct FindSelectionIndicesData
   CharacterIndex* noTextHitIndex;                 ///< The expected character index when there is no hit.
 };
 
+struct PrimaryCursorHeightData
+{
+  std::string     description;                    ///< Description of the test.
+  std::string     text;                           ///< Input text.
+  unsigned int    numberOfTests;                  ///< The number of tests.
+  CharacterIndex* logicalIndex;                   ///< The logical cursor index for each test.
+  float*          heights;                        ///< The expected primary cursor height for each test.
+};
+
 bool GetClosestLineTest( const GetClosestLineData& data )
 {
   std::cout << "  testing : " << data.description << std::endl;
@@ -114,7 +125,8 @@ bool GetClosestLineTest( const GetClosestLineData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -163,7 +175,8 @@ bool GetClosestCursorIndexTest( const GetClosestCursorIndexData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -216,7 +229,8 @@ bool GetCursorPositionTest( const GetCursorPositionData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -233,6 +247,7 @@ bool GetCursorPositionTest( const GetCursorPositionData& data )
     parameters.logical = data.logicalIndex[index];
 
     GetCursorPosition( parameters,
+                       0.f,// Since this test case is not testing the primary cursor height, the default font line height can be set to 0.f.
                        cursorInfo );
 
     if( floor(cursorInfo.primaryPosition.x) != data.visualX[index] )
@@ -243,7 +258,7 @@ bool GetCursorPositionTest( const GetCursorPositionData& data )
     if( floor(cursorInfo.primaryPosition.y) != data.visualY[index] )
     {
       std::cout << "  test " << index << " failed. Different 'y' cursor position : " << cursorInfo.primaryPosition.y << ", expected : " << data.visualY[index] << std::endl;
-       return false;
+      return false;
     }
   }
 
@@ -272,7 +287,8 @@ bool FindSelectionIndicesTest( const FindSelectionIndicesData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -315,12 +331,102 @@ bool FindSelectionIndicesTest( const FindSelectionIndicesData& data )
   return true;
 }
 
+bool PrimaryCursorHeightTest( const PrimaryCursorHeightData& data )
+{
+  std::cout << "  testing : " << data.description << std::endl;
+
+  // 1) Create the model.
+  ModelPtr textModel;
+  MetricsPtr metrics;
+  Size textArea(400.f, 600.f);
+  Size layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+
+  const std::string fontFamily( "DejaVuSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun1;
+  fontDescriptionRun1.characterRun.characterIndex = 0u;
+  fontDescriptionRun1.characterRun.numberOfCharacters = 13u;
+  fontDescriptionRun1.familyLength = fontFamily.size();
+  fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength];
+  memcpy( fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength );
+  fontDescriptionRun1.familyDefined = true;
+  fontDescriptionRun1.weightDefined = false;
+  fontDescriptionRun1.widthDefined = false;
+  fontDescriptionRun1.slantDefined = false;
+  fontDescriptionRun1.sizeDefined = true;
+  fontDescriptionRun1.size = 768u;//Font size = 12.0f (768/64 = 12)
+
+  fontDescriptionRuns.PushBack( fontDescriptionRun1 );
+
+  LayoutOptions options;
+  CreateTextModel( data.text,
+                   textArea,
+                   fontDescriptionRuns,
+                   options,
+                   layoutSize,
+                   textModel,
+                   metrics,
+                   false,
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   50.f );
+
+  LogicalModelPtr logicalModel = textModel->mLogicalModel;
+  VisualModelPtr visualModel = textModel->mVisualModel;
+
+  GetCursorPositionParameters parameters;
+  parameters.visualModel = visualModel;
+  parameters.logicalModel = logicalModel;
+  parameters.metrics = metrics;
+  parameters.isMultiline = true;
+
+  for( unsigned int index = 0; index < data.numberOfTests; ++index )
+  {
+    CursorInfo cursorInfo;
+    parameters.logical = data.logicalIndex[index];
+
+    // Load some fonts.
+    TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+    fontClient.SetDpi( 93u, 93u );
+
+    char* pathNamePtr = get_current_dir_name();
+    const std::string pathName( pathNamePtr );
+    free( pathNamePtr );
+
+    FontId fontID = fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf" );
+
+    Text::FontMetrics fontMetrics;
+    MetricsPtr mMetrics = Metrics::New(fontClient);
+    mMetrics->GetFontMetrics(fontID, fontMetrics);
+    float defaultFontLineHeight = (fontMetrics.ascender - fontMetrics.descender);
+
+    GetCursorPosition( parameters,
+                       defaultFontLineHeight,
+                       cursorInfo );
+
+    if( floor(cursorInfo.primaryCursorHeight) != data.heights[index] )
+    {
+      std::cout << "  test " << index << " failed. Different primaryCursorHeight : " << cursorInfo.primaryCursorHeight << ", expected : " << data.heights[index] << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
 } // namespace
 
 //////////////////////////////////////////////////////////
 //
 // UtcDaliGetClosestLine
 // UtcDaliGetClosestCursorIndex
+// UtcDaliGetCursorPosition
+// UtcDaliFindSelectionIndices
+// UtcDaliPrimaryCursorHeight
 //
 //////////////////////////////////////////////////////////
 
@@ -805,3 +911,35 @@ int UtcDaliFindSelectionIndices(void)
   tet_result(TET_PASS);
   END_TEST;
 }
+
+int UtcDaliPrimaryCursorHeight(void)
+{
+  tet_infoline(" UtcDaliPrimaryCursorHeight");
+
+  float heights[] = { 19.f };
+  CharacterIndex logicalIndex[] = { 1u };
+
+  struct PrimaryCursorHeightData data[] =
+  {
+    {
+      "Testing primary cursor height when line spacing is used.",
+      "Hello World",
+      1u,
+      logicalIndex,
+      heights,
+    }
+  };
+  const unsigned int numberOfTests = 1u;
+
+  for( unsigned int index = 0; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !PrimaryCursorHeightTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
index 402cc40dad525e49433e75f4a5d296e75801cc46..4f1d0f5b76432eb48eeb6d228ad556681fc1cb0c 100755 (executable)
@@ -93,7 +93,8 @@ bool LayoutTextTest( const LayoutTextData& data )
                    false,
                    data.wrapMode,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   Vector<LineRun>& lines = textModel->mVisualModel->mLines;
 
index 281dbbaf2892d4251eee90df22707f8ce2b1dd7c..b50ab834617876e8b443f4e25219018816b481e1 100755 (executable)
@@ -112,7 +112,8 @@ bool LayoutTextTest( const LayoutTextData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -370,7 +371,8 @@ bool AlignTest( const AlignData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index 272db3182f0ac90a916637f5a81cdd59ac289cc6..59a0dfdb17b35f1bdb4176c7b6bc038f83f643bf 100755 (executable)
@@ -144,7 +144,8 @@ bool ShapeInfoTest( const ShapeInfoData& data )
                    data.markupProcessorEnabled,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index 2453771afb4395c029826d049f719beed771292e..a88a85d93589a03435b88d699fcfdcddb16d8668 100644 (file)
@@ -82,7 +82,8 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -169,7 +170,8 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
                    false,
                    LineWrap::WORD,
                    false,
-                   Toolkit::DevelText::EllipsisPosition::END );
+                   Toolkit::DevelText::EllipsisPosition::END,
+                   0.f );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index 0bac46af1a0d263ccfd8bdee27c5b082d74cb7a4..4e9890c999588db791f8ad6b85908c6f8e089779 100644 (file)
@@ -4842,6 +4842,53 @@ int utcDaliTextEditorSelectionClearedSignal(void)
   END_TEST;
 }
 
+int utcDaliTextEditorSelectionWithSecondaryCursor(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextEditorSelectionWithSecondaryCursor");
+
+  // Checks if the actor is created.
+
+  TextEditor editor = TextEditor::New();
+  DALI_TEST_CHECK( editor );
+
+  application.GetScene().Add( editor );
+
+  editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true );
+  editor.SetProperty( TextEditor::Property::TEXT, "اللغة العربية\nمرحبا بالجميع\nالسلام عليكم <span font-size='12' font-family='DejaVu Sans' >Hello world</span>" );
+  editor.SetProperty( TextEditor::Property::POINT_SIZE, 12.f );
+  editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) );
+  editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+  editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+  editor.SetProperty( DevelTextEditor::Property::MIN_LINE_SIZE, 50.f );
+  editor.SetProperty( DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION, false );
+
+  // Avoid a crash when core load gl resources.
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Tap on the text editor
+  TestGenerateTap( application, 3.0f, 25.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  //Select the last Arabic word (RTL) & some the space before the English (LTR) letters.
+  DevelTextEditor::SelectText( editor, 35, 41 );// This will activate the alternative cursor position and thus 'cursorInfo.isSecondaryCursor' will be true.
+
+  application.SendNotification();
+  application.Render();
+
+  std::string selectedText = editor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT ).Get<std::string>();
+  DALI_TEST_EQUALS( "عليكم ", selectedText, TEST_LOCATION );
+
+  END_TEST;
+}
+
 int utcDaliTextEditorSelectionChangedSignal(void)
 {
   ToolkitTestApplication application;
index c2d35d9be5e1731d64384d027632ec637c2a4fba..7b08c47eee53e94a045ad3d5588c15a906777547 100644 (file)
@@ -458,6 +458,7 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr         visualModel,
 }
 
 void GetCursorPosition(GetCursorPositionParameters& parameters,
+                       float                        defaultFontLineHeight,
                        CursorInfo&                  cursorInfo)
 {
   const LineRun* const modelLines = parameters.visualModel->mLines.Begin();
@@ -479,6 +480,15 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
   const LineIndex lineIndex = parameters.visualModel->GetLineOfCharacter(characterOfLine);
   const LineRun&  line      = *(modelLines + lineIndex);
 
+  const GlyphIndex* const charactersToGlyphBuffer  = parameters.visualModel->mCharactersToGlyph.Begin();
+  const Length* const     glyphsPerCharacterBuffer = parameters.visualModel->mGlyphsPerCharacter.Begin();
+  const GlyphInfo* const  glyphInfoBuffer          = parameters.visualModel->mGlyphs.Begin();
+  CharacterIndex          index;
+  GlyphMetrics            glyphMetrics;
+  MetricsPtr&             metrics = parameters.metrics;
+  GlyphIndex glyphIndex = 0u;
+  Length numberOfGlyphs = 0u;
+
   if(isLastNewParagraph)
   {
     // The cursor is in a new line with no characters. Place the cursor in that line.
@@ -493,8 +503,14 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
 
     cursorInfo.lineHeight = GetLineHeight(newLine);
 
+    const Length totalNumberOfCharacters = parameters.logicalModel->mText.Count();
+    index                                = totalNumberOfCharacters - 1;
+
+    GetGlyphMetricsFromCharacterIndex(index, glyphInfoBuffer, charactersToGlyphBuffer, glyphsPerCharacterBuffer, metrics, glyphMetrics, glyphIndex, numberOfGlyphs);
+
     // Set the primary cursor's height.
-    cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
+    // The primary cursor height will take the font height of the last character and if there are no characters, it'll take the default font line height.
+    cursorInfo.primaryCursorHeight = (totalNumberOfCharacters > 0) ? (cursorInfo.isSecondaryCursor ? 0.5f * glyphMetrics.fontHeight : glyphMetrics.fontHeight) : defaultFontLineHeight;
 
     // Set the primary cursor's position.
     cursorInfo.primaryPosition.x = (LTR == line.direction) ? newLine.alignmentOffset : parameters.visualModel->mControlSize.width - newLine.alignmentOffset;
@@ -541,7 +557,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
 
     // Calculate the primary cursor.
 
-    CharacterIndex index = characterIndex;
+    index = characterIndex;
     if(cursorInfo.isSecondaryCursor)
     {
       // If there is a secondary position, the primary cursor may be in a different place than the logical index.
@@ -574,26 +590,14 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
       }
     }
 
-    const GlyphIndex* const     charactersToGlyphBuffer  = parameters.visualModel->mCharactersToGlyph.Begin();
-    const Length* const         glyphsPerCharacterBuffer = parameters.visualModel->mGlyphsPerCharacter.Begin();
     const Length* const         charactersPerGlyphBuffer = parameters.visualModel->mCharactersPerGlyph.Begin();
     const CharacterIndex* const glyphsToCharactersBuffer = parameters.visualModel->mGlyphsToCharacters.Begin();
     const Vector2* const        glyphPositionsBuffer     = parameters.visualModel->mGlyphPositions.Begin();
-    const GlyphInfo* const      glyphInfoBuffer          = parameters.visualModel->mGlyphs.Begin();
 
-    // Convert the cursor position into the glyph position.
-    const GlyphIndex primaryGlyphIndex         = *(charactersToGlyphBuffer + index);
-    const Length     primaryNumberOfGlyphs     = *(glyphsPerCharacterBuffer + index);
+    GetGlyphMetricsFromCharacterIndex(index, glyphInfoBuffer, charactersToGlyphBuffer, glyphsPerCharacterBuffer, metrics, glyphMetrics, glyphIndex, numberOfGlyphs);
+    const GlyphIndex primaryGlyphIndex         = glyphIndex;
     const Length     primaryNumberOfCharacters = *(charactersPerGlyphBuffer + primaryGlyphIndex);
 
-    // Get the metrics for the group of glyphs.
-    GlyphMetrics glyphMetrics;
-    GetGlyphsMetrics(primaryGlyphIndex,
-                     primaryNumberOfGlyphs,
-                     glyphMetrics,
-                     glyphInfoBuffer,
-                     parameters.metrics);
-
     // Whether to add the glyph's advance to the cursor position.
     // i.e if the paragraph is left to right and the logical cursor is zero, the position is the position of the first glyph and the advance is not added,
     //     if the logical cursor is one, the position is the position of the first glyph and the advance is added.
@@ -676,16 +680,9 @@ void GetCursorPosition(GetCursorPositionParameters& parameters,
         index = (isRightToLeftParagraph == isCurrentRightToLeft) ? nextCharacterIndex : characterIndex;
       }
 
-      const GlyphIndex secondaryGlyphIndex     = *(charactersToGlyphBuffer + index);
-      const Length     secondaryNumberOfGlyphs = *(glyphsPerCharacterBuffer + index);
-
-      const Vector2& secondaryPosition = *(glyphPositionsBuffer + secondaryGlyphIndex);
-
-      GetGlyphsMetrics(secondaryGlyphIndex,
-                       secondaryNumberOfGlyphs,
-                       glyphMetrics,
-                       glyphInfoBuffer,
-                       parameters.metrics);
+      GetGlyphMetricsFromCharacterIndex(index, glyphInfoBuffer, charactersToGlyphBuffer, glyphsPerCharacterBuffer, metrics, glyphMetrics, glyphIndex, numberOfGlyphs);
+      const GlyphIndex secondaryGlyphIndex = glyphIndex;
+      const Vector2&   secondaryPosition   = *(glyphPositionsBuffer + secondaryGlyphIndex);
 
       // Set the secondary cursor's position.
 
index dc005a3626c35f690e10f63688cb6a2b50bb70a8..441474318fb96a47db8a19888afed55d1d3ccebe 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali-toolkit/internal/text/logical-model-impl.h>
 #include <dali-toolkit/internal/text/metrics.h>
 #include <dali-toolkit/internal/text/visual-model-impl.h>
+#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 
 namespace Dali
 {
@@ -142,9 +143,11 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr         visualModel,
  * if there is a valid alternative cursor, its position and height.
  *
  * @param[in] parameters Parameters used to calculate the cursor's position.
+ * @param[in] defaultFontLineHeight The default font line height.
  * @param[out] cursorInfo The line's height, the cursor's height, the cursor's position and whether there is an alternative cursor.
  */
 void GetCursorPosition(GetCursorPositionParameters& parameters,
+                       float                        defaultFontLineHeight,
                        CursorInfo&                  cursorInfo);
 
 /**
index 1f27a84e1467a508fe269fe9de6baf370887858f..f87555eaa395b8dd947a2f098c4a8ee71862d726 100644 (file)
@@ -100,6 +100,20 @@ void GetGlyphsMetrics(GlyphIndex             glyphIndex,
   glyphMetrics.width += (firstGlyph.isItalicRequired && !isItalicFont) ? TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE * firstGlyph.height : 0.f;
 }
 
+void GetGlyphMetricsFromCharacterIndex(CharacterIndex index, const GlyphInfo* const glyphInfoBuffer, const GlyphIndex* const charactersToGlyphBuffer, const Length* const glyphsPerCharacterBuffer, MetricsPtr& metrics, GlyphMetrics& glyphMetrics, GlyphIndex& glyphIndex, Length& numberOfGlyphs)
+{
+  //Takes the character index, obtains the glyph index (and the number of Glyphs) from it and finally gets the glyph metrics.
+  glyphIndex     = *(charactersToGlyphBuffer + index);
+  numberOfGlyphs = *(glyphsPerCharacterBuffer + index);
+
+  // Get the metrics for the group of glyphs.
+  GetGlyphsMetrics(glyphIndex,
+                   numberOfGlyphs,
+                   glyphMetrics,
+                   glyphInfoBuffer,
+                   metrics);
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index 05ba882dfc7b64786ee83649655611b7f258ecc2..dac57f02aeb12953ea409de593e6038113c805fe 100644 (file)
@@ -83,6 +83,28 @@ void GetGlyphsMetrics(GlyphIndex             glyphIndex,
                       const GlyphInfo* const glyphsBuffer,
                       MetricsPtr&            metrics);
 
+/**
+ * @brief Takes the character index, obtains the glyph index (and the number of Glyphs) from it and finally gets the glyph metrics.
+ *
+ * @param[in] index The character index.
+ * @param[in] glyphInfoBuffer The glyphs buffer.
+ * @param[in] charactersToGlyphBuffer A vector containing the glyph index for each character.
+ * @param[in] glyphsPerCharacterBuffer A vector containing the number of glyphs in each character.
+ * @param[in] metrics Used to access metrics from FontClient.
+ * @param[out] glyphMetrics Some glyph metrics (font height, advance, ascender and x bearing).
+ * @param[out] glyphIndex The glyph index obtained from the character index.
+ * @param[out] numberOfGlyphs The number of glyphs in the character of which the index was passed to the function.
+ *
+ */
+void GetGlyphMetricsFromCharacterIndex(CharacterIndex          index,
+                                       const GlyphInfo* const  glyphInfoBuffer,
+                                       const GlyphIndex* const charactersToGlyphBuffer,
+                                       const Length* const     glyphsPerCharacterBuffer,
+                                       MetricsPtr&             metrics,
+                                       GlyphMetrics&           glyphMetrics,
+                                       GlyphIndex&             glyphIndex,
+                                       Length&                 numberOfGlyphs);
+
 } // namespace Text
 
 } // namespace Toolkit
index f287daf84cc80827c1434efa9d84f9b3d670631c..e0603f81b43d6f2e2ad720dd41160f6c2e8f9889 100644 (file)
@@ -1195,7 +1195,10 @@ void Controller::Impl::GetCursorPosition(CharacterIndex logical,
   parameters.logical      = logical;
   parameters.isMultiline  = isMultiLine;
 
+  float defaultFontLineHeight = GetDefaultFontLineHeight();
+
   Text::GetCursorPosition(parameters,
+                          defaultFontLineHeight,
                           cursorInfo);
 
   // Adds Outline offset.