Merge "Prevention for being assigned NULL value" into devel/master
authorSeoyeon Kim <seoyeon2.kim@samsung.com>
Thu, 2 Jun 2016 06:07:09 +0000 (23:07 -0700)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Thu, 2 Jun 2016 06:07:09 +0000 (23:07 -0700)
45 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-model.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-model.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 [new file with mode: 0644]
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
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
dali-toolkit/dali-toolkit.h
dali-toolkit/devel-api/file.list
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-label-impl.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/text/cursor-helper-functions.cpp
dali-toolkit/internal/text/cursor-helper-functions.h
dali-toolkit/internal/text/input-style.h
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/property-string-parser.cpp [new file with mode: 0644]
dali-toolkit/internal/text/property-string-parser.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-effects-style.cpp [new file with mode: 0644]
dali-toolkit/internal/text/text-effects-style.h [new file with mode: 0644]
dali-toolkit/internal/text/text-font-style.cpp
dali-toolkit/internal/text/text-font-style.h
dali-toolkit/internal/text/text-scroller.cpp
dali-toolkit/internal/text/text-scroller.h
dali-toolkit/public-api/controls/text-controls/text-editor.cpp [moved from dali-toolkit/devel-api/controls/text-controls/text-editor.cpp with 95% similarity]
dali-toolkit/public-api/controls/text-controls/text-editor.h [moved from dali-toolkit/devel-api/controls/text-controls/text-editor.h with 64% similarity]
dali-toolkit/public-api/controls/text-controls/text-field.h
dali-toolkit/public-api/controls/text-controls/text-label.h
dali-toolkit/public-api/file.list
docs/content/shared-javascript-and-cpp-documentation/text-editor.md
docs/content/shared-javascript-and-cpp-documentation/text-field.md
docs/content/shared-javascript-and-cpp-documentation/text-label.md

index b2a4e29..b23014b 100644 (file)
@@ -9,6 +9,7 @@ SET(CAPI_LIB "dali-toolkit-internal")
 SET(TC_SOURCES
  utc-Dali-PushButton.cpp
  utc-Dali-Text-CharacterSetConversion.cpp
+ utc-Dali-Text-Cursor.cpp
  utc-Dali-Text-Segmentation.cpp
  utc-Dali-Text-MultiLanguage.cpp
  utc-Dali-LogicalModel.cpp
index 83fa45c..21d9f42 100644 (file)
@@ -25,7 +25,6 @@
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
-#include <dali-toolkit/internal/text/metrics.h>
 #include <dali-toolkit/internal/text/multi-language-support.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
@@ -97,9 +96,13 @@ void CreateTextModel( const std::string& text,
                       const Vector<FontDescriptionRun>& fontDescriptions,
                       const LayoutOptions& options,
                       Size& layoutSize,
-                      LogicalModelPtr logicalModel,
-                      VisualModelPtr visualModel )
+                      LogicalModelPtr& logicalModel,
+                      VisualModelPtr& visualModel,
+                      MetricsPtr& metrics )
 {
+  logicalModel = LogicalModel::New();
+  visualModel = VisualModel::New();
+
   // 1) Convert to utf32
   Vector<Character>& utf32Characters = logicalModel->mText;
   utf32Characters.Resize( text.size() );
@@ -242,7 +245,7 @@ void CreateTextModel( const std::string& text,
   const Length numberOfGlyphs = glyphs.Count();
 
   // 8) Get the glyph metrics
-  MetricsPtr metrics = Metrics::New( fontClient );
+  metrics = Metrics::New( fontClient );
 
   GlyphInfo* glyphsBuffer = glyphs.Begin();
   metrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
index 631b151..288627f 100644 (file)
@@ -22,6 +22,7 @@
 
 // INTERNAL INCLUDES
 #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>
 
 namespace Dali
@@ -58,14 +59,16 @@ struct LayoutOptions
  * @param[out] layoutSize The laid-out size.
  * @param[out] logicalModel Pointer to a logical text model instance.
  * @param[out] visualModel Pointer to a visual text model instance.
+ * @param[out] metrics Pointer to a wrapper around FontClient used to get metrics.
  */
 void CreateTextModel( const std::string& text,
                       const Size& textArea,
                       const Vector<FontDescriptionRun>& fontDescriptions,
                       const LayoutOptions& options,
                       Size& layoutSize,
-                      LogicalModelPtr logicalModel,
-                      VisualModelPtr visualModel );
+                      LogicalModelPtr& logicalModel,
+                      VisualModelPtr& visualModel,
+                      MetricsPtr& metrics );
 
 } // namespace Text
 
index f61e539..629e4f3 100644 (file)
@@ -111,8 +111,9 @@ struct GetCharactersDirectionData
 bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
@@ -125,7 +126,8 @@ bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // 2) Clear the bidirectional paragraph info data.
   Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
@@ -215,8 +217,9 @@ void FreeBidirectionalLineInfoResources( Vector<BidirectionalLineInfoRun> bidire
 bool ReorderLinesTest( const ReorderLinesData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 300.f);
   Size layoutSize;
 
@@ -229,7 +232,8 @@ bool ReorderLinesTest( const ReorderLinesData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // 2) Clear the bidirectional line info data.
   uint32_t startRemoveIndex = logicalModel->mBidirectionalLineInfo.Count();
@@ -338,8 +342,9 @@ bool ReorderLinesTest( const ReorderLinesData& data )
 bool GetMirroredTextTest( const GetMirroredTextData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
@@ -352,7 +357,8 @@ bool GetMirroredTextTest( const GetMirroredTextData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // 2) Call the GetMirroredText() function for the whole text
   Vector<Character> mirroredText;
@@ -410,8 +416,9 @@ bool GetMirroredTextTest( const GetMirroredTextData& data )
 bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
@@ -424,7 +431,8 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
 
@@ -459,7 +467,6 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
 
 int UtcDaliSetBidirectionalInfo(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliSetBidirectionalInfo");
 
   unsigned int indices01[] = {};
@@ -594,6 +601,7 @@ int UtcDaliSetBidirectionalInfo(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !SetBidirectionalInfoTest( data[index] ) )
     {
       tet_result(TET_FAIL);
@@ -606,7 +614,6 @@ int UtcDaliSetBidirectionalInfo(void)
 
 int UtcDaliReorderLines(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliSetBidirectionalInfo");
 
   unsigned int visualToLogical0301[] = { 0u, 1u, 2u, 3u, 4u, 5u, 9u, 8u, 7u, 6u, 10u };
@@ -781,6 +788,7 @@ int UtcDaliReorderLines(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !ReorderLinesTest( data[index] ) )
     {
       tet_result(TET_FAIL);
@@ -793,7 +801,6 @@ int UtcDaliReorderLines(void)
 
 int UtcDaliGetMirroredText(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliGetMirroredText");
 
   struct GetMirroredTextData data[] =
@@ -865,6 +872,7 @@ int UtcDaliGetMirroredText(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !GetMirroredTextTest( data[index] ) )
     {
       tet_result(TET_FAIL);
@@ -877,7 +885,6 @@ int UtcDaliGetMirroredText(void)
 
 int UtcDaliGetCharactersDirection(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliGetCharactersDirection");
 
   bool directions01[] = {};
@@ -987,6 +994,7 @@ int UtcDaliGetCharactersDirection(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !GetCharactersDirectionTest( data[index] ) )
     {
       tet_result(TET_FAIL);
index 9fe39c0..25a724c 100644 (file)
@@ -100,8 +100,9 @@ struct GetLogicalCursorIndexData
 bool CreateParagraphTest( const CreateParagraphData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
@@ -113,7 +114,8 @@ bool CreateParagraphTest( const CreateParagraphData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // 2) Clear the paragraphs.
   Vector<ParagraphRun>& paragraphs = logicalModel->mParagraphInfo;
@@ -158,8 +160,9 @@ bool CreateParagraphTest( const CreateParagraphData& data )
 bool FindParagraphTest( const FindParagraphData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
@@ -171,7 +174,8 @@ bool FindParagraphTest( const FindParagraphData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // 2) Find the paragraphs.
   Vector<ParagraphRunIndex> paragraphs;
@@ -204,8 +208,9 @@ bool FetchBidirectionalLineInfoTest( const FetchBidirectionalLineInfoData& data
 {
   std::cout << "  testing : " << data.description << std::endl;
   // Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea( 100.f, 300.f );
   Size layoutSize;
 
@@ -218,7 +223,8 @@ bool FetchBidirectionalLineInfoTest( const FetchBidirectionalLineInfoData& data
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   for( unsigned int index = 0; index < data.numberOfTests; ++index )
   {
@@ -247,8 +253,9 @@ bool GetLogicalCharacterIndexTest( const GetLogicalCharacterIndexData& data )
 {
   std::cout << "  testing : " << data.description << std::endl;
   // Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size layoutSize;
 
   // Create the model with the whole text.
@@ -260,7 +267,8 @@ bool GetLogicalCharacterIndexTest( const GetLogicalCharacterIndexData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
   {
@@ -287,8 +295,9 @@ bool GetLogicalCursorIndexTest( const GetLogicalCursorIndexData& data )
 {
   std::cout << "  testing : " << data.description << std::endl;
   // Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size layoutSize;
 
   // Create the model with the whole text.
@@ -300,7 +309,8 @@ bool GetLogicalCursorIndexTest( const GetLogicalCursorIndexData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
   {
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp
new file mode 100644 (file)
index 0000000..195c81b
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <toolkit-text-model.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions.
+//
+// LineIndex GetClosestLine( VisualModelPtr visualModel,
+//                           float visualY )
+// CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
+//                                       LogicalModelPtr logicalModel,
+//                                       MetricsPtr metrics,
+//                                       float visualX,
+//                                       float visualY )
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct GetClosestLineData
+{
+  std::string    description;                    ///< Description of the test.
+  std::string    text;                           ///< Input text.
+  unsigned int   numberOfTests;                  ///< The number of tests.
+  float*         visualY;                        ///< The visual 'y' position for each test.
+  LineIndex*     lineIndex;                      ///< The expected line index for each test.
+};
+
+struct GetClosestCursorIndexData
+{
+  std::string     description;                    ///< Description of the test.
+  std::string     text;                           ///< Input text.
+  unsigned int    numberOfTests;                  ///< The number of tests.
+  float*          visualX;                        ///< The visual 'x' position for each test.
+  float*          visualY;                        ///< The visual 'y' position for each test.
+  CharacterIndex* logicalIndex;                   ///< The expected logical cursor index for each test.
+};
+
+bool GetClosestLineTest( const GetClosestLineData& data )
+{
+  std::cout << "  testing : " << data.description << std::endl;
+
+  // 1) Create the model.
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
+  Size textArea(400.f, 600.f);
+  Size layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  LayoutOptions options;
+  CreateTextModel( data.text,
+                   textArea,
+                   fontDescriptionRuns,
+                   options,
+                   layoutSize,
+                   logicalModel,
+                   visualModel,
+                   metrics );
+
+  for( unsigned int index = 0u; index < data.numberOfTests; ++index )
+  {
+    const LineIndex lineIndex = GetClosestLine( visualModel,
+                                                data.visualY[index] );
+
+    if( lineIndex != data.lineIndex[index] )
+    {
+      std::cout << "  test " << index << " failed. Different line index : " << lineIndex << ", expected : " << data.lineIndex[index] << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool GetClosestCursorIndexTest( const GetClosestCursorIndexData& data )
+{
+  std::cout << "  testing : " << data.description << std::endl;
+
+  // 1) Create the model.
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
+  Size textArea(400.f, 600.f);
+  Size layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  LayoutOptions options;
+  CreateTextModel( data.text,
+                   textArea,
+                   fontDescriptionRuns,
+                   options,
+                   layoutSize,
+                   logicalModel,
+                   visualModel,
+                   metrics );
+
+  for( unsigned int index = 0u; index < data.numberOfTests; ++index )
+  {
+    const CharacterIndex logicalCursorIndex = GetClosestCursorIndex( visualModel,
+                                                                     logicalModel,
+                                                                     metrics,
+                                                                     data.visualX[index],
+                                                                     data.visualY[index] );
+
+    if( logicalCursorIndex != data.logicalIndex[index] )
+    {
+      std::cout << "  test " << index << " failed. Different logical cursor index : " << logicalCursorIndex << ", expected : " << data.logicalIndex[index] << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+//
+// UtcDaliGetClosestLine
+// UtcDaliGetClosestCursorIndex
+//
+//////////////////////////////////////////////////////////
+
+int UtcDaliGetClosestLine(void)
+{
+  tet_infoline(" UtcDaliGetClosestLine");
+
+  float visualY01[] = { -4.f, 3.f, 1000.f };
+  LineIndex lineIndices01[] = { 0u, 0u, 0u };
+
+  float visualY02[] = { -4.f, 3.f, 1000.f };
+  LineIndex lineIndices02[] = { 0u, 0u, 0u };
+
+  float visualY03[] = { -4.f, 11.f, 30.f, 51.f, 68.f, 87.f, 109.f, 130.f };
+  LineIndex lineIndices03[] = { 0u, 0u, 1u, 2u, 3u, 4u, 5u, 5u };
+
+  struct GetClosestLineData data[] =
+  {
+    {
+      "void text.",
+      "",
+      3u,
+      visualY01,
+      lineIndices01,
+    },
+    {
+      "Single line text.",
+      "hello world",
+      3u,
+      visualY02,
+      lineIndices02,
+    },
+    {
+      "Multi-line text.",
+      "abcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuדאוvwxה"
+      "סתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuד"
+      "אוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqr"
+      "פרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmno"
+      "צמםpqrפרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjkl"
+      "חלךmnoצמםpqrפרףstuדאוvwxהסתyzטזץ",
+      8u,
+      visualY03,
+      lineIndices03
+    }
+  };
+  const unsigned int numberOfTests = 3u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !GetClosestLineTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliGetClosestCursorIndex(void)
+{
+  tet_infoline(" UtcDaliGetClosestCursorIndex");
+  float visualX01[] = { -100.f };
+  float visualY01[] = { -100.f };
+  CharacterIndex logicalIndex01[] = { 0u };
+
+  float visualX02[] = { -100.f, 1000.f, 60.f, 79.f, 83.f, 148.f, 99.f };
+  float visualY02[] = { -100.f, 1000.f, 12.f, 12.f, 12.f, 12.f, 12.f };
+  CharacterIndex logicalIndex02[] = { 0u, 21u, 7u, 10u, 11u, 13u, 20u };
+
+  float visualX03[] = { 19.f, 104.f, -2.f, 127.f };
+  float visualY03[] = { 12.f, 12.f, 12.f, 12.f };
+  CharacterIndex logicalIndex03[] = { 3u, 12u, 0u, 18u };
+
+  //  0     5 _ 6     11  12
+  //   Hello     world  \n
+  // 12    16 _ 17    21   22
+  //   שלום       עולם  \n
+  // 22         31_32      40  41
+  //   different     الأربعاء  \n
+  float visualX04[] = { -100.f, 40.f, 44.f, 85.f, 500.f,
+                         500.f, 367.f, 359.f, 329.f, -100.f,
+                        -100.f, 19.f, 64.f, 72.f, 104.f, 111.f, 500.f};
+  float visualY04[] = { -100.f, 12.f, 12.f, 12.f, 12.f,
+                          30.f, 30.f, 30.f, 30.f, 30.f,
+                          50.f, 50.f, 50.f, 50.f, 50.f, 50.f, 50.f };
+  CharacterIndex logicalIndex04[] = {  0u,  5u,  6u, 11u, 11u,
+                                       12u, 16u, 17u, 21u, 21u,
+                                       22u, 25u, 31u, 32u, 34u, 40u, 40u,
+                                       41u };
+
+  //   0           10           20            30           40      46
+  //    abcשנבdefג   קכghiעיןjk   lחלךmnoצמם   pqrפרףstuד   אוvwxה
+  //  46     50            60            70           80               93
+  //    סתyz   טזץabcשנבd    efגקכghiעי    ןjklחלךmno   צמםpqrפרףstuד
+  //  93       100           110          120         130          139
+  //    אוvwxהס   תyzטזץabcש   נבdefגקכgh   iעיןjklחלך   mnoצמםpqr
+  // 139           150           160           170          180       186
+  //    פרףstuדאוvw   xהסתyzטזץa   bcשנבdefגק    כghiעיןjkl    חלךmno
+  // 186     190           200           210          220            233
+  //    צמםp   qrפרףstuדא    וvwxהסתyzט   זץabcשנבde   fגקכghiעיןjkl
+  // 233        240            250           260     265
+  //    חלךmnoצ    מםpqrפרףst   uדאוvwxהסת    yzטזץ
+
+  float visualX05[] = { -100.f, 96.f, 155.f, 250.f, 344.f, 500.f,
+                        -100.f, 36.f, 124.f, 190.f, 280.f, 500.f,
+                        -100.f, 56.f, 158.f, 237.f, 303.f, 500.f,
+                        -100.f, 98.f, 184.f, 261.f, 337.f, 500.f,
+                        -100.f, 40.f, 113.f, 223.f, 302.f, 500.f,
+                        -100.f, 82.f, 160.f, 253.f, 500.f };
+  float visualY05[] = { -100.f, 12.f, 12.f, 12.f, 12.f, 12.f,
+                        30.f, 30.f, 30.f, 30.f, 30.f, 30.f,
+                        50.f, 50.f, 50.f, 50.f, 50.f, 50.f,
+                        67.f, 67.f, 67.f, 67.f, 67.f, 67.f,
+                        87.f, 87.f, 87.f, 87.f, 87.f, 87.f,
+                        107.f, 107.f, 107.f, 107.f, 107.f };
+  CharacterIndex logicalIndex05[] = {   0u,  10u,  20u,  30u,  40u,  45u,
+                                       46u,  50u,  60u,  70u,  80u,  92u,
+                                       93u, 100u, 110u, 120u, 130u, 138u,
+                                      139u, 150u, 160u, 170u, 180u, 185u,
+                                      186u, 190u, 200u, 210u, 220u, 232u,
+                                      233u, 240u, 250u, 260u, 265u };
+
+  //   0            10           20           30           40        46
+  //    שנבabcגקכd    efעיןghiחל   ךjklצמםmno   פרףpqrדאוs   tuהסתv
+  //  46     50           60          70            80              93
+  //    wxטז   ץyzשנבabcג   קכdefעיןgh   iחלךjklצמם   mnoפרףpqrדאוs
+  //  93        100          110          120           130           139
+  //    tuהסתvw   xטזץyzשנבa   bcגקכdefעי    ןghiחלךjkl    צמםmnoפרף
+  // 139           150           160          170         180       186
+  //    pqrדאוstuהס   תvwxטזץyzש   נבabcגקכde   fעיןghiחלך   jklצמם
+  // 186    190          200           210           220            232
+  //    mnoפ   רףpqrדאוst   uהסתvwxטזץ   yzשנבabcגק    כdefעיןghiחל
+  // 232         240           250           260     265
+  //    ךjklצמםm   noפרףpqrדא    וstuהסתvwx   טזץyz
+
+  float visualX06[] = { 500.f, 307.f, 237.f, 148.f, 55.f, -100.f,
+                        500.f, 362.f, 276.f, 213.f, 121.f, -100.f,
+                        500.f, 344.f, 238.f, 167.f, 93.f, -100.f,
+                        500.f, 306.f, 216.f, 142.f, 58.f, -100.f,
+                        500.f, 355.f, 279.f, 182.f, 92.f, -100.f,
+                        500.f, 326.f, 238.f, 150.f, -100.f };
+  float visualY06[] = { -100.f, 12.f, 12.f, 12.f, 12.f, 12.f,
+                        30.f, 30.f, 30.f, 30.f, 30.f, 30.f,
+                        50.f, 50.f, 50.f, 50.f, 50.f, 50.f,
+                        67.f, 67.f, 67.f, 67.f, 67.f, 67.f,
+                        87.f, 87.f, 87.f, 87.f, 87.f, 87.f,
+                        107.f, 107.f, 107.f, 107.f, 107.f };
+  CharacterIndex logicalIndex06[] = {   0u,  10u,  20u,  30u,  40u,  45u,
+                                       46u,  50u,  60u,  70u,  80u,  92u,
+                                       93u, 100u, 110u, 120u, 130u, 138u,
+                                      139u, 150u, 160u, 170u, 180u, 185u,
+                                      186u, 190u, 200u, 210u, 220u, 231u,
+                                      232u, 240u, 250u, 260u, 265u  };
+
+  struct GetClosestCursorIndexData data[] =
+  {
+    {
+      "Void text.",
+      "",
+      1u,
+      visualX01,
+      visualY01,
+      logicalIndex01
+    },
+    {
+      "Single line text.",
+      "Hello world שלום עולם",
+      7u,
+      visualX02,
+      visualY02,
+      logicalIndex02
+    },
+    {
+      "Single line with ligatures",
+      "different الأربعاء",
+      4u,
+      visualX03,
+      visualY03,
+      logicalIndex03
+    },
+    {
+      "Multiline. Single line paragraphs",
+      "Hello world\n"
+      "שלום עולם\n"
+      "different الأربعاء\n",
+      17u,
+      visualX04,
+      visualY04,
+      logicalIndex04
+    },
+    {
+      "Multiline. Single bidirectional paragraph, starts LTR, wrapped lines",
+      "abcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuדאוvwxה"
+      "סתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuד"
+      "אוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqr"
+      "פרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjklחלךmno"
+      "צמםpqrפרףstuדאוvwxהסתyzטזץabcשנבdefגקכghiעיןjkl"
+      "חלךmnoצמםpqrפרףstuדאוvwxהסתyzטזץ",
+      35u,
+      visualX05,
+      visualY05,
+      logicalIndex05
+    },
+    {
+      "Multiline. Single bidirectional paragraph, starts RTL, wrapped lines",
+      "שנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוstuהסתv"
+      "wxטזץyzשנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוs"
+      "tuהסתvwxטזץyzשנבabcגקכdefעיןghiחלךjklצמםmnoפרף"
+      "pqrדאוstuהסתvwxטזץyzשנבabcגקכdefעיןghiחלךjklצמם"
+      "mnoפרףpqrדאוstuהסתvwxטזץyzשנבabcגקכdefעיןghiחל"
+      "ךjklצמםmnoפרףpqrדאוstuהסתvwxטזץyz",
+      35u,
+      visualX06,
+      visualY06,
+      logicalIndex06
+    }
+  };
+  const unsigned int numberOfTests = 6u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !GetClosestCursorIndexTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
index 521cbf9..219fba1 100644 (file)
@@ -86,8 +86,9 @@ bool LayoutTextTest( const LayoutTextData& data )
   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
 
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size layoutSize;
 
   Vector<FontDescriptionRun> fontDescriptionRuns;
@@ -107,7 +108,8 @@ bool LayoutTextTest( const LayoutTextData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // 2) Clear the layout.
   Vector<LineRun>& lines = visualModel->mLines;
@@ -150,8 +152,6 @@ bool LayoutTextTest( const LayoutTextData& data )
                         glyphPositions.Begin() + data.startIndex + data.numberOfGlyphs );
 
   // 3) Layout
-  MetricsPtr metrics = Metrics::New( fontClient );
-
   LayoutEngine engine;
   engine.SetMetrics( metrics );
   engine.SetTextEllipsisEnabled( data.ellipsis );
@@ -343,8 +343,9 @@ bool ReLayoutRightToLeftLinesTest( const ReLayoutRightToLeftLinesData& data )
   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
 
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size layoutSize;
 
   Vector<FontDescriptionRun> fontDescriptionRuns;
@@ -364,11 +365,10 @@ bool ReLayoutRightToLeftLinesTest( const ReLayoutRightToLeftLinesData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // 2) Call the ReLayoutRightToLeftLines() method.
-  MetricsPtr metrics = Metrics::New( fontClient );
-
   LayoutEngine engine;
   engine.SetMetrics( metrics );
 
@@ -452,8 +452,9 @@ bool AlignTest( const AlignData& data )
   fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
 
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size layoutSize;
 
   Vector<FontDescriptionRun> fontDescriptionRuns;
@@ -472,11 +473,10 @@ bool AlignTest( const AlignData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // Call the Align method.
-  MetricsPtr metrics = Metrics::New( fontClient );
-
   LayoutEngine engine;
   engine.SetMetrics( metrics );
 
index 9e830ec..7b319fb 100644 (file)
@@ -112,8 +112,9 @@ struct ShapeInfoData
 bool ShapeInfoTest( const ShapeInfoData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
@@ -125,7 +126,8 @@ bool ShapeInfoTest( const ShapeInfoData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   // 2) Clear the model.
 
@@ -267,7 +269,6 @@ bool ShapeInfoTest( const ShapeInfoData& data )
 
 int UtcDaliTextShape(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliTextShape");
 
   struct GlyphInfoData glyphs02[] =
@@ -521,6 +522,7 @@ int UtcDaliTextShape(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !ShapeInfoTest( data[index] ) )
     {
       tet_result(TET_FAIL);
index 115a0d1..11b09f1 100644 (file)
@@ -65,8 +65,9 @@ struct SetCharacterToGlyphData
 bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
@@ -78,7 +79,8 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
@@ -145,8 +147,9 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
 bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
 {
   // 1) Create the model.
-  LogicalModelPtr logicalModel = LogicalModel::New();
-  VisualModelPtr visualModel = VisualModel::New();
+  LogicalModelPtr logicalModel;
+  VisualModelPtr visualModel;
+  MetricsPtr metrics;
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
@@ -158,7 +161,8 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
                    options,
                    layoutSize,
                    logicalModel,
-                   visualModel );
+                   visualModel,
+                   metrics );
 
   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
@@ -226,7 +230,6 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
 
 int UtcDaliSetGlyphsPerCharacter(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliSetGlyphsPerCharacter");
 
   Length glyphsPerCharacter02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
@@ -293,6 +296,7 @@ int UtcDaliSetGlyphsPerCharacter(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !SetGlyphsPerCharacterTest( data[index] ) )
     {
       tet_result(TET_FAIL);
@@ -305,7 +309,6 @@ int UtcDaliSetGlyphsPerCharacter(void)
 
 int UtcDaliSetCharacterToGlyph(void)
 {
-  ToolkitTestApplication application;
   tet_infoline(" UtcDaliSetGlyphsPerCharacter");
 
   GlyphIndex glyphIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
@@ -370,6 +373,7 @@ int UtcDaliSetCharacterToGlyph(void)
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
+    ToolkitTestApplication application;
     if( !SetCharacterToGlyphTest( data[index] ) )
     {
       tet_result(TET_FAIL);
index 809b07b..b1cc593 100644 (file)
@@ -22,7 +22,6 @@
 #include <dali/integration-api/events/tap-gesture-event.h>
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
-#include <dali-toolkit/devel-api/controls/text-controls/text-editor.h> ///< @todo to be removed when text-editor is added to the dali-toolkit.h
 
 using namespace Dali;
 using namespace Toolkit;
@@ -71,6 +70,17 @@ const char* const PROPERTY_NAME_INPUT_FONT_FAMILY                    = "inputFon
 const char* const PROPERTY_NAME_INPUT_FONT_STYLE                     = "inputFontStyle";
 const char* const PROPERTY_NAME_INPUT_POINT_SIZE                     = "inputPointSize";
 
+const char* const PROPERTY_NAME_LINE_SPACING                         = "lineSpacing";
+const char* const PROPERTY_NAME_INPUT_LINE_SPACING                   = "inputLineSpacing";
+const char* const PROPERTY_NAME_UNDERLINE                            = "underline";
+const char* const PROPERTY_NAME_INPUT_UNDERLINE                      = "inputUnderline";
+const char* const PROPERTY_NAME_SHADOW                               = "shadow";
+const char* const PROPERTY_NAME_INPUT_SHADOW                         = "inputShadow";
+const char* const PROPERTY_NAME_EMBOSS                               = "emboss";
+const char* const PROPERTY_NAME_INPUT_EMBOSS                         = "inputEmboss";
+const char* const PROPERTY_NAME_OUTLINE                              = "outline";
+const char* const PROPERTY_NAME_INPUT_OUTLINE                        = "inputOutline";
+
 const int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
 
 const Dali::Vector4 LIGHT_BLUE( 0.75f, 0.96f, 1.f, 1.f ); // The text highlight color.
@@ -180,7 +190,7 @@ int UtcDaliToolkitTextEditorCopyConstructorP(void)
 
   TextEditor copy( textEditor );
   DALI_TEST_CHECK( copy );
-  DALI_TEST_CHECK( copy.GetProperty<std::string>( TextLabel::Property::TEXT ) == textEditor.GetProperty<std::string>( TextLabel::Property::TEXT ) );
+  DALI_TEST_CHECK( copy.GetProperty<std::string>( TextEditor::Property::TEXT ) == textEditor.GetProperty<std::string>( TextEditor::Property::TEXT ) );
   END_TEST;
 }
 
@@ -245,6 +255,18 @@ int UtcDaliTextEditorGetPropertyP(void)
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_FONT_FAMILY ) == TextEditor::Property::INPUT_FONT_FAMILY );
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_FONT_STYLE ) == TextEditor::Property::INPUT_FONT_STYLE );
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_POINT_SIZE ) == TextEditor::Property::INPUT_POINT_SIZE );
+
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_LINE_SPACING ) == TextEditor::Property::LINE_SPACING );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_LINE_SPACING ) == TextEditor::Property::INPUT_LINE_SPACING );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_UNDERLINE ) == TextEditor::Property::UNDERLINE );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_UNDERLINE ) == TextEditor::Property::INPUT_UNDERLINE );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_SHADOW ) == TextEditor::Property::SHADOW );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_SHADOW ) == TextEditor::Property::INPUT_SHADOW );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_EMBOSS ) == TextEditor::Property::EMBOSS );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_EMBOSS ) == TextEditor::Property::INPUT_EMBOSS );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_OUTLINE ) == TextEditor::Property::OUTLINE );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_OUTLINE ) == TextEditor::Property::INPUT_OUTLINE );
+
   END_TEST;
 }
 
@@ -362,6 +384,48 @@ int UtcDaliTextEditorSetPropertyP(void)
   editor.SetProperty( TextEditor::Property::INPUT_POINT_SIZE, 12.f );
   DALI_TEST_EQUALS( editor.GetProperty<float>( TextEditor::Property::INPUT_POINT_SIZE ), 12.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
 
+  // Check the line spacing property
+  DALI_TEST_EQUALS( editor.GetProperty<float>( TextEditor::Property::LINE_SPACING ), 0.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  editor.SetProperty( TextEditor::Property::LINE_SPACING, 10.f );
+  DALI_TEST_EQUALS( editor.GetProperty<float>( TextEditor::Property::LINE_SPACING ), 10.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  // Check the input line spacing property
+  DALI_TEST_EQUALS( editor.GetProperty<float>( TextEditor::Property::INPUT_LINE_SPACING ), 0.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  editor.SetProperty( TextEditor::Property::INPUT_LINE_SPACING, 20.f );
+  DALI_TEST_EQUALS( editor.GetProperty<float>( TextEditor::Property::INPUT_LINE_SPACING ), 20.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  // Check the underline property
+  editor.SetProperty( TextEditor::Property::UNDERLINE, "Underline properties" );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::UNDERLINE ), std::string("Underline properties"), TEST_LOCATION );
+
+  // Check the input underline property
+  editor.SetProperty( TextEditor::Property::INPUT_UNDERLINE, "Underline input properties" );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::INPUT_UNDERLINE ), std::string("Underline input properties"), TEST_LOCATION );
+
+  // Check the shadow property
+  editor.SetProperty( TextEditor::Property::SHADOW, "Shadow properties" );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION );
+
+  // Check the input shadow property
+  editor.SetProperty( TextEditor::Property::INPUT_SHADOW, "Shadow input properties" );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::INPUT_SHADOW ), std::string("Shadow input properties"), TEST_LOCATION );
+
+  // Check the emboss property
+  editor.SetProperty( TextEditor::Property::EMBOSS, "Emboss properties" );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::EMBOSS ), std::string("Emboss properties"), TEST_LOCATION );
+
+  // Check the input emboss property
+  editor.SetProperty( TextEditor::Property::INPUT_EMBOSS, "Emboss input properties" );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::INPUT_EMBOSS ), std::string("Emboss input properties"), TEST_LOCATION );
+
+  // Check the outline property
+  editor.SetProperty( TextEditor::Property::OUTLINE, "Outline properties" );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION );
+
+  // Check the input outline property
+  editor.SetProperty( TextEditor::Property::INPUT_OUTLINE, "Outline input properties" );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::INPUT_OUTLINE ), std::string("Outline input properties"), TEST_LOCATION );
+
   END_TEST;
 }
 
index 2498c57..22bc525 100644 (file)
@@ -79,6 +79,15 @@ const char* const PROPERTY_NAME_INPUT_FONT_FAMILY                    = "inputFon
 const char* const PROPERTY_NAME_INPUT_FONT_STYLE                     = "inputFontStyle";
 const char* const PROPERTY_NAME_INPUT_POINT_SIZE                     = "inputPointSize";
 
+const char* const PROPERTY_NAME_UNDERLINE                            = "underline";
+const char* const PROPERTY_NAME_INPUT_UNDERLINE                      = "inputUnderline";
+const char* const PROPERTY_NAME_SHADOW                               = "shadow";
+const char* const PROPERTY_NAME_INPUT_SHADOW                         = "inputShadow";
+const char* const PROPERTY_NAME_EMBOSS                               = "emboss";
+const char* const PROPERTY_NAME_INPUT_EMBOSS                         = "inputEmboss";
+const char* const PROPERTY_NAME_OUTLINE                              = "outline";
+const char* const PROPERTY_NAME_INPUT_OUTLINE                        = "inputOutline";
+
 const int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
 
 const Vector4 PLACEHOLDER_TEXT_COLOR( 0.8f, 0.8f, 0.8f, 0.8f );
@@ -271,6 +280,15 @@ int UtcDaliTextFieldGetPropertyP(void)
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_FONT_FAMILY ) == TextField::Property::INPUT_FONT_FAMILY );
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_FONT_STYLE ) == TextField::Property::INPUT_FONT_STYLE );
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_POINT_SIZE ) == TextField::Property::INPUT_POINT_SIZE );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_UNDERLINE ) == TextField::Property::UNDERLINE );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_UNDERLINE ) == TextField::Property::INPUT_UNDERLINE );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SHADOW ) == TextField::Property::SHADOW );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_SHADOW ) == TextField::Property::INPUT_SHADOW );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_EMBOSS ) == TextField::Property::EMBOSS );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_EMBOSS ) == TextField::Property::INPUT_EMBOSS );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_OUTLINE ) == TextField::Property::OUTLINE );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_OUTLINE ) == TextField::Property::INPUT_OUTLINE );
+
   END_TEST;
 }
 
@@ -415,6 +433,38 @@ int UtcDaliTextFieldSetPropertyP(void)
   field.SetProperty( TextField::Property::INPUT_POINT_SIZE, 12.f );
   DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::INPUT_POINT_SIZE ), 12.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
 
+  // Check the underline property
+  field.SetProperty( TextField::Property::UNDERLINE, "Underline properties" );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::UNDERLINE ), std::string("Underline properties"), TEST_LOCATION );
+
+  // Check the input underline property
+  field.SetProperty( TextField::Property::INPUT_UNDERLINE, "Underline input properties" );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::INPUT_UNDERLINE ), std::string("Underline input properties"), TEST_LOCATION );
+
+  // Check the shadow property
+  field.SetProperty( TextField::Property::SHADOW, "Shadow properties" );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION );
+
+  // Check the input shadow property
+  field.SetProperty( TextField::Property::INPUT_SHADOW, "Shadow input properties" );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::INPUT_SHADOW ), std::string("Shadow input properties"), TEST_LOCATION );
+
+  // Check the emboss property
+  field.SetProperty( TextField::Property::EMBOSS, "Emboss properties" );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::EMBOSS ), std::string("Emboss properties"), TEST_LOCATION );
+
+  // Check the input emboss property
+  field.SetProperty( TextField::Property::INPUT_EMBOSS, "Emboss input properties" );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::INPUT_EMBOSS ), std::string("Emboss input properties"), TEST_LOCATION );
+
+  // Check the outline property
+  field.SetProperty( TextField::Property::OUTLINE, "Outline properties" );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION );
+
+  // Check the input outline property
+  field.SetProperty( TextField::Property::INPUT_OUTLINE, "Outline input properties" );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::INPUT_OUTLINE ), std::string("Outline input properties"), TEST_LOCATION );
+
   END_TEST;
 }
 
index 08f085d..2f71832 100644 (file)
@@ -56,6 +56,12 @@ const char* const PROPERTY_NAME_ENABLE_AUTO_SCROLL_SPEED = "autoScrollSpeed";
 const char* const PROPERTY_NAME_ENABLE_AUTO_SCROLL_LOOPS = "autoScrollLoopCount";
 const char* const PROPERTY_NAME_ENABLE_AUTO_SCROLL_GAP = "autoScrollGap";
 
+const char* const PROPERTY_NAME_LINE_SPACING = "lineSpacing";
+const char* const PROPERTY_NAME_UNDERLINE = "underline";
+const char* const PROPERTY_NAME_SHADOW = "shadow";
+const char* const PROPERTY_NAME_EMBOSS = "emboss";
+const char* const PROPERTY_NAME_OUTLINE = "outline";
+
 const int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
 
 } // namespace
@@ -160,6 +166,11 @@ int UtcDaliToolkitTextLabelGetPropertyP(void)
   DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ENABLE_AUTO_SCROLL_SPEED ) == TextLabel::Property::AUTO_SCROLL_SPEED );
   DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ENABLE_AUTO_SCROLL_LOOPS ) == TextLabel::Property::AUTO_SCROLL_LOOP_COUNT );
   DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ENABLE_AUTO_SCROLL_GAP ) == TextLabel::Property::AUTO_SCROLL_GAP );
+  DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_LINE_SPACING ) == TextLabel::Property::LINE_SPACING );
+  DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE ) == TextLabel::Property::UNDERLINE );
+  DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_SHADOW ) == TextLabel::Property::SHADOW );
+  DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_EMBOSS ) == TextLabel::Property::EMBOSS );
+  DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_OUTLINE ) == TextLabel::Property::OUTLINE );
 
   END_TEST;
 }
@@ -215,7 +226,7 @@ int UtcDaliToolkitTextLabelSetPropertyP(void)
   label.SetProperty( TextLabel::Property::UNDERLINE_COLOR, Color::RED );
   DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::UNDERLINE_COLOR ), Color::RED, TEST_LOCATION );
   label.SetProperty( TextLabel::Property::UNDERLINE_HEIGHT, 1.0f );
-  DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 1.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
 
   TextLabel label2 = TextLabel::New( "New text" );
   DALI_TEST_CHECK( label2 );
@@ -240,6 +251,28 @@ int UtcDaliToolkitTextLabelSetPropertyP(void)
   DALI_TEST_EQUALS( SCROLL_LOOPS, label.GetProperty<int>( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT ), TEST_LOCATION );
   label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, SCROLL_GAP );
   DALI_TEST_EQUALS( SCROLL_GAP, label.GetProperty<float>( TextLabel::Property::AUTO_SCROLL_GAP ), TEST_LOCATION );
+
+  // Check the line spacing property
+  DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::LINE_SPACING ), 0.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  label.SetProperty( TextLabel::Property::LINE_SPACING, 10.f );
+  DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::LINE_SPACING ), 10.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  // Check the underline property
+  label.SetProperty( TextLabel::Property::UNDERLINE, "Underline properties" );
+  DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::UNDERLINE ), std::string("Underline properties"), TEST_LOCATION );
+
+  // Check the shadow property
+  label.SetProperty( TextLabel::Property::SHADOW, "Shadow properties" );
+  DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION );
+
+  // Check the emboss property
+  label.SetProperty( TextLabel::Property::EMBOSS, "Emboss properties" );
+  DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::EMBOSS ), std::string("Emboss properties"), TEST_LOCATION );
+
+  // Check the outline property
+  label.SetProperty( TextLabel::Property::OUTLINE, "Outline properties" );
+  DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::OUTLINE ), std::string("Outline properties"), TEST_LOCATION );
+
   END_TEST;
 }
 
index 637d534..1883e2f 100644 (file)
@@ -48,6 +48,7 @@
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
 #include <dali-toolkit/public-api/controls/scrollable/scrollable.h>
 #include <dali-toolkit/public-api/controls/table-view/table-view.h>
+#include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-field.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
index e6b7576..e6d9397 100755 (executable)
@@ -15,7 +15,6 @@ devel_api_src_files = \
   $(devel_api_src_dir)/controls/shadow-view/shadow-view.cpp \
   $(devel_api_src_dir)/controls/slider/slider.cpp \
   $(devel_api_src_dir)/controls/super-blur-view/super-blur-view.cpp \
-  $(devel_api_src_dir)/controls/text-controls/text-editor.cpp \
   $(devel_api_src_dir)/controls/text-controls/text-selection-popup.cpp \
   $(devel_api_src_dir)/controls/text-controls/text-selection-toolbar.cpp \
   $(devel_api_src_dir)/controls/tool-bar/tool-bar.cpp \
@@ -103,7 +102,6 @@ devel_api_super_blur_view_header_files = \
   $(devel_api_src_dir)/controls/super-blur-view/super-blur-view.h
 
 devel_api_text_controls_header_files = \
-  $(devel_api_src_dir)/controls/text-controls/text-editor.h \
   $(devel_api_src_dir)/controls/text-controls/text-selection-popup.h \
   $(devel_api_src_dir)/controls/text-controls/text-selection-toolbar.h
 
index 57a66ca..f4e79c4 100644 (file)
@@ -32,6 +32,7 @@
 #include <dali-toolkit/public-api/text/rendering-backend.h>
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/internal/text/rendering/text-backend.h>
+#include <dali-toolkit/internal/text/text-effects-style.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
 #include <dali-toolkit/internal/text/text-view.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
@@ -107,6 +108,16 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputColor",
 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputFontFamily",                      STRING,    INPUT_FONT_FAMILY                    )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputFontStyle",                       STRING,    INPUT_FONT_STYLE                     )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputPointSize",                       FLOAT,     INPUT_POINT_SIZE                     )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "lineSpacing",                          FLOAT,     LINE_SPACING                         )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputLineSpacing",                     FLOAT,     INPUT_LINE_SPACING                   )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "underline",                            STRING,    UNDERLINE                            )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputUnderline",                       STRING,    INPUT_UNDERLINE                      )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "shadow",                               STRING,    SHADOW                               )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputShadow",                          STRING,    INPUT_SHADOW                         )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "emboss",                               STRING,    EMBOSS                               )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputEmboss",                          STRING,    INPUT_EMBOSS                         )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "outline",                              STRING,    OUTLINE                              )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputOutline",                         STRING,    INPUT_OUTLINE                        )
 
 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "textChanged",        SIGNAL_TEXT_CHANGED )
 
@@ -482,6 +493,98 @@ void TextEditor::SetProperty( BaseObject* object, Property::Index index, const P
         }
         break;
       }
+      case Toolkit::TextEditor::Property::LINE_SPACING:
+      {
+        if( impl.mController )
+        {
+          const float lineSpacing = value.Get<float>();
+          impl.mController->SetDefaultLineSpacing( lineSpacing );
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_LINE_SPACING:
+      {
+        if( impl.mController )
+        {
+          const float lineSpacing = value.Get<float>();
+          impl.mController->SetInputLineSpacing( lineSpacing );
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::UNDERLINE:
+      {
+        const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_UNDERLINE:
+      {
+        const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::SHADOW:
+      {
+        const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_SHADOW:
+      {
+        const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::EMBOSS:
+      {
+        const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_EMBOSS:
+      {
+        const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::OUTLINE:
+      {
+        const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_OUTLINE:
+      {
+        const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
     } // switch
   } // texteditor
 }
@@ -727,6 +830,62 @@ Property::Value TextEditor::GetProperty( BaseObject* object, Property::Index ind
         }
         break;
       }
+      case Toolkit::TextEditor::Property::LINE_SPACING:
+      {
+        if( impl.mController )
+        {
+          value = impl.mController->GetDefaultLineSpacing();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_LINE_SPACING:
+      {
+        if( impl.mController )
+        {
+          value = impl.mController->GetInputLineSpacing();
+        }
+        break;
+      }
+      case Toolkit::TextEditor::Property::UNDERLINE:
+      {
+        GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_UNDERLINE:
+      {
+        GetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        break;
+      }
+      case Toolkit::TextEditor::Property::SHADOW:
+      {
+        GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_SHADOW:
+      {
+        GetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        break;
+      }
+      case Toolkit::TextEditor::Property::EMBOSS:
+      {
+        GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_EMBOSS:
+      {
+        GetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        break;
+      }
+      case Toolkit::TextEditor::Property::OUTLINE:
+      {
+        GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextEditor::Property::INPUT_OUTLINE:
+      {
+        GetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        break;
+      }
     } //switch
   }
 
@@ -883,11 +1042,9 @@ void TextEditor::RenderText()
 
   if( mRenderableActor )
   {
-    // TODO: Scroll and alignment needs to be refactored.
-    const Vector2& alignmentOffset = mController->GetAlignmentOffset();
     const Vector2& scrollOffset = mController->GetScrollPosition();
 
-    mRenderableActor.SetPosition( scrollOffset.x, alignmentOffset.y + scrollOffset.y );
+    mRenderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
 
     Actor clipRootActor;
     if( mClipper )
index b10b78b..f00d66d 100644 (file)
@@ -20,7 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-impl.h>
-#include <dali-toolkit/devel-api/controls/text-controls/text-editor.h>
+#include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
 #include <dali-toolkit/internal/text/clipping/text-clipper.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
index f88dcb7..8f1b434 100644 (file)
@@ -31,6 +31,7 @@
 #include <dali-toolkit/public-api/text/rendering-backend.h>
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/internal/text/rendering/text-backend.h>
+#include <dali-toolkit/internal/text/text-effects-style.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
 #include <dali-toolkit/internal/text/text-view.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
@@ -123,6 +124,14 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "enableMarkup",
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputFontFamily",                      STRING,    INPUT_FONT_FAMILY                    )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputFontStyle",                       STRING,    INPUT_FONT_STYLE                     )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputPointSize",                       FLOAT,     INPUT_POINT_SIZE                     )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "underline",                            STRING,    UNDERLINE                            )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputUnderline",                       STRING,    INPUT_UNDERLINE                      )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadow",                               STRING,    SHADOW                               )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputShadow",                          STRING,    INPUT_SHADOW                         )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "emboss",                               STRING,    EMBOSS                               )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputEmboss",                          STRING,    INPUT_EMBOSS                         )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "outline",                              STRING,    OUTLINE                              )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputOutline",                         STRING,    INPUT_OUTLINE                        )
 
 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "textChanged",        SIGNAL_TEXT_CHANGED )
 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "maxLengthReached",   SIGNAL_MAX_LENGTH_REACHED )
@@ -618,6 +627,78 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::TextField::Property::UNDERLINE:
+      {
+        const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_UNDERLINE:
+      {
+        const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextField::Property::SHADOW:
+      {
+        const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_SHADOW:
+      {
+        const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextField::Property::EMBOSS:
+      {
+        const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_EMBOSS:
+      {
+        const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextField::Property::OUTLINE:
+      {
+        const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_OUTLINE:
+      {
+        const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
     } // switch
   } // textfield
 }
@@ -938,6 +1019,46 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         }
         break;
       }
+      case Toolkit::TextField::Property::UNDERLINE:
+      {
+        GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_UNDERLINE:
+      {
+        GetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        break;
+      }
+      case Toolkit::TextField::Property::SHADOW:
+      {
+        GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_SHADOW:
+      {
+        GetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        break;
+      }
+      case Toolkit::TextField::Property::EMBOSS:
+      {
+        GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_EMBOSS:
+      {
+        GetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        break;
+      }
+      case Toolkit::TextField::Property::OUTLINE:
+      {
+        GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_OUTLINE:
+      {
+        GetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
+        break;
+      }
     } //switch
   }
 
@@ -1105,11 +1226,9 @@ void TextField::RenderText()
 
   if( mRenderableActor )
   {
-    // TODO: Scroll and alignment needs to be refactored.
-    const Vector2& alignmentOffset = mController->GetAlignmentOffset();
     const Vector2& scrollOffset = mController->GetScrollPosition();
 
-    mRenderableActor.SetPosition( scrollOffset.x, alignmentOffset.y + scrollOffset.y );
+    mRenderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
 
     Actor clipRootActor;
     if( mClipper )
index cefe7ad..c2b154e 100644 (file)
@@ -25,7 +25,9 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/text/rendering-backend.h>
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/internal/text/property-string-parser.h>
 #include <dali-toolkit/internal/text/rendering/text-backend.h>
+#include <dali-toolkit/internal/text/text-effects-style.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
 #include <dali-toolkit/internal/text/text-view.h>
 #include <dali-toolkit/internal/text/text-definitions.h>
@@ -99,6 +101,11 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "enableAutoScroll",     BOOLEAN,
 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "autoScrollSpeed",      INTEGER, AUTO_SCROLL_SPEED      )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "autoScrollLoopCount",  INTEGER, AUTO_SCROLL_LOOP_COUNT )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "autoScrollGap",        FLOAT,   AUTO_SCROLL_GAP        )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "lineSpacing",          FLOAT,   LINE_SPACING           )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underline",            STRING,  UNDERLINE              )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadow",               STRING,  SHADOW                 )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "emboss",               STRING,  EMBOSS                 )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "outline",              STRING,  OUTLINE                )
 
 DALI_TYPE_REGISTRATION_END()
 
@@ -372,6 +379,52 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
         impl.mTextScroller->SetGap( value.Get<float>() );
         break;
       }
+      case Toolkit::TextLabel::Property::LINE_SPACING:
+      {
+        if( impl.mController )
+        {
+          const float lineSpacing = value.Get<float>();
+          impl.mController->SetDefaultLineSpacing( lineSpacing );
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextLabel::Property::UNDERLINE:
+      {
+        const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextLabel::Property::SHADOW:
+      {
+        const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextLabel::Property::EMBOSS:
+      {
+        const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
+      case Toolkit::TextLabel::Property::OUTLINE:
+      {
+        const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        if( update )
+        {
+          impl.mRenderer.Reset();
+        }
+        break;
+      }
     }
   }
 }
@@ -553,6 +606,34 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde
         }
         break;
       }
+      case Toolkit::TextLabel::Property::LINE_SPACING:
+      {
+        if( impl.mController )
+        {
+          value = impl.mController->GetDefaultLineSpacing();
+        }
+        break;
+      }
+      case Toolkit::TextLabel::Property::UNDERLINE:
+      {
+        GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextLabel::Property::SHADOW:
+      {
+        GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextLabel::Property::EMBOSS:
+      {
+        GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
+      case Toolkit::TextLabel::Property::OUTLINE:
+      {
+        GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
+        break;
+      }
     }
   }
 
@@ -664,9 +745,8 @@ void TextLabel::RenderText()
 
     if( renderableActor )
     {
-      // TODO: Scroll and alignment needs to be refactored.
-      const Vector2& alignmentOffset = mController->GetAlignmentOffset();
-      renderableActor.SetPosition( 0.f, alignmentOffset.y );
+      const Vector2& scrollOffset = mController->GetScrollPosition();
+      renderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
 
       self.Add( renderableActor );
     }
@@ -683,15 +763,15 @@ void TextLabel::SetUpAutoScrolling()
 {
   const Size& controlSize = mController->GetView().GetControlSize();
   const Size offScreenSize = GetNaturalSize().GetVectorXY(); // As relayout of text may not be done at this point natural size is used to get size. Single line scrolling only.
-  const Vector2& alignmentOffset = mController->GetAlignmentOffset();
+  const float alignmentOffset = mController->GetAutoScrollLineAlignment();
   const Text::CharacterDirection direction = mController->GetAutoScrollDirection();
 
-  DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling alignmentOffset[%f,%f] offScreenSize[%f,%f] controlSize[%f,%f]\n",
-                 alignmentOffset.x, alignmentOffset.y, offScreenSize.x,offScreenSize.y , controlSize.x,controlSize.y);
+  DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling alignmentOffset[%f] offScreenSize[%f,%f] controlSize[%f,%f]\n",
+                 alignmentOffset, offScreenSize.x,offScreenSize.y , controlSize.x,controlSize.y );
 
   if ( !mTextScroller )
   {
-    DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling Creating default TextScoller\n");
+    DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling Creating default TextScoller\n" );
 
     // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults
     mTextScroller = Text::TextScroller::New( *this );
index 7fba3eb..3c71f0b 100644 (file)
@@ -100,11 +100,13 @@ toolkit_src_files = \
    $(toolkit_src_dir)/text/markup-processor-font.cpp \
    $(toolkit_src_dir)/text/markup-processor-helper-functions.cpp \
    $(toolkit_src_dir)/text/multi-language-support.cpp \
+   $(toolkit_src_dir)/text/property-string-parser.cpp \
    $(toolkit_src_dir)/text/segmentation.cpp \
    $(toolkit_src_dir)/text/shaper.cpp \
    $(toolkit_src_dir)/text/text-control-interface.cpp \
    $(toolkit_src_dir)/text/text-controller.cpp \
    $(toolkit_src_dir)/text/text-controller-impl.cpp \
+   $(toolkit_src_dir)/text/text-effects-style.cpp \
    $(toolkit_src_dir)/text/text-font-style.cpp \
    $(toolkit_src_dir)/text/text-io.cpp \
    $(toolkit_src_dir)/text/text-scroller.cpp \
index 1bce75a..2b5e328 100644 (file)
@@ -31,7 +31,9 @@ namespace
   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
 #endif
 
-} // namespace
+const Dali::Toolkit::Text::CharacterDirection LTR = false; ///< Left To Right direction.
+
+} //namespace
 
 namespace Dali
 {
@@ -49,19 +51,25 @@ LineIndex GetClosestLine( VisualModelPtr visualModel,
   LineIndex lineIndex = 0u;
 
   const Vector<LineRun>& lines = visualModel->mLines;
-  for( LineIndex endLine = lines.Count();
-       lineIndex < endLine;
-       ++lineIndex )
+
+  for( Vector<LineRun>::ConstIterator it = lines.Begin(),
+         endIt = lines.End();
+       it != endIt;
+       ++it, ++lineIndex )
   {
-    const LineRun& lineRun = lines[lineIndex];
-    totalHeight += lineRun.ascender + -lineRun.descender;
+    const LineRun& lineRun = *it;
+
+    // The line height is the addition of the line ascender and the line descender.
+    // However, the line descender has a negative value, hence the subtraction.
+    totalHeight += lineRun.ascender - lineRun.descender;
+
     if( visualY < totalHeight )
     {
       return lineIndex;
     }
   }
 
-  if( lineIndex == 0 )
+  if( lineIndex == 0u )
   {
     return 0;
   }
@@ -69,6 +77,26 @@ LineIndex GetClosestLine( VisualModelPtr visualModel,
   return lineIndex-1;
 }
 
+float CalculateLineOffset( const Vector<LineRun>& lines,
+                           LineIndex lineIndex )
+{
+  float offset = 0.f;
+
+  for( Vector<LineRun>::ConstIterator it = lines.Begin(),
+         endIt = lines.Begin() + lineIndex;
+       it != endIt;
+       ++it )
+  {
+    const LineRun& lineRun = *it;
+
+    // The line height is the addition of the line ascender and the line descender.
+    // However, the line descender has a negative value, hence the subtraction.
+    offset += lineRun.ascender - lineRun.descender;
+  }
+
+  return offset;
+}
+
 CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
                                       LogicalModelPtr logicalModel,
                                       MetricsPtr metrics,
@@ -90,11 +118,15 @@ CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
   // Find which line is closest.
   const LineIndex lineIndex = Text::GetClosestLine( visualModel,
                                                     visualY );
-  const LineRun& line = visualModel->mLines[lineIndex];
+
+  // Convert from text's coords to line's coords.
+  const LineRun& line = *( visualModel->mLines.Begin() + lineIndex );
+
+  // Transform the tap point from text's coords to line's coords.
+  visualX -= line.alignmentOffset;
 
   // Get the positions of the glyphs.
-  const Vector<Vector2>& positions = visualModel->mGlyphPositions;
-  const Vector2* const positionsBuffer = positions.Begin();
+  const Vector2* const positionsBuffer = visualModel->mGlyphPositions.Begin();
 
   // Get the character to glyph conversion table.
   const GlyphIndex* const charactersToGlyphBuffer = visualModel->mCharactersToGlyph.Begin();
@@ -102,6 +134,9 @@ CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
   // Get the glyphs per character table.
   const Length* const glyphsPerCharacterBuffer = visualModel->mGlyphsPerCharacter.Begin();
 
+  // Get the characters per glyph table.
+  const Length* const charactersPerGlyphBuffer = visualModel->mCharactersPerGlyph.Begin();
+
   // Get the glyph's info buffer.
   const GlyphInfo* const glyphInfoBuffer = visualModel->mGlyphs.Begin();
 
@@ -112,29 +147,29 @@ CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
   // Whether this line is a bidirectional line.
   const bool bidiLineFetched = logicalModel->FetchBidirectionalLineInfo( startCharacter );
 
+  // The character's direction buffer.
+  const CharacterDirection* const directionsBuffer = bidiLineFetched ? logicalModel->mCharacterDirections.Begin() : NULL;
+
   // Whether there is a hit on a glyph.
   bool matched = false;
 
   // Traverses glyphs in visual order. To do that use the visual to logical conversion table.
   CharacterIndex visualIndex = startCharacter;
-  Length numberOfCharacters = 0u;
-  for( ; !matched && ( visualIndex < endCharacter ); ++visualIndex )
+  Length numberOfVisualCharacters = 0u;
+  for( ; visualIndex < endCharacter; ++visualIndex )
   {
     // The character in logical order.
     const CharacterIndex characterLogicalOrderIndex = ( bidiLineFetched ? logicalModel->GetLogicalCharacterIndex( visualIndex ) : visualIndex );
-
-    // Get the script of the character.
-    const Script script = logicalModel->GetScript( characterLogicalOrderIndex );
+    const CharacterDirection direction = ( bidiLineFetched ? *( directionsBuffer + characterLogicalOrderIndex ) : LTR );
 
     // The number of glyphs for that character
     const Length numberOfGlyphs = *( glyphsPerCharacterBuffer + characterLogicalOrderIndex );
-    ++numberOfCharacters;
-
+    ++numberOfVisualCharacters;
 
     if( 0u != numberOfGlyphs )
     {
       // Get the first character/glyph of the group of glyphs.
-      const CharacterIndex firstVisualCharacterIndex = 1u + visualIndex - numberOfCharacters;
+      const CharacterIndex firstVisualCharacterIndex = 1u + visualIndex - numberOfVisualCharacters;
       const CharacterIndex firstLogicalCharacterIndex = ( bidiLineFetched ? logicalModel->GetLogicalCharacterIndex( firstVisualCharacterIndex ) : firstVisualCharacterIndex );
       const GlyphIndex firstLogicalGlyphIndex = *( charactersToGlyphBuffer + firstLogicalCharacterIndex );
 
@@ -150,12 +185,25 @@ CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
       const Vector2& position = *( positionsBuffer + firstLogicalGlyphIndex );
 
       // Whether the glyph can be split, like Latin ligatures fi, ff or Arabic ﻻ.
+      const Length numberOfCharacters = *( charactersPerGlyphBuffer + firstLogicalGlyphIndex );
+      if( direction != LTR )
+      {
+        // As characters are being traversed in visual order,
+        // for right to left ligatures, the character which contains the
+        // number of glyphs in the table is found first.
+        // Jump the number of characters to the next glyph is needed.
+        visualIndex += numberOfCharacters - 1u;
+      }
+
+      // Get the script of the character.
+      const Script script = logicalModel->GetScript( characterLogicalOrderIndex );
+
       const bool isInterglyphIndex = ( numberOfCharacters > numberOfGlyphs ) && HasLigatureMustBreak( script );
       const Length numberOfBlocks = isInterglyphIndex ? numberOfCharacters : 1u;
       const float glyphAdvance = glyphMetrics.advance / static_cast<float>( numberOfBlocks );
 
-      GlyphIndex index = 0u;
-      for( ; !matched && ( index < numberOfBlocks ); ++index )
+      CharacterIndex index = 0u;
+      for( ; index < numberOfBlocks; ++index )
       {
         // Find the mid-point of the area containing the glyph
         const float glyphCenter = -glyphMetrics.xBearing + position.x + ( static_cast<float>( index ) + 0.5f ) * glyphAdvance;
@@ -169,23 +217,83 @@ CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
 
       if( matched )
       {
+        // If the glyph is shaped from more than one character, it matches the character of the glyph.
         visualIndex = firstVisualCharacterIndex + index;
         break;
       }
 
-      numberOfCharacters = 0u;
+      numberOfVisualCharacters = 0u;
     }
-
   }
 
+  // The number of characters of the whole text.
+  const Length totalNumberOfCharacters = logicalModel->mText.Count();
+
   // Return the logical position of the cursor in characters.
 
   if( !matched )
   {
+    // If no character is matched, then the last character (in visual order) of the line is used.
     visualIndex = endCharacter;
   }
 
+  // Get the paragraph direction.
+  const CharacterDirection paragraphDirection = line.direction;
+
+  if( totalNumberOfCharacters != visualIndex )
+  {
+    // The visual index is not at the end of the text.
+
+    if( LTR == paragraphDirection )
+    {
+      // The paragraph direction is left to right.
+
+      if( visualIndex == endCharacter )
+      {
+        // It places the cursor just before the last character in visual order.
+        // i.e. it places the cursor just before the '\n' or before the last character
+        // if there is a long line with no word breaks which is wrapped.
+
+        // It doesn't check if the closest line is the last one like the RTL branch below
+        // because the total number of characters is different than the visual index and
+        // the visual index is the last character of the line.
+        --visualIndex;
+      }
+    }
+    else
+    {
+      // The paragraph direction is right to left.
+
+      if( ( lineIndex != numberOfLines - 1u ) && // is not the last line.
+          ( visualIndex == startCharacter ) )
+      {
+        // It places the cursor just after the first character in visual order.
+        // i.e. it places the cursor just after the '\n' or after the last character
+        // if there is a long line with no word breaks which is wrapped.
+
+        // If the last line doesn't end with '\n' it won't increase the visual index
+        // placing the cursor at the beginning of the line (in visual order).
+        ++visualIndex;
+      }
+    }
+  }
+  else
+  {
+    // The visual index is at the end of text.
+
+    // If the text ends with a new paragraph character i.e. a '\n', an extra line with no characters is added at the end of the text.
+    // This branch checks if the closest line is the one with the last '\n'. If it is, it decrements the visual index to place
+    // the cursor just before the last '\n'.
+
+    if( ( lineIndex != numberOfLines - 1u ) &&
+        TextAbstraction::IsNewParagraph( *( logicalModel->mText.Begin() + visualIndex - 1u ) ) )
+    {
+      --visualIndex;
+    }
+  }
+
   logicalIndex = ( bidiLineFetched ? logicalModel->GetLogicalCursorIndex( visualIndex ) : visualIndex );
+
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "closest visualIndex %d logicalIndex %d\n", visualIndex, logicalIndex );
 
   DALI_ASSERT_DEBUG( ( logicalIndex <= logicalModel->mText.Count() && logicalIndex >= 0 ) && "GetClosestCursorIndex - Out of bounds index" );
@@ -200,186 +308,261 @@ void GetCursorPosition( VisualModelPtr visualModel,
                         CharacterIndex logical,
                         CursorInfo& cursorInfo )
 {
-  // TODO: Check for multiline with \n, etc...
+  // Whether the logical cursor position is at the end of the whole text.
+  const bool isLastPosition = logicalModel->mText.Count() == logical;
 
-  const Length numberOfCharacters = logicalModel->mText.Count();
-
-  // Check if the logical position is the first or the last one of the text.
-  const bool isFirstPosition = 0u == logical;
-  const bool isLastPosition = numberOfCharacters == logical;
-
-  // 'logical' is the logical 'cursor' index.
-  // Get the next and current logical 'character' index.
-  const CharacterIndex nextCharacterIndex = logical;
-  const CharacterIndex characterIndex = isFirstPosition ? logical : logical - 1u;
+  // Get the line where the character is laid-out.
+  const CharacterIndex characterOfLine = isLastPosition ? ( logical - 1u ) : logical;
 
-  // Get the direction of the character and the next one.
-  const CharacterDirection* const modelCharacterDirectionsBuffer = ( 0u != logicalModel->mCharacterDirections.Count() ) ? logicalModel->mCharacterDirections.Begin() : NULL;
+  // Whether the cursor is in the last position and the last position is a new paragraph character.
+  const bool isLastNewParagraph = isLastPosition && TextAbstraction::IsNewParagraph( *( logicalModel->mText.Begin() + characterOfLine ) );
 
-  CharacterDirection isCurrentRightToLeft = false;
-  CharacterDirection isNextRightToLeft = false;
-  if( NULL != modelCharacterDirectionsBuffer ) // If modelCharacterDirectionsBuffer is NULL, it means the whole text is left to right.
-  {
-    isCurrentRightToLeft = *( modelCharacterDirectionsBuffer + characterIndex );
-    isNextRightToLeft = *( modelCharacterDirectionsBuffer + nextCharacterIndex );
-  }
-
-  // Get the line where the character is laid-out.
   const LineRun* const modelLines = visualModel->mLines.Begin();
 
-  const LineIndex lineIndex = visualModel->GetLineOfCharacter( characterIndex );
+  const LineIndex lineIndex = visualModel->GetLineOfCharacter( characterOfLine );
   const LineRun& line = *( modelLines + lineIndex );
 
-  // Get the paragraph's direction.
-  const CharacterDirection isRightToLeftParagraph = line.direction;
+  if( isLastNewParagraph )
+  {
+    // The cursor is in a new line with no characters. Place the cursor in that line.
+    const LineIndex newLineIndex = lineIndex + 1u;
+    const LineRun& newLine = *( modelLines + newLineIndex );
+
+    cursorInfo.isSecondaryCursor = false;
 
-  // Check whether there is an alternative position:
+    // Set the line offset and height.
+    cursorInfo.lineOffset = CalculateLineOffset( visualModel->mLines,
+                                                 newLineIndex );
 
-  cursorInfo.isSecondaryCursor = ( !isLastPosition && ( isCurrentRightToLeft != isNextRightToLeft ) ) ||
-                                 ( isLastPosition && ( isRightToLeftParagraph != isCurrentRightToLeft ) );
+    // The line height is the addition of the line ascender and the line descender.
+    // However, the line descender has a negative value, hence the subtraction.
+    cursorInfo.lineHeight = newLine.ascender - newLine.descender;
 
-  // Set the line offset and height.
-  cursorInfo.lineOffset = 0.f;
-  cursorInfo.lineHeight = line.ascender + -line.descender;
+    // Set the primary cursor's height.
+    cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
 
-  // Calculate the primary cursor.
+    // Set the primary cursor's position.
+    cursorInfo.primaryPosition.x = 0.f;
+    cursorInfo.primaryPosition.y = cursorInfo.lineOffset;
 
-  CharacterIndex index = characterIndex;
-  if( cursorInfo.isSecondaryCursor )
+    // Transform the cursor info from line's coords to text's coords.
+    cursorInfo.primaryPosition.x += ( LTR == line.direction ) ? 0.f : visualModel->mControlSize.width;
+  }
+  else
   {
-    // If there is a secondary position, the primary cursor may be in a different place than the logical index.
+    // Whether this line is a bidirectional line.
+    const bool bidiLineFetched = logicalModel->FetchBidirectionalLineInfo( characterOfLine );
 
-    if( isLastPosition )
-    {
-      // The position of the cursor after the last character needs special
-      // care depending on its direction and the direction of the paragraph.
+    // Check if the logical position is the first or the last one of the line.
+    const bool isFirstPositionOfLine = line.characterRun.characterIndex == logical;
+    const bool isLastPositionOfLine = line.characterRun.characterIndex + line.characterRun.numberOfCharacters == logical;
 
-      // Need to find the first character after the last character with the paragraph's direction.
-      // i.e l0 l1 l2 r0 r1 should find r0.
+    // 'logical' is the logical 'cursor' index.
+    // Get the next and current logical 'character' index.
+    const CharacterIndex characterIndex = isFirstPositionOfLine ? logical : logical - 1u;
+    const CharacterIndex nextCharacterIndex = isLastPositionOfLine ? characterIndex : logical;
 
-      // TODO: check for more than one line!
-      index = isRightToLeftParagraph ? line.characterRun.characterIndex : line.characterRun.characterIndex + line.characterRun.numberOfCharacters - 1u;
-      index = logicalModel->GetLogicalCharacterIndex( index );
-    }
-    else
+    // The character's direction buffer.
+    const CharacterDirection* const directionsBuffer = bidiLineFetched ? logicalModel->mCharacterDirections.Begin() : NULL;
+
+    CharacterDirection isCurrentRightToLeft = false;
+    CharacterDirection isNextRightToLeft = false;
+    if( bidiLineFetched ) // If bidiLineFetched is false, it means the whole text is left to right.
     {
-      index = ( isRightToLeftParagraph == isCurrentRightToLeft ) ? characterIndex : nextCharacterIndex;
+      isCurrentRightToLeft = *( directionsBuffer + characterIndex );
+      isNextRightToLeft = *( directionsBuffer + nextCharacterIndex );
     }
-  }
 
-  const GlyphIndex* const charactersToGlyphBuffer = visualModel->mCharactersToGlyph.Begin();
-  const Length* const glyphsPerCharacterBuffer = visualModel->mGlyphsPerCharacter.Begin();
-  const Length* const charactersPerGlyphBuffer = visualModel->mCharactersPerGlyph.Begin();
-  const CharacterIndex* const glyphsToCharactersBuffer = visualModel->mGlyphsToCharacters.Begin();
-  const Vector2* const glyphPositionsBuffer = visualModel->mGlyphPositions.Begin();
-  const GlyphInfo* const glyphInfoBuffer = visualModel->mGlyphs.Begin();
+    // Get the paragraph's direction.
+    const CharacterDirection isRightToLeftParagraph = line.direction;
 
-  // Convert the cursor position into the glyph position.
-  const GlyphIndex primaryGlyphIndex = *( charactersToGlyphBuffer + index );
-  const Length primaryNumberOfGlyphs = *( glyphsPerCharacterBuffer + index );
-  const Length primaryNumberOfCharacters = *( charactersPerGlyphBuffer + primaryGlyphIndex );
-
-  // Get the metrics for the group of glyphs.
-  GlyphMetrics glyphMetrics;
-  GetGlyphsMetrics( primaryGlyphIndex,
-                    primaryNumberOfGlyphs,
-                    glyphMetrics,
-                    glyphInfoBuffer,
-                    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.
-  // A 'truth table' was build and an online Karnaugh map tool was used to simplify the logic.
-  //
-  // FLCP A
-  // ------
-  // 0000 1
-  // 0001 1
-  // 0010 0
-  // 0011 0
-  // 0100 1
-  // 0101 0
-  // 0110 1
-  // 0111 0
-  // 1000 0
-  // 1001 x
-  // 1010 x
-  // 1011 1
-  // 1100 x
-  // 1101 x
-  // 1110 x
-  // 1111 x
-  //
-  // Where F -> isFirstPosition
-  //       L -> isLastPosition
-  //       C -> isCurrentRightToLeft
-  //       P -> isRightToLeftParagraph
-  //       A -> Whether to add the glyph's advance.
-
-  const bool addGlyphAdvance = ( ( isLastPosition && !isRightToLeftParagraph ) ||
-                                 ( isFirstPosition && isRightToLeftParagraph ) ||
-                                 ( !isFirstPosition && !isLastPosition && !isCurrentRightToLeft ) );
-
-  float glyphAdvance = addGlyphAdvance ? glyphMetrics.advance : 0.f;
-
-  if( !isLastPosition &&
-      ( primaryNumberOfCharacters > 1u ) )
-  {
-    const CharacterIndex firstIndex = *( glyphsToCharactersBuffer + primaryGlyphIndex );
+    // Check whether there is an alternative position:
+    cursorInfo.isSecondaryCursor = ( ( !isLastPositionOfLine && ( isCurrentRightToLeft != isNextRightToLeft ) )     ||
+                                     ( isLastPositionOfLine && ( isRightToLeftParagraph != isCurrentRightToLeft ) ) ||
+                                     ( isFirstPositionOfLine && ( isRightToLeftParagraph != isCurrentRightToLeft ) ) );
+
+    // Set the line offset and height.
+    cursorInfo.lineOffset = CalculateLineOffset( visualModel->mLines,
+                                                 lineIndex );
 
-    bool isCurrentRightToLeft = false;
-    if( NULL != modelCharacterDirectionsBuffer ) // If modelCharacterDirectionsBuffer is NULL, it means the whole text is left to right.
+    // The line height is the addition of the line ascender and the line descender.
+    // However, the line descender has a negative value, hence the subtraction.
+    cursorInfo.lineHeight = line.ascender - line.descender;
+
+    // Calculate the primary cursor.
+
+    CharacterIndex index = characterIndex;
+    if( cursorInfo.isSecondaryCursor )
     {
-      isCurrentRightToLeft = *( modelCharacterDirectionsBuffer + index );
+      // If there is a secondary position, the primary cursor may be in a different place than the logical index.
+
+      if( isLastPositionOfLine )
+      {
+        // The position of the cursor after the last character needs special
+        // care depending on its direction and the direction of the paragraph.
+
+        // Need to find the first character after the last character with the paragraph's direction.
+        // i.e l0 l1 l2 r0 r1 should find r0.
+
+        index = isRightToLeftParagraph ? line.characterRun.characterIndex : line.characterRun.characterIndex + line.characterRun.numberOfCharacters - 1u;
+        if( bidiLineFetched )
+        {
+          index = logicalModel->GetLogicalCharacterIndex( index );
+        }
+      }
+      else if( isFirstPositionOfLine )
+      {
+        index = isRightToLeftParagraph ? line.characterRun.characterIndex + line.characterRun.numberOfCharacters - 1u : line.characterRun.characterIndex;
+        if( bidiLineFetched )
+        {
+          index = logicalModel->GetLogicalCharacterIndex( index );
+        }
+      }
+      else
+      {
+        index = ( isRightToLeftParagraph == isCurrentRightToLeft ) ? characterIndex : nextCharacterIndex;
+      }
     }
 
-    Length numberOfGlyphAdvance = ( isFirstPosition ? 0u : 1u ) + characterIndex - firstIndex;
-    if( isCurrentRightToLeft )
+    const GlyphIndex* const charactersToGlyphBuffer = visualModel->mCharactersToGlyph.Begin();
+    const Length* const glyphsPerCharacterBuffer = visualModel->mGlyphsPerCharacter.Begin();
+    const Length* const charactersPerGlyphBuffer = visualModel->mCharactersPerGlyph.Begin();
+    const CharacterIndex* const glyphsToCharactersBuffer = visualModel->mGlyphsToCharacters.Begin();
+    const Vector2* const glyphPositionsBuffer = visualModel->mGlyphPositions.Begin();
+    const GlyphInfo* const glyphInfoBuffer = visualModel->mGlyphs.Begin();
+
+    // Convert the cursor position into the glyph position.
+    const GlyphIndex primaryGlyphIndex = *( charactersToGlyphBuffer + index );
+    const Length primaryNumberOfGlyphs = *( glyphsPerCharacterBuffer + index );
+    const Length primaryNumberOfCharacters = *( charactersPerGlyphBuffer + primaryGlyphIndex );
+
+    // Get the metrics for the group of glyphs.
+    GlyphMetrics glyphMetrics;
+    GetGlyphsMetrics( primaryGlyphIndex,
+                      primaryNumberOfGlyphs,
+                      glyphMetrics,
+                      glyphInfoBuffer,
+                      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.
+    // A 'truth table' was build and an online Karnaugh map tool was used to simplify the logic.
+    //
+    // FLCP A
+    // ------
+    // 0000 1
+    // 0001 1
+    // 0010 0
+    // 0011 0
+    // 0100 1
+    // 0101 0
+    // 0110 1
+    // 0111 0
+    // 1000 0
+    // 1001 1
+    // 1010 0
+    // 1011 1
+    // 1100 x
+    // 1101 x
+    // 1110 x
+    // 1111 x
+    //
+    // Where F -> isFirstPosition
+    //       L -> isLastPosition
+    //       C -> isCurrentRightToLeft
+    //       P -> isRightToLeftParagraph
+    //       A -> Whether to add the glyph's advance.
+
+    const bool addGlyphAdvance = ( ( isLastPositionOfLine && !isRightToLeftParagraph ) ||
+                                   ( isFirstPositionOfLine && isRightToLeftParagraph ) ||
+                                   ( !isFirstPositionOfLine && !isLastPosition && !isCurrentRightToLeft ) );
+
+    float glyphAdvance = addGlyphAdvance ? glyphMetrics.advance : 0.f;
+
+    if( !isLastPositionOfLine &&
+        ( primaryNumberOfCharacters > 1u ) )
     {
-      numberOfGlyphAdvance = primaryNumberOfCharacters - numberOfGlyphAdvance;
-    }
+      const CharacterIndex firstIndex = *( glyphsToCharactersBuffer + primaryGlyphIndex );
 
-    glyphAdvance = static_cast<float>( numberOfGlyphAdvance ) * glyphMetrics.advance / static_cast<float>( primaryNumberOfCharacters );
-  }
+      bool isCurrentRightToLeft = false;
+      if( bidiLineFetched ) // If bidiLineFetched is false, it means the whole text is left to right.
+      {
+        isCurrentRightToLeft = *( directionsBuffer + index );
+      }
 
-  // Get the glyph position and x bearing.
-  const Vector2& primaryPosition = *( glyphPositionsBuffer + primaryGlyphIndex );
+      Length numberOfGlyphAdvance = ( isFirstPositionOfLine ? 0u : 1u ) + characterIndex - firstIndex;
+      if( isCurrentRightToLeft )
+      {
+        numberOfGlyphAdvance = primaryNumberOfCharacters - numberOfGlyphAdvance;
+      }
 
-  // Set the primary cursor's height.
-  cursorInfo.primaryCursorHeight = cursorInfo.isSecondaryCursor ? 0.5f * glyphMetrics.fontHeight : glyphMetrics.fontHeight;
+      glyphAdvance = static_cast<float>( numberOfGlyphAdvance ) * glyphMetrics.advance / static_cast<float>( primaryNumberOfCharacters );
+    }
 
-  // Set the primary cursor's position.
-  cursorInfo.primaryPosition.x = -glyphMetrics.xBearing + primaryPosition.x + glyphAdvance;
-  cursorInfo.primaryPosition.y = line.ascender - glyphMetrics.ascender;
+    // Get the glyph position and x bearing (in the line's coords).
+    const Vector2& primaryPosition = *( glyphPositionsBuffer + primaryGlyphIndex );
 
-  // Calculate the secondary cursor.
+    // Set the primary cursor's height.
+    cursorInfo.primaryCursorHeight = cursorInfo.isSecondaryCursor ? 0.5f * glyphMetrics.fontHeight : glyphMetrics.fontHeight;
 
-  if( cursorInfo.isSecondaryCursor )
-  {
-    // Set the secondary cursor's height.
-    cursorInfo.secondaryCursorHeight = 0.5f * glyphMetrics.fontHeight;
+    // Set the primary cursor's position.
+    cursorInfo.primaryPosition.x = -glyphMetrics.xBearing + primaryPosition.x + glyphAdvance;
+    cursorInfo.primaryPosition.y = cursorInfo.lineOffset + line.ascender - glyphMetrics.ascender;
 
-    CharacterIndex index = characterIndex;
-    if( !isLastPosition )
+    // Transform the cursor info from line's coords to text's coords.
+    cursorInfo.primaryPosition.x += line.alignmentOffset;
+
+    // Calculate the secondary cursor.
+    if( cursorInfo.isSecondaryCursor )
     {
-      index = ( isRightToLeftParagraph == isCurrentRightToLeft ) ? nextCharacterIndex : characterIndex;
-    }
+      // Set the secondary cursor's height.
+      cursorInfo.secondaryCursorHeight = 0.5f * glyphMetrics.fontHeight;
 
-    const GlyphIndex secondaryGlyphIndex = *( charactersToGlyphBuffer + index );
-    const Length secondaryNumberOfGlyphs = *( glyphsPerCharacterBuffer + index );
+      CharacterIndex index = characterIndex;
+      if( !isLastPositionOfLine )
+      {
+        index = ( isRightToLeftParagraph == isCurrentRightToLeft ) ? nextCharacterIndex : characterIndex;
+      }
 
-    const Vector2& secondaryPosition = *( glyphPositionsBuffer + secondaryGlyphIndex );
+      const GlyphIndex secondaryGlyphIndex = *( charactersToGlyphBuffer + index );
+      const Length secondaryNumberOfGlyphs = *( glyphsPerCharacterBuffer + index );
 
-    GetGlyphsMetrics( secondaryGlyphIndex,
-                      secondaryNumberOfGlyphs,
-                      glyphMetrics,
-                      glyphInfoBuffer,
-                      metrics );
+      const Vector2& secondaryPosition = *( glyphPositionsBuffer + secondaryGlyphIndex );
+
+      GetGlyphsMetrics( secondaryGlyphIndex,
+                        secondaryNumberOfGlyphs,
+                        glyphMetrics,
+                        glyphInfoBuffer,
+                        metrics );
 
-    // Set the secondary cursor's position.
-    cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + ( isCurrentRightToLeft ? 0.f : glyphMetrics.advance );
-    cursorInfo.secondaryPosition.y = cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight - line.descender - ( glyphMetrics.fontHeight - glyphMetrics.ascender );
+      // Set the secondary cursor's position.
+
+      // FCP A
+      // ------
+      // 000 1
+      // 001 x
+      // 010 0
+      // 011 0
+      // 100 x
+      // 101 0
+      // 110 1
+      // 111 x
+      //
+      // Where F -> isFirstPosition
+      //       C -> isCurrentRightToLeft
+      //       P -> isRightToLeftParagraph
+      //       A -> Whether to add the glyph's advance.
+
+      const bool addGlyphAdvance = ( ( !isFirstPositionOfLine && !isCurrentRightToLeft ) ||
+                                     ( isFirstPositionOfLine && !isRightToLeftParagraph ) );
+
+      cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + ( addGlyphAdvance ? glyphMetrics.advance : 0.f );
+      cursorInfo.secondaryPosition.y = cursorInfo.lineOffset + cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight - line.descender - ( glyphMetrics.fontHeight - glyphMetrics.ascender );
+
+      // Transform the cursor info from line's coords to text's coords.
+      cursorInfo.secondaryPosition.x += line.alignmentOffset;
+    }
   }
 }
 
index 7ce02bf..e89c335 100644 (file)
@@ -47,8 +47,8 @@ struct CursorInfo
   ~CursorInfo()
   {}
 
-  Vector2 primaryPosition;       ///< The primary cursor's position.
-  Vector2 secondaryPosition;     ///< The secondary cursor's position.
+  Vector2 primaryPosition;       ///< The primary cursor's position (in text's coords).
+  Vector2 secondaryPosition;     ///< The secondary cursor's position (in text's coords).
   float   lineOffset;            ///< The vertical offset where the line containing the cursor starts.
   float   lineHeight;            ///< The height of the line where the cursor is placed.
   float   primaryCursorHeight;   ///< The primary cursor's height.
@@ -61,19 +61,35 @@ struct CursorInfo
  *
  * It returns the first line if the touch point is above the text and the last line if the touch point is below.
  *
+ * @param[in] visualModel The visual model.
+ * @param[in] visualY The touch point 'y' in text's coords.
+ *
  * @return A line index.
  */
 LineIndex GetClosestLine( VisualModelPtr visualModel,
                           float visualY );
 
 /**
+ * @brief Calculates the vertical line's offset for a given line.
+ *
+ * @pre @p lineIndex must be between 0 and the number of lines (both inclusive).
+ *
+ * @param[in] lines The laid-out lines.
+ * @param[in] lineIndex Index to the line.
+ *
+ * @return The vertical offset of the given line.
+ */
+float CalculateLineOffset( const Vector<LineRun>& lines,
+                           LineIndex lineIndex );
+
+/**
  * @brief Retrieves the cursor's logical position for a given touch point x,y
  *
  * @param[in] visualModel The visual model.
  * @param[in] logicalModel The logical model.
  * @param[in] metrics A wrapper around FontClient used to get metrics.
- * @param[in] visualX The touch point x.
- * @param[in] visualY The touch point y.
+ * @param[in] visualX The touch point 'x' in text's coords.
+ * @param[in] visualY The touch point 'y' in text's coords.
  *
  * @return The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character.
  */
@@ -90,6 +106,9 @@ CharacterIndex GetClosestCursorIndex( VisualModelPtr visualModel,
  * It retrieves as well the line's height and the cursor's height and
  * if there is a valid alternative cursor, its position and height.
  *
+ * @param[in] visualModel The visual model.
+ * @param[in] logicalModel The logical model.
+ * @param[in] metrics A wrapper around FontClient used to get metrics.
  * @param[in] logical The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character.
  * @param[out] cursorInfo The line's height, the cursor's height, the cursor's position and whether there is an alternative cursor.
  */
@@ -100,7 +119,15 @@ void GetCursorPosition( VisualModelPtr visualModel,
                         CursorInfo& cursorInfo );
 
 /**
+ * @brief Find the indices to the first and last characters of a word for the given touch point.
  *
+ * @param[in] visualModel The visual model.
+ * @param[in] logicalModel The logical model.
+ * @param[in] metrics A wrapper around FontClient used to get metrics.
+ * @param[in] visualX The touch point 'x' in text's coords.
+ * @param[in] visualY The touch point 'y' in text's coords.
+ * @param[out] startIndex Index to the first character of the selected word.
+ * @param[out] endIndex Index to the last character of the selected word.
  */
 void FindSelectionIndices( VisualModelPtr visualModel,
                            LogicalModelPtr logicalModel,
index 5d7aead..30ce38c 100644 (file)
@@ -46,31 +46,45 @@ struct InputStyle
     width( TextAbstraction::FontWidth::NORMAL ),
     slant( TextAbstraction::FontSlant::NORMAL ),
     size( 0.f ),
+    lineSpacing( 0.f ),
+    underlineProperties(),
+    shadowProperties(),
+    embossProperties(),
+    outlineProperties(),
     isDefaultColor( true ),
     familyDefined( false ),
     weightDefined( false ),
     widthDefined( false ),
     slantDefined( false ),
-    sizeDefined( false )
+    sizeDefined( false ),
+    lineSpacingDefined( false )
   {}
 
   ~InputStyle()
   {};
 
-  Vector4     textColor;  ///< The text's color.
-  std::string fontStyle;  ///< The font's style string.
-  std::string familyName; ///< The font's family name.
-  FontWeight  weight;     ///< The font's weight.
-  FontWidth   width;      ///< The font's width.
-  FontSlant   slant;      ///< The font's slant.
-  float       size;       ///< The font's size.
-
-  bool        isDefaultColor : 1; ///< Whether the text's color is the default.
-  bool        familyDefined  : 1; ///< Whether the font's family is defined.
-  bool        weightDefined  : 1; ///< Whether the font's weight is defined.
-  bool        widthDefined   : 1; ///< Whether the font's width is defined.
-  bool        slantDefined   : 1; ///< Whether the font's slant is defined.
-  bool        sizeDefined    : 1; ///< Whether the font's size is defined.
+  Vector4     textColor;           ///< The text's color.
+  std::string fontStyle;           ///< The font's style string.
+  std::string familyName;          ///< The font's family name.
+  FontWeight  weight;              ///< The font's weight.
+  FontWidth   width;               ///< The font's width.
+  FontSlant   slant;               ///< The font's slant.
+  float       size;                ///< The font's size.
+
+  float       lineSpacing;         ///< The line's spacing.
+  std::string underlineProperties; ///< The underline properties string.
+  std::string shadowProperties;    ///< The shadow properties string.
+  std::string embossProperties;    ///< The emboss properties string.
+  std::string outlineProperties;   ///< The outline properties string.
+
+  bool        isDefaultColor     : 1; ///< Whether the text's color is the default.
+  bool        familyDefined      : 1; ///< Whether the font's family is defined.
+  bool        weightDefined      : 1; ///< Whether the font's weight is defined.
+  bool        widthDefined       : 1; ///< Whether the font's width is defined.
+  bool        slantDefined       : 1; ///< Whether the font's slant is defined.
+  bool        sizeDefined        : 1; ///< Whether the font's size is defined.
+
+  bool        lineSpacingDefined : 1; ///< Whether the line spacing is defined.
 };
 
 } // namespace Text
index ac9110e..8d9f8f5 100644 (file)
@@ -25,6 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 
@@ -47,6 +48,7 @@ namespace
 const float MAX_FLOAT = std::numeric_limits<float>::max();
 const bool RTL = true;
 const float CURSOR_WIDTH = 1.f;
+const float LINE_SPACING= 0.f;
 
 } //namespace
 
@@ -104,6 +106,7 @@ struct LayoutEngine::Impl
     mHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ),
     mVerticalAlignment( LayoutEngine::VERTICAL_ALIGN_TOP ),
     mCursorWidth( CURSOR_WIDTH ),
+    mDefaultLineSpacing( LINE_SPACING ),
     mEllipsisEnabled( false )
   {
   }
@@ -464,34 +467,6 @@ struct LayoutEngine::Impl
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
   }
 
-  /**
-   * @brief Calculates the vertical offset to add to the new laid-out glyphs.
-   *
-   * @pre @p lineIndex must be between 0 and the number of lines (both inclusive).
-   *
-   * @param[in] lines The previously laid-out lines.
-   * @param[in] lineIndex Index to the line where the new laid-out lines are inserted.
-   *
-   * @return The vertical offset of the lines starting from the beginning to the line @p lineIndex.
-   */
-  float SetParagraphOffset( const Vector<LineRun>& lines,
-                            LineIndex lineIndex )
-  {
-    float offset = 0.f;
-
-    for( Vector<LineRun>::ConstIterator it = lines.Begin(),
-           endIt = lines.Begin() + lineIndex;
-         it != endIt;
-         ++it )
-    {
-      const LineRun& line = *it;
-
-      offset += line.ascender + -line.descender;
-    }
-
-    return offset;
-  }
-
   void SetGlyphPositions( const GlyphInfo* const glyphsBuffer,
                           Length numberOfGlyphs,
                           Vector2* glyphPositionsBuffer )
@@ -871,8 +846,8 @@ struct LayoutEngine::Impl
       linesBuffer = lines.Begin();
     }
 
-    float penY = SetParagraphOffset( lines,
-                                     layoutParameters.startLineIndex );
+    float penY = CalculateLineOffset( lines,
+                                      layoutParameters.startLineIndex );
 
     for( GlyphIndex index = layoutParameters.startGlyphIndex; index < lastGlyphPlusOne; )
     {
@@ -1213,6 +1188,7 @@ struct LayoutEngine::Impl
   LayoutEngine::HorizontalAlignment mHorizontalAlignment;
   LayoutEngine::VerticalAlignment mVerticalAlignment;
   float mCursorWidth;
+  float mDefaultLineSpacing;
 
   IntrusivePtr<Metrics> mMetrics;
 
@@ -1320,6 +1296,16 @@ void LayoutEngine::Align( const Size& size,
                 lines );
 }
 
+void LayoutEngine::SetDefaultLineSpacing( float lineSpacing )
+{
+  mImpl->mDefaultLineSpacing = lineSpacing;
+}
+
+float LayoutEngine::GetDefaultLineSpacing() const
+{
+  return mImpl->mDefaultLineSpacing;
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index e672c53..79daa23 100644 (file)
@@ -192,6 +192,20 @@ public:
               Length numberOfCharacters,
               Vector<LineRun>& lines );
 
+  /**
+   * @brief Sets the default line spacing.
+   *
+   * @param[in] lineSpacing The line spacing.
+   */
+  void SetDefaultLineSpacing( float lineSpacing );
+
+  /**
+   * @brief Retrieves the default line spacing.
+   *
+   * @return The line spacing.
+   */
+  float GetDefaultLineSpacing() const;
+
 private:
 
   // Undefined
diff --git a/dali-toolkit/internal/text/property-string-parser.cpp b/dali-toolkit/internal/text/property-string-parser.cpp
new file mode 100644 (file)
index 0000000..c120e00
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/property-string-parser.h>
+
+// EXTERNAL HEADERS
+#include <sstream>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/builder/json-parser.h>
+#include <dali-toolkit/devel-api/builder/tree-node.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+void CreatePropertyMap( const TreeNode* const node, Property::Map& map )
+{
+  switch( node->GetType() )
+  {
+    case TreeNode::IS_NULL:
+    case TreeNode::OBJECT:
+    case TreeNode::ARRAY: // FALL THROUGH
+    {
+      break;
+    }
+    case TreeNode::STRING:
+    {
+      map.Insert( node->GetName(), Property::Value( node->GetString() ) );
+      break;
+    }
+    case TreeNode::INTEGER:
+    case TreeNode::FLOAT:
+    case TreeNode::BOOLEAN: // FALL THROUGH
+    {
+      break;
+    }
+  }
+
+  for( TreeNode::ConstIterator it = node->CBegin(), endIt = node->CEnd(); it != endIt; ++it )
+  {
+    const TreeNode::KeyNodePair& pair = *it;
+    CreatePropertyMap( &pair.second, map );
+  }
+}
+
+void ParsePropertyString( const std::string& property, Property::Map& map )
+{
+  Toolkit::JsonParser parser = Toolkit::JsonParser::New();
+
+  if( parser.Parse( property ) )
+  {
+    const TreeNode* const node = parser.GetRoot();
+
+    CreatePropertyMap( node, map );
+  }
+}
+
+void StringOffsetToVector2( const std::string& offsetStr,
+                            Vector2& offset )
+{
+  offset = Vector2::ZERO;
+
+  unsigned int wsIndex = 0u;
+  for( std::string::const_iterator it = offsetStr.begin(),
+         endIt = offsetStr.end();
+       it != endIt;
+       ++it, ++wsIndex )
+  {
+    if( *it == ' ' )
+    {
+      break;
+    }
+  }
+
+  offset[0] = StringToFloat( offsetStr.c_str() );
+  offset[1] = StringToFloat( offsetStr.c_str() + wsIndex );
+}
+
+} //namespace Text
+
+} //namespace Toolkit
+
+} //namespace Dali
diff --git a/dali-toolkit/internal/text/property-string-parser.h b/dali-toolkit/internal/text/property-string-parser.h
new file mode 100644 (file)
index 0000000..b6ebf27
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef __DALI_TOOLKIT_PROPERTY_STRING_PARSER_H__
+#define __DALI_TOOLKIT_PROPERTY_STRING_PARSER_H__
+
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/property-map.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+// Forward declaration
+struct Vector2;
+
+namespace Toolkit
+{
+
+// Forward declaration
+class TreeNode;
+
+namespace Text
+{
+
+/**
+ * @brief Creates a map with pairs 'key,value' with the property's parameters.
+ *
+ * @param[in] node Data structure with the property's parameters.
+ * @param[out] map A map with the property's parameters.
+ *
+ */
+void CreatePropertyMap( const TreeNode* const node, Property::Map& map );
+
+/**
+ * @brief Parses a property string.
+ *
+ * @param[in] property A property string.
+ * @param[out] map A map with the property's parameters.
+ *
+ */
+void ParsePropertyString( const std::string& property, Property::Map& map );
+
+/**
+ * @brief Converts an offset packed inside a string into a Vector2.
+ *
+ * @param[in] offsetStr The offset packed inside a string.
+ * @param[out] offset The offset packed in a Vector2.
+ *
+ */
+void StringOffsetToVector2( const std::string& offsetStr,
+                            Vector2& offset );
+
+} //namespace Text
+
+} //namespace Toolkit
+
+} //namespace Dali
+
+#endif //__DALI_TOOLKIT_PROPERTY_STRING_PARSER_H__
index 32ab39b..f2e5596 100644 (file)
@@ -689,22 +689,26 @@ struct AtlasRenderer::Impl
       vert.mPosition.y = baseLine;
       vert.mTexCoords.x = ZERO;
       vert.mTexCoords.y = ZERO;
+      vert.mColor = underlineColor;
       newMesh.mVertices.PushBack( vert );
 
       vert.mPosition.x = brx;
       vert.mPosition.y = baseLine;
       vert.mTexCoords.x = u;
+      vert.mColor = underlineColor;
       newMesh.mVertices.PushBack( vert );
 
       vert.mPosition.x = tlx;
       vert.mPosition.y = baseLine + thickness;
       vert.mTexCoords.x = ZERO;
       vert.mTexCoords.y = v;
+      vert.mColor = underlineColor;
       newMesh.mVertices.PushBack( vert );
 
       vert.mPosition.x = brx;
       vert.mPosition.y = baseLine + thickness;
       vert.mTexCoords.x = u;
+      vert.mColor = underlineColor;
       newMesh.mVertices.PushBack( vert );
 
       // Six indices in counter clockwise winding
@@ -716,8 +720,6 @@ struct AtlasRenderer::Impl
       newMesh.mIndices.PushBack( faceIndex + 1u );
       faceIndex += 4;
 
-      vert.mColor = underlineColor;
-
       Toolkit::Internal::AtlasMeshFactory::AppendMesh( meshRecords[ index ].mMesh, newMesh );
     }
   }
index 7bbf04d..187c3f7 100644 (file)
@@ -57,7 +57,6 @@ EventData::EventData( DecoratorPtr decorator )
   mPlaceholderTextInactive(),
   mPlaceholderTextColor( 0.8f, 0.8f, 0.8f, 0.8f ),
   mEventQueue(),
-  mScrollPosition(),
   mState( INACTIVE ),
   mPrimaryCursorPosition( 0u ),
   mLeftSelectionPosition( 0u ),
@@ -1001,8 +1000,9 @@ void Controller::Impl::OnTapEvent( const Event& event )
     {
       if( IsShowingRealText() )
       {
-        const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
-        const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
+        // Convert from control's coords to text's coords.
+        const float xPosition = event.p2.mFloat - mScrollPosition.x;
+        const float yPosition = event.p3.mFloat - mScrollPosition.y;
 
         mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mVisualModel,
                                                                           mLogicalModel,
@@ -1042,16 +1042,16 @@ void Controller::Impl::OnPanEvent( const Event& event )
 
   int state = event.p1.mInt;
 
-  if( Gesture::Started    == state ||
-      Gesture::Continuing == state )
+  if( ( Gesture::Started == state ) ||
+      ( Gesture::Continuing == state ) )
   {
     const Vector2& actualSize = mVisualModel->GetLayoutSize();
-    const Vector2 currentScroll = mEventData->mScrollPosition;
+    const Vector2 currentScroll = mScrollPosition;
 
     if( mEventData->mHorizontalScrollingEnabled )
     {
       const float displacementX = event.p2.mFloat;
-      mEventData->mScrollPosition.x += displacementX;
+      mScrollPosition.x += displacementX;
 
       ClampHorizontalScroll( actualSize );
     }
@@ -1059,14 +1059,14 @@ void Controller::Impl::OnPanEvent( const Event& event )
     if( mEventData->mVerticalScrollingEnabled )
     {
       const float displacementY = event.p3.mFloat;
-      mEventData->mScrollPosition.y += displacementY;
+      mScrollPosition.y += displacementY;
 
       ClampVerticalScroll( actualSize );
     }
 
     if( mEventData->mDecorator )
     {
-      mEventData->mDecorator->UpdatePositions( mEventData->mScrollPosition - currentScroll );
+      mEventData->mDecorator->UpdatePositions( mScrollPosition - currentScroll );
     }
   }
 }
@@ -1095,9 +1095,9 @@ void Controller::Impl::OnHandleEvent( const Event& event )
 
   if( HANDLE_PRESSED == state )
   {
-    // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords.
-    const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
-    const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
+    // Convert from decorator's coords to text's coords.
+    const float xPosition = event.p2.mFloat - mScrollPosition.x;
+    const float yPosition = event.p3.mFloat - mScrollPosition.y;
 
     const CharacterIndex handleNewPosition = Text::GetClosestCursorIndex( mVisualModel,
                                                                           mLogicalModel,
@@ -1146,9 +1146,9 @@ void Controller::Impl::OnHandleEvent( const Event& event )
     CharacterIndex handlePosition = 0u;
     if( handleStopScrolling )
     {
-      // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords.
-      const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
-      const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
+      // Convert from decorator's coords to text's coords.
+      const float xPosition = event.p2.mFloat - mScrollPosition.x;
+      const float yPosition = event.p3.mFloat - mScrollPosition.y;
 
       handlePosition = Text::GetClosestCursorIndex( mVisualModel,
                                                     mLogicalModel,
@@ -1209,14 +1209,14 @@ void Controller::Impl::OnHandleEvent( const Event& event )
   {
     const float xSpeed = event.p2.mFloat;
     const Vector2& actualSize = mVisualModel->GetLayoutSize();
-    const Vector2 currentScrollPosition = mEventData->mScrollPosition;
+    const Vector2 currentScrollPosition = mScrollPosition;
 
-    mEventData->mScrollPosition.x += xSpeed;
+    mScrollPosition.x += xSpeed;
 
     ClampHorizontalScroll( actualSize );
 
     bool endOfScroll = false;
-    if( Vector2::ZERO == ( currentScrollPosition - mEventData->mScrollPosition ) )
+    if( Vector2::ZERO == ( currentScrollPosition - mScrollPosition ) )
     {
       // Notify the decorator there is no more text to scroll.
       // The decorator won't send more scroll events.
@@ -1240,12 +1240,12 @@ void Controller::Impl::OnHandleEvent( const Event& event )
       position.x = scrollRightDirection ? 0.f : mVisualModel->mControlSize.width;
 
       // Get the new handle position.
-      // The grab handle's position is in decorator coords. Need to transforms to text coords.
+      // The grab handle's position is in decorator's coords. Need to transforms to text's coords.
       const CharacterIndex handlePosition = Text::GetClosestCursorIndex( mVisualModel,
                                                                          mLogicalModel,
                                                                          mMetrics,
-                                                                         position.x - mEventData->mScrollPosition.x - mAlignmentOffset.x,
-                                                                         position.y - mEventData->mScrollPosition.y - mAlignmentOffset.y );
+                                                                         position.x - mScrollPosition.x,
+                                                                         position.y - mScrollPosition.y );
 
       mEventData->mUpdateCursorPosition = mEventData->mPrimaryCursorPosition != handlePosition;
       mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateCursorPosition;
@@ -1265,12 +1265,12 @@ void Controller::Impl::OnHandleEvent( const Event& event )
       position.x = scrollRightDirection ? 0.f : mVisualModel->mControlSize.width;
 
       // Get the new handle position.
-      // The selection handle's position is in decorator coords. Need to transforms to text coords.
+      // The selection handle's position is in decorator's coords. Need to transform to text's coords.
       const CharacterIndex handlePosition = Text::GetClosestCursorIndex( mVisualModel,
                                                                          mLogicalModel,
                                                                          mMetrics,
-                                                                         position.x - mEventData->mScrollPosition.x - mAlignmentOffset.x,
-                                                                         position.y - mEventData->mScrollPosition.y - mAlignmentOffset.y );
+                                                                         position.x - mScrollPosition.x,
+                                                                         position.y - mScrollPosition.y );
 
       if( leftSelectionHandleEvent )
       {
@@ -1312,9 +1312,9 @@ void Controller::Impl::OnSelectEvent( const Event& event )
 
   if( mEventData->mSelectionEnabled )
   {
-    // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords.
-    const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
-    const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
+    // Convert from control's coords to text's coords.
+    const float xPosition = event.p2.mFloat - mScrollPosition.x;
+    const float yPosition = event.p3.mFloat - mScrollPosition.y;
 
     // Calculates the logical position from the x,y coords.
     RepositionSelectionHandles( xPosition,
@@ -1497,8 +1497,6 @@ void Controller::Impl::RepositionSelectionHandles()
   const Length numberOfCharactersEnd = *( charactersPerGlyphBuffer + glyphEnd );
   bool splitEndGlyph = ( glyphStart != glyphEnd ) && ( numberOfCharactersEnd > 1u ) && HasLigatureMustBreak( mLogicalModel->GetScript( selectionEndMinusOne ) );
 
-  const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset;
-
   // Traverse the glyphs.
   for( GlyphIndex index = glyphStart; index <= glyphEnd; ++index )
   {
@@ -1522,12 +1520,12 @@ void Controller::Impl::RepositionSelectionHandles()
       // Calculate the number of characters selected.
       const Length numberOfCharacters = ( glyphStart == glyphEnd ) ? ( selectionEnd - selectionStart ) : ( numberOfCharactersStart - interGlyphIndex );
 
-      const float xPosition = position.x - glyph.xBearing + offset.x + glyphAdvance * static_cast<float>( isCurrentRightToLeft ? ( numberOfCharactersStart - interGlyphIndex - numberOfCharacters ) : interGlyphIndex );
+      const float xPosition = firstLine.alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x + glyphAdvance * static_cast<float>( isCurrentRightToLeft ? ( numberOfCharactersStart - interGlyphIndex - numberOfCharacters ) : interGlyphIndex );
 
       mEventData->mDecorator->AddHighlight( xPosition,
-                                            offset.y,
+                                            mScrollPosition.y,
                                             xPosition + static_cast<float>( numberOfCharacters ) * glyphAdvance,
-                                            offset.y + height );
+                                            mScrollPosition.y + height );
 
       splitStartGlyph = false;
       continue;
@@ -1548,21 +1546,21 @@ void Controller::Impl::RepositionSelectionHandles()
 
       const Length numberOfCharacters = numberOfCharactersEnd - interGlyphIndex;
 
-      const float xPosition = position.x - glyph.xBearing + offset.x + ( isCurrentRightToLeft ? ( glyphAdvance * static_cast<float>( numberOfCharacters ) ) : 0.f );
+      const float xPosition = firstLine.alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x + ( isCurrentRightToLeft ? ( glyphAdvance * static_cast<float>( numberOfCharacters ) ) : 0.f );
       mEventData->mDecorator->AddHighlight( xPosition,
-                                            offset.y,
+                                            mScrollPosition.y,
                                             xPosition + static_cast<float>( interGlyphIndex ) * glyphAdvance,
-                                            offset.y + height );
+                                            mScrollPosition.y + height );
 
       splitEndGlyph = false;
       continue;
     }
 
-    const float xPosition = position.x - glyph.xBearing + offset.x;
+    const float xPosition = firstLine.alignmentOffset + position.x - glyph.xBearing + mScrollPosition.x;
     mEventData->mDecorator->AddHighlight( xPosition,
-                                          offset.y,
+                                          mScrollPosition.y,
                                           xPosition + glyph.advance,
-                                          offset.y + height );
+                                          mScrollPosition.y + height );
   }
 
   CursorInfo primaryCursorInfo;
@@ -1573,17 +1571,17 @@ void Controller::Impl::RepositionSelectionHandles()
   GetCursorPosition( mEventData->mRightSelectionPosition,
                      secondaryCursorInfo );
 
-  const Vector2 primaryPosition = primaryCursorInfo.primaryPosition + offset;
-  const Vector2 secondaryPosition = secondaryCursorInfo.primaryPosition + offset;
+  const Vector2 primaryPosition = primaryCursorInfo.primaryPosition + mScrollPosition;
+  const Vector2 secondaryPosition = secondaryCursorInfo.primaryPosition + mScrollPosition;
 
   mEventData->mDecorator->SetPosition( LEFT_SELECTION_HANDLE,
                                        primaryPosition.x,
-                                       primaryCursorInfo.lineOffset + offset.y,
+                                       primaryCursorInfo.lineOffset + mScrollPosition.y,
                                        primaryCursorInfo.lineHeight );
 
   mEventData->mDecorator->SetPosition( RIGHT_SELECTION_HANDLE,
                                        secondaryPosition.x,
-                                       secondaryCursorInfo.lineOffset + offset.y,
+                                       secondaryCursorInfo.lineOffset + mScrollPosition.y,
                                        secondaryCursorInfo.lineHeight );
 
   // Cursor to be positioned at end of selection so if selection interrupted and edit mode restarted the cursor will be at end of selection
@@ -1893,25 +1891,6 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
       }
     }
 
-    switch( mLayoutEngine.GetVerticalAlignment() )
-    {
-      case LayoutEngine::VERTICAL_ALIGN_TOP:
-      {
-        cursorInfo.primaryPosition.y = 0.f;
-        break;
-      }
-      case LayoutEngine::VERTICAL_ALIGN_CENTER:
-      {
-        cursorInfo.primaryPosition.y = floorf( 0.5f * ( mVisualModel->mControlSize.height - cursorInfo.lineHeight ) );
-        break;
-      }
-      case LayoutEngine::VERTICAL_ALIGN_BOTTOM:
-      {
-        cursorInfo.primaryPosition.y = mVisualModel->mControlSize.height - cursorInfo.lineHeight;
-        break;
-      }
-    }
-
     // Nothing else to do.
     return;
   }
@@ -1998,8 +1977,7 @@ void Controller::Impl::UpdateCursorPosition( const CursorInfo& cursorInfo )
     return;
   }
 
-  const Vector2 offset = mEventData->mScrollPosition + ( IsShowingRealText() ? mAlignmentOffset : Vector2::ZERO );
-  const Vector2 cursorPosition = cursorInfo.primaryPosition + offset;
+  const Vector2 cursorPosition = cursorInfo.primaryPosition + mScrollPosition;
 
   // Sets the cursor position.
   mEventData->mDecorator->SetPosition( PRIMARY_CURSOR,
@@ -2012,17 +1990,17 @@ void Controller::Impl::UpdateCursorPosition( const CursorInfo& cursorInfo )
   // Sets the grab handle position.
   mEventData->mDecorator->SetPosition( GRAB_HANDLE,
                                        cursorPosition.x,
-                                       cursorInfo.lineOffset + offset.y,
+                                       cursorInfo.lineOffset + mScrollPosition.y,
                                        cursorInfo.lineHeight );
 
   if( cursorInfo.isSecondaryCursor )
   {
     mEventData->mDecorator->SetPosition( SECONDARY_CURSOR,
-                                         cursorInfo.secondaryPosition.x + offset.x,
-                                         cursorInfo.secondaryPosition.y + offset.y,
+                                         cursorInfo.secondaryPosition.x + mScrollPosition.x,
+                                         cursorInfo.secondaryPosition.y + mScrollPosition.y,
                                          cursorInfo.secondaryCursorHeight,
                                          cursorInfo.lineHeight );
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + offset.x, cursorInfo.secondaryPosition.y + offset.y );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + mScrollPosition.x, cursorInfo.secondaryPosition.y + mScrollPosition.y );
   }
 
   // Set which cursors are active according the state.
@@ -2054,13 +2032,12 @@ void Controller::Impl::UpdateSelectionHandle( HandleType handleType,
     return;
   }
 
-  const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset;
-  const Vector2 cursorPosition = cursorInfo.primaryPosition + offset;
+  const Vector2 cursorPosition = cursorInfo.primaryPosition + mScrollPosition;
 
   // Sets the handle's position.
   mEventData->mDecorator->SetPosition( handleType,
                                        cursorPosition.x,
-                                       cursorInfo.lineOffset + offset.y,
+                                       cursorInfo.lineOffset + mScrollPosition.y,
                                        cursorInfo.lineHeight );
 
   // If selection handle at start of the text and other at end of the text then all text is selected.
@@ -2071,36 +2048,36 @@ void Controller::Impl::UpdateSelectionHandle( HandleType handleType,
 
 void Controller::Impl::ClampHorizontalScroll( const Vector2& actualSize )
 {
-  // Clamp between -space & 0 (and the text alignment).
+  // Clamp between -space & 0.
 
   if( actualSize.width > mVisualModel->mControlSize.width )
   {
-    const float space = ( actualSize.width - mVisualModel->mControlSize.width ) + mAlignmentOffset.x;
-    mEventData->mScrollPosition.x = ( mEventData->mScrollPosition.x < -space ) ? -space : mEventData->mScrollPosition.x;
-    mEventData->mScrollPosition.x = ( mEventData->mScrollPosition.x > -mAlignmentOffset.x ) ? -mAlignmentOffset.x : mEventData->mScrollPosition.x;
+    const float space = ( actualSize.width - mVisualModel->mControlSize.width );
+    mScrollPosition.x = ( mScrollPosition.x < -space ) ? -space : mScrollPosition.x;
+    mScrollPosition.x = ( mScrollPosition.x > 0.f ) ? 0.f : mScrollPosition.x;
 
     mEventData->mDecoratorUpdated = true;
   }
   else
   {
-    mEventData->mScrollPosition.x = 0.f;
+    mScrollPosition.x = 0.f;
   }
 }
 
 void Controller::Impl::ClampVerticalScroll( const Vector2& actualSize )
 {
-  // Clamp between -space & 0 (and the text alignment).
+  // Clamp between -space & 0.
   if( actualSize.height > mVisualModel->mControlSize.height )
   {
-    const float space = ( actualSize.height - mVisualModel->mControlSize.height ) + mAlignmentOffset.y;
-    mEventData->mScrollPosition.y = ( mEventData->mScrollPosition.y < -space ) ? -space : mEventData->mScrollPosition.y;
-    mEventData->mScrollPosition.y = ( mEventData->mScrollPosition.y > -mAlignmentOffset.y ) ? -mAlignmentOffset.y : mEventData->mScrollPosition.y;
+    const float space = ( actualSize.height - mVisualModel->mControlSize.height );
+    mScrollPosition.y = ( mScrollPosition.y < -space ) ? -space : mScrollPosition.y;
+    mScrollPosition.y = ( mScrollPosition.y > 0.f ) ? 0.f : mScrollPosition.y;
 
     mEventData->mDecoratorUpdated = true;
   }
   else
   {
-    mEventData->mScrollPosition.y = 0.f;
+    mScrollPosition.y = 0.f;
   }
 }
 
@@ -2112,18 +2089,16 @@ void Controller::Impl::ScrollToMakePositionVisible( const Vector2& position )
   const float positionEnd = position.x + cursorWidth;
 
   // Transform the position to decorator coords.
-  const float alignment = IsShowingRealText() ? mAlignmentOffset.x : 0.f;
-  const float offset = mEventData->mScrollPosition.x + alignment;
-  const float decoratorPositionBegin = position.x + offset;
-  const float decoratorPositionEnd = positionEnd + offset;
+  const float decoratorPositionBegin = position.x + mScrollPosition.x;
+  const float decoratorPositionEnd = positionEnd + mScrollPosition.x;
 
   if( decoratorPositionBegin < 0.f )
   {
-    mEventData->mScrollPosition.x = -position.x - alignment;
+    mScrollPosition.x = -position.x;
   }
   else if( decoratorPositionEnd > mVisualModel->mControlSize.width )
   {
-    mEventData->mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd - alignment;
+    mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd;
   }
 }
 
@@ -2133,7 +2108,7 @@ void Controller::Impl::ScrollTextToMatchCursor( const CursorInfo& cursorInfo )
   const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
 
   // Calculate the offset to match the cursor position before the character was deleted.
-  mEventData->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x - mAlignmentOffset.x;
+  mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x;
 
   ClampHorizontalScroll( mVisualModel->GetLayoutSize() );
 
index 2031ab5..cefc5aa 100644 (file)
@@ -117,12 +117,6 @@ struct EventData
 
   InputStyle         mInputStyle;              ///< The style to be set to the new inputed text.
 
-  /**
-   * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control.
-   * Typically this will have a negative value with scrolling occurs.
-   */
-  Vector2            mScrollPosition;          ///< The text is offset by this position when scrolling.
-
   State              mState;                   ///< Selection mode, edit mode etc.
 
   CharacterIndex     mPrimaryCursorPosition;   ///< Index into logical model for primary cursor.
@@ -259,6 +253,30 @@ struct TextUpdateInfo
   }
 };
 
+struct UnderlineDefaults
+{
+  std::string properties;
+  // TODO: complete with underline parameters.
+};
+
+struct ShadowDefaults
+{
+  std::string properties;
+  // TODO: complete with shadow parameters.
+};
+
+struct EmbossDefaults
+{
+  std::string properties;
+  // TODO: complete with emboss parameters.
+};
+
+struct OutlineDefaults
+{
+  std::string properties;
+  // TODO: complete with outline parameters.
+};
+
 struct Controller::Impl
 {
   Impl( ControlInterface& controlInterface )
@@ -266,6 +284,10 @@ struct Controller::Impl
     mLogicalModel(),
     mVisualModel(),
     mFontDefaults( NULL ),
+    mUnderlineDefaults( NULL ),
+    mShadowDefaults( NULL ),
+    mEmbossDefaults( NULL ),
+    mOutlineDefaults( NULL ),
     mEventData( NULL ),
     mFontClient(),
     mClipboard(),
@@ -274,7 +296,6 @@ struct Controller::Impl
     mLayoutEngine(),
     mModifyEvents(),
     mTextColor( Color::BLACK ),
-    mAlignmentOffset(),
     mTextUpdateInfo(),
     mOperationsPending( NO_OPERATION ),
     mMaximumNumberOfCharacters( 50u ),
@@ -304,6 +325,10 @@ struct Controller::Impl
   ~Impl()
   {
     delete mFontDefaults;
+    delete mUnderlineDefaults;
+    delete mShadowDefaults;
+    delete mEmbossDefaults;
+    delete mOutlineDefaults;
     delete mEventData;
   }
 
@@ -616,6 +641,10 @@ public:
   LogicalModelPtr mLogicalModel;           ///< Pointer to the logical model.
   VisualModelPtr  mVisualModel;            ///< Pointer to the visual model.
   FontDefaults* mFontDefaults;             ///< Avoid allocating this when the user does not specify a font.
+  UnderlineDefaults* mUnderlineDefaults;   ///< Avoid allocating this when the user does not specify underline parameters.
+  ShadowDefaults* mShadowDefaults;         ///< Avoid allocating this when the user does not specify shadow parameters.
+  EmbossDefaults* mEmbossDefaults;         ///< Avoid allocating this when the user does not specify emboss parameters.
+  OutlineDefaults* mOutlineDefaults;       ///< Avoid allocating this when the user does not specify outline parameters.
   EventData* mEventData;                   ///< Avoid allocating everything for text input until EnableTextInput().
   TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
   Clipboard mClipboard;                    ///< Handle to the system clipboard
@@ -624,7 +653,11 @@ public:
   LayoutEngine mLayoutEngine;              ///< The layout engine.
   Vector<ModifyEvent> mModifyEvents;       ///< Temporary stores the text set until the next relayout.
   Vector4 mTextColor;                      ///< The regular text color
-  Vector2 mAlignmentOffset;                ///< Vertical and horizontal offset of the whole text inside the control due to alignment.
+  /**
+   * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control.
+   * Typically this will have a negative value with scrolling occurs.
+   */
+  Vector2 mScrollPosition;                 ///< The text is offset by this position when scrolling.
   TextUpdateInfo mTextUpdateInfo;          ///< Info of the characters updated.
   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
   Length mMaximumNumberOfCharacters;       ///< Maximum number of characters that can be inserted.
index 09a4441..2891953 100644 (file)
@@ -181,6 +181,19 @@ CharacterDirection Controller::GetAutoScrollDirection() const
   return mImpl->mAutoScrollDirectionRTL;
 }
 
+float Controller::GetAutoScrollLineAlignment() const
+{
+  float offset = 0.f;
+
+  if( mImpl->mVisualModel &&
+      ( 0u != mImpl->mVisualModel->mLines.Count() ) )
+  {
+    offset = ( *mImpl->mVisualModel->mLines.Begin() ).alignmentOffset;
+  }
+
+  return offset;
+}
+
 void Controller::SetText( const std::string& text )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText\n" );
@@ -672,6 +685,26 @@ const Vector4& Controller::GetShadowColor() const
   return mImpl->mVisualModel->GetShadowColor();
 }
 
+void Controller::SetDefaultShadowProperties( const std::string& shadowProperties )
+{
+  if( NULL == mImpl->mShadowDefaults )
+  {
+    mImpl->mShadowDefaults = new ShadowDefaults();
+  }
+
+  mImpl->mShadowDefaults->properties = shadowProperties;
+}
+
+const std::string& Controller::GetDefaultShadowProperties() const
+{
+  if( NULL != mImpl->mShadowDefaults )
+  {
+    return mImpl->mShadowDefaults->properties;
+  }
+
+  return EMPTY_STRING;
+}
+
 void Controller::SetUnderlineColor( const Vector4& color )
 {
   mImpl->mVisualModel->SetUnderlineColor( color );
@@ -708,6 +741,77 @@ float Controller::GetUnderlineHeight() const
   return mImpl->mVisualModel->GetUnderlineHeight();
 }
 
+void Controller::SetDefaultUnderlineProperties( const std::string& underlineProperties )
+{
+  if( NULL == mImpl->mUnderlineDefaults )
+  {
+    mImpl->mUnderlineDefaults = new UnderlineDefaults();
+  }
+
+  mImpl->mUnderlineDefaults->properties = underlineProperties;
+}
+
+const std::string& Controller::GetDefaultUnderlineProperties() const
+{
+  if( NULL != mImpl->mUnderlineDefaults )
+  {
+    return mImpl->mUnderlineDefaults->properties;
+  }
+
+  return EMPTY_STRING;
+}
+
+void Controller::SetDefaultEmbossProperties( const std::string& embossProperties )
+{
+  if( NULL == mImpl->mEmbossDefaults )
+  {
+    mImpl->mEmbossDefaults = new EmbossDefaults();
+  }
+
+  mImpl->mEmbossDefaults->properties = embossProperties;
+}
+
+const std::string& Controller::GetDefaultEmbossProperties() const
+{
+  if( NULL != mImpl->mEmbossDefaults )
+  {
+    return mImpl->mEmbossDefaults->properties;
+  }
+
+  return EMPTY_STRING;
+}
+
+void Controller::SetDefaultOutlineProperties( const std::string& outlineProperties )
+{
+  if( NULL == mImpl->mOutlineDefaults )
+  {
+    mImpl->mOutlineDefaults = new OutlineDefaults();
+  }
+
+  mImpl->mOutlineDefaults->properties = outlineProperties;
+}
+
+const std::string& Controller::GetDefaultOutlineProperties() const
+{
+  if( NULL != mImpl->mOutlineDefaults )
+  {
+    return mImpl->mOutlineDefaults->properties;
+  }
+
+  return EMPTY_STRING;
+}
+
+void Controller::SetDefaultLineSpacing( float lineSpacing )
+{
+  //TODO finish implementation
+  mImpl->mLayoutEngine.SetDefaultLineSpacing( lineSpacing );
+}
+
+float Controller::GetDefaultLineSpacing() const
+{
+  return mImpl->mLayoutEngine.GetDefaultLineSpacing();
+}
+
 void Controller::SetInputColor( const Vector4& color )
 {
   if( NULL != mImpl->mEventData )
@@ -1044,6 +1148,96 @@ float Controller::GetInputFontPointSize() const
   return GetDefaultPointSize();
 }
 
+void Controller::SetInputLineSpacing( float lineSpacing )
+{
+  if( NULL != mImpl->mEventData )
+  {
+    mImpl->mEventData->mInputStyle.lineSpacing = lineSpacing;
+  }
+}
+
+float Controller::GetInputLineSpacing() const
+{
+  if( NULL != mImpl->mEventData )
+  {
+    return mImpl->mEventData->mInputStyle.lineSpacing;
+  }
+
+  return 0.f;
+}
+
+void Controller::SetInputShadowProperties( const std::string& shadowProperties )
+{
+  if( NULL != mImpl->mEventData )
+  {
+    mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
+  }
+}
+
+const std::string& Controller::GetInputShadowProperties() const
+{
+  if( NULL != mImpl->mEventData )
+  {
+    return mImpl->mEventData->mInputStyle.shadowProperties;
+  }
+
+  return GetDefaultShadowProperties();
+}
+
+void Controller::SetInputUnderlineProperties( const std::string& underlineProperties )
+{
+  if( NULL != mImpl->mEventData )
+  {
+    mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
+  }
+}
+
+const std::string& Controller::GetInputUnderlineProperties() const
+{
+  if( NULL != mImpl->mEventData )
+  {
+    return mImpl->mEventData->mInputStyle.underlineProperties;
+  }
+
+  return GetDefaultUnderlineProperties();
+}
+
+void Controller::SetInputEmbossProperties( const std::string& embossProperties )
+{
+  if( NULL != mImpl->mEventData )
+  {
+    mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
+  }
+}
+
+const std::string& Controller::GetInputEmbossProperties() const
+{
+  if( NULL != mImpl->mEventData )
+  {
+    return mImpl->mEventData->mInputStyle.embossProperties;
+  }
+
+  return GetDefaultEmbossProperties();
+}
+
+void Controller::SetInputOutlineProperties( const std::string& outlineProperties )
+{
+  if( NULL != mImpl->mEventData )
+  {
+    mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
+  }
+}
+
+const std::string& Controller::GetInputOutlineProperties() const
+{
+  if( NULL != mImpl->mEventData )
+  {
+    return mImpl->mEventData->mInputStyle.outlineProperties;
+  }
+
+  return GetDefaultOutlineProperties();
+}
+
 void Controller::SetEnableCursorBlink( bool enable )
 {
   DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "TextInput disabled" );
@@ -1072,17 +1266,7 @@ bool Controller::GetEnableCursorBlink() const
 
 const Vector2& Controller::GetScrollPosition() const
 {
-  if( NULL != mImpl->mEventData )
-  {
-    return mImpl->mEventData->mScrollPosition;
-  }
-
-  return Vector2::ZERO;
-}
-
-const Vector2& Controller::GetAlignmentOffset() const
-{
-  return mImpl->mAlignmentOffset;
+  return mImpl->mScrollPosition;
 }
 
 Vector3 Controller::GetNaturalSize()
@@ -1286,15 +1470,18 @@ bool Controller::Relayout( const Size& size )
   // Whether the text control is editable
   const bool isEditable = NULL != mImpl->mEventData;
 
-  // Keep the current offset and alignment as it will be used to update the decorator's positions (if the size changes).
+  // Keep the current offset as it will be used to update the decorator's positions (if the size changes).
   Vector2 offset;
   if( newSize && isEditable )
   {
-    offset = mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition;
+    offset = mImpl->mScrollPosition;
   }
 
-  // After doing the text layout, the alignment offset to place the actor in the desired position can be calculated.
-  CalculateTextAlignment( size );
+  if( !isEditable || !IsMultiLineEnabled() )
+  {
+    // After doing the text layout, the vertical offset to place the actor in the desired position can be calculated.
+    CalculateVerticalOffset( size );
+  }
 
   if( isEditable )
   {
@@ -1304,7 +1491,7 @@ bool Controller::Relayout( const Size& size )
       mImpl->ClampHorizontalScroll( layoutSize );
 
       // Update the decorator's positions is needed if there is a new size.
-      mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition - offset );
+      mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mScrollPosition - offset );
     }
 
     // Move the cursor, grab handle etc.
@@ -1408,7 +1595,7 @@ void Controller::ResetScrollPosition()
   if( NULL != mImpl->mEventData )
   {
     // Reset the scroll position.
-    mImpl->mEventData->mScrollPosition = Vector2::ZERO;
+    mImpl->mScrollPosition = Vector2::ZERO;
     mImpl->mEventData->mScrollAfterUpdatePosition = true;
   }
 }
@@ -1687,7 +1874,7 @@ LayoutEngine::VerticalAlignment Controller::GetVerticalAlignment() const
   return mImpl->mLayoutEngine.GetVerticalAlignment();
 }
 
-void Controller::CalculateTextAlignment( const Size& controlSize )
+void Controller::CalculateVerticalOffset( const Size& controlSize )
 {
   Size layoutSize = mImpl->mVisualModel->GetLayoutSize();
 
@@ -1697,71 +1884,21 @@ void Controller::CalculateTextAlignment( const Size& controlSize )
     layoutSize.height = mImpl->GetDefaultFontLineHeight();
   }
 
-  if( LayoutEngine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout() )
-  {
-    // Get the direction of the first character.
-    const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u );
-
-    // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END;
-    LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment();
-    if( firstParagraphDirection )
-    {
-      switch( horizontalAlignment )
-      {
-        case LayoutEngine::HORIZONTAL_ALIGN_BEGIN:
-        {
-          horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END;
-          break;
-        }
-        case LayoutEngine::HORIZONTAL_ALIGN_CENTER:
-        {
-          // Nothing to do.
-          break;
-        }
-        case LayoutEngine::HORIZONTAL_ALIGN_END:
-        {
-          horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN;
-          break;
-        }
-      }
-    }
-
-    switch( horizontalAlignment )
-    {
-      case LayoutEngine::HORIZONTAL_ALIGN_BEGIN:
-      {
-        mImpl->mAlignmentOffset.x = 0.f;
-        break;
-      }
-      case LayoutEngine::HORIZONTAL_ALIGN_CENTER:
-      {
-        mImpl->mAlignmentOffset.x = floorf( 0.5f * ( controlSize.width - layoutSize.width ) ); // try to avoid pixel alignment.
-        break;
-      }
-      case LayoutEngine::HORIZONTAL_ALIGN_END:
-      {
-        mImpl->mAlignmentOffset.x = controlSize.width - layoutSize.width;
-        break;
-      }
-    }
-  }
-
-  const LayoutEngine::VerticalAlignment verticalAlignment = mImpl->mLayoutEngine.GetVerticalAlignment();
-  switch( verticalAlignment )
+  switch( mImpl->mLayoutEngine.GetVerticalAlignment() )
   {
     case LayoutEngine::VERTICAL_ALIGN_TOP:
     {
-      mImpl->mAlignmentOffset.y = 0.f;
+      mImpl->mScrollPosition.y = 0.f;
       break;
     }
     case LayoutEngine::VERTICAL_ALIGN_CENTER:
     {
-      mImpl->mAlignmentOffset.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment.
+      mImpl->mScrollPosition.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment.
       break;
     }
     case LayoutEngine::VERTICAL_ALIGN_BOTTOM:
     {
-      mImpl->mAlignmentOffset.y = controlSize.height - layoutSize.height;
+      mImpl->mScrollPosition.y = controlSize.height - layoutSize.height;
       break;
     }
   }
index 5a96349..7badd1e 100644 (file)
@@ -174,6 +174,13 @@ public:
   CharacterDirection GetAutoScrollDirection() const;
 
   /**
+   * @brief Get the alignment offset of the first line of text.
+   *
+   * @return The alignment offset.
+   */
+  float GetAutoScrollLineAlignment() const;
+
+  /**
    * @brief Replaces any text previously set.
    *
    * @note This will be converted into UTF-32 when stored in the text model.
@@ -390,6 +397,22 @@ public:
   const Vector4& GetShadowColor() const;
 
   /**
+   * @brief Sets the shadow's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] shadowProperties The shadow's properties string.
+   */
+  void SetDefaultShadowProperties( const std::string& shadowProperties );
+
+  /**
+   * @brief Retrieves the shadow's properties string.
+   *
+   * @return The shadow's properties string.
+   */
+  const std::string& GetDefaultShadowProperties() const;
+
+  /**
    * @brief Set the underline color.
    *
    * @param[in] color color of underline.
@@ -432,6 +455,68 @@ public:
   float GetUnderlineHeight() const;
 
   /**
+   * @brief Sets the underline's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] underlineProperties The underline's properties string.
+   */
+  void SetDefaultUnderlineProperties( const std::string& underlineProperties );
+
+  /**
+   * @brief Retrieves the underline's properties string.
+   *
+   * @return The underline's properties string.
+   */
+  const std::string& GetDefaultUnderlineProperties() const;
+
+  /**
+   * @brief Sets the emboss's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] embossProperties The emboss's properties string.
+   */
+  void SetDefaultEmbossProperties( const std::string& embossProperties );
+
+  /**
+   * @brief Retrieves the emboss's properties string.
+   *
+   * @return The emboss's properties string.
+   */
+  const std::string& GetDefaultEmbossProperties() const;
+
+  /**
+   * @brief Sets the outline's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] outlineProperties The outline's properties string.
+   */
+  void SetDefaultOutlineProperties( const std::string& outlineProperties );
+
+  /**
+   * @brief Retrieves the outline's properties string.
+   *
+   * @return The outline's properties string.
+   */
+  const std::string& GetDefaultOutlineProperties() const;
+
+  /**
+   * @brief Sets the default line spacing.
+   *
+   * @param[in] lineSpacing The line spacing.
+   */
+  void SetDefaultLineSpacing( float lineSpacing );
+
+  /**
+   * @brief Retrieves the default line spacing.
+   *
+   * @return The line spacing.
+   */
+  float GetDefaultLineSpacing() const;
+
+  /**
    * @brief Sets the input text's color.
    *
    * @param[in] color The input text's color.
@@ -530,6 +615,84 @@ public:
   float GetInputFontPointSize() const;
 
   /**
+   * @brief Sets the input line spacing.
+   *
+   * @param[in] lineSpacing The line spacing.
+   */
+  void SetInputLineSpacing( float lineSpacing );
+
+  /**
+   * @brief Retrieves the input line spacing.
+   *
+   * @return The line spacing.
+   */
+  float GetInputLineSpacing() const;
+
+  /**
+   * @brief Sets the input shadow's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] shadowProperties The shadow's properties string.
+   */
+  void SetInputShadowProperties( const std::string& shadowProperties );
+
+  /**
+   * @brief Retrieves the input shadow's properties string.
+   *
+   * @return The shadow's properties string.
+   */
+  const std::string& GetInputShadowProperties() const;
+
+  /**
+   * @brief Sets the input underline's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] underlineProperties The underline's properties string.
+   */
+  void SetInputUnderlineProperties( const std::string& underlineProperties );
+
+  /**
+   * @brief Retrieves the input underline's properties string.
+   *
+   * @return The underline's properties string.
+   */
+  const std::string& GetInputUnderlineProperties() const;
+
+  /**
+   * @brief Sets the input emboss's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] embossProperties The emboss's properties string.
+   */
+  void SetInputEmbossProperties( const std::string& embossProperties );
+
+  /**
+   * @brief Retrieves the input emboss's properties string.
+   *
+   * @return The emboss's properties string.
+   */
+  const std::string& GetInputEmbossProperties() const;
+
+  /**
+   * @brief Sets input the outline's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] outlineProperties The outline's properties string.
+   */
+  void SetInputOutlineProperties( const std::string& outlineProperties );
+
+  /**
+   * @brief Retrieves the input outline's properties string.
+   *
+   * @return The outline's properties string.
+   */
+  const std::string& GetInputOutlineProperties() const;
+
+  /**
    * @brief Called to enable/disable cursor blink.
    *
    * @note Only editable controls should calls this.
@@ -552,13 +715,6 @@ public:
   const Vector2& GetScrollPosition() const;
 
   /**
-   * @brief Query the alignment offset.
-   *
-   * @return The alignmnet offset.
-   */
-  const Vector2& GetAlignmentOffset() const;
-
-  /**
    * @copydoc Control::GetNaturalSize()
    */
   Vector3 GetNaturalSize();
@@ -660,11 +816,11 @@ public:
   LayoutEngine::VerticalAlignment GetVerticalAlignment() const;
 
   /**
-   * @brief Calulates the alignment of the whole text inside the bounding box.
+   * @brief Calulates the vertical offset to align the text inside the bounding box.
    *
    * @param[in] size The size of the bounding box.
    */
-  void CalculateTextAlignment( const Size& size );
+  void CalculateVerticalOffset( const Size& size );
 
   /**
    * @brief Return the layout engine.
diff --git a/dali-toolkit/internal/text/text-effects-style.cpp b/dali-toolkit/internal/text/text-effects-style.cpp
new file mode 100644 (file)
index 0000000..7172f23
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/text-effects-style.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/property-string-parser.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace
+{
+const std::string COLOR_KEY( "color" );
+const std::string OFFSET_KEY( "offset" );
+const std::string THICKNESS_KEY( "thickness" );
+}
+
+bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
+{
+  bool update = false;
+
+  if( controller )
+  {
+    const std::string properties = value.Get< std::string >();
+
+    switch( type )
+    {
+      case EffectStyle::DEFAULT:
+      {
+        // Stores the default underline's properties string to be recovered by the GetUnderlineProperties() function.
+        controller->SetDefaultUnderlineProperties( properties );
+        break;
+      }
+      case EffectStyle::INPUT:
+      {
+        // Stores the input underline's properties string to be recovered by the GetUnderlineProperties() function.
+        controller->SetInputUnderlineProperties( properties );
+        break;
+      }
+    }
+
+    // Parses and applies the style.
+    Property::Map map;
+    ParsePropertyString( properties, map );
+
+    if( !map.Empty() )
+    {
+      /// Color key
+      Property::Value* colorValue = map.Find( COLOR_KEY );
+
+      Vector4 color;
+      const bool colorDefined = colorValue != NULL;
+      if( colorDefined )
+      {
+        const std::string colorStr = colorValue->Get<std::string>();
+
+        ColorStringToVector4( colorStr.c_str(), colorStr.size(), color );
+      }
+
+      /// Thickness key
+      Property::Value* thicknessValue = map.Find( THICKNESS_KEY );
+
+      float thickness = 0.f;
+      const bool thicknessDefined = thicknessValue != NULL;
+      if( thicknessDefined )
+      {
+        const std::string thicknessStr = thicknessValue->Get<std::string>();
+
+        thickness = StringToFloat( thicknessStr.c_str() );
+      }
+
+      switch( type )
+      {
+        case EffectStyle::DEFAULT:
+        {
+          if( !controller->IsUnderlineEnabled() )
+          {
+            controller->SetUnderlineEnabled( true );
+            update = true;
+          }
+          // Sets the default underline values.
+          if( colorDefined && ( controller->GetUnderlineColor() != color ) )
+          {
+            controller->SetUnderlineColor( color );
+            update = true;
+          }
+
+          if( thicknessDefined &&  fabsf( controller->GetUnderlineHeight() - thickness ) > Math::MACHINE_EPSILON_1000 )
+          {
+            controller->SetUnderlineHeight( thickness );
+            update = true;
+          }
+        }
+        case EffectStyle::INPUT:
+        {
+          // Sets the input underline values.
+          // TODO: to be implemented.
+          break;
+        }
+      }
+    }
+    else
+    {
+      // Disable underline.
+      if( controller->IsUnderlineEnabled() )
+      {
+        controller->SetUnderlineEnabled( false );
+        update = true;
+      }
+    }
+  }
+
+  return update;
+}
+
+void GetUnderlineProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
+{
+  if( controller )
+  {
+    switch( type )
+    {
+      case EffectStyle::DEFAULT:
+      {
+        value = controller->GetDefaultUnderlineProperties();
+        break;
+      }
+      case EffectStyle::INPUT:
+      {
+        value = controller->GetInputUnderlineProperties();
+        break;
+      }
+    }
+  }
+}
+
+bool SetShadowProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
+{
+  bool update = false;
+
+  if( controller )
+  {
+    const std::string properties = value.Get< std::string >();
+
+    switch( type )
+    {
+      case EffectStyle::DEFAULT:
+      {
+        // Stores the default shadow's properties string to be recovered by the GetShadowProperties() function.
+        controller->SetDefaultShadowProperties( properties );
+        break;
+      }
+      case EffectStyle::INPUT:
+      {
+        // Stores the input shadow's properties string to be recovered by the GetShadowProperties() function.
+        controller->SetInputShadowProperties( properties );
+        break;
+      }
+    }
+
+    // Parses and applies the style.
+    Property::Map map;
+    ParsePropertyString( properties, map );
+
+    if( !map.Empty() )
+    {
+      /// Color key
+      Property::Value* colorValue = map.Find( COLOR_KEY );
+
+      Vector4 color;
+      const bool colorDefined = colorValue != NULL;
+      if( colorDefined )
+      {
+        const std::string colorStr = colorValue->Get<std::string>();
+
+        ColorStringToVector4( colorStr.c_str(), colorStr.size(), color );
+      }
+
+      /// Offset key
+      Property::Value* offsetValue = map.Find( OFFSET_KEY );
+
+      Vector2 offset;
+      const bool offsetDefined = offsetValue != NULL;
+      if( offsetDefined )
+      {
+        const std::string offsetStr = offsetValue->Get<std::string>();
+
+        StringOffsetToVector2( offsetStr, offset );
+      }
+
+      switch( type )
+      {
+        case EffectStyle::DEFAULT:
+        {
+          // Sets the default shadow values.
+          if( colorDefined && ( controller->GetShadowColor() != color ) )
+          {
+            controller->SetShadowColor( color );
+            update = true;
+          }
+
+          if( offsetDefined && ( controller->GetShadowOffset() != offset ) )
+          {
+            controller->SetShadowOffset( offset );
+            update = true;
+          }
+        }
+        case EffectStyle::INPUT:
+        {
+          // Sets the input shadow values.
+          // TODO: to be implemented.
+          break;
+        }
+      }
+    }
+  }
+
+  return update;
+}
+
+void GetShadowProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
+{
+  if( controller )
+  {
+    switch( type )
+    {
+      case EffectStyle::DEFAULT:
+      {
+        value = controller->GetDefaultShadowProperties();
+        break;
+      }
+      case EffectStyle::INPUT:
+      {
+        value = controller->GetInputShadowProperties();
+        break;
+      }
+    }
+  }
+}
+
+bool SetEmbossProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
+{
+  bool update = false;
+
+  if( controller )
+  {
+    const std::string properties = value.Get< std::string >();
+
+    switch( type )
+    {
+      case EffectStyle::DEFAULT:
+      {
+        // Stores the default emboss's properties string to be recovered by the GetEmbossProperties() function.
+        controller->SetDefaultEmbossProperties( properties );
+        break;
+      }
+      case EffectStyle::INPUT:
+      {
+        // Stores the input emboss's properties string to be recovered by the GetEmbossProperties() function.
+        controller->SetInputEmbossProperties( properties );
+        break;
+      }
+    }
+  }
+
+  return update;
+}
+
+void GetEmbossProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
+{
+  if( controller )
+  {
+    switch( type )
+    {
+      case EffectStyle::DEFAULT:
+      {
+        value = controller->GetDefaultEmbossProperties();
+        break;
+      }
+      case EffectStyle::INPUT:
+      {
+        value = controller->GetInputEmbossProperties();
+        break;
+      }
+    }
+  }
+}
+
+bool SetOutlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
+{
+  bool update = false;
+
+  if( controller )
+  {
+    const std::string properties = value.Get< std::string >();
+
+    switch( type )
+    {
+      case EffectStyle::DEFAULT:
+      {
+        // Stores the default outline's properties string to be recovered by the GetOutlineProperties() function.
+        controller->SetDefaultOutlineProperties( properties );
+        break;
+      }
+      case EffectStyle::INPUT:
+      {
+        // Stores the input outline's properties string to be recovered by the GetOutlineProperties() function.
+        controller->SetInputOutlineProperties( properties );
+        break;
+      }
+    }
+  }
+
+  return update;
+}
+
+void GetOutlineProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
+{
+  if( controller )
+  {
+    switch( type )
+    {
+      case EffectStyle::DEFAULT:
+      {
+        value = controller->GetDefaultOutlineProperties();
+        break;
+      }
+      case EffectStyle::INPUT:
+      {
+        value = controller->GetInputOutlineProperties();
+        break;
+      }
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/text-effects-style.h b/dali-toolkit/internal/text/text-effects-style.h
new file mode 100644 (file)
index 0000000..9feb75c
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_EFFECTS_STYLE_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_EFFECTS_STYLE_H__
+
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/scripting/scripting.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace EffectStyle
+{
+  enum Type
+  {
+    DEFAULT, ///< The default text effect style.
+    INPUT    ///< The input text effect style.
+  };
+};
+
+/**
+ * @brief Sets the underline properties.
+ *
+ * @param[in] controller The text's controller.
+ * @param[in] value The values of the underline's properties.
+ * @param[in] type Whether the property is for the default underline or the input underline.
+ *
+ * @return Whether the underline properties have been updated.
+ */
+bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type );
+
+/**
+ * @brief Retrieves the underline's properties.
+ *
+ * @param[in] controller The text's controller.
+ * @param[out] value The value of the underline's properties.
+ * @param[in] type Whether the property is for the default underline or the input underline.
+ */
+void GetUnderlineProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type );
+
+/**
+ * @brief Sets the shadow properties.
+ *
+ * @param[in] controller The text's controller.
+ * @param[in] value The values of the shadow's style.
+ * @param[in] type Whether the property is for the default shadow's style or the input shadow's style.
+ *
+ * @return Whether the shadow properties have been updated.
+ */
+bool SetShadowProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type );
+
+/**
+ * @brief Retrieves the shadow's properties.
+ *
+ * @param[in] controller The text's controller.
+ * @param[out] value The value of the shadow's properties.
+ * @param[in] type Whether the property is for the default shadow or the input shadow.
+ */
+void GetShadowProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type );
+
+/**
+ * @brief Sets the emboss properties.
+ *
+ * @param[in] controller The text's controller.
+ * @param[in] value The values of the emboss's properties.
+ * @param[in] type Whether the property is for the default emboss or the input emboss.
+ *
+ * @return Whether the emboss properties have been updated.
+ */
+bool SetEmbossProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type );
+
+/**
+ * @brief Retrieves the emboss's properties.
+ *
+ * @param[in] controller The text's controller.
+ * @param[out] value The value of the emboss's properties.
+ * @param[in] type Whether the property is for the default emboss or the input emboss.
+ */
+void GetEmbossProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type );
+
+/**
+ * @brief Sets the outline properties.
+ *
+ * @param[in] controller The text's controller.
+ * @param[in] value The values of the outline's properties.
+ * @param[in] type Whether the property is for the default outline or the input outline.
+ *
+ * @return Whether the outline properties have been updated.
+ */
+bool SetOutlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type );
+
+/**
+ * @brief Retrieves the outline's properties.
+ *
+ * @param[in] controller The text's controller.
+ * @param[out] value The value of the outline's properties.
+ * @param[in] type Whether the property is for the default outline or the input outline.
+ */
+void GetOutlineProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_EFFECTS_STYLE_H__
index b346d90..b31decb 100644 (file)
@@ -22,8 +22,7 @@
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/builder/json-parser.h>
-#include <dali-toolkit/devel-api/builder/tree-node.h>
+#include <dali-toolkit/internal/text/property-string-parser.h>
 
 namespace Dali
 {
@@ -40,7 +39,6 @@ const std::string STYLE_KEY( "style" );
 const std::string WEIGHT_KEY( "weight" );
 const std::string WIDTH_KEY( "width" );
 const std::string SLANT_KEY( "slant" );
-const std::string EMPTY_STRING( "" );
 
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
@@ -48,65 +46,6 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_C
 
 } // namespace
 
-/**
- * @brief Creates a map with pairs 'key,value' with the font's style parameters.
- *
- * @param[in] node Data structure with the font's style parameters.
- * @param[out] map A map with the font's style parameters.
- *
- */
-void CreateFontStyleMap( const TreeNode* const node, Property::Map& map )
-{
-  switch( node->GetType() )
-  {
-    case TreeNode::IS_NULL:
-    case TreeNode::OBJECT:
-    case TreeNode::ARRAY: // FALL THROUGH
-    {
-      break;
-    }
-    case TreeNode::STRING:
-    {
-      map.Insert( node->GetName(), Property::Value( node->GetString() ) );
-      break;
-    }
-    case TreeNode::INTEGER:
-    case TreeNode::FLOAT:
-    case TreeNode::BOOLEAN: // FALL THROUGH
-    {
-      break;
-    }
-  }
-
-  for( TreeNode::ConstIterator it = node->CBegin(), endIt = node->CEnd(); it != endIt; ++it )
-  {
-    const TreeNode::KeyNodePair& pair = *it;
-    CreateFontStyleMap( &pair.second, map );
-  }
-}
-
-/**
- * @brief Parses the font's style string.
- *
- * @param[in] style The font's style string.
- * @param[out] map A map with the font's style parameters.
- *
- */
-void ParseFontStyleString( const std::string& style, Property::Map& map )
-{
-  Toolkit::JsonParser parser = Toolkit::JsonParser::New();
-
-  if( parser.Parse( style ) )
-  {
-    const TreeNode* const node = parser.GetRoot();
-
-    if( NULL != node )
-    {
-      CreateFontStyleMap( node, map );
-    }
-  }
-}
-
 void SetFontStyleProperty( ControllerPtr controller, const Property::Value& value, FontStyle::Type type )
 {
   if( controller )
@@ -132,7 +71,7 @@ void SetFontStyleProperty( ControllerPtr controller, const Property::Value& valu
 
     // Parses and applies the style.
     Property::Map map;
-    ParseFontStyleString( style, map );
+    ParsePropertyString( style, map );
 
     if( !map.Empty() )
     {
index b87a8c9..425131d 100644 (file)
@@ -94,6 +94,7 @@ namespace FontStyle
  *
  * @param[in] controller The text's controller.
  * @param[in] value The value of the font's style.
+ * @param[in] type Whether the property is for the default font's style or the input font's style.
  *
  */
 void SetFontStyleProperty( ControllerPtr controller, const Property::Value& value, FontStyle::Type type );
@@ -103,6 +104,7 @@ void SetFontStyleProperty( ControllerPtr controller, const Property::Value& valu
  *
  * @param[in] controller The text's controller.
  * @param[out] value The value of the font's style.
+ * @param[in] type Whether the property is for the default font's style or the input font's style.
  */
 void GetFontStyleProperty( ControllerPtr controller, Property::Value& value, FontStyle::Type type );
 
index a8180fc..1201619 100644 (file)
@@ -262,10 +262,10 @@ TextScroller::~TextScroller()
   CleanUp();
 }
 
-void TextScroller::SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, const Vector2 alignmentOffset )
+void TextScroller::SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, float alignmentOffset )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] offscreenSize[%f,%f] direction[%d] alignmentOffset[%f,%f]\n",
-                 controlSize.x, controlSize.y, offScreenSize.x, offScreenSize.y, direction, alignmentOffset.x, alignmentOffset.y );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] offscreenSize[%f,%f] direction[%d] alignmentOffset[%f]\n",
+                 controlSize.x, controlSize.y, offScreenSize.x, offScreenSize.y, direction, alignmentOffset );
 
   FrameBufferImage offscreenRenderTargetForText = FrameBufferImage::New( offScreenSize.width, offScreenSize.height, Pixel::RGBA8888, Dali::Image::UNUSED );
   Renderer renderer;
@@ -277,7 +277,7 @@ void TextScroller::SetParameters( Actor sourceActor, const Size& controlSize, co
   // Reposition camera to match alignment of target, RTL text has direction=true
   if ( direction )
   {
-    mOffscreenCameraActor.SetX( alignmentOffset.x + offScreenSize.width*0.5f );
+    mOffscreenCameraActor.SetX( alignmentOffset + offScreenSize.width*0.5f );
   }
   else
   {
index d4f92b9..ef50b77 100644 (file)
@@ -65,7 +65,7 @@ public:
    * @param[in] alignmentOffset alignment of source text
    *
    */
-  void SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, const Vector2 alignmentOffset );
+  void SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, float alignmentOffset );
 
   /**
    * @brief Set the gap distance to elapse before the text wraps around
@@ -16,7 +16,7 @@
  */
 
 // CLASS HEADER
-#include <dali-toolkit/devel-api/controls/text-controls/text-editor.h>
+#include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/text-controls/text-editor-impl.h>
@@ -65,36 +65,46 @@ public:
   {
     enum
     {
-      RENDERING_BACKEND = PROPERTY_START_INDEX, ///< name "renderingBackend",                    The type or rendering e.g. bitmap-based,                                         type INT
-      TEXT,                                     ///< name "text",                                The text to display in UTF-8 format,                                             type STRING
-      TEXT_COLOR,                               ///< name "textColor",                           The text color,                                                                  type VECTOR4
-      FONT_FAMILY,                              ///< name "fontFamily",                          The requested font family,                                                       type STRING
-      FONT_STYLE,                               ///< name "fontStyle",                           The requested font style,                                                        type STRING
-      POINT_SIZE,                               ///< name "pointSize",                           The size of font in points,                                                      type FLOAT
-      HORIZONTAL_ALIGNMENT,                     ///< name "horizontalAlignment",                 The text horizontal alignment,                                                   type STRING,  values "BEGIN", "CENTER", "END"
-      SCROLL_THRESHOLD,                         ///< name "scrollThreshold"                      Vertical scrolling will occur if the cursor is this close to the control border, type FLOAT
-      SCROLL_SPEED,                             ///< name "scrollSpeed"                          The scroll speed in pixels per second,                                           type FLOAT
-      PRIMARY_CURSOR_COLOR,                     ///< name "primaryCursorColor",                  The color to apply to the primary cursor,                                        type VECTOR4
-      SECONDARY_CURSOR_COLOR,                   ///< name "secondaryCursorColor",                The color to apply to the secondary cursor,                                      type VECTOR4
-      ENABLE_CURSOR_BLINK,                      ///< name "enableCursorBlink",                   Whether the cursor should blink or not,                                          type BOOLEAN
-      CURSOR_BLINK_INTERVAL,                    ///< name "cursorBlinkInterval",                 The time interval in seconds between cursor on/off states,                       type FLOAT
-      CURSOR_BLINK_DURATION,                    ///< name "cursorBlinkDuration",                 The cursor will stop blinking after this number of seconds (if non-zero),        type FLOAT
-      CURSOR_WIDTH,                             ///< name "cursorWidth",                         The cursor width,                                                                type INTEGER
-      GRAB_HANDLE_IMAGE,                        ///< name "grabHandleImage",                     The image to display for the grab handle,                                        type STRING
-      GRAB_HANDLE_PRESSED_IMAGE,                ///< name "grabHandlePressedImage",              The image to display when the grab handle is pressed,                            type STRING
-      SELECTION_HANDLE_IMAGE_LEFT,              ///< name "selectionHandleImageLeft",            The image to display for the left selection handle,                              type MAP
-      SELECTION_HANDLE_IMAGE_RIGHT,             ///< name "selectionHandleImageRight",           The image to display for the right selection handle,                             type MAP
-      SELECTION_HANDLE_PRESSED_IMAGE_LEFT,      ///< name "selectionHandlePressedImageLeft",     The image to display when the left selection handle is pressed,                  type MAP
-      SELECTION_HANDLE_PRESSED_IMAGE_RIGHT,     ///< name "selectionHandlePressedImageRight",    The image to display when the right selection handle is pressed,                 type MAP
-      SELECTION_HANDLE_MARKER_IMAGE_LEFT,       ///< name "selectionHandleMarkerImageLeft",      The image to display for the left selection handle marker,                       type MAP
-      SELECTION_HANDLE_MARKER_IMAGE_RIGHT,      ///< name "selectionHandleMarkerImageRight",     The image to display for the right selection handle marker,                      type MAP
-      SELECTION_HIGHLIGHT_COLOR,                ///< name "selectionHighlightColor",             The color of the selection highlight,                                            type VECTOR4
-      DECORATION_BOUNDING_BOX,                  ///< name "decorationBoundingBox",               The decorations (handles etc) will positioned within this area on-screen,        type RECTANGLE
-      ENABLE_MARKUP,                            ///< name "enableMarkup",                        Whether the mark-up processing is enabled.                                       type BOOLEAN
-      INPUT_COLOR,                              ///< name "inputColor",                          The color of the new input text,                                                 type VECTOR4
-      INPUT_FONT_FAMILY,                        ///< name "inputFontFamily",                     The font's family of the new input text,                                         type STRING
-      INPUT_FONT_STYLE,                         ///< name "inputFontStyle",                      The font's style of the new input text,                                          type STRING
-      INPUT_POINT_SIZE                          ///< name "inputPointSize",                      The font's size of the new input text in points,                                 type FLOAT
+      RENDERING_BACKEND = PROPERTY_START_INDEX, ///< name "renderingBackend",                    The type or rendering e.g. bitmap-based,                                         type INT @SINCE_1_1.37
+      TEXT,                                     ///< name "text",                                The text to display in UTF-8 format,                                             type STRING @SINCE_1_1.37
+      TEXT_COLOR,                               ///< name "textColor",                           The text color,                                                                  type VECTOR4 @SINCE_1_1.37
+      FONT_FAMILY,                              ///< name "fontFamily",                          The requested font family,                                                       type STRING @SINCE_1_1.37
+      FONT_STYLE,                               ///< name "fontStyle",                           The requested font style,                                                        type STRING @SINCE_1_1.37
+      POINT_SIZE,                               ///< name "pointSize",                           The size of font in points,                                                      type FLOAT @SINCE_1_1.37
+      HORIZONTAL_ALIGNMENT,                     ///< name "horizontalAlignment",                 The text horizontal alignment,                                                   type STRING,  values "BEGIN", "CENTER", "END" @SINCE_1_1.37
+      SCROLL_THRESHOLD,                         ///< name "scrollThreshold"                      Vertical scrolling will occur if the cursor is this close to the control border, type FLOAT @SINCE_1_1.37
+      SCROLL_SPEED,                             ///< name "scrollSpeed"                          The scroll speed in pixels per second,                                           type FLOAT @SINCE_1_1.37
+      PRIMARY_CURSOR_COLOR,                     ///< name "primaryCursorColor",                  The color to apply to the primary cursor,                                        type VECTOR4 @SINCE_1_1.37
+      SECONDARY_CURSOR_COLOR,                   ///< name "secondaryCursorColor",                The color to apply to the secondary cursor,                                      type VECTOR4 @SINCE_1_1.37
+      ENABLE_CURSOR_BLINK,                      ///< name "enableCursorBlink",                   Whether the cursor should blink or not,                                          type BOOLEAN @SINCE_1_1.37
+      CURSOR_BLINK_INTERVAL,                    ///< name "cursorBlinkInterval",                 The time interval in seconds between cursor on/off states,                       type FLOAT @SINCE_1_1.37
+      CURSOR_BLINK_DURATION,                    ///< name "cursorBlinkDuration",                 The cursor will stop blinking after this number of seconds (if non-zero),        type FLOAT @SINCE_1_1.37
+      CURSOR_WIDTH,                             ///< name "cursorWidth",                         The cursor width,                                                                type INTEGER @SINCE_1_1.37
+      GRAB_HANDLE_IMAGE,                        ///< name "grabHandleImage",                     The image to display for the grab handle,                                        type STRING @SINCE_1_1.37
+      GRAB_HANDLE_PRESSED_IMAGE,                ///< name "grabHandlePressedImage",              The image to display when the grab handle is pressed,                            type STRING @SINCE_1_1.37
+      SELECTION_HANDLE_IMAGE_LEFT,              ///< name "selectionHandleImageLeft",            The image to display for the left selection handle,                              type MAP @SINCE_1_1.37
+      SELECTION_HANDLE_IMAGE_RIGHT,             ///< name "selectionHandleImageRight",           The image to display for the right selection handle,                             type MAP @SINCE_1_1.37
+      SELECTION_HANDLE_PRESSED_IMAGE_LEFT,      ///< name "selectionHandlePressedImageLeft",     The image to display when the left selection handle is pressed,                  type MAP @SINCE_1_1.37
+      SELECTION_HANDLE_PRESSED_IMAGE_RIGHT,     ///< name "selectionHandlePressedImageRight",    The image to display when the right selection handle is pressed,                 type MAP @SINCE_1_1.37
+      SELECTION_HANDLE_MARKER_IMAGE_LEFT,       ///< name "selectionHandleMarkerImageLeft",      The image to display for the left selection handle marker,                       type MAP @SINCE_1_1.37
+      SELECTION_HANDLE_MARKER_IMAGE_RIGHT,      ///< name "selectionHandleMarkerImageRight",     The image to display for the right selection handle marker,                      type MAP @SINCE_1_1.37
+      SELECTION_HIGHLIGHT_COLOR,                ///< name "selectionHighlightColor",             The color of the selection highlight,                                            type VECTOR4 @SINCE_1_1.37
+      DECORATION_BOUNDING_BOX,                  ///< name "decorationBoundingBox",               The decorations (handles etc) will positioned within this area on-screen,        type RECTANGLE @SINCE_1_1.37
+      ENABLE_MARKUP,                            ///< name "enableMarkup",                        Whether the mark-up processing is enabled.                                       type BOOLEAN @SINCE_1_1.37
+      INPUT_COLOR,                              ///< name "inputColor",                          The color of the new input text,                                                 type VECTOR4 @SINCE_1_1.37
+      INPUT_FONT_FAMILY,                        ///< name "inputFontFamily",                     The font's family of the new input text,                                         type STRING @SINCE_1_1.37
+      INPUT_FONT_STYLE,                         ///< name "inputFontStyle",                      The font's style of the new input text,                                          type STRING @SINCE_1_1.37
+      INPUT_POINT_SIZE,                         ///< name "inputPointSize",                      The font's size of the new input text in points,                                 type FLOAT @SINCE_1_1.37
+      LINE_SPACING,                             ///< name "lineSpacing",                         The default extra space between lines in points,                                 type FLOAT @SINCE_1_1.37
+      INPUT_LINE_SPACING,                       ///< name "inputLineSpacing"                     The extra space between lines in points. It affects the whole paragraph where the new input text is inserted, type FLOAT @SINCE_1_1.37
+      UNDERLINE,                                ///< name "underline"                            The default underline parameters,                                                type STRING @SINCE_1_1.37
+      INPUT_UNDERLINE,                          ///< name "inputUnderline"                       The underline parameters of the new input text,                                  type STRING @SINCE_1_1.37
+      SHADOW,                                   ///< name "shadow"                               The default shadow parameters,                                                   type STRING @SINCE_1_1.37
+      INPUT_SHADOW,                             ///< name "inputShadow"                          The shadow parameters of the new input text,                                     type STRING @SINCE_1_1.37
+      EMBOSS,                                   ///< name "emboss"                               The default emboss parameters,                                                   type STRING @SINCE_1_1.37
+      INPUT_EMBOSS,                             ///< name "inputEmboss"                          The emboss parameters of the new input text,                                     type STRING @SINCE_1_1.37
+      OUTLINE,                                  ///< name "outline"                              The default outline parameters,                                                  type STRING @SINCE_1_1.37
+      INPUT_OUTLINE,                            ///< name "inputOutline"                         The outline parameters of the new input text,                                    type STRING @SINCE_1_1.37
     };
   };
 
index e5115fe..fc29af4 100644 (file)
@@ -82,8 +82,8 @@ public:
       VERTICAL_ALIGNMENT,                       ///< name "verticalAlignment",                   The line vertical alignment,                                                       type STRING,  values "TOP",   "CENTER", "BOTTOM" @SINCE_1_0.0
       TEXT_COLOR,                               ///< name "textColor",                           The text color,                                                                    type VECTOR4 @SINCE_1_0.0
       PLACEHOLDER_TEXT_COLOR,                   ///< name "placeholderTextColor",                The placeholder-text color,                                                        type VECTOR4 @SINCE_1_0.0
-      SHADOW_OFFSET,                            ///< name "shadowOffset",                        The drop shadow offset 0 indicates no shadow,                                      type VECTOR2 @SINCE_1_0.0
-      SHADOW_COLOR,                             ///< name "shadowColor",                         The color of a drop shadow,                                                        type VECTOR4 @SINCE_1_0.0
+      SHADOW_OFFSET,                            ///< name "shadowOffset",                        The drop shadow offset 0 indicates no shadow,                                      type VECTOR2 @DEPRECATED_1_1.37 Use SHADOW instead.
+      SHADOW_COLOR,                             ///< name "shadowColor",                         The color of a drop shadow,                                                        type VECTOR4 @DEPRECATED_1_1.37 Use SHADOW instead.
       PRIMARY_CURSOR_COLOR,                     ///< name "primaryCursorColor",                  The color to apply to the primary cursor,                                          type VECTOR4 @SINCE_1_0.0
       SECONDARY_CURSOR_COLOR,                   ///< name "secondaryCursorColor",                The color to apply to the secondary cursor,                                        type VECTOR4 @SINCE_1_0.0
       ENABLE_CURSOR_BLINK,                      ///< name "enableCursorBlink",                   Whether the cursor should blink or not,                                            type BOOLEAN @SINCE_1_0.0
@@ -107,7 +107,15 @@ public:
       ENABLE_MARKUP,                            ///< name "enableMarkup",                        Whether the mark-up processing is enabled.                                         type BOOLEAN @SINCE_1_0.0
       INPUT_FONT_FAMILY,                        ///< name "inputFontFamily",                     The font's family of the new input text,                                           type STRING @SINCE_1_0.0
       INPUT_FONT_STYLE,                         ///< name "inputFontStyle",                      The font's style of the new input text,                                            type STRING @SINCE_1_0.0
-      INPUT_POINT_SIZE                          ///< name "inputPointSize",                      The font's size of the new input text in points,                                   type FLOAT @SINCE_1_0.0
+      INPUT_POINT_SIZE,                         ///< name "inputPointSize",                      The font's size of the new input text in points,                                   type FLOAT @SINCE_1_0.0
+      UNDERLINE,                                ///< name "underline"                            The default underline parameters,                                                  type STRING @SINCE_1_1.37
+      INPUT_UNDERLINE,                          ///< name "inputUnderline"                       The underline parameters of the new input text,                                    type STRING @SINCE_1_1.37
+      SHADOW,                                   ///< name "shadow"                               The default shadow parameters,                                                     type STRING @SINCE_1_1.37
+      INPUT_SHADOW,                             ///< name "inputShadow"                          The shadow parameters of the new input text,                                       type STRING @SINCE_1_1.37
+      EMBOSS,                                   ///< name "emboss"                               The default emboss parameters,                                                     type STRING @SINCE_1_1.37
+      INPUT_EMBOSS,                             ///< name "inputEmboss"                          The emboss parameters of the new input text,                                       type STRING @SINCE_1_1.37
+      OUTLINE,                                  ///< name "outline"                              The default outline parameters,                                                    type STRING @SINCE_1_1.37
+      INPUT_OUTLINE,                            ///< name "inputOutline"                         The outline parameters of the new input text,                                      type STRING @SINCE_1_1.37
     };
   };
 
index 33e95f1..105690a 100644 (file)
@@ -53,16 +53,13 @@ class TextLabel;
  * | Property::HORIZONTAL_ALIGNMENT   | horizontalAlignment |  STRING      | O      | X        |
  * | Property::VERTICAL_ALIGNMENT     | verticalAlignment   |  STRING      | O      | X        |
  * | Property::TEXT_COLOR             | textColor           |  VECTOR4     | O      | X        |
- * | Property::SHADOW_OFFSET          | shadowOffset        |  VECTOR2     | O      | X        |
- * | Property::SHADOW_COLOR           | shadowColor         |  VECTOR4     | O      | X        |
- * | Property::UNDERLINE_ENABLED      | underlineEnabled    |  BOOLEAN     | O      | X        |
- * | Property::UNDERLINE_COLOR        | underlineColor      |  VECTOR4     | O      | X        |
- * | Property::UNDERLINE_HEIGHT       | underlineHeight     |  FLOAT       | O      | X        |
  * | Property::ENABLE_MARKUP          | enableMarkup        |  BOOLEAN     | O      | X        |
  * | Property::ENABLE_AUTO_SCROLL     | enableAutoScroll    |  BOOLEAN     | O      | X        |
  * | Property::AUTO_SCROLL_SPEED      | autoScrollSpeed     |  INTEGER     | O      | X        |
  * | Property::AUTO_SCROLL_LOOP_COUNT | autoScrollLoopCount |  INTEGER     | O      | X        |
  * | Property::AUTO_SCROLL_GAP        | autoScrollGap       |  INTEGER     | O      | X        |
+ * | Property::SHADOW                 | shadow              |  STRING      | O      | X        |
+ * | Property::UNDERLINE              | underline           |  STRING      | O      | X        |
  *
  * @SINCE_1_0.0
  */
@@ -154,35 +151,35 @@ public:
       /**
        * @brief The drop shadow offset 0 indicates no shadow
        * @details name "shadowOffset", type VECTOR4
-       * @SINCE_1_0.0
+       * @DEPRECATED_1_1.37 Use SHADOW instead
        */
       SHADOW_OFFSET,
 
       /**
        * @brief The color of a drop shadow
        * @details name "shadowColor", type VECTOR4
-       * @SINCE_1_0.0
+       * @DEPRECATED_1_1.37 Use SHADOW instead
        */
       SHADOW_COLOR,
 
       /**
        * @brief The underline enabled flag
        * @details name "underlineEnabled", type BOOLEAN
-       * @SINCE_1_0.0
+       * @DEPRECATED_1_1.37 Use UNDERLINE instead
        */
       UNDERLINE_ENABLED,
 
       /**
        * @brief The color of the underline
        * @details name "underlineColor", type VECTOR4
-       * @SINCE_1_0.0
+       * @DEPRECATED_1_1.37 Use UNDERLINE instead
        */
       UNDERLINE_COLOR,
 
       /**
        * @brief Overrides the underline height from font metrics
        * @details name "underlineHeight", type FLOAT
-       * @SINCE_1_0.0
+       * @DEPRECATED_1_1.37 Use UNDERLINE instead
        */
       UNDERLINE_HEIGHT,
 
@@ -219,7 +216,42 @@ public:
        * @details name "autoScrollGap", type INT, default in style sheet but can be overridden to prevent same text being show at start and end.
        * @SINCE_1_1.35
        */
-      AUTO_SCROLL_GAP
+      AUTO_SCROLL_GAP,
+
+      /**
+       * @brief The default extra space between lines in points.
+       * @details name "lineSpacing", type FLOAT.
+       * @SINCE_1_1.37
+       */
+      LINE_SPACING,
+
+      /**
+       * @brief The default underline parameters.
+       * @details name "underline", type STRING.
+       * @SINCE_1_1.37
+       */
+      UNDERLINE,
+
+      /**
+       * @brief The default shadow parameters.
+       * @details name "shadow", type STRING.
+       * @SINCE_1_1.37
+       */
+      SHADOW,
+
+      /**
+       * @brief The default emboss parameters.
+       * @details name "emboss", type STRING.
+       * @SINCE_1_1.37
+       */
+      EMBOSS,
+
+      /**
+       * @brief The default outline parameters.
+       * @details name "outline", type STRING.
+       * @SINCE_1_1.37
+       */
+      OUTLINE,
     };
   };
 
index a7b1a02..d7e7034 100755 (executable)
@@ -25,6 +25,7 @@ public_api_src_files = \
   $(public_api_src_dir)/controls/scrollable/scroll-view/scroll-view.cpp \
   $(public_api_src_dir)/controls/scrollable/scrollable.cpp \
   $(public_api_src_dir)/controls/table-view/table-view.cpp \
+  $(public_api_src_dir)/controls/text-controls/text-editor.cpp \
   $(public_api_src_dir)/controls/text-controls/text-label.cpp \
   $(public_api_src_dir)/controls/text-controls/text-field.cpp \
   $(public_api_src_dir)/controls/gaussian-blur-view/gaussian-blur-view.cpp \
@@ -100,6 +101,7 @@ public_api_table_view_header_files = \
   $(public_api_src_dir)/controls/table-view/table-view.h
 
 public_api_text_controls_header_files = \
+  $(public_api_src_dir)/controls/text-controls/text-editor.h \
   $(public_api_src_dir)/controls/text-controls/text-label.h \
   $(public_api_src_dir)/controls/text-controls/text-field.h
 
index 0da1f43..707258e 100644 (file)
@@ -128,6 +128,16 @@ editor.textColor = dali.COLOR_CYAN;
  inputFontFamily                   | INPUT_FONT_FAMILY                    |  STRING      | O            | X
  inputFontStyle                    | INPUT_FONT_STYLE                     |  STRING      | O            | X
  inputPointSize                    | INPUT_POINT_SIZE                     |  FLOAT       | O            | X
+ lineSpacing                       | LINE_SPACING                         |  FLOAT       | O            | X
+ inputLineSpacing                  | INPUT_LINE_SPACING                   |  FLOAT       | O            | X
+ underline                         | UNDERLINE                            |  STRING      | O            | X
+ inputUnderline                    | INPUT_UNDERLINE                      |  STRING      | O            | X
+ shadow                            | SHADOW                               |  STRING      | O            | X
+ inputShadow                       | INPUT_SHADOW                         |  STRING      | O            | X
+ emboss                            | EMBOSS                               |  STRING      | O            | X
+ inputEmboss                       | INPUT_EMBOSS                         |  STRING      | O            | X
+ outline                           | OUTLINE                              |  STRING      | O            | X
+ inputOutline                      | INPUT_OUTLINE                        |  STRING      | O            | X
 
 @class TextEditor
 
index f6c8ecc..74b8cfd 100644 (file)
@@ -122,8 +122,6 @@ field.placeholderTextColor = dali.COLOR_BLACK;
  verticalAlignment                 | VERTICAL_ALIGNMENT                   |  STRING      | O            | X
  textColor                         | TEXT_COLOR                           |  VECTOR4     | O            | X
  placeholderTextColor              | PLACEHOLDER_TEXT_COLOR               |  VECTOR4     | O            | X
- shadowOffset                      | SHADOW_OFFSET                        |  VECTOR2     | O            | X
- shadowColor                       | SHADOW_COLOR                         |  VECTOR4     | O            | X
  primaryCursorColor                | PRIMARY_CURSOR_COLOR                 |  VECTOR4     | O            | X
  secondaryCursorColor              | SECONDARY_CURSOR_COLOR               |  VECTOR4     | O            | X
  enableCursorBlink                 | ENABLE_CURSOR_BLINK                  |  BOOLEAN     | O            | X
@@ -148,6 +146,14 @@ field.placeholderTextColor = dali.COLOR_BLACK;
  inputFontFamily                   | INPUT_FONT_FAMILY                    |  STRING      | O            | X
  inputFontStyle                    | INPUT_FONT_STYLE                     |  STRING      | O            | X
  inputPointSize                    | INPUT_POINT_SIZE                     |  FLOAT       | O            | X
+ underline                         | UNDERLINE                            |  STRING      | O            | X
+ inputUnderline                    | INPUT_UNDERLINE                      |  STRING      | O            | X
+ shadow                            | SHADOW                               |  STRING      | O            | X
+ inputShadow                       | INPUT_SHADOW                         |  STRING      | O            | X
+ emboss                            | EMBOSS                               |  STRING      | O            | X
+ inputEmboss                       | INPUT_EMBOSS                         |  STRING      | O            | X
+ outline                           | OUTLINE                              |  STRING      | O            | X
+ inputOutline                      | INPUT_OUTLINE                        |  STRING      | O            | X
 
 @class TextField
 
index ae03364..98734b2 100644 (file)
@@ -207,8 +207,7 @@ label.textColor = dali.COLOR_RED;
 
 #### Drop Shadow
 
-To add a drop-shadow to the text, simply set the SHADOW_OFFSET property with non-zero values.  
-The color can also be selected using the SHADOW_COLOR property.  
+To add a drop-shadow to the text, simply set the SHADOW property. Shadow parameters can be set through a json string, see the examples below.
 
 ~~~{.cpp}
  // C++
@@ -218,16 +217,13 @@ stage.SetBackgroundColor( Color::BLUE );
 label1.SetProperty( TextLabel::Property::TEXT, "Plain Text" );
 
 label2.SetProperty( TextLabel::Property::TEXT, "Text with Shadow" );
-label2.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 1.0f, 1.0f ) );
-label2.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK );
+label2.SetProperty( TextLabel::Property::SHADOW, "{\"offset\":\"1 1\",\"color\":\"black\"}" );
 
 label3.SetProperty( TextLabel::Property::TEXT, "Text with Bigger Shadow" );
-label3.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 2.0f, 2.0f ) );
-label3.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK );
+label3.SetProperty( TextLabel::Property::SHADOW, "{\"offset\":\"2 2\",\"color\":\"black\"}" );
 
 label4.SetProperty( TextLabel::Property::TEXT, "Text with Color Shadow" );
-label4.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 1.0f, 1.0f ) );
-label4.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::RED );
+label4.SetProperty( TextLabel::Property::SHADOW, "{\"offset\":\"1 1\",\"color\":\"red\"}" );
 ~~~
 
 ~~~{.js}
@@ -239,16 +235,13 @@ label1.text = "Plain Text";
 
 
 label2.text = "Text with Shadow";
-label2.shadowOffset = [1, 1];
-label2.shadowColor = dali.COLOR_BLACK;
+label2.shadow = "{\"offset\":\"1 1\",\"color\":\"black\"}";
 
 label3.text = "Text with Bigger Shadow";
-label3.shadowOffset = [2, 2];
-label3.shadowColor = dali.COLOR_BLACK;
+label3.shadow = "{\"offset\":\"2 2\",\"color\":\"black\"}";
 
 label4.SetProperty( TextLabel::Property::TEXT, "Text with Color Shadow" );
-label3.shadowOffset = [1, 1];
-label3.shadowColor = dali.COLOR_RED;
+label3.shadow = "{\"offset\":\"1 1\",\"color\":\"red\"}";
 ~~~