[dali_1.3.4] Merge branch 'devel/master' 39/164139/1
authorFrancisco Santos <f1.santos@samsung.com>
Fri, 15 Dec 2017 11:19:45 +0000 (11:19 +0000)
committerFrancisco Santos <f1.santos@samsung.com>
Fri, 15 Dec 2017 11:19:45 +0000 (11:19 +0000)
Change-Id: I10679ea694931c87d64accd9d6c67e31386393b6

37 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.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
automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
build/tizen/docs/dali.doxy.in
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/visuals/text-visual-properties-devel.h [new file with mode: 0644]
dali-toolkit/internal/text/decorator/text-decorator.cpp
dali-toolkit/internal/text/decorator/text-decorator.h
dali-toolkit/internal/text/markup-processor-helper-functions.cpp
dali-toolkit/internal/text/markup-processor-helper-functions.h
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-effects-style.cpp
dali-toolkit/internal/text/text-effects-style.h
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/text/visual-model-impl.cpp
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/internal/visuals/npatch-loader.cpp
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/internal/visuals/texture-manager-impl.cpp
dali-toolkit/public-api/controls/image-view/image-view.h
dali-toolkit/public-api/controls/text-controls/text-editor.h
dali-toolkit/public-api/controls/text-controls/text-field.h
dali-toolkit/public-api/controls/text-controls/text-label.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 8d73622..02f2e66 100644 (file)
@@ -184,9 +184,16 @@ int UtcDaliTextControllerImfEvent(void)
   // Enables the text input.
   controller->EnableTextInput( decorator );
 
+  // Set the placeholder text.
+  controller->SetPlaceholderText( Controller::PLACEHOLDER_TYPE_INACTIVE, "Hello Dali" );
+
   // Creates an ImfManager.
   ImfManager imfManager = ImfManager::Get();
 
+  // For coverage.
+  imfEvent = ImfManager::ImfEventData( ImfManager::GETSURROUNDING, "", 0, 0 );
+  controller->OnImfEvent( imfManager, imfEvent );
+
   // Send VOID event.
   imfEvent = ImfManager::ImfEventData( ImfManager::VOID, "", 0, 0 );
   controller->OnImfEvent( imfManager, imfEvent );
index 487ae20..6f9784f 100644 (file)
@@ -314,9 +314,38 @@ bool DaliTestCheckMaps( const Property::Map& fontStyleMapGet, const Property::Ma
 
       if( NULL != valueSet )
       {
-        if( valueGet.second.Get<std::string>() != valueSet->Get<std::string>() )
+        if( valueSet->GetType() == Dali::Property::STRING && ( valueGet.second.Get<std::string>() != valueSet->Get<std::string>() ) )
         {
-          tet_printf( "  Value got : [%s], expected : [%s]", valueGet.second.Get<std::string>().c_str(), valueSet->Get<std::string>().c_str() );
+          tet_printf( "Value got : [%s], expected : [%s]", valueGet.second.Get<std::string>().c_str(), valueSet->Get<std::string>().c_str() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::BOOLEAN && ( valueGet.second.Get<bool>() != valueSet->Get<bool>() ) )
+        {
+          tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get<bool>(), valueSet->Get<bool>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::INTEGER && ( valueGet.second.Get<int>() != valueSet->Get<int>() ) )
+        {
+          tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get<int>(), valueSet->Get<int>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::FLOAT && ( valueGet.second.Get<float>() != valueSet->Get<float>() ) )
+        {
+          tet_printf( "Value got : [%f], expected : [%f]", valueGet.second.Get<float>(), valueSet->Get<float>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::VECTOR2 && ( valueGet.second.Get<Vector2>() != valueSet->Get<Vector2>() ) )
+        {
+          Vector2 vector2Get = valueGet.second.Get<Vector2>();
+          Vector2 vector2Set = valueSet->Get<Vector2>();
+          tet_printf( "Value got : [%f, %f], expected : [%f, %f]", vector2Get.x, vector2Get.y, vector2Set.x, vector2Set.y );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::VECTOR4 && ( valueGet.second.Get<Vector4>() != valueSet->Get<Vector4>() ) )
+        {
+          Vector4 vector4Get = valueGet.second.Get<Vector4>();
+          Vector4 vector4Set = valueSet->Get<Vector4>();
+          tet_printf( "Value got : [%f, %f, %f, %f], expected : [%f, %f, %f, %f]", vector4Get.r, vector4Get.g, vector4Get.b, vector4Get.a, vector4Set.r, vector4Set.g, vector4Set.b, vector4Set.a );
           return false;
         }
       }
@@ -785,8 +814,6 @@ int UtcDaliTextEditorSetPropertyP(void)
 
   editor.SetProperty( TextEditor::Property::OUTLINE, outlineMapSet );
 
-  outlineMapSet["color"] = "red";
-  outlineMapSet["width"] = "2";
   outlineMapGet = editor.GetProperty<Property::Map>( TextEditor::Property::OUTLINE );
   DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION );
   DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION );
index 0074c78..633ff81 100644 (file)
@@ -329,39 +329,65 @@ bool DaliTestCheckMaps( const Property::Map& fontStyleMapGet, const Property::Ma
     {
       const KeyValuePair& valueGet = fontStyleMapGet.GetKeyValue( index );
 
-      if( valueGet.first.type == Property::Key::STRING )
+      Property::Value* valueSet = NULL;
+      if ( valueGet.first.type == Property::Key::INDEX )
       {
-        Property::Value* valueSet = fontStyleMapSet.Find( valueGet.first.stringKey );
-        if( NULL != valueSet )
+        valueSet = fontStyleMapSet.Find( valueGet.first.indexKey );
+      }
+      else
+      {
+        // Get Key is a string so searching Set Map for a string key
+        valueSet = fontStyleMapSet.Find( valueGet.first.stringKey );
+      }
+
+      if( NULL != valueSet )
+      {
+        if( valueSet->GetType() == Dali::Property::STRING && ( valueGet.second.Get<std::string>() != valueSet->Get<std::string>() ) )
         {
-          if( valueGet.second.Get<std::string>() != valueSet->Get<std::string>() )
-          {
-            tet_printf( "  Value got : [%s], expected : [%s]", valueGet.second.Get<std::string>().c_str(), valueSet->Get<std::string>().c_str() );
-            return false;
-          }
+          tet_printf( "Value got : [%s], expected : [%s]", valueGet.second.Get<std::string>().c_str(), valueSet->Get<std::string>().c_str() );
+          return false;
         }
-        else
+        else if( valueSet->GetType() == Dali::Property::BOOLEAN && ( valueGet.second.Get<bool>() != valueSet->Get<bool>() ) )
         {
-          tet_printf( "  The key %s doesn't exist.", valueGet.first.stringKey.c_str() );
+          tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get<bool>(), valueSet->Get<bool>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::INTEGER && ( valueGet.second.Get<int>() != valueSet->Get<int>() ) )
+        {
+          tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get<int>(), valueSet->Get<int>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::FLOAT && ( valueGet.second.Get<float>() != valueSet->Get<float>() ) )
+        {
+          tet_printf( "Value got : [%f], expected : [%f]", valueGet.second.Get<float>(), valueSet->Get<float>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::VECTOR2 && ( valueGet.second.Get<Vector2>() != valueSet->Get<Vector2>() ) )
+        {
+          Vector2 vector2Get = valueGet.second.Get<Vector2>();
+          Vector2 vector2Set = valueSet->Get<Vector2>();
+          tet_printf( "Value got : [%f, %f], expected : [%f, %f]", vector2Get.x, vector2Get.y, vector2Set.x, vector2Set.y );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::VECTOR4 && ( valueGet.second.Get<Vector4>() != valueSet->Get<Vector4>() ) )
+        {
+          Vector4 vector4Get = valueGet.second.Get<Vector4>();
+          Vector4 vector4Set = valueSet->Get<Vector4>();
+          tet_printf( "Value got : [%f, %f, %f, %f], expected : [%f, %f, %f, %f]", vector4Get.r, vector4Get.g, vector4Get.b, vector4Get.a, vector4Set.r, vector4Set.g, vector4Set.b, vector4Set.a );
           return false;
         }
       }
       else
       {
-        Property::Value* valueSet = fontStyleMapSet.Find( valueGet.first.indexKey );
-        if( NULL != valueSet )
+        if ( valueGet.first.type == Property::Key::INDEX )
         {
-          if( valueGet.second.Get<int>() != valueSet->Get<int>() )
-          {
-            tet_printf( "  Integer Value got : [%d], expected : [%d]", valueGet.second.Get<int>(), valueSet->Get<int>() );
-            return false;
-          }
+          tet_printf( "  The key %d doesn't exist.", valueGet.first.indexKey );
         }
         else
         {
-          tet_printf( "  The Int key %d doesn't exist.", valueGet.first.indexKey );
-          return false;
+          tet_printf( "  The key %s doesn't exist.", valueGet.first.stringKey.c_str() );
         }
+        return false;
       }
     }
   }
@@ -843,8 +869,6 @@ int UtcDaliTextFieldSetPropertyP(void)
 
   field.SetProperty( TextField::Property::OUTLINE, outlineMapSet );
 
-  outlineMapSet["color"] = "red";
-  outlineMapSet["width"] = "2";
   outlineMapGet = field.GetProperty<Property::Map>( TextField::Property::OUTLINE );
   DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION );
   DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION );
index 45214f8..f8d7497 100644 (file)
@@ -82,18 +82,64 @@ bool DaliTestCheckMaps( const Property::Map& fontStyleMapGet, const Property::Ma
     {
       const KeyValuePair& valueGet = fontStyleMapGet.GetKeyValue( index );
 
-      Property::Value* valueSet = fontStyleMapSet.Find( valueGet.first.stringKey );
+      Property::Value* valueSet = NULL;
+      if ( valueGet.first.type == Property::Key::INDEX )
+      {
+        valueSet = fontStyleMapSet.Find( valueGet.first.indexKey );
+      }
+      else
+      {
+        // Get Key is a string so searching Set Map for a string key
+        valueSet = fontStyleMapSet.Find( valueGet.first.stringKey );
+      }
+
       if( NULL != valueSet )
       {
-        if( valueGet.second.Get<std::string>() != valueSet->Get<std::string>() )
+        if( valueSet->GetType() == Dali::Property::STRING && ( valueGet.second.Get<std::string>() != valueSet->Get<std::string>() ) )
+        {
+          tet_printf( "Value got : [%s], expected : [%s]", valueGet.second.Get<std::string>().c_str(), valueSet->Get<std::string>().c_str() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::BOOLEAN && ( valueGet.second.Get<bool>() != valueSet->Get<bool>() ) )
+        {
+          tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get<bool>(), valueSet->Get<bool>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::INTEGER && ( valueGet.second.Get<int>() != valueSet->Get<int>() ) )
+        {
+          tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get<int>(), valueSet->Get<int>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::FLOAT && ( valueGet.second.Get<float>() != valueSet->Get<float>() ) )
+        {
+          tet_printf( "Value got : [%f], expected : [%f]", valueGet.second.Get<float>(), valueSet->Get<float>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::VECTOR2 && ( valueGet.second.Get<Vector2>() != valueSet->Get<Vector2>() ) )
+        {
+          Vector2 vector2Get = valueGet.second.Get<Vector2>();
+          Vector2 vector2Set = valueSet->Get<Vector2>();
+          tet_printf( "Value got : [%f, %f], expected : [%f, %f]", vector2Get.x, vector2Get.y, vector2Set.x, vector2Set.y );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::VECTOR4 && ( valueGet.second.Get<Vector4>() != valueSet->Get<Vector4>() ) )
         {
-          tet_printf( "  Value got : [%s], expected : [%s]", valueGet.second.Get<std::string>().c_str(), valueSet->Get<std::string>().c_str() );
+          Vector4 vector4Get = valueGet.second.Get<Vector4>();
+          Vector4 vector4Set = valueSet->Get<Vector4>();
+          tet_printf( "Value got : [%f, %f, %f, %f], expected : [%f, %f, %f, %f]", vector4Get.r, vector4Get.g, vector4Get.b, vector4Get.a, vector4Set.r, vector4Set.g, vector4Set.b, vector4Set.a );
           return false;
         }
       }
       else
       {
-        tet_printf( "  The key %s doesn't exist.", valueGet.first.stringKey.c_str() );
+        if ( valueGet.first.type == Property::Key::INDEX )
+        {
+          tet_printf( "  The key %d doesn't exist.", valueGet.first.indexKey );
+        }
+        else
+        {
+          tet_printf( "  The key %s doesn't exist.", valueGet.first.stringKey.c_str() );
+        }
         return false;
       }
     }
@@ -463,8 +509,6 @@ int UtcDaliToolkitTextLabelSetPropertyP(void)
   outlineMapSet["width"] = 2.0f;
   label.SetProperty( TextLabel::Property::OUTLINE, outlineMapSet );
 
-  outlineMapSet["color"] = "red";
-  outlineMapSet["width"] = "2";
   outlineMapGet = label.GetProperty<Property::Map>( TextLabel::Property::OUTLINE );
   DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION );
   DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION );
@@ -1163,18 +1207,15 @@ int UtcDaliToolkitTextlabelTextDirection(void)
   tet_infoline(" UtcDaliToolkitTextlabelTextDirection");
 
   TextLabel label = TextLabel::New();
+  DALI_TEST_EQUALS( label.GetProperty< int >( DevelTextLabel::Property::TEXT_DIRECTION ), static_cast< int >( Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ), TEST_LOCATION );
+
   label.SetProperty( TextLabel::Property::TEXT, "Hello world" );
   label.SetProperty( TextLabel::Property::POINT_SIZE, 20 );
   Stage::GetCurrent().Add( label );
 
-  application.SendNotification();
-  application.Render();
-
   DALI_TEST_EQUALS( label.GetProperty< int >( DevelTextLabel::Property::TEXT_DIRECTION ), static_cast< int >( Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ), TEST_LOCATION );
 
   label.SetProperty( TextLabel::Property::TEXT, "ﻡﺮﺤﺑﺍ ﺏﺎﻠﻋﺎﻠﻣ ﻡﺮﺤﺑﺍ" );
-  application.SendNotification();
-  application.Render();
   DALI_TEST_EQUALS( label.GetProperty< int >( DevelTextLabel::Property::TEXT_DIRECTION ), static_cast< int >( Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT ), TEST_LOCATION );
 
   END_TEST;
index b1f2e2e..ab45fc0 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali-toolkit/devel-api/visual-factory/transition-data.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/devel-api/visuals/text-visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/animated-gradient-visual-properties-devel.h>
 #include <dali-toolkit/dali-toolkit.h>
 
@@ -68,18 +69,64 @@ bool DaliTestCheckMaps( const Property::Map& fontStyleMapGet, const Property::Ma
     {
       const KeyValuePair& valueGet = fontStyleMapGet.GetKeyValue( index );
 
-      Property::Value* valueSet = fontStyleMapSet.Find( valueGet.first.stringKey );
+      Property::Value* valueSet = NULL;
+      if ( valueGet.first.type == Property::Key::INDEX )
+      {
+        valueSet = fontStyleMapSet.Find( valueGet.first.indexKey );
+      }
+      else
+      {
+        // Get Key is a string so searching Set Map for a string key
+        valueSet = fontStyleMapSet.Find( valueGet.first.stringKey );
+      }
+
       if( NULL != valueSet )
       {
-        if( valueGet.second.Get<std::string>() != valueSet->Get<std::string>() )
+        if( valueSet->GetType() == Dali::Property::STRING && ( valueGet.second.Get<std::string>() != valueSet->Get<std::string>() ) )
+        {
+          tet_printf( "Value got : [%s], expected : [%s]", valueGet.second.Get<std::string>().c_str(), valueSet->Get<std::string>().c_str() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::BOOLEAN && ( valueGet.second.Get<bool>() != valueSet->Get<bool>() ) )
+        {
+          tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get<bool>(), valueSet->Get<bool>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::INTEGER && ( valueGet.second.Get<int>() != valueSet->Get<int>() ) )
+        {
+          tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get<int>(), valueSet->Get<int>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::FLOAT && ( valueGet.second.Get<float>() != valueSet->Get<float>() ) )
         {
-          tet_printf( "  Value got : [%s], expected : [%s]", valueGet.second.Get<std::string>().c_str(), valueSet->Get<std::string>().c_str() );
+          tet_printf( "Value got : [%f], expected : [%f]", valueGet.second.Get<float>(), valueSet->Get<float>() );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::VECTOR2 && ( valueGet.second.Get<Vector2>() != valueSet->Get<Vector2>() ) )
+        {
+          Vector2 vector2Get = valueGet.second.Get<Vector2>();
+          Vector2 vector2Set = valueSet->Get<Vector2>();
+          tet_printf( "Value got : [%f, %f], expected : [%f, %f]", vector2Get.x, vector2Get.y, vector2Set.x, vector2Set.y );
+          return false;
+        }
+        else if( valueSet->GetType() == Dali::Property::VECTOR4 && ( valueGet.second.Get<Vector4>() != valueSet->Get<Vector4>() ) )
+        {
+          Vector4 vector4Get = valueGet.second.Get<Vector4>();
+          Vector4 vector4Set = valueSet->Get<Vector4>();
+          tet_printf( "Value got : [%f, %f, %f, %f], expected : [%f, %f, %f, %f]", vector4Get.r, vector4Get.g, vector4Get.b, vector4Get.a, vector4Set.r, vector4Set.g, vector4Set.b, vector4Set.a );
           return false;
         }
       }
       else
       {
-        tet_printf( "  The key %s doesn't exist.", valueGet.first.stringKey.c_str() );
+        if ( valueGet.first.type == Property::Key::INDEX )
+        {
+          tet_printf( "  The key %d doesn't exist.", valueGet.first.indexKey );
+        }
+        else
+        {
+          tet_printf( "  The key %s doesn't exist.", valueGet.first.stringKey.c_str() );
+        }
         return false;
       }
     }
@@ -1070,6 +1117,16 @@ int UtcDaliVisualGetPropertyMap10(void)
   propertyMap.Insert( "horizontalAlignment", "CENTER" );
   propertyMap.Insert( "verticalAlignment", "CENTER" );
   propertyMap.Insert( "textColor", Color::RED );
+
+  Property::Map shadowMapSet;
+  propertyMap.Insert( "shadow", shadowMapSet.Add("color", Color::RED).Add("offset", Vector2(2.0f, 2.0f)).Add("blurRadius", 3.0f) );
+
+  Property::Map underlineMapSet;
+  propertyMap.Insert( "underline", underlineMapSet.Add("enable", "true").Add("color", "green").Add("height", "1") );
+
+  Property::Map outlineMapSet;
+  propertyMap.Insert( "outline", outlineMapSet.Add("color", Color::YELLOW).Add("width", 1) );
+
   Visual::Base textVisual = factory.CreateVisual( propertyMap );
 
   Property::Map resultMap;
@@ -1123,6 +1180,27 @@ int UtcDaliVisualGetPropertyMap10(void)
   DALI_TEST_CHECK( value );
   DALI_TEST_CHECK( !value->Get<bool>() );
 
+  value = resultMap.Find( TextVisual::Property::SHADOW, Property::MAP );
+  DALI_TEST_CHECK( value );
+
+  Property::Map shadowMapGet = value->Get<Property::Map>();
+  DALI_TEST_EQUALS( shadowMapGet.Count(), shadowMapSet.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( DaliTestCheckMaps( shadowMapGet, shadowMapSet ), true, TEST_LOCATION );
+
+  value = resultMap.Find( TextVisual::Property::UNDERLINE, Property::MAP );
+  DALI_TEST_CHECK( value );
+
+  Property::Map underlineMapGet = value->Get<Property::Map>();
+  DALI_TEST_EQUALS( underlineMapGet.Count(), underlineMapSet.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( DaliTestCheckMaps( underlineMapGet, underlineMapSet ), true, TEST_LOCATION );
+
+  value = resultMap.Find( DevelTextVisual::Property::OUTLINE, Property::MAP );
+  DALI_TEST_CHECK( value );
+
+  Property::Map outlineMapGet = value->Get<Property::Map>();
+  DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION );
+
   END_TEST;
 }
 
index ddcd598..5c5d44b 100644 (file)
@@ -354,6 +354,9 @@ ALIASES += SINCE_1_2_10="@since 1.2.10"
 ALIASES += SINCE_1_2_14="@since 1.2.14"
 ALIASES += SINCE_1_2_32="@since 1.2.32"
 
+# Extra tags for Tizen 4.0
+ALIASES += SINCE_1_3_4="@since 1.3.4"
+
 ALIASES += DEPRECATED_1_0="@deprecated Deprecated since 1.0"
 ALIASES += DEPRECATED_1_1="@deprecated Deprecated since 1.1"
 ALIASES += DEPRECATED_1_2_8="@deprecated Deprecated since 1.2.8"
@@ -384,6 +387,9 @@ ALIASES += REMARK_RAWVIDEO=""
 #ALIASES += SINCE_1_2_14="\par Since:\n 3.0, DALi version 1.2.14"
 #ALIASES += SINCE_1_2_32="\par Since:\n 3.0, DALi version 1.2.32"
 
+## Extra tags for Tizen 4.0
+#ALIASES += SINCE_1_3_4="\par Since:\n 4.0, DALi version 1.3.4"
+
 ## DALi has no deprecated API in Tizen 2.4 because it's DALi's first release.
 ## Thus deprecated APIs in DALi 1.0.xx will be deprecated in Tizen 3.0.
 #ALIASES += DEPRECATED_1_0="@deprecated Deprecated since 3.0, DALi version 1.0"
index 3f114bb..a995986 100644 (file)
@@ -94,6 +94,7 @@ devel_api_visuals_header_files = \
   $(devel_api_src_dir)/visuals/image-visual-properties-devel.h \
   $(devel_api_src_dir)/visuals/image-visual-actions-devel.h \
   $(devel_api_src_dir)/visuals/animated-gradient-visual-properties-devel.h \
+  $(devel_api_src_dir)/visuals/text-visual-properties-devel.h \
   $(devel_api_src_dir)/visuals/visual-properties-devel.h
 
 devel_api_shadow_view_header_files = \
diff --git a/dali-toolkit/devel-api/visuals/text-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/text-visual-properties-devel.h
new file mode 100644 (file)
index 0000000..ec80f49
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_TEXT_VISUAL_PROPERTIES_DEVEL_H
+#define DALI_TOOLKIT_DEVEL_API_VISUALS_TEXT_VISUAL_PROPERTIES_DEVEL_H
+
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/visuals/text-visual-properties.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace DevelTextVisual
+{
+
+namespace Property
+{
+
+/**
+ * @brief All the visual types.
+ */
+enum
+{
+  TEXT                  = Dali::Toolkit::TextVisual::Property::TEXT,
+  FONT_FAMILY           = Dali::Toolkit::TextVisual::Property::FONT_FAMILY,
+  FONT_STYLE            = Dali::Toolkit::TextVisual::Property::FONT_STYLE,
+  POINT_SIZE            = Dali::Toolkit::TextVisual::Property::POINT_SIZE,
+  MULTI_LINE            = Dali::Toolkit::TextVisual::Property::MULTI_LINE,
+  HORIZONTAL_ALIGNMENT  = Dali::Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT,
+  VERTICAL_ALIGNMENT    = Dali::Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT,
+  TEXT_COLOR            = Dali::Toolkit::TextVisual::Property::TEXT_COLOR,
+  ENABLE_MARKUP         = Dali::Toolkit::TextVisual::Property::ENABLE_MARKUP,
+  SHADOW                = Dali::Toolkit::TextVisual::Property::SHADOW,
+  UNDERLINE             = Dali::Toolkit::TextVisual::Property::UNDERLINE,
+
+  /**
+   * @brief The default outline parameters.
+   * @details name "outline", type Property::MAP.
+   */
+  OUTLINE               = UNDERLINE + 1
+};
+
+
+} // namespace Property
+
+} // namespace DevelTextVisual
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_TEXT_VISUAL_PROPERTIES_DEVEL_H
index e9e0b1a..aa4d5c6 100644 (file)
@@ -236,6 +236,9 @@ struct Decorator::Impl : public ConnectionTracker
     mBoundingBox(),
     mHighlightColor( LIGHT_BLUE ),
     mHighlightPosition( Vector2::ZERO ),
+    mHighlightSize( Vector2::ZERO ),
+    mControlSize( Vector2::ZERO ),
+    mHighlightOutlineOffset( 0.f ),
     mActiveCursor( ACTIVE_CURSOR_NONE ),
     mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ),
     mCursorBlinkDuration( 0.0f ),
@@ -1163,8 +1166,8 @@ struct Decorator::Impl : public ConnectionTracker
     if ( mHighlightActor )
     {
       // Sets the position of the highlight actor inside the decorator.
-      mHighlightActor.SetPosition( mHighlightPosition.x,
-                                   mHighlightPosition.y );
+      mHighlightActor.SetPosition( mHighlightPosition.x + mHighlightOutlineOffset,
+                                   mHighlightPosition.y + mHighlightOutlineOffset );
 
       const unsigned int numberOfQuads = mHighlightQuadList.Count();
       if( 0u != numberOfQuads )
@@ -1912,6 +1915,7 @@ struct Decorator::Impl : public ConnectionTracker
   Vector2             mHighlightPosition;         ///< The position of the highlight actor.
   Size                mHighlightSize;             ///< The size of the highlighted text.
   Size                mControlSize;               ///< The control's size. Set by the Relayout.
+  float               mHighlightOutlineOffset;    ///< The outline's offset.
 
   unsigned int        mActiveCursor;
   unsigned int        mCursorBlinkInterval;
@@ -2199,16 +2203,18 @@ void Decorator::AddHighlight( unsigned int index, const Vector4& quad )
   *( mImpl->mHighlightQuadList.Begin() + index ) = quad;
 }
 
-void Decorator::SetHighLightBox( const Vector2& position, const Size& size )
+void Decorator::SetHighLightBox( const Vector2& position, const Size& size, float outlineOffset )
 {
   mImpl->mHighlightPosition = position;
   mImpl->mHighlightSize = size;
+  mImpl->mHighlightOutlineOffset = outlineOffset;
 }
 
 void Decorator::ClearHighlights()
 {
   mImpl->mHighlightQuadList.Clear();
   mImpl->mHighlightPosition = Vector2::ZERO;
+  mImpl->mHighlightOutlineOffset = 0.f;
 }
 
 void Decorator::ResizeHighlightQuads( unsigned int numberOfQuads )
index 8cff322..11f7062 100644 (file)
@@ -468,9 +468,11 @@ public:
    *
    * @param[in] position The position of the highlighted text in decorator's coords.
    * @param[in] size The size of the highlighted text.
+   * @param[in] outlineOffset The outline's offset.
    */
   void SetHighLightBox( const Vector2& position,
-                        const Size& size );
+                        const Size& size,
+                        float outlineOffset );
 
   /**
    * @brief Removes all of the previously added highlights.
index 8af6140..76d9a6a 100644 (file)
@@ -109,6 +109,13 @@ void FloatToString( float value, std::string& floatStr )
   floatStr = ss.str();
 }
 
+void UintToString( unsigned int value, std::string& uIntStr )
+{
+  std::stringstream ss;
+  ss << value;
+  uIntStr = ss.str();
+}
+
 void UintColorToVector4( unsigned int color, Vector4& retColor )
 {
   retColor.a = static_cast<float>( ( color & 0xFF000000 ) >> 24u ) / 255.f;
index 45f586c..d1ecbc8 100644 (file)
@@ -121,6 +121,14 @@ float StringToFloat( const char* const floatStr );
 void FloatToString( float value, std::string& floatStr );
 
 /**
+ * @brief Converts an unsigned int into a string.
+ *
+ * @param[in] value The unsigned int value.
+ * @param[out] uIntStr The string.
+ */
+void UintToString( unsigned int value, std::string& uIntStr );
+
+/**
  * @brief Converts an ARGB color packed in 4 byte unsigned int into a Vector4 color used in Dali.
  *
  * @param[in] color An ARGB color packed in an unsigned int.
index 0d72be9..957fd8e 100644 (file)
@@ -44,6 +44,7 @@ AtlasGlyphManager::AtlasGlyphManager()
 }
 
 void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
+                             const uint32_t outlineWidth,
                              const PixelData& bitmap,
                              Dali::Toolkit::AtlasManager::AtlasSlot& slot )
 {
@@ -62,6 +63,7 @@ void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
 
   GlyphRecordEntry record;
   record.mIndex = glyph.index;
+  record.mOutlineWidth = outlineWidth;
   record.mImageId = slot.mImageId;
   record.mCount = 1;
 
@@ -98,6 +100,7 @@ void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
 
 bool AtlasGlyphManager::IsCached( Text::FontId fontId,
                                 Text::GlyphIndex index,
+                                uint32_t outlineWidth,
                                 Dali::Toolkit::AtlasManager::AtlasSlot& slot )
 {
   for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
@@ -110,7 +113,7 @@ bool AtlasGlyphManager::IsCached( Text::FontId fontId,
             glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
             ++glyphRecordIt )
       {
-        if ( glyphRecordIt->mIndex == index )
+        if ( glyphRecordIt->mIndex == index && glyphRecordIt->mOutlineWidth == outlineWidth )
         {
           slot.mImageId = glyphRecordIt->mImageId;
           slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
@@ -171,7 +174,7 @@ const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
   return mMetrics;
 }
 
-void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta )
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta )
 {
   if( 0 != delta )
   {
@@ -187,7 +190,7 @@ void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIn
               glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
               ++glyphRecordIt )
         {
-          if ( glyphRecordIt->mIndex == index )
+          if ( glyphRecordIt->mIndex == index && glyphRecordIt->mOutlineWidth == outlineWidth )
           {
             glyphRecordIt->mCount += delta;
             DALI_ASSERT_DEBUG( glyphRecordIt->mCount >= 0 && "Glyph ref-count should not be negative" );
index a2232f9..0d32834 100644 (file)
@@ -51,6 +51,7 @@ public:
   struct GlyphRecordEntry
   {
     Text::GlyphIndex mIndex;
+    uint32_t mOutlineWidth;
     uint32_t mImageId;
     int32_t mCount;
   };
@@ -70,6 +71,7 @@ public:
    * @copydoc Toolkit::AtlasGlyphManager::Add
    */
   void Add( const Text::GlyphInfo& glyph,
+            const uint32_t outlineWidth,
             const PixelData& bitmap,
             Dali::Toolkit::AtlasManager::AtlasSlot& slot );
 
@@ -85,6 +87,7 @@ public:
    */
   bool IsCached( Text::FontId fontId,
                  Text::GlyphIndex index,
+                 uint32_t outlineWidth,
                  Dali::Toolkit::AtlasManager::AtlasSlot& slot );
 
   /**
@@ -105,7 +108,7 @@ public:
   /**
    * @copydoc toolkit::AtlasGlyphManager::AdjustReferenceCount
    */
-  void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta );
+  void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta );
 
   /**
    * @copydoc Toolkit::AtlasGlyphManager::GetTextures
index 743bc6c..bd6850d 100644 (file)
@@ -69,10 +69,11 @@ AtlasGlyphManager::AtlasGlyphManager(Internal::AtlasGlyphManager *impl)
 }
 
 void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
+                             const uint32_t outlineWidth,
                              const PixelData& bitmap,
                              AtlasManager::AtlasSlot& slot )
 {
-  GetImplementation(*this).Add( glyph, bitmap, slot );
+  GetImplementation(*this).Add( glyph, outlineWidth, bitmap, slot );
 }
 
 void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
@@ -86,9 +87,10 @@ void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
 
 bool AtlasGlyphManager::IsCached( Text::FontId fontId,
                                   Text::GlyphIndex index,
+                                  uint32_t outlineWidth,
                                   AtlasManager::AtlasSlot& slot )
 {
-  return GetImplementation(*this).IsCached( fontId, index, slot );
+  return GetImplementation(*this).IsCached( fontId, index, outlineWidth, slot );
 }
 
 void AtlasGlyphManager::SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight )
@@ -116,9 +118,9 @@ const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
   return GetImplementation(*this).GetMetrics();
 }
 
-void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta )
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta )
 {
-  GetImplementation(*this).AdjustReferenceCount( fontId, index, delta );
+  GetImplementation(*this).AdjustReferenceCount( fontId, index, outlineWidth, delta );
 }
 
 } // namespace Toolkit
index 1bc058b..c41415e 100644 (file)
@@ -80,10 +80,12 @@ public:
    * @brief Ask Atlas Manager to add a glyph
    *
    * @param[in] glyph glyph to add to an atlas
+   * @param[in] outlineWidth the outline width of the glyph
    * @param[in] bitmap bitmap to use for glyph addition
    * @param[out] slot information returned by atlas manager for addition
    */
   void Add( const Text::GlyphInfo& glyph,
+            const uint32_t outlineWidth,
             const PixelData& bitmap,
             AtlasManager::AtlasSlot& slot );
 
@@ -103,12 +105,14 @@ public:
    *
    * @param[in] fontId The font that this glyph comes from
    * @param[in] index The GlyphIndex of this glyph
+   * @param[in] outlineWidth The outline width of this glyph
    * @param[out] slot container holding information about the glyph( mImage = 0 indicates not being cached )
    *
    * @return Whether glyph is cached or not ?
    */
   bool IsCached( Text::FontId fontId,
                  Text::GlyphIndex index,
+                 uint32_t outlineWidth,
                  AtlasManager::AtlasSlot& slot );
 
   /**
@@ -160,9 +164,10 @@ public:
    *
    * @param[in] fontId The font this image came from
    * @param[in] index The index of the glyph
+   * @param[in] outlineWidth The outline width of the glyph
    * @param[in] delta The adjustment to make to the reference count
    */
-  void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta );
+  void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta );
 
 private:
 
index 62865d6..03d02f5 100644 (file)
@@ -94,7 +94,7 @@ const float HALF( 0.5f );
 const float ONE( 1.0f );
 const uint32_t DEFAULT_ATLAS_WIDTH = 512u;
 const uint32_t DEFAULT_ATLAS_HEIGHT = 512u;
-const int NO_OUTLINE( 0 );
+const uint32_t NO_OUTLINE = 0;
 }
 
 struct AtlasRenderer::Impl
@@ -172,12 +172,14 @@ struct AtlasRenderer::Impl
     TextCacheEntry()
     : mFontId( 0 ),
       mIndex( 0 ),
+      mOutlineWidth( 0 ),
       mImageId( 0 )
     {
     }
 
     FontId mFontId;
     Text::GlyphIndex mIndex;
+    uint32_t mOutlineWidth;
     uint32_t mImageId;
   };
 
@@ -211,6 +213,207 @@ struct AtlasRenderer::Impl
     return false;
   }
 
+  void CacheGlyph( const GlyphInfo& glyph, FontId lastFontId, uint32_t outline, AtlasManager::AtlasSlot& slot )
+  {
+    const bool glyphNotCached = !mGlyphManager.IsCached( glyph.fontId, glyph.index, outline, slot );  // Check FontGlyphRecord vector for entry with glyph index and fontId
+
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "AddGlyphs fontID[%u] glyphIndex[%u] [%s]\n", glyph.fontId, glyph.index, (glyphNotCached)?"not cached":"cached" );
+
+    if( glyphNotCached )
+    {
+      MaxBlockSize& blockSize = mBlockSizes[0u];
+
+      if ( lastFontId != glyph.fontId )
+      {
+        uint32_t index = 0u;
+        // Looks through all stored block sizes until finds the one which mataches required glyph font it.  Ensures new atlas block size will match existing for same font id.
+        // CalculateBlocksSize() above ensures a block size entry exists.
+        for( std::vector<MaxBlockSize>::const_iterator it = mBlockSizes.begin(),
+               endIt = mBlockSizes.end();
+             it != endIt;
+             ++it, ++index )
+        {
+          const MaxBlockSize& blockSizeEntry = *it;
+          if( blockSizeEntry.mFontId == glyph.fontId )
+          {
+            blockSize = mBlockSizes[index];
+          }
+        }
+      }
+
+      // Create a new image for the glyph
+      PixelData bitmap;
+
+      // Whether the glyph is an outline.
+      const bool isOutline = 0u != outline;
+
+      // Whether the current glyph is a color one.
+      const bool isColorGlyph = mFontClient.IsColorGlyph( glyph.fontId, glyph.index );
+
+      if( !isOutline || ( isOutline && !isColorGlyph) )
+      {
+        // Retrieve the emoji's bitmap.
+        TextAbstraction::FontClient::GlyphBufferData glyphBufferData;
+        glyphBufferData.width = isColorGlyph ? glyph.width : 0;   // Desired width and height.
+        glyphBufferData.height = isColorGlyph ? glyph.height : 0;
+
+        mFontClient.CreateBitmap( glyph.fontId,
+                                  glyph.index,
+                                  glyphBufferData,
+                                  outline );
+
+        // Create the pixel data.
+        bitmap = PixelData::New( glyphBufferData.buffer,
+                                 glyphBufferData.width * glyphBufferData.height * GetBytesPerPixel( glyphBufferData.format ),
+                                 glyphBufferData.width,
+                                 glyphBufferData.height,
+                                 glyphBufferData.format,
+                                 PixelData::DELETE_ARRAY );
+
+        if( bitmap )
+        {
+          // Ensure that the next image will fit into the current block size
+          if( bitmap.GetWidth() > blockSize.mNeededBlockWidth )
+          {
+            blockSize.mNeededBlockWidth = bitmap.GetWidth();
+          }
+
+          if( bitmap.GetHeight() > blockSize.mNeededBlockHeight )
+          {
+            blockSize.mNeededBlockHeight = bitmap.GetHeight();
+          }
+
+          // If CheckAtlas in AtlasManager::Add can't fit the bitmap in the current atlas it will create a new atlas
+
+          // Setting the block size and size of new atlas does not mean a new one will be created. An existing atlas may still surffice.
+          mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH,
+                                         DEFAULT_ATLAS_HEIGHT,
+                                         blockSize.mNeededBlockWidth,
+                                         blockSize.mNeededBlockHeight );
+
+          // Locate a new slot for our glyph
+          mGlyphManager.Add( glyph, outline, bitmap, slot ); // slot will be 0 is glyph not added
+        }
+      }
+    }
+    else
+    {
+      // We have 2+ copies of the same glyph
+      mGlyphManager.AdjustReferenceCount( glyph.fontId, glyph.index, outline, 1 ); //increment
+    }
+  }
+
+  void GenerateMesh( const GlyphInfo& glyph,
+                     const Vector2& position,
+                     const Vector4& color,
+                     uint32_t outline,
+                     AtlasManager::AtlasSlot& slot,
+                     bool underlineGlyph,
+                     float currentUnderlinePosition,
+                     float currentUnderlineThickness,
+                     std::vector<MeshRecord>& meshContainer,
+                     Vector<TextCacheEntry>& newTextCache,
+                     Vector<Extent>& extents )
+  {
+    // Generate mesh data for this quad, plugging in our supplied position
+    AtlasManager::Mesh2D newMesh;
+    mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh );
+
+    TextCacheEntry textCacheEntry;
+    textCacheEntry.mFontId = glyph.fontId;
+    textCacheEntry.mImageId = slot.mImageId;
+    textCacheEntry.mIndex = glyph.index;
+    textCacheEntry.mOutlineWidth = outline;
+
+    newTextCache.PushBack( textCacheEntry );
+
+    AtlasManager::Vertex2D* verticesBuffer = newMesh.mVertices.Begin();
+
+    for( unsigned int index = 0u, size = newMesh.mVertices.Count();
+         index < size;
+         ++index )
+    {
+      AtlasManager::Vertex2D& vertex = *( verticesBuffer + index );
+
+      // Set the color of the vertex.
+      vertex.mColor = color;
+    }
+
+    // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas)
+    StitchTextMesh( meshContainer,
+                    newMesh,
+                    extents,
+                    position.y + glyph.yBearing,
+                    underlineGlyph,
+                    currentUnderlinePosition,
+                    currentUnderlineThickness,
+                    slot );
+  }
+
+  void CreateActors( const std::vector<MeshRecord>& meshContainer,
+                     const Size& textSize,
+                     const Vector4& color,
+                     const Vector4& shadowColor,
+                     const Vector2& shadowOffset,
+                     Actor textControl,
+                     Property::Index animatablePropertyIndex,
+                     bool drawShadow )
+  {
+    if( !mActor )
+    {
+      // Create a container actor to act as a common parent for text and shadow, to avoid color inheritence issues.
+      mActor = Actor::New();
+      mActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+      mActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+      mActor.SetSize( textSize );
+      mActor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
+    }
+
+    for( std::vector< MeshRecord >::const_iterator it = meshContainer.begin(),
+           endIt = meshContainer.end();
+         it != endIt; ++it )
+    {
+      const MeshRecord& meshRecord = *it;
+
+      Actor actor = CreateMeshActor( textControl, animatablePropertyIndex, color, meshRecord, textSize, STYLE_NORMAL );
+
+      // Whether the actor has renderers.
+      const bool hasRenderer = actor.GetRendererCount() > 0u;
+
+      // Create an effect if necessary
+      if( hasRenderer &&
+          drawShadow )
+      {
+        // Change the color of the vertices.
+        for( Vector<AtlasManager::Vertex2D>::Iterator vIt =  meshRecord.mMesh.mVertices.Begin(),
+               vEndIt = meshRecord.mMesh.mVertices.End();
+             vIt != vEndIt;
+             ++vIt )
+        {
+          AtlasManager::Vertex2D& vertex = *vIt;
+
+          vertex.mColor = shadowColor;
+        }
+
+        Actor shadowActor = CreateMeshActor(textControl, animatablePropertyIndex, color, meshRecord, textSize, STYLE_DROP_SHADOW );
+#if defined(DEBUG_ENABLED)
+        shadowActor.SetName( "Text Shadow renderable actor" );
+#endif
+        // Offset shadow in x and y
+        shadowActor.RegisterProperty("uOffset", shadowOffset );
+        Dali::Renderer renderer( shadowActor.GetRendererAt( 0 ) );
+        int depthIndex = renderer.GetProperty<int>(Dali::Renderer::Property::DEPTH_INDEX);
+        renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex - 1 );
+        mActor.Add( shadowActor );
+      }
+
+      if( hasRenderer )
+      {
+        mActor.Add( actor );
+      }
+    }
+  }
+
   void AddGlyphs( Text::ViewInterface& view,
                   Actor textControl,
                   Property::Index animatablePropertyIndex,
@@ -223,18 +426,28 @@ struct AtlasRenderer::Impl
                   float minLineOffset )
   {
     AtlasManager::AtlasSlot slot;
+    slot.mImageId = 0u;
+    slot.mAtlasId = 0u;
+
+    AtlasManager::AtlasSlot slotOutline;
+    slotOutline.mImageId = 0u;
+    slotOutline.mAtlasId = 0u;
+
     std::vector< MeshRecord > meshContainer;
+    std::vector< MeshRecord > meshContainerOutline;
     Vector< Extent > extents;
-    TextCacheEntry textCacheEntry;
     mDepth = depth;
 
     const Vector2& textSize( view.GetLayoutSize() );
     const Vector2 halfTextSize( textSize * 0.5f );
     const Vector2& shadowOffset( view.GetShadowOffset() );
     const Vector4& shadowColor( view.GetShadowColor() );
-    const bool underlineEnabled( view.IsUnderlineEnabled() );
+    const bool underlineEnabled = view.IsUnderlineEnabled();
     const Vector4& underlineColor( view.GetUnderlineColor() );
-    const float underlineHeight( view.GetUnderlineHeight() );
+    const float underlineHeight = view.GetUnderlineHeight();
+    const unsigned int outlineWidth = view.GetOutlineWidth();
+    const Vector4& outlineColor( view.GetOutlineColor() );
+    const bool isOutline = 0u != outlineWidth;
 
     const bool useDefaultColor = ( NULL == colorsBuffer );
 
@@ -250,7 +463,6 @@ struct AtlasRenderer::Impl
 
     float currentUnderlinePosition = ZERO;
     float currentUnderlineThickness = underlineHeight;
-    uint32_t currentBlockSize = 0;
     FontId lastFontId = 0;
     FontId lastUnderlinedFontId = 0;
     Style style = STYLE_NORMAL;
@@ -271,14 +483,14 @@ struct AtlasRenderer::Impl
     for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i )
     {
       const GlyphInfo& glyph = *( glyphsBuffer + i );
-      const bool underlineGlyph = underlineEnabled || IsGlyphUnderlined( i, underlineRuns );
-      thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph;
+      const bool isGlyphUnderlined = underlineEnabled || IsGlyphUnderlined( i, underlineRuns );
+      thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || isGlyphUnderlined;
 
       // No operation for white space
       if( glyph.width && glyph.height )
       {
         // Are we still using the same fontId as previous
-        if( underlineGlyph && ( glyph.fontId != lastUnderlinedFontId ) )
+        if( isGlyphUnderlined && ( glyph.fontId != lastUnderlinedFontId ) )
         {
           // We need to fetch fresh font underline metrics
           FontMetrics fontMetrics;
@@ -316,85 +528,13 @@ struct AtlasRenderer::Impl
           lastUnderlinedFontId = glyph.fontId;
         } // underline
 
-        bool glyphNotCached = !mGlyphManager.IsCached( glyph.fontId, glyph.index, slot );  // Check FontGlyphRecord vector for entry with glyph index and fontId
-
-        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "AddGlyphs fontID[%u] glyphIndex[%u] [%s]\n", glyph.fontId, glyph.index, (glyphNotCached)?"not cached":"cached" );
+        // Retrieves and caches the glyph's bitmap.
+        CacheGlyph( glyph, lastFontId, NO_OUTLINE, slot );
 
-        if( glyphNotCached )
+        // Retrieves and caches the outline glyph's bitmap.
+        if( isOutline )
         {
-          MaxBlockSize& blockSize = mBlockSizes[currentBlockSize];
-
-          if ( lastFontId != glyph.fontId )
-          {
-            uint32_t index = 0u;
-            // Looks through all stored block sizes until finds the one which mataches required glyph font it.  Ensures new atlas block size will match existing for same font id.
-            // CalculateBlocksSize() above ensures a block size entry exists.
-            for( std::vector<MaxBlockSize>::const_iterator it = mBlockSizes.begin(),
-                   endIt = mBlockSizes.end();
-                 it != endIt;
-                 ++it, ++index )
-            {
-              const MaxBlockSize& blockSizeEntry = *it;
-              if( blockSizeEntry.mFontId == glyph.fontId )
-              {
-                blockSize = mBlockSizes[index];
-              }
-            }
-          }
-
-          // Create a new image for the glyph
-          PixelData bitmap;
-
-          // Whether the current glyph is a color one.
-          const bool isColorGlyph = mFontClient.IsColorGlyph( glyph.fontId, glyph.index );
-
-          // Retrieve the emoji's bitmap.
-          TextAbstraction::FontClient::GlyphBufferData glyphBufferData;
-          glyphBufferData.width = isColorGlyph ? glyph.width : 0;   // Desired width and height.
-          glyphBufferData.height = isColorGlyph ? glyph.height : 0;
-
-          mFontClient.CreateBitmap( glyph.fontId,
-                                    glyph.index,
-                                    glyphBufferData,
-                                    NO_OUTLINE );
-
-          // Create the pixel data.
-          bitmap = PixelData::New( glyphBufferData.buffer,
-                                   glyph.width * glyph.height * GetBytesPerPixel( glyphBufferData.format ),
-                                   glyph.width,
-                                   glyph.height,
-                                   glyphBufferData.format,
-                                   PixelData::DELETE_ARRAY );
-
-          if( bitmap )
-          {
-            // Ensure that the next image will fit into the current block size
-            if( bitmap.GetWidth() > blockSize.mNeededBlockWidth )
-            {
-              blockSize.mNeededBlockWidth = bitmap.GetWidth();
-            }
-
-            if( bitmap.GetHeight() > blockSize.mNeededBlockHeight )
-            {
-              blockSize.mNeededBlockHeight = bitmap.GetHeight();
-            }
-
-            // If CheckAtlas in AtlasManager::Add can't fit the bitmap in the current atlas it will create a new atlas
-
-            // Setting the block size and size of new atlas does not mean a new one will be created. An existing atlas may still surffice.
-            mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH,
-                                           DEFAULT_ATLAS_HEIGHT,
-                                           blockSize.mNeededBlockWidth,
-                                           blockSize.mNeededBlockHeight );
-
-            // Locate a new slot for our glyph
-            mGlyphManager.Add( glyph, bitmap, slot ); // slot will be 0 is glyph not added
-          }
-        }
-        else
-        {
-          // We have 2+ copies of the same glyph
-          mGlyphManager.AdjustReferenceCount( glyph.fontId, glyph.index, 1/*increment*/ );
+          CacheGlyph( glyph, lastFontId, outlineWidth, slotOutline );
         }
 
         // Move the origin (0,0) of the mesh to the center of the actor
@@ -402,42 +542,47 @@ struct AtlasRenderer::Impl
 
         if ( 0u != slot.mImageId ) // invalid slot id, glyph has failed to be added to atlas
         {
-          // Generate mesh data for this quad, plugging in our supplied position
-          AtlasManager::Mesh2D newMesh;
-          mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh );
-          textCacheEntry.mFontId = glyph.fontId;
-          textCacheEntry.mImageId = slot.mImageId;
-          textCacheEntry.mIndex = glyph.index;
-          newTextCache.PushBack( textCacheEntry );
-
-          AtlasManager::Vertex2D* verticesBuffer = newMesh.mVertices.Begin();
+          Vector2 positionPlusOutlineOffset = position;
+          if( isOutline )
+          {
+            // Add an offset to the text.
+            const float outlineWidthOffset = static_cast<float>( outlineWidth );
+            positionPlusOutlineOffset += Vector2( outlineWidthOffset, outlineWidthOffset );
+          }
 
           // Get the color of the character.
           const ColorIndex colorIndex = useDefaultColor ? 0u : *( colorIndicesBuffer + i );
           const Vector4& color = ( useDefaultColor || ( 0u == colorIndex ) ) ? defaultColor : *( colorsBuffer + colorIndex - 1u );
 
-          for( unsigned int index = 0u, size = newMesh.mVertices.Count();
-               index < size;
-               ++index )
-          {
-            AtlasManager::Vertex2D& vertex = *( verticesBuffer + index );
-
-            // Set the color of the vertex.
-            vertex.mColor = color;
-          }
-
-          // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas)
-          StitchTextMesh( meshContainer,
-                          newMesh,
-                          extents,
-                          position.y + glyph.yBearing,
-                          underlineGlyph,
-                          currentUnderlinePosition,
-                          currentUnderlineThickness,
-                          slot );
+          GenerateMesh( glyph,
+                        positionPlusOutlineOffset,
+                        color,
+                        NO_OUTLINE,
+                        slot,
+                        isGlyphUnderlined,
+                        currentUnderlinePosition,
+                        currentUnderlineThickness,
+                        meshContainer,
+                        newTextCache,
+                        extents);
 
           lastFontId = glyph.fontId; // Prevents searching for existing blocksizes when string of the same fontId.
         }
+
+        if( isOutline && ( 0u != slotOutline.mImageId ) ) // invalid slot id, glyph has failed to be added to atlas
+        {
+          GenerateMesh( glyph,
+                        position,
+                        outlineColor,
+                        outlineWidth,
+                        slotOutline,
+                        false,
+                        currentUnderlinePosition,
+                        currentUnderlineThickness,
+                        meshContainerOutline,
+                        newTextCache,
+                        extents);
+        }
       }
     } // glyphs
 
@@ -452,62 +597,36 @@ struct AtlasRenderer::Impl
     }
 
     // For each MeshData object, create a mesh actor and add to the renderable actor
-    if( !meshContainer.empty() )
+    bool isShadowDrawn = false;
+    if( !meshContainerOutline.empty() )
     {
-      if( !mActor )
-      {
-        // Create a container actor to act as a common parent for text and shadow, to avoid color inheritence issues.
-        mActor = Actor::New();
-        mActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
-        mActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
-        mActor.SetSize( textSize );
-        mActor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
-      }
-
-      for( std::vector< MeshRecord >::iterator it = meshContainer.begin(),
-              endIt = meshContainer.end();
-            it != endIt; ++it )
-      {
-        MeshRecord& meshRecord = *it;
-
-        Actor actor = CreateMeshActor( textControl, animatablePropertyIndex, defaultColor, meshRecord, textSize, STYLE_NORMAL );
-
-        // Whether the actor has renderers.
-        const bool hasRenderer = actor.GetRendererCount() > 0u;
-
-        // Create an effect if necessary
-        if( hasRenderer &&
-            ( style == STYLE_DROP_SHADOW ) )
-        {
-          // Change the color of the vertices.
-          for( Vector<AtlasManager::Vertex2D>::Iterator vIt =  meshRecord.mMesh.mVertices.Begin(),
-                 vEndIt = meshRecord.mMesh.mVertices.End();
-               vIt != vEndIt;
-               ++vIt )
-          {
-            AtlasManager::Vertex2D& vertex = *vIt;
-
-            vertex.mColor = shadowColor;
-          }
-
-          Actor shadowActor = CreateMeshActor(textControl, animatablePropertyIndex, defaultColor, meshRecord, textSize, STYLE_DROP_SHADOW );
-#if defined(DEBUG_ENABLED)
-          shadowActor.SetName( "Text Shadow renderable actor" );
-#endif
-          // Offset shadow in x and y
-          shadowActor.RegisterProperty("uOffset", shadowOffset );
-          Dali::Renderer renderer( shadowActor.GetRendererAt( 0 ) );
-          int depthIndex = renderer.GetProperty<int>(Dali::Renderer::Property::DEPTH_INDEX);
-          renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex - 1 );
-          mActor.Add( shadowActor );
-        }
+      const bool drawShadow = STYLE_DROP_SHADOW == style;
+      CreateActors( meshContainerOutline,
+                    textSize,
+                    outlineColor,
+                    shadowColor,
+                    shadowOffset,
+                    textControl,
+                    animatablePropertyIndex,
+                    drawShadow );
+
+      isShadowDrawn = drawShadow;
+    }
 
-        if( hasRenderer )
-        {
-          mActor.Add( actor );
-        }
-      }
+    // For each MeshData object, create a mesh actor and add to the renderable actor
+    if( !meshContainer.empty() )
+    {
+      const bool drawShadow = !isShadowDrawn && ( STYLE_DROP_SHADOW == style );
+      CreateActors( meshContainer,
+                    textSize,
+                    defaultColor,
+                    shadowColor,
+                    shadowOffset,
+                    textControl,
+                    animatablePropertyIndex,
+                    drawShadow );
     }
+
 #if defined(DEBUG_ENABLED)
     Toolkit::AtlasGlyphManager::Metrics metrics = mGlyphManager.GetMetrics();
     DALI_LOG_INFO( gLogFilter, Debug::General, "TextAtlasRenderer::GlyphManager::GlyphCount: %i, AtlasCount: %i, TextureMemoryUse: %iK\n",
@@ -536,7 +655,7 @@ struct AtlasRenderer::Impl
   {
     for( Vector< TextCacheEntry >::Iterator oldTextIter = mTextCache.Begin(); oldTextIter != mTextCache.End(); ++oldTextIter )
     {
-      mGlyphManager.AdjustReferenceCount( oldTextIter->mFontId, oldTextIter->mIndex, -1/*decrement*/ );
+      mGlyphManager.AdjustReferenceCount( oldTextIter->mFontId, oldTextIter->mIndex, oldTextIter->mOutlineWidth, -1/*decrement*/ );
     }
     mTextCache.Resize( 0 );
   }
@@ -611,6 +730,7 @@ struct AtlasRenderer::Impl
     actor.SetSize( actorSize );
     actor.RegisterProperty("uOffset", Vector2::ZERO );
     actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
+
     return actor;
   }
 
index 874503d..e2b482f 100644 (file)
@@ -888,7 +888,7 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
       TextAbstraction::FontDescription defaultFontDescription;
       TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
 
-      if( IsShowingPlaceholderText() && ( NULL != mEventData->mPlaceholderFont ) )
+      if( IsShowingPlaceholderText() && mEventData && ( NULL != mEventData->mPlaceholderFont ) )
       {
         // If the placeholder font is set specifically, only placeholder font is changed.
         defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription;
@@ -1144,7 +1144,7 @@ float Controller::Impl::GetDefaultFontLineHeight()
 
 void Controller::Impl::OnCursorKeyEvent( const Event& event )
 {
-  if( NULL == mEventData )
+  if( NULL == mEventData || !IsShowingRealText() )
   {
     // Nothing to do if there is no text input.
     return;
@@ -2291,7 +2291,7 @@ void Controller::Impl::RepositionSelectionHandles()
   const SelectionBoxInfo& firstSelectionBoxLineInfo = *( selectionBoxLinesInfo.Begin() );
   highLightPosition.y = firstSelectionBoxLineInfo.lineOffset;
 
-  mEventData->mDecorator->SetHighLightBox( highLightPosition, highLightSize );
+  mEventData->mDecorator->SetHighLightBox( highLightPosition, highLightSize, static_cast<float>( mModel->GetOutlineWidth() ) );
 
   if( !mEventData->mDecorator->IsSmoothHandlePanEnabled() )
   {
@@ -2711,6 +2711,13 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
   Text::GetCursorPosition( parameters,
                            cursorInfo );
 
+  // Adds Outline offset.
+  const float outlineWidth = static_cast<float>( mModel->GetOutlineWidth() );
+  cursorInfo.primaryPosition.x += outlineWidth;
+  cursorInfo.primaryPosition.y += outlineWidth;
+  cursorInfo.secondaryPosition.x += outlineWidth;
+  cursorInfo.secondaryPosition.y += outlineWidth;
+
   if( isMultiLine )
   {
     // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control.
index d054cbc..7a31d72 100755 (executable)
@@ -1182,14 +1182,14 @@ const Vector4& Controller::GetOutlineColor() const
   return mImpl->mModel->mVisualModel->GetOutlineColor();
 }
 
-void Controller::SetOutlineWidth( float width )
+void Controller::SetOutlineWidth( unsigned int width )
 {
   mImpl->mModel->mVisualModel->SetOutlineWidth( width );
 
   mImpl->RequestRelayout();
 }
 
-float Controller::GetOutlineWidth() const
+unsigned int Controller::GetOutlineWidth() const
 {
   return mImpl->mModel->mVisualModel->GetOutlineWidth();
 }
@@ -2105,8 +2105,15 @@ void Controller::GetPlaceholderProperty( Property::Map& map )
 
 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
 {
-  const LineRun* const firstline = mImpl->mModel->mVisualModel->mLines.Begin();
-  if ( firstline && firstline->direction )
+  if( ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) )
+  {
+    return Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
+  }
+
+  const Character character = mImpl->mModel->mLogicalModel->mText[0];
+  Script script = TextAbstraction::GetCharacterScript( character );
+
+  if( TextAbstraction::IsRightToLeftScript( script ) )
   {
     return Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT;
   }
@@ -2737,7 +2744,17 @@ ImfManager::ImfCallbackData Controller::OnImfEvent( ImfManager& imfManager, cons
 
   if( retrieveText )
   {
-    mImpl->GetText( numberOfWhiteSpaces, text );
+    if( !mImpl->IsShowingPlaceholderText() )
+    {
+      // Retrieves the normal text string.
+      mImpl->GetText( numberOfWhiteSpaces, text );
+    }
+    else
+    {
+      // When the current text is Placeholder Text, the surrounding text should be empty string.
+      // It means DALi should send empty string ("") to IME.
+      text = "";
+    }
   }
 
   ImfManager::ImfCallbackData callbackData( ( retrieveText || retrieveCursor ), cursorPosition, text, false );
@@ -3370,7 +3387,7 @@ bool Controller::DoRelayout( const Size& size,
     const Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mModel->mVisualModel->mGlyphsToCharacters;
     const Vector<Length>& charactersPerGlyph = mImpl->mModel->mVisualModel->mCharactersPerGlyph;
     const Character* const textBuffer = mImpl->mModel->mLogicalModel->mText.Begin();
-    float outlineWidth = mImpl->mModel->GetOutlineWidth();
+    const float outlineWidth = static_cast<float>( mImpl->mModel->GetOutlineWidth() );
 
     // Set the layout parameters.
     Layout::Parameters layoutParameters( size,
@@ -3697,7 +3714,7 @@ bool Controller::DeleteEvent( int keyCode )
                           1,
                           UPDATE_INPUT_STYLE );
   }
-  else if( ( mImpl->mEventData->mPrimaryCursorPosition >= 0 ) && ( keyCode == Dali::DevelKey::DALI_KEY_DELETE ) )
+  else if( keyCode == Dali::DevelKey::DALI_KEY_DELETE )
   {
     // Remove the character after the current cursor position
     removed = RemoveText( 0,
index 07d91be..88831db 100755 (executable)
@@ -834,14 +834,14 @@ public: // Default style & Input style
    *
    * @param[in] width The width in pixels of the outline, 0 indicates no outline
    */
-  void SetOutlineWidth( float width );
+  void SetOutlineWidth( unsigned int width );
 
   /**
    * @brief Retrieves the width of an outline
    *
    * @return The width of the outline.
    */
-  float GetOutlineWidth() const;
+  unsigned int GetOutlineWidth() const;
 
   /**
    * @brief Sets the emboss's properties string.
index 7c08ebe..d8d35de 100755 (executable)
@@ -125,26 +125,45 @@ bool ParseUnderlineProperties( const Property::Map& underlinePropertiesMap,
     if( ENABLE_KEY == valueGet.first.stringKey )
     {
       /// Enable key.
-      const std::string enableStr = valueGet.second.Get<std::string>();
-      enabled = Text::TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() );
+      if( valueGet.second.GetType() == Dali::Property::STRING )
+      {
+        const std::string enableStr = valueGet.second.Get<std::string>();
+        enabled = Text::TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() );
+      }
+      else
+      {
+        enabled = valueGet.second.Get<bool>();
+      }
     }
     else if( COLOR_KEY == valueGet.first.stringKey )
     {
       /// Color key.
       colorDefined = true;
 
-      const std::string colorStr = valueGet.second.Get<std::string>();
-
-      Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color );
+      if( valueGet.second.GetType() == Dali::Property::STRING )
+      {
+        const std::string colorStr = valueGet.second.Get<std::string>();
+        Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color );
+      }
+      else
+      {
+        color = valueGet.second.Get<Vector4>();
+      }
     }
     else if( HEIGHT_KEY == valueGet.first.stringKey )
     {
       /// Height key.
       heightDefined = true;
 
-      const std::string heightStr = valueGet.second.Get<std::string>();
-
-      height = StringToFloat( heightStr.c_str() );
+      if( valueGet.second.GetType() == Dali::Property::STRING )
+      {
+        const std::string heightStr = valueGet.second.Get<std::string>();
+        height = StringToFloat( heightStr.c_str() );
+      }
+      else
+      {
+        height = valueGet.second.Get<float>();
+      }
     }
   }
 
@@ -155,7 +174,7 @@ bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap,
                                bool& colorDefined,
                                Vector4& color,
                                bool& widthDefined,
-                               float& width )
+                               unsigned int& width )
 {
   const unsigned int numberOfItems = underlinePropertiesMap.Count();
 
@@ -174,7 +193,7 @@ bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap,
     {
       /// Width key.
       widthDefined = true;
-      width = valueGet.second.Get<float>();
+      width = static_cast<unsigned int>( valueGet.second.Get<float>() );
     }
   }
 
@@ -218,7 +237,7 @@ bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& va
                                               heightDefined,
                                               height );
 
-            controller->UnderlineSetByString( !empty);
+            controller->UnderlineSetByString( !empty );
           }
         }
         else
@@ -546,7 +565,7 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu
         bool colorDefined = false;
         Vector4 color;
         bool widthDefined = false;
-        float width = 0.f;
+        unsigned int width = 0u;
 
         bool empty = true;
 
@@ -581,7 +600,7 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu
             update = true;
           }
 
-          if( widthDefined && ( fabsf( controller->GetOutlineWidth() - width ) > Math::MACHINE_EPSILON_1000 ) )
+          if( widthDefined && ( controller->GetOutlineWidth() != width ) )
           {
             controller->SetOutlineWidth( width );
             update = true;
@@ -590,9 +609,9 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu
         else
         {
           // Disable outline
-          if( fabsf( controller->GetOutlineWidth() ) > Math::MACHINE_EPSILON_1000 )
+          if( 0u != controller->GetOutlineWidth() )
           {
-            controller->SetOutlineWidth( 0.0f );
+            controller->SetOutlineWidth( 0u );
             update = true;
           }
         }
@@ -627,17 +646,11 @@ void GetOutlineProperties( ControllerPtr controller, Property::Value& value, Eff
         else
         {
           const Vector4& color = controller->GetOutlineColor();
-          const float width = controller->GetOutlineWidth();
+          const unsigned int width = controller->GetOutlineWidth();
 
           Property::Map map;
-
-          std::string colorStr;
-          Vector4ToColorString( color, colorStr );
-          map.Insert( COLOR_KEY, colorStr );
-
-          std::string widthStr;
-          FloatToString( width, widthStr );
-          map.Insert( WIDTH_KEY, widthStr );
+          map.Insert( COLOR_KEY, color );
+          map.Insert( WIDTH_KEY, static_cast<int>( width ) );
 
           value = map;
 
index 521f52c..e2b0f0c 100755 (executable)
@@ -84,7 +84,7 @@ bool ParseOutlineProperties( const Property::Map& outlineProperties,
                                bool& colorDefined,
                                Vector4& color,
                                bool& widthDefined,
-                               float& width );
+                               unsigned int& width );
 
 /**
  * @brief Sets the underline properties.
index efa88ad..96f9005 100644 (file)
@@ -172,6 +172,21 @@ public:
   virtual void GetUnderlineRuns( GlyphRun* underlineRuns,
                                  UnderlineRunIndex index,
                                  Length numberOfRuns ) const = 0;
+
+  /**
+   * @brief Retrieve the outline color.
+   *
+   * @return The outline color.
+   */
+  virtual const Vector4& GetOutlineColor() const = 0;
+
+  /**
+   * @brief Retrieves the width of an outline
+   *
+   * @return The width of the outline.
+   */
+  virtual unsigned int GetOutlineWidth() const = 0;
+
 };
 
 } // namespace Text
index 9e8d0be..62c0008 100644 (file)
@@ -402,6 +402,24 @@ void View::GetUnderlineRuns( GlyphRun* underlineRuns,
   }
 }
 
+const Vector4& View::GetOutlineColor() const
+{
+  if( mImpl->mVisualModel )
+  {
+    return mImpl->mVisualModel->GetOutlineColor();
+  }
+  return Vector4::ZERO;
+}
+
+unsigned int View::GetOutlineWidth() const
+{
+  if( mImpl->mVisualModel )
+  {
+    return mImpl->mVisualModel->GetOutlineWidth();
+  }
+  return 0u;
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index d494d2b..51426de 100644 (file)
@@ -131,6 +131,16 @@ public:
                                  UnderlineRunIndex index,
                                  Length numberOfRuns ) const;
 
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineColor()
+   */
+  virtual const Vector4& GetOutlineColor() const;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineWidth()
+   */
+  virtual unsigned int GetOutlineWidth() const;
+
 private:
 
   // Undefined
index 9caa523..5373a6a 100755 (executable)
@@ -370,7 +370,7 @@ void VisualModel::SetUnderlineHeight( float height )
   mUnderlineHeight = height;
 }
 
-void VisualModel::SetOutlineWidth( float width )
+void VisualModel::SetOutlineWidth( unsigned int width )
 {
   mOutlineWidth = width;
 }
@@ -415,7 +415,7 @@ float VisualModel::GetUnderlineHeight() const
   return mUnderlineHeight;
 }
 
-float VisualModel::GetOutlineWidth() const
+unsigned int VisualModel::GetOutlineWidth() const
 {
   return mOutlineWidth;
 }
@@ -449,7 +449,7 @@ VisualModel::VisualModel()
   mControlSize(),
   mShadowOffset(),
   mUnderlineHeight( 0.0f ),
-  mOutlineWidth( 0.0f ),
+  mOutlineWidth( 0u ),
   mShadowBlurRadius( 0.0f ),
   mNaturalSize(),
   mLayoutSize(),
index 28d2269..24be0c7 100755 (executable)
@@ -320,14 +320,14 @@ public:
    *
    * @param[in] width The width in pixels of the outline, 0 indicates no outline
    */
-  void SetOutlineWidth( float width );
+  void SetOutlineWidth( unsigned int width );
 
   /**
    * @brief Retrieves the width of an outline
    *
    * @return The width of the outline.
    */
-  float GetOutlineWidth() const;
+  unsigned int GetOutlineWidth() const;
 
 protected:
 
@@ -369,7 +369,7 @@ public:
   Size                   mControlSize;          ///< The size of the UI control.
   Vector2                mShadowOffset;         ///< Offset for drop shadow, 0 indicates no shadow
   float                  mUnderlineHeight;      ///< Fixed height for underline to override font metrics.
-  float                  mOutlineWidth;         ///< Width of outline.
+  unsigned int           mOutlineWidth;         ///< Width of outline.
   float                  mShadowBlurRadius;     ///< Blur radius of shadow, 0 indicates no blur.
 
 private:
index f23f1ca..8bc050f 100644 (file)
@@ -79,10 +79,10 @@ std::size_t NPatchLoader::Load( const std::string& url, const Rect< int >& borde
     data->textureSet = mCache[ cachedIndex ]->textureSet;
 
     NinePatchImage::StretchRanges stretchRangesX;
-    stretchRangesX.PushBack( Uint16Pair( border.left, data->croppedWidth - border.right ) );
+    stretchRangesX.PushBack( Uint16Pair( border.left, ( (data->croppedWidth >= static_cast< unsigned int >( border.right )) ? data->croppedWidth - border.right : 0 ) ) );
 
     NinePatchImage::StretchRanges stretchRangesY;
-    stretchRangesY.PushBack( Uint16Pair( border.top, data->croppedHeight - border.bottom ) );
+    stretchRangesY.PushBack( Uint16Pair( border.top, ( (data->croppedHeight >= static_cast< unsigned int >( border.bottom )) ? data->croppedHeight - border.bottom : 0 ) ) );
 
     data->stretchPixelsX = stretchRangesX;
     data->stretchPixelsY = stretchRangesY;
@@ -137,10 +137,10 @@ std::size_t NPatchLoader::Load( const std::string& url, const Rect< int >& borde
       data->textureSet.SetTexture( 0u, texture );
 
       NinePatchImage::StretchRanges stretchRangesX;
-      stretchRangesX.PushBack( Uint16Pair( border.left, data->croppedWidth - border.right ) );
+      stretchRangesX.PushBack( Uint16Pair( border.left, ( (data->croppedWidth >= static_cast< unsigned int >( border.right )) ? data->croppedWidth - border.right : 0 ) ) );
 
       NinePatchImage::StretchRanges stretchRangesY;
-      stretchRangesY.PushBack( Uint16Pair( border.top, data->croppedHeight - border.bottom ) );
+      stretchRangesY.PushBack( Uint16Pair( border.top, ( (data->croppedHeight >= static_cast< unsigned int >( border.bottom )) ? data->croppedHeight - border.bottom : 0 ) ) );
 
       data->stretchPixelsX = stretchRangesX;
       data->stretchPixelsY = stretchRangesY;
index 33a4842..f61848c 100755 (executable)
@@ -56,6 +56,7 @@ const char * const AUXILIARY_IMAGE_ALPHA_NAME( "auxiliaryImageAlpha" );
 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
   attribute mediump vec2 aPosition;\n
   varying mediump vec2 vTexCoord;\n
+  varying mediump vec2 vMaskTexCoord;\n
   uniform mediump mat4 uMvpMatrix;\n
   uniform mediump vec3 uSize;\n
   uniform mediump vec2 uNinePatchFactorsX[ FACTOR_SIZE_X ];\n
@@ -83,7 +84,7 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
     mediump vec4 gridPosition = vec4( fixedFactor + ( visualSize.xy - fixedTotal ) * stretch / stretchTotal, 0.0, 1.0 );\n
     mediump vec4 vertexPosition = gridPosition;\n
     vertexPosition.xy -= visualSize.xy * vec2( 0.5, 0.5 );\n
-    vertexPostion.xy += anchorPoint*visualSize + (visualOffset + origin)*uSize.xy;\n
+    vertexPosition.xy += anchorPoint*visualSize + (visualOffset + origin)*uSize.xy;\n
     vertexPosition = uMvpMatrix * vertexPosition;\n
     \n
     vTexCoord = ( fixedFactor + stretch ) / ( fixedTotal + stretchTotal );\n
@@ -569,8 +570,8 @@ void NPatchVisual::ApplyTextureAndUniforms()
       Uint16Pair stretchX = data->stretchPixelsX[ 0 ];
       Uint16Pair stretchY = data->stretchPixelsY[ 0 ];
 
-      uint16_t stretchWidth = stretchX.GetY() - stretchX.GetX();
-      uint16_t stretchHeight = stretchY.GetY() - stretchY.GetX();
+      uint16_t stretchWidth = ( stretchX.GetY() >= stretchX.GetX() ) ? stretchX.GetY() - stretchX.GetX() : 0;
+      uint16_t stretchHeight = ( stretchY.GetY() >= stretchY.GetX() ) ? stretchY.GetY() - stretchY.GetX() : 0;
 
       mImpl->mRenderer.RegisterProperty( "uFixed[0]", Vector2::ZERO );
       mImpl->mRenderer.RegisterProperty( "uFixed[1]", Vector2( stretchX.GetX(), stretchY.GetX()) );
index f5817ea..e44b005 100755 (executable)
@@ -24,6 +24,7 @@
 
 // INTERNAL HEADER
 #include <dali-toolkit/public-api/visuals/text-visual-properties.h>
+#include <dali-toolkit/devel-api/visuals/text-visual-properties-devel.h>
 #include <dali-toolkit/public-api/visuals/visual-properties.h>
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
@@ -58,6 +59,7 @@ const char * const TEXT_COLOR_PROPERTY( "textColor" );
 const char * const ENABLE_MARKUP_PROPERTY( "enableMarkup" );
 const char * const SHADOW_PROPERTY( "shadow" );
 const char * const UNDERLINE_PROPERTY( "underline" );
+const char * const OUTLINE_PROPERTY( "outline" );
 
 const Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
 
@@ -328,6 +330,10 @@ Dali::Property::Index StringKeyToIndexKey( const std::string& stringKey )
   {
     result = Toolkit::TextVisual::Property::UNDERLINE;
   }
+  else if( stringKey == OUTLINE_PROPERTY )
+  {
+    result = Toolkit::DevelTextVisual::Property::OUTLINE;
+  }
 
   return result;
 }
@@ -405,6 +411,9 @@ void TextVisual::DoCreatePropertyMap( Property::Map& map ) const
 
   GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT );
   map.Insert( Toolkit::TextVisual::Property::UNDERLINE, value );
+
+  GetOutlineProperties( mController, value, Text::EffectStyle::DEFAULT );
+  map.Insert( Toolkit::DevelTextVisual::Property::OUTLINE, value );
 }
 
 void TextVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
@@ -593,6 +602,11 @@ void TextVisual::DoSetProperty( Dali::Property::Index index, const Dali::Propert
       SetUnderlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT );
       break;
     }
+    case Toolkit::DevelTextVisual::Property::OUTLINE:
+    {
+      SetOutlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT );
+      break;
+    }
   }
 }
 
index b2e0d03..11d3b0f 100644 (file)
@@ -47,8 +47,10 @@ size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue)
 {
   using Dali::EnvironmentVariable::GetEnvironmentVariable;
   auto numberString = GetEnvironmentVariable(environmentVariable);
-  auto numberOfThreads = numberString ? std::strtol(numberString, nullptr, 10) : 0;
-  return (numberOfThreads > 0) ? numberOfThreads : defaultValue;
+  auto numberOfThreads = numberString ? std::strtoul(numberString, nullptr, 10) : 0;
+  constexpr auto MAX_NUMBER_OF_THREADS = 100u;
+  DALI_ASSERT_DEBUG( numberOfThreads < MAX_NUMBER_OF_THREADS );
+  return ( numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS ) ? numberOfThreads : defaultValue;
 }
 
 size_t GetNumberOfLocalLoaderThreads()
index ac2befa..7c99a5f 100644 (file)
@@ -48,7 +48,7 @@ class ImageView;
  * ResouceReadySignal is done after the resource is set then signal will be missed.
  *
  * To protect against this, IsResourceReady() can be checked before connecting to ResourceReadySignal,
- * or the signal connection can be done before setting the resource"
+ * or the signal connection can be done before setting the resource.
  *
  * @code
  *    auto myImageView = ImageView::New( resourceUrl );
index fdda010..f633f45 100644 (file)
@@ -301,9 +301,7 @@ public:
       INPUT_LINE_SPACING,
 
       /**
-       * @brief The default underline parameters.
-       * @details Name "underline", type Property::MAP.
-       * @SINCE_1_2.13
+       * @copydoc Dali::Toolkit::TextLabel::Property::UNDERLINE
        */
       UNDERLINE,
 
@@ -315,9 +313,7 @@ public:
       INPUT_UNDERLINE,
 
       /**
-       * @brief The default shadow parameters.
-       * @details Name "shadow", type Property::MAP.
-       * @SINCE_1_2.13
+       * @copydoc Dali::Toolkit::TextLabel::Property::SHADOW
        */
       SHADOW,
 
@@ -343,9 +339,7 @@ public:
       INPUT_EMBOSS,
 
       /**
-       * @brief The default outline parameters.
-       * @details Name "outline", type Property::MAP.
-       * @SINCE_1_2.13
+       * @copydoc Dali::Toolkit::TextLabel::Property::OUTLINE
        */
       OUTLINE,
 
index 0875753..5af78b2 100644 (file)
@@ -353,9 +353,7 @@ public:
       INPUT_POINT_SIZE,
 
       /**
-       * @brief The default underline parameters.
-       * @details Name "underline", type Property::MAP.
-       * @SINCE_1_2.13
+       * @copydoc Dali::Toolkit::TextLabel::Property::UNDERLINE
        */
       UNDERLINE,
 
@@ -367,9 +365,7 @@ public:
       INPUT_UNDERLINE,
 
       /**
-       * @brief The default shadow parameters.
-       * @details Name "shadow", type Property::MAP.
-       * @SINCE_1_2.13
+       * @copydoc Dali::Toolkit::TextLabel::Property::SHADOW
        */
       SHADOW,
 
@@ -395,9 +391,7 @@ public:
       INPUT_EMBOSS,
 
       /**
-       * @brief The default outline parameters.
-       * @details Name "outline", type Property::MAP.
-       * @SINCE_1_2.13
+       * @copydoc Dali::Toolkit::TextLabel::Property::OUTLINE
        */
       OUTLINE,
 
index ec6613c..106f234 100644 (file)
@@ -254,6 +254,15 @@ public:
       /**
        * @brief The default underline parameters.
        * @details Name "underline", type Property::MAP.
+       *
+       * The underline map contains the following keys:
+       *
+       * | %Property Name       | Type     | Required | Description                                                                                                        |
+       * |----------------------|----------|----------|--------------------------------------------------------------------------------------------------------------------|
+       * | enable               | BOOLEAN  | No       | True to enable the underline or false to disable (the default value is false)                                      |
+       * | color                | VECTOR4  | No       | The color of the underline (the default value is Color::BLACK)                                                     |
+       * | height               | FLOAT    | No       | The height of the underline (the default value is 0)                                                               |
+       *
        * @SINCE_1_2.13
        */
       UNDERLINE,
@@ -261,6 +270,15 @@ public:
       /**
        * @brief The default shadow parameters.
        * @details Name "shadow", type Property::MAP.
+       *
+       * The shadow map contains the following keys:
+       *
+       * | %Property Name       | Type     | Required | Description                                                                                                        |
+       * |----------------------|----------|----------|--------------------------------------------------------------------------------------------------------------------|
+       * | color                | VECTOR4  | No       | The color of the shadow (the default value is Color::BLACK)                                                        |
+       * | offset               | VECTOR2  | No       | The offset from the text to draw the shadow in the X and Y axes (the default value is 0 which means no shadow)     |
+       * | blurRadius           | FLOAT    | No       | The radius of blur to be applied to the shadow (the default value is 0 which means no blur)                        |
+       *
        * @SINCE_1_2.13
        */
       SHADOW,
@@ -275,6 +293,14 @@ public:
       /**
        * @brief The default outline parameters.
        * @details Name "outline", type Property::MAP.
+       *
+       * The outline map contains the following keys:
+       *
+       * | %Property Name       | Type     | Required | Description                                                                                                        |
+       * |----------------------|----------|----------|--------------------------------------------------------------------------------------------------------------------|
+       * | color                | VECTOR4  | No       | The color of the outline (the default value is Color::WHITE)                                                       |
+       * | width                | INTEGER  | No       | The width of the outline (the default value is 0 which means no outline)                                           |
+       *
        * @SINCE_1_2.13
        */
       OUTLINE,
index 6ed8280..d417fe7 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 3;
-const unsigned int TOOLKIT_MICRO_VERSION = 3;
+const unsigned int TOOLKIT_MICRO_VERSION = 4;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index b1b4cef..981b30a 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    1.3.3
+Version:    1.3.4
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT