Merge "Change MatchSystemLanguageDirection is true." into devel/master
authorjoogab yun <joogab.yun@samsung.com>
Thu, 24 Jun 2021 09:34:15 +0000 (09:34 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 24 Jun 2021 09:34:15 +0000 (09:34 +0000)
52 files changed:
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/utc-Dali-Fade.cpp [new file with mode: 0755]
automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp
dali-toolkit/devel-api/focus-manager/focus-finder.cpp
dali-toolkit/devel-api/focus-manager/focus-finder.h
dali-toolkit/devel-api/text/text-utils-devel.cpp
dali-toolkit/devel-api/visuals/visual-properties-devel.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/image-view/image-view-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/file.list
dali-toolkit/internal/focus-manager/focus-finder-impl.cpp [deleted file]
dali-toolkit/internal/focus-manager/focus-finder-impl.h [deleted file]
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/graphics/shaders/color-visual-shader.frag
dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag
dali-toolkit/internal/graphics/shaders/image-visual-shader.frag
dali-toolkit/internal/text/markup-processor-background.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor-background.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor.cpp
dali-toolkit/internal/text/markup-processor.h
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/rendering/view-model.cpp
dali-toolkit/internal/text/rendering/view-model.h
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-text-updater.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-model-interface.h
dali-toolkit/internal/text/text-model.cpp
dali-toolkit/internal/text/text-model.h
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/transition/fade-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/transition/fade-impl.h [new file with mode: 0644]
dali-toolkit/internal/transition/transition-base-impl.cpp
dali-toolkit/internal/transition/transition-base-impl.h
dali-toolkit/internal/transition/transition-impl.cpp
dali-toolkit/internal/transition/transition-impl.h
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/public-api/file.list
dali-toolkit/public-api/transition/fade.cpp [new file with mode: 0644]
dali-toolkit/public-api/transition/fade.h [new file with mode: 0644]
dali-toolkit/public-api/transition/transition-base.cpp
dali-toolkit/public-api/transition/transition-base.h
packaging/dali-toolkit.spec

index 918e9cc..6028e02 100755 (executable)
@@ -112,7 +112,8 @@ void CreateTextModel( const std::string& text,
                                        logicalModel->mFontDescriptionRuns,
                                        logicalModel->mEmbeddedItems,
                                        logicalModel->mAnchors,
-                                       logicalModel->mUnderlinedCharacterRuns);
+                                       logicalModel->mUnderlinedCharacterRuns,
+                                       logicalModel->mBackgroundColorRuns);
 
   Length textSize = 0u;
   const uint8_t* utf8 = NULL;
index f46c401..1a4b5e1 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -186,7 +186,8 @@ namespace
     Vector<EmbeddedItem> items;
     Vector<Anchor> anchors;
     Vector<UnderlinedCharacterRun> underlinedCharacterRuns;
-    MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors, underlinedCharacterRuns );
+    Vector<ColorRun> backgroundColorRuns;
+    MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns );
     ProcessMarkupString( data.xHTMLEntityString, markupProcessData );
 
     for( Vector<EmbeddedItem>::Iterator it = items.Begin(),
index b19d653..73d9e12 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -167,4 +167,35 @@ int UtcDaliTextEditorFontPointSizeLargerThanAtlasPlaceholderCase(void)
   DALI_TEST_EQUALS( countAtlas, 1, TEST_LOCATION );
 
   END_TEST;
+}
+
+int UtcDaliTextEditorBackgroundTag(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextEditorBackgroundTag\n");
+
+  TextEditor editor = TextEditor::New();
+  DALI_TEST_CHECK( editor );
+
+  editor.SetProperty( TextEditor ::Property::ENABLE_MARKUP,  true );
+  editor.SetProperty( TextEditor::Property::TEXT, "H<background color='red'>e</background> Worl<background color='yellow'>d</background>" );
+  application.GetScene().Add( editor );
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextEditor& editorImpl = GetImpl( editor );
+  const ColorIndex* const backgroundColorIndicesBuffer = editorImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+
+  DALI_TEST_CHECK( backgroundColorIndicesBuffer );
+
+  //default color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION);
+
+  //red color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION);
+
+  //yellow color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
index 619e5f4..73fe7e2 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -251,4 +251,35 @@ int UtcDaliTextFieldFontPointSizeLargerThanAtlasPlaceholderCase(void)
 
 
   END_TEST;
+}
+
+int UtcDaliTextFieldBackgroundTag(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextFieldBackgroundTag\n");
+
+  TextField field = TextField::New();
+  DALI_TEST_CHECK( field );
+
+  field.SetProperty( TextField ::Property::ENABLE_MARKUP,  true );
+  field.SetProperty( TextField::Property::TEXT, "H<background color='red'>e</background> Worl<background color='yellow'>d</background>" );
+  application.GetScene().Add( field );
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextField& fieldImpl = GetImpl( field );
+  const ColorIndex* const backgroundColorIndicesBuffer = fieldImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+
+  DALI_TEST_CHECK( backgroundColorIndicesBuffer );
+
+  //default color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION);
+
+  //red color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION);
+
+  //yellow color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
index e85ea21..f67d88a 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -66,4 +66,35 @@ int UtcDaliTextLabelMarkupUnderline(void)
 
   END_TEST;
 
+}
+
+int UtcDaliTextLabelBackgroundTag(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliTextLabelBackgroundTag\n");
+
+  TextLabel label = TextLabel::New();
+  DALI_TEST_CHECK( label );
+
+  label.SetProperty( TextLabel ::Property::ENABLE_MARKUP,  true );
+  label.SetProperty( TextLabel::Property::TEXT, "H<background color='red'>e</background> Worl<background color='yellow'>d</background>" );
+  application.GetScene().Add( label );
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextLabel& labelImpl = GetImpl( label );
+  const ColorIndex* const backgroundColorIndicesBuffer = labelImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+
+  DALI_TEST_CHECK( backgroundColorIndicesBuffer );
+
+  //default color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION);
+
+  //red color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION);
+
+  //yellow color
+  DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
index 2b73142..9b2691c 100755 (executable)
@@ -19,6 +19,7 @@ SET(TC_SOURCES
   utc-Dali-ConfirmationPopup.cpp
   utc-Dali-CubeTransitionEffect.cpp
   utc-Dali-EffectsView.cpp
+  utc-Dali-Fade.cpp
   utc-Dali-FlexContainer.cpp
   utc-Dali-FlexNode.cpp
   utc-Dali-GaussianBlurView.cpp
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Fade.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Fade.cpp
new file mode 100755 (executable)
index 0000000..8fc8fba
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2021 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/dali-toolkit.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
+#include <dali-toolkit/public-api/transition/transition-set.h>
+#include <dali-toolkit/public-api/transition/transition-base.h>
+#include <dali-toolkit/public-api/transition/fade.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+// Functor to test whether a Finish signal is emitted
+struct TransitionFinishCheck
+{
+  TransitionFinishCheck(bool& signalReceived)
+  : mSignalReceived(signalReceived)
+  {
+  }
+
+  void operator()(TransitionSet& transitionSet)
+  {
+    mSignalReceived = true;
+  }
+
+  void Reset()
+  {
+    mSignalReceived = false;
+  }
+
+  void CheckSignalReceived()
+  {
+    if(!mSignalReceived)
+    {
+      tet_printf("Expected Finish signal was not received\n");
+      tet_result(TET_FAIL);
+    }
+    else
+    {
+      tet_result(TET_PASS);
+    }
+  }
+
+  void CheckSignalNotReceived()
+  {
+    if(mSignalReceived)
+    {
+      tet_printf("Unexpected Finish signal was received\n");
+      tet_result(TET_FAIL);
+    }
+    else
+    {
+      tet_result(TET_PASS);
+    }
+  }
+
+  bool& mSignalReceived; // owned by individual tests
+};
+
+int UtcDaliFadeSetGetProperty(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliFadeSetGetProperty");
+
+  Control control = Control::New();
+
+  Fade fade = Fade::New(control, 0.5, TimePeriod(-0.5f, -0.5f));
+
+  TimePeriod timePeriod = fade.GetTimePeriod();
+  DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliFadeWithOffScene(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliFadeWithOffScene");
+
+  Control control = Control::New();
+  control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+  control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  control.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0));
+  control.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0));
+  control.SetProperty(Actor::Property::OPACITY, 1.0f);
+  Property::Map controlProperty;
+  controlProperty.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+  controlProperty.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  control.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty);
+
+  application.SendNotification();
+  application.Render(20);
+
+  DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  Fade fade = Fade::New(control, 0.5, TimePeriod(0.5f));
+  fade.SetAppearingTransition(false); // set fade out
+  TransitionSet transitionSet = TransitionSet::New();
+  transitionSet.AddTransition(fade);
+  transitionSet.Play();
+
+  bool signalReceived(false);
+  TransitionFinishCheck finishCheck(signalReceived);
+  transitionSet.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(400);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+  
+  application.SendNotification();
+  application.Render(200);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+
+  application.SendNotification();
+  application.Render(20);
+
+  DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliFadeOut(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliFadeOut");
+
+  Control control = Control::New();
+  control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+  control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  control.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0));
+  control.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0));
+  control.SetProperty(Actor::Property::OPACITY, 1.0f);
+  Property::Map controlProperty;
+  controlProperty.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+  controlProperty.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  control.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty);
+
+  application.GetScene().Add(control);
+
+  application.SendNotification();
+  application.Render(20);
+
+  DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  Fade fade = Fade::New(control, 0.5, TimePeriod(0.5f));
+  fade.SetAppearingTransition(false); // set fade out
+  TransitionSet transitionSet = TransitionSet::New();
+  transitionSet.AddTransition(fade);
+  transitionSet.Play();
+
+  bool signalReceived(false);
+  TransitionFinishCheck finishCheck(signalReceived);
+  transitionSet.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(400);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  float currentOpacity = control.GetCurrentProperty<float>(Actor::Property::OPACITY);
+  DALI_TEST_CHECK(currentOpacity <= 0.7 && currentOpacity >= 0.5);
+  
+  application.SendNotification();
+  application.Render(200);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+
+  application.SendNotification();
+  application.Render(20);
+
+  // Property is reset after animation.
+  DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliFadeIn(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliFadeIn");
+
+  Control control = Control::New();
+  control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+  control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  control.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0));
+  control.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0));
+  control.SetProperty(Actor::Property::OPACITY, 1.0f);
+  Property::Map controlProperty;
+  controlProperty.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+  controlProperty.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  control.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty);
+
+  application.GetScene().Add(control);
+
+  application.SendNotification();
+  application.Render(20);
+
+  DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  Fade fade = Fade::New(control, 0.5, TimePeriod(0.5f));
+  fade.SetAppearingTransition(true); // set fade in
+  TransitionSet transitionSet = TransitionSet::New();
+  transitionSet.AddTransition(fade);
+  transitionSet.Play();
+
+  bool signalReceived(false);
+  TransitionFinishCheck finishCheck(signalReceived);
+  transitionSet.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(400);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  float currentOpacity = control.GetCurrentProperty<float>(Actor::Property::OPACITY);
+  DALI_TEST_CHECK(currentOpacity <= 1.0 && currentOpacity >= 0.8);
+  
+  application.SendNotification();
+  application.Render(200);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+
+  application.SendNotification();
+  application.Render(20);
+
+  DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+  END_TEST;
+}
index 55de778..053b25c 100644 (file)
@@ -1643,22 +1643,22 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   PushButton button4 = PushButton::New();
   PushButton button5 = PushButton::New();
 
-  button1.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
-  button2.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
-  button3.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
-  button4.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
-  button5.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
-
-  button1.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
-  button2.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
-  button3.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
-  button4.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
-  button5.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
+  button1.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+  button2.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+  button3.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+  button4.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+  button5.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+
+  button1.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+  button2.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+  button3.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+  button4.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+  button5.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
 
   application.GetScene().Add(button1);
   application.GetScene().Add(button2);
   application.GetScene().Add(button3);
-  application.GetScene().Add(button4);
+  button5.Add(button4);
   application.GetScene().Add(button5);
 
   // set position
@@ -1666,11 +1666,11 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   //   |           |
   //   |    button5|
   // button3 -- button4
-  button1.SetProperty( Actor::Property::POSITION, Vector2(0.0f, 0.0f));
-  button2.SetProperty( Actor::Property::POSITION, Vector2(100.0f, 0.0f));
-  button3.SetProperty( Actor::Property::POSITION, Vector2(0.0f, 100.0f));
-  button4.SetProperty( Actor::Property::POSITION, Vector2(100.0f, 100.0f));
-  button5.SetProperty( Actor::Property::POSITION, Vector2(60.0f, 60.0f));
+  button1.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
+  button2.SetProperty(Actor::Property::POSITION, Vector2(100.0f, 0.0f));
+  button3.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 100.0f));
+  button4.SetProperty(Actor::Property::POSITION, Vector2(40.0f, 40.0f));
+  button5.SetProperty(Actor::Property::POSITION, Vector2(60.0f, 60.0f));
 
   // flush the queue and render once
   application.SendNotification();
@@ -1698,7 +1698,7 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
 
   // Confirm whether focus is moved to button2
-  DALI_TEST_EQUALS(button2.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+  DALI_TEST_EQUALS(button2.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button1);
   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button2);
@@ -1712,7 +1712,7 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::DOWN) == true);
 
   // Confirm whether focus is moved to button5
-  DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+  DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button2);
   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button5);
@@ -1726,7 +1726,7 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
 
   // Confirm whether focus is moved to button4
-  DALI_TEST_EQUALS(button4.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+  DALI_TEST_EQUALS(button4.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button5);
   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button4);
@@ -1740,7 +1740,7 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
 
   // Confirm whether focus is moved to button5
-  DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+  DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button4);
   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button5);
@@ -1754,7 +1754,35 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
 
   // Confirm whether focus is moved to button3
-  DALI_TEST_EQUALS(button3.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+  DALI_TEST_EQUALS(button3.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
+  DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button5);
+  DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button3);
+  focusChangedCallback.Reset();
+
+  // Move the focus towards right
+  // button1 -- button2
+  //   |           |
+  //   |  [button5]|
+  // button3 -- button4
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
+
+  // Confirm whether focus is moved to button5
+  DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
+  DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button3);
+  DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button5);
+  focusChangedCallback.Reset();
+
+  // Move the focus towards left
+  // button1 -- button2
+  //   |           |
+  //   |    button5|
+  //[button3] -- button4
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
+
+  // Confirm whether focus is moved to button3
+  DALI_TEST_EQUALS(button3.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button5);
   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button3);
@@ -1768,7 +1796,7 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::UP) == true);
 
   // Confirm whether focus is moved to button1
-  DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+  DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
   DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
   DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button3);
   DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
index d12ed11..952c261 100644 (file)
  *\r
  */\r
 \r
+/*\r
+ * Copyright (C) 2017 The Android Open Source Project\r
+ *\r
+ * Modified by joogab yun(joogab.yun@samsung.com)\r
+ */\r
+\r
 // CLASS HEADER\r
 #include "focus-finder.h"\r
 \r
 // EXTERNAL INCLUDES\r
-#include <dali/devel-api/common/singleton-service.h>\r
-\r
-// INTERNAL INCLUDES\r
-#include <dali-toolkit/internal/focus-manager/focus-finder-impl.h>\r
+#include <dali/devel-api/actors/actor-devel.h>\r
+#include <dali/integration-api/adaptor-framework/scene-holder.h>\r
+#include <dali/public-api/actors/layer.h>\r
 \r
 namespace Dali\r
 {\r
 namespace Toolkit\r
 {\r
-FocusFinder::FocusFinder()\r
+namespace FocusFinder\r
+{\r
+namespace\r
+{\r
+static int MajorAxisDistanceRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
+{\r
+  switch(direction)\r
+  {\r
+    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+    {\r
+      return source.left - dest.right;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+    {\r
+      return dest.left - source.right;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+    {\r
+      return source.top - dest.bottom;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+    {\r
+      return dest.top - source.bottom;\r
+    }\r
+    default:\r
+    {\r
+      return 0;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+ * @return The distance from the edge furthest in the given direction\r
+ *   of source to the edge nearest in the given direction of dest.\r
+ *   If the dest is not in the direction from source, return 0.\r
+ */\r
+static int MajorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
 {\r
+  return std::max(0, MajorAxisDistanceRaw(direction, source, dest));\r
 }\r
 \r
-FocusFinder::~FocusFinder()\r
+static int MajorAxisDistanceToFarEdgeRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
 {\r
+  switch(direction)\r
+  {\r
+    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+    {\r
+      return source.left - dest.left;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+    {\r
+      return dest.right - source.right;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+    {\r
+      return source.top - dest.top;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+    {\r
+      return dest.bottom - source.bottom;\r
+    }\r
+    default:\r
+    {\r
+      return 0;\r
+    }\r
+  }\r
 }\r
 \r
-FocusFinder FocusFinder::Get()\r
+/**\r
+ * @return The distance along the major axis w.r.t the direction from the\r
+ *   edge of source to the far edge of dest.\r
+ *   If the dest is not in the direction from source, return 1\r
+ */\r
+static int MajorAxisDistanceToFarEdge(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
 {\r
-  FocusFinder finder;\r
+  return std::max(1, MajorAxisDistanceToFarEdgeRaw(direction, source, dest));\r
+}\r
 \r
-  // Check whether the focus finder is already created\r
-  SingletonService singletonService(SingletonService::Get());\r
-  if(singletonService)\r
+/**\r
+ * Find the distance on the minor axis w.r.t the direction to the nearest\r
+ * edge of the destination rectangle.\r
+ * @param direction the direction (up, down, left, right)\r
+ * @param source The source rect.\r
+ * @param dest The destination rect.\r
+ * @return The distance.\r
+ */\r
+static int MinorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
+{\r
+  switch(direction)\r
   {\r
-    Dali::BaseHandle handle = singletonService.GetSingleton(typeid(FocusFinder));\r
-    if(handle)\r
+    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+    {\r
+      // the distance between the center verticals\r
+      return std::abs(\r
+        (((source.top + source.bottom) * 0.5f) -\r
+         (((dest.top + dest.bottom) * 0.5f))));\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
     {\r
-      // If so, downcast the handle of singleton to focus finder\r
-      finder = FocusFinder(dynamic_cast<Internal::FocusFinder*>(handle.GetObjectPtr()));\r
+      // the distance between the center horizontals\r
+      return std::abs(\r
+        (((source.left + source.right) * 0.5f) -\r
+         (((dest.left + dest.right) * 0.5f))));\r
     }\r
+    default:\r
+    {\r
+      return 0;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+ * Calculate distance given major and minor axis distances.\r
+ * @param majorAxisDistance The majorAxisDistance\r
+ * @param minorAxisDistance The minorAxisDistance\r
+ * @return The distance\r
+ */\r
+static int GetWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance)\r
+{\r
+  return 13 * majorAxisDistance * majorAxisDistance + minorAxisDistance * minorAxisDistance;\r
+}\r
+\r
+/**\r
+ * Convert x,y,width,height coordinates into left, right, bottom, top coordinates.\r
+ * @param[in,out] rect The rect\r
+ */\r
+static void ConvertCoordinate(Dali::Rect<float>& rect)\r
+{\r
+  // convert x, y, width, height -> left, right, bottom, top\r
+  float left   = rect.x;\r
+  float right  = rect.x + rect.width;\r
+  float bottom = rect.y + rect.height;\r
+  float top    = rect.y;\r
+\r
+  rect.left   = left;\r
+  rect.right  = right;\r
+  rect.bottom = bottom;\r
+  rect.top    = top;\r
+}\r
 \r
-    if(!finder)\r
+/**\r
+ * Is destRect a candidate for the next focus given the direction?\r
+ * @param srcRect The source rect.\r
+ * @param destRect The dest rect.\r
+ * @param direction The direction (up, down, left, right)\r
+ * @return Whether destRect is a candidate.\r
+ */\r
+static bool IsCandidate(Dali::Rect<float> srcRect, Dali::Rect<float> destRect, Dali::Toolkit::Control::KeyboardFocus::Direction direction)\r
+{\r
+  switch(direction)\r
+  {\r
+    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+    {\r
+      return (srcRect.right > destRect.right || srcRect.left >= destRect.right) && srcRect.left > destRect.left;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+    {\r
+      return (srcRect.left < destRect.left || srcRect.right <= destRect.left) && srcRect.right < destRect.right;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+    {\r
+      return (srcRect.bottom > destRect.bottom || srcRect.top >= destRect.bottom) && srcRect.top > destRect.top;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
     {\r
-      // If not, create the focus finder and register it as a singleton\r
-      finder = FocusFinder(new Internal::FocusFinder());\r
-      singletonService.Register(typeid(finder), finder);\r
+      return (srcRect.top < destRect.top || srcRect.bottom <= destRect.top) && srcRect.bottom < destRect.bottom;\r
+    }\r
+    default:\r
+    {\r
+      return false;\r
     }\r
   }\r
+  return false;\r
+}\r
 \r
-  return finder;\r
+/**\r
+ * Is dest in a given direction from src?\r
+ * @param direction the direction (up, down, left, right)\r
+ * @param src The source rect\r
+ * @param dest The dest rect\r
+ */\r
+static bool IsToDirectionOf(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> src, Dali::Rect<float> dest)\r
+{\r
+  switch(direction)\r
+  {\r
+    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+    {\r
+      return src.left >= dest.right;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+    {\r
+      return src.right <= dest.left;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+    {\r
+      return src.top >= dest.bottom;\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+    {\r
+      return src.bottom <= dest.top;\r
+    }\r
+    default:\r
+    {\r
+      return false;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+ * Do the given direction's axis of rect1 and rect2 overlap?\r
+ * @param direction the direction (up, down, left, right)\r
+ * @param rect1 The first rect\r
+ * @param rect2 The second rect\r
+ * @return whether the beams overlap\r
+ */\r
+static bool BeamsOverlap(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
+{\r
+  switch(direction)\r
+  {\r
+    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+    {\r
+      return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom);\r
+    }\r
+    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+    {\r
+      return (rect2.right >= rect1.left) && (rect2.left <= rect1.right);\r
+    }\r
+    default:\r
+    {\r
+      return false;\r
+    }\r
+  }\r
 }\r
 \r
-FocusFinder::FocusFinder(Internal::FocusFinder* impl)\r
-: BaseHandle(impl)\r
+/**\r
+ * One rectangle may be another candidate than another by virtue of being exclusively in the beam of the source rect.\r
+ * @param direction The direction (up, down, left, right)\r
+ * @param source The source rect\r
+ * @param rect1 The first rect\r
+ * @param rect2 The second rect\r
+ * @return Whether rect1 is a better candidate than rect2 by virtue of it being in src's beam\r
+ */\r
+static bool BeamBeats(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
 {\r
+  const bool rect1InSrcBeam = BeamsOverlap(direction, source, rect1);\r
+  const bool rect2InSrcBeam = BeamsOverlap(direction, source, rect2);\r
+  // if rect1 isn't exclusively in the src beam, it doesn't win\r
+  if(rect2InSrcBeam || !rect1InSrcBeam)\r
+  {\r
+    return false;\r
+  }\r
+  // we know rect1 is in the beam, and rect2 is not\r
+  // if rect1 is to the direction of, and rect2 is not, rect1 wins.\r
+  // for example, for direction left, if rect1 is to the left of the source\r
+  // and rect2 is below, then we always prefer the in beam rect1, since rect2\r
+  // could be reached by going down.\r
+  if(!IsToDirectionOf(direction, source, rect2))\r
+  {\r
+    return true;\r
+  }\r
+  // for horizontal directions, being exclusively in beam always wins\r
+  if((direction == Dali::Toolkit::Control::KeyboardFocus::LEFT || direction == Dali::Toolkit::Control::KeyboardFocus::RIGHT))\r
+  {\r
+    return true;\r
+  }\r
+  // for vertical directions, beams only beat up to a point:\r
+  // now, as long as rect2 isn't completely closer, rect1 wins\r
+  // e.g for direction down, completely closer means for rect2's top\r
+  // edge to be closer to the source's top edge than rect1's bottom edge.\r
+  return (MajorAxisDistance(direction, source, rect1) < MajorAxisDistanceToFarEdge(direction, source, rect2));\r
 }\r
 \r
-Actor FocusFinder::GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction)\r
+bool IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect<float>& focusedRect, Rect<float>& candidateRect, Rect<float>& bestCandidateRect)\r
 {\r
-  return GetImpl(*this).GetNearestFocusableActor(focusedActor, direction);\r
+  // to be a better candidate, need to at least be a candidate in the first place\r
+  if(!IsCandidate(focusedRect, candidateRect, direction))\r
+  {\r
+    return false;\r
+  }\r
+  // we know that candidateRect is a candidate.. if bestCandidateRect is not a candidate,\r
+  // candidateRect is better\r
+  if(!IsCandidate(focusedRect, bestCandidateRect, direction))\r
+  {\r
+    return true;\r
+  }\r
+  // if candidateRect is better by beam, it wins\r
+  if(BeamBeats(direction, focusedRect, candidateRect, bestCandidateRect))\r
+  {\r
+    return true;\r
+  }\r
+  // if bestCandidateRect is better, then candidateRect cant' be :)\r
+  if(BeamBeats(direction, focusedRect, bestCandidateRect, candidateRect))\r
+  {\r
+    return false;\r
+  }\r
+\r
+  // otherwise, do fudge-tastic comparison of the major and minor axis\r
+  return (GetWeightedDistanceFor(\r
+            MajorAxisDistance(direction, focusedRect, candidateRect),\r
+            MinorAxisDistance(direction, focusedRect, candidateRect)) < GetWeightedDistanceFor(MajorAxisDistance(direction, focusedRect, bestCandidateRect),\r
+                                                                                               MinorAxisDistance(direction, focusedRect, bestCandidateRect)));\r
 }\r
 \r
+Actor FindNextFocus(Actor& actor, Actor& focusedActor, Rect<float>& focusedRect, Rect<float>& bestCandidateRect, Toolkit::Control::KeyboardFocus::Direction direction)\r
+{\r
+  Actor nearestActor;\r
+  if(actor)\r
+  {\r
+    // Recursively children\r
+    const auto childCount = actor.GetChildCount();\r
+    for(auto i = 0u; i < childCount; ++i)\r
+    {\r
+      Dali::Actor child = actor.GetChildAt(i);\r
+      if(child && child != focusedActor && child.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))\r
+      {\r
+        Rect<float> candidateRect = DevelActor::CalculateScreenExtents(child);\r
+\r
+        // convert x, y, width, height -> left, right, bottom, top\r
+        ConvertCoordinate(candidateRect);\r
+\r
+        if(IsBetterCandidate(direction, focusedRect, candidateRect, bestCandidateRect))\r
+        {\r
+          bestCandidateRect = candidateRect;\r
+          nearestActor      = child;\r
+        }\r
+      }\r
+      Actor nextActor = FindNextFocus(child, focusedActor, focusedRect, bestCandidateRect, direction);\r
+      if(nextActor)\r
+      {\r
+        nearestActor = nextActor;\r
+      }\r
+    }\r
+  }\r
+  return nearestActor;\r
+}\r
+\r
+} // unnamed namespace\r
+\r
+Actor GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction)\r
+{\r
+  Actor nearestActor;\r
+  if(!focusedActor)\r
+  {\r
+    return nearestActor;\r
+  }\r
+\r
+  Rect<float> focusedRect = DevelActor::CalculateScreenExtents(focusedActor);\r
+\r
+  // initialize the best candidate to something impossible\r
+  // (so the first plausible actor will become the best choice)\r
+  Rect<float> bestCandidateRect = focusedRect;\r
+  switch(direction)\r
+  {\r
+    case Toolkit::Control::KeyboardFocus::LEFT:\r
+    {\r
+      bestCandidateRect.x += 1;\r
+      break;\r
+    }\r
+    case Toolkit::Control::KeyboardFocus::RIGHT:\r
+    {\r
+      bestCandidateRect.x -= 1;\r
+      break;\r
+    }\r
+    case Toolkit::Control::KeyboardFocus::UP:\r
+    {\r
+      bestCandidateRect.y += 1;\r
+      break;\r
+    }\r
+    case Toolkit::Control::KeyboardFocus::DOWN:\r
+    {\r
+      bestCandidateRect.y -= 1;\r
+      break;\r
+    }\r
+    default:\r
+    {\r
+      break;\r
+    }\r
+  }\r
+\r
+  ConvertCoordinate(bestCandidateRect);\r
+\r
+  ConvertCoordinate(focusedRect);\r
+\r
+  Integration::SceneHolder window = Integration::SceneHolder::Get(focusedActor);\r
+  if(window)\r
+  {\r
+    Actor rootActor = window.GetRootLayer();\r
+    nearestActor    = FindNextFocus(rootActor, focusedActor, focusedRect, bestCandidateRect, direction);\r
+  }\r
+  return nearestActor;\r
+}\r
+\r
+} // namespace FocusFinder\r
+\r
 } // namespace Toolkit\r
 \r
 } // namespace Dali\r
index 8012675..47f313d 100644 (file)
@@ -25,50 +25,17 @@ namespace Dali
 {\r
 namespace Toolkit\r
 {\r
-namespace Internal DALI_INTERNAL\r
+namespace FocusFinder\r
 {\r
-class FocusFinder;\r
-}\r
-\r
 /**\r
- * FocusFinder\r
- * This class used for finding the next focusable actor in a given direction\r
- * from a actor that currently has focus.\r
+ * Get the nearest focusable actor.\r
+ * @param [in] focusedActor The current focused actor.\r
+ * @param [in] direction The direction.\r
+ * @return The nearest focusable actor, or an empty handle if none exists.\r
  */\r
-class DALI_TOOLKIT_API FocusFinder : public BaseHandle\r
-{\r
-public:\r
-  /**\r
-   * Create a FocusFinder handle; this can be initialised with FocusFinder::Get()\r
-   * Calling member functions with an uninitialised handle is not allowed.\r
-   */\r
-  FocusFinder();\r
-\r
-  /**\r
-   * @brief Destructor\r
-   *\r
-   * This is non-virtual since derived Handle types must not contain data or virtual methods.\r
-   */\r
-  ~FocusFinder();\r
-\r
-  /**\r
-   * @brief Get the singleton of FocusFinder object.\r
-   * @return A handle to the FocusFinder control.\r
-   */\r
-  static FocusFinder Get();\r
-\r
-  /**\r
-   * Get the nearest focusable actor.\r
-   * @param [in] focusedActor The current focused actor.\r
-   * @param [in] direction The direction.\r
-   * @return The nearest focusable actor, or null if none exists.\r
-   */\r
-  Actor GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction);\r
-\r
-private:\r
-  explicit DALI_INTERNAL FocusFinder(Internal::FocusFinder* impl);\r
+DALI_TOOLKIT_API Actor GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction);\r
 \r
-}; // class FocusFinder\r
+} // namespace FocusFinder\r
 \r
 } // namespace Toolkit\r
 \r
index a4dbce4..99ff139 100644 (file)
@@ -174,7 +174,8 @@ void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstracti
                                       fontDescriptionRuns,
                                       textModel->mLogicalModel->mEmbeddedItems,
                                       textModel->mLogicalModel->mAnchors,
-                                      textModel->mLogicalModel->mUnderlinedCharacterRuns);
+                                      textModel->mLogicalModel->mUnderlinedCharacterRuns,
+                                      textModel->mLogicalModel->mBackgroundColorRuns);
 
   if(textParameters.markupEnabled)
   {
index ddb02d5..5d620bb 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_PROPERTIES_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -76,6 +76,8 @@ enum Type
    * @details Name "cornerRadius", type Property::FLOAT or Prooperty::VECTOR4, animatable
    * @note By default, it is Vector::ZERO.
    * @note Only Property::Vector4 can be animated.
+   * @note Each radius will clamp internally to the half of smaller of the visual width and visual height.
+   * @note Their may exist some alias when you use it as ClippingMode::CLIP_CHILDREN
    * @note Radius value are used in clockwise order from top-left-corner to bottom-left-corner.
    *       When radius is Vector4(x, y, z, w)
    *       x    y
@@ -113,7 +115,7 @@ enum Type
    * @brief The offset from the visual borderline (recommend [-1.0f to 1.0f]).
    * @details Name "borderlineOffset", type Property::FLOAT, animatable
    * @note Default value is 0.0f.
-   * @note This value will be clipped by [-1.0f to 1.0f].
+   * @note This value will clamp internally to [-1.0f to 1.0f].
    */
   BORDERLINE_OFFSET = OPACITY + 6,
 };
index 06027de..33670d6 100644 (file)
@@ -1456,10 +1456,10 @@ Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfo
   else
   {
     Dali::Accessibility::ReadingInfoTypes types;
-    types[Dali::Accessibility::ReadingInfoType::NAME] = true;
-    types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
+    types[Dali::Accessibility::ReadingInfoType::NAME]        = true;
+    types[Dali::Accessibility::ReadingInfoType::ROLE]        = true;
     types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
-    types[Dali::Accessibility::ReadingInfoType::STATE] = true;
+    types[Dali::Accessibility::ReadingInfoType::STATE]       = true;
     return types;
   }
 
@@ -1828,13 +1828,22 @@ void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolk
   Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
   Property::Map          destinationMap    = destinationHandle.GetProperty<Property::Map>(visualIndex);
 
-  Vector4                  mixColor(1.0f, 1.0f, 1.0f, 1.0f);
-  Vector4                  cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
+  Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
+  Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
 
   if(!destinationMap.Empty())
   {
-    mixColor     = destinationMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
-    cornerRadius = destinationMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+    static auto findValue = [](const Property::Map& map, Property::Index index) -> Vector4 {
+      Property::Value* propertyValue = map.Find(index);
+      if(propertyValue)
+      {
+        return propertyValue->Get<Vector4>();
+      }
+      return Vector4{};
+    };
+
+    mixColor     = findValue(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
+    cornerRadius = findValue(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
 
     if(sourceMap.Empty())
     {
@@ -1843,10 +1852,10 @@ void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolk
       sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
     }
 
-    Vector4 sourceMixColor     = sourceMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
-    Vector4 sourceCornerRadius = sourceMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+    Vector4 sourceMixColor     = findValue(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
+    Vector4 sourceCornerRadius = findValue(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
 
-    std::vector<Dali::Property> properties;
+    std::vector<Dali::Property>                              properties;
     std::vector<std::pair<Property::Value, Property::Value>> values;
 
     if(Vector3(sourceMixColor) != Vector3(mixColor))
index 031befd..556711f 100644 (file)
@@ -300,10 +300,19 @@ void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::C
 
   destinationVisual.CreatePropertyMap(destinationMap);
 
+  static auto findValue = [](const Property::Map& map, Property::Index index) -> Vector4 {
+    Property::Value* propertyValue = map.Find(index);
+    if(propertyValue)
+    {
+      return propertyValue->Get<Vector4>();
+    }
+    return Vector4{};
+  };
+
   Vector4 sourceMixColor(0.0f, 0.0f, 0.0f, 0.0f);
   Vector4 sourceCornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
-  Vector4 destinationMixColor     = destinationMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
-  Vector4 destinationCornerRadius = destinationMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+  Vector4 destinationMixColor     = findValue(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
+  Vector4 destinationCornerRadius = findValue(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
 
   Dali::Toolkit::ImageView sourceHandle = Dali::Toolkit::ImageView::DownCast(source);
   Toolkit::Visual::Base    sourceVisual;
@@ -317,11 +326,11 @@ void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::C
   if(sourceVisual)
   {
     sourceVisual.CreatePropertyMap(sourceMap);
-    sourceMixColor     = sourceMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
-    sourceCornerRadius = sourceMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+    sourceMixColor     = findValue(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
+    sourceCornerRadius = findValue(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
   }
 
-  std::vector<Dali::Property> properties;
+  std::vector<Dali::Property>                              properties;
   std::vector<std::pair<Property::Value, Property::Value>> values;
 
   if(Vector3(sourceMixColor) != Vector3(destinationMixColor))
index 9b9e7d9..db7096a 100644 (file)
@@ -1560,16 +1560,50 @@ void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType)
 
     if(renderableActor != mRenderableActor)
     {
+      UnparentAndReset(mBackgroundActor);
       UnparentAndReset(mRenderableActor);
       mRenderableActor = renderableActor;
+
+      if(mRenderableActor)
+      {
+        mBackgroundActor = mController->CreateBackgroundActor();
+      }
     }
   }
 
   if(mRenderableActor)
   {
+    const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
+
+    float renderableActorPositionX, renderableActorPositionY;
+
+    if(mStencil)
+    {
+      renderableActorPositionX = scrollOffset.x + mAlignmentOffset;
+      renderableActorPositionY = scrollOffset.y;
+    }
+    else
+    {
+      Extents padding;
+      padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+
+      // Support Right-To-Left of padding
+      Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+      if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
+      {
+        std::swap(padding.start, padding.end);
+      }
+
+      renderableActorPositionX = scrollOffset.x + mAlignmentOffset + padding.start;
+      renderableActorPositionY = scrollOffset.y + padding.top;
+    }
+
+    mRenderableActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY));
     // Make sure the actors are parented correctly with/without clipping
     Actor self = mStencil ? mStencil : Self();
 
+    Actor highlightActor;
+
     for(std::vector<Actor>::iterator it    = mClippingDecorationActors.begin(),
                                      endIt = mClippingDecorationActors.end();
         it != endIt;
@@ -1577,11 +1611,32 @@ void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType)
     {
       self.Add(*it);
       it->LowerToBottom();
+
+      if(it->GetProperty<std::string>(Dali::Actor::Property::NAME) == "HighlightActor")
+      {
+        highlightActor = *it;
+      }
     }
     mClippingDecorationActors.clear();
 
     self.Add(mRenderableActor);
 
+    if(mBackgroundActor)
+    {
+      if(mDecorator && mDecorator->IsHighlightVisible())
+      {
+        self.Add(mBackgroundActor);
+        mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // In text field's coords.
+        mBackgroundActor.LowerBelow(highlightActor);
+      }
+      else
+      {
+        mRenderableActor.Add(mBackgroundActor);
+        mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f)); // In renderable actor's coords.
+        mBackgroundActor.LowerToBottom();
+      }
+    }
+
     ApplyScrollPosition();
   }
   UpdateScrollBar();
@@ -2323,7 +2378,7 @@ Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates()
   return states;
 }
 
-bool TextEditor::AccessibleImpl::InsertText(size_t startPosition,
+bool TextEditor::AccessibleImpl::InsertText(size_t      startPosition,
                                             std::string text)
 {
   auto slf = Toolkit::TextEditor::DownCast(Self());
index 9a06ea5..0286da2 100644 (file)
@@ -413,6 +413,7 @@ private: // Data
 
   Actor         mRenderableActor;
   Actor         mActiveLayer;
+  Actor         mBackgroundActor;
   CallbackBase* mIdleCallback;
 
   float mAlignmentOffset;
index aabd0c0..f712e9f 100644 (file)
@@ -114,7 +114,6 @@ SET( toolkit_src_files
 
    ${toolkit_src_dir}/focus-manager/keyboard-focus-manager-impl.cpp
    ${toolkit_src_dir}/focus-manager/keyinput-focus-manager-impl.cpp
-   ${toolkit_src_dir}/focus-manager/focus-finder-impl.cpp
    ${toolkit_src_dir}/helpers/color-conversion.cpp
    ${toolkit_src_dir}/helpers/property-helper.cpp
    ${toolkit_src_dir}/filters/blur-two-pass-filter.cpp
@@ -137,6 +136,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/markup-processor-embedded-item.cpp
    ${toolkit_src_dir}/text/markup-processor-anchor.cpp
    ${toolkit_src_dir}/text/markup-processor-font.cpp
+   ${toolkit_src_dir}/text/markup-processor-background.cpp
    ${toolkit_src_dir}/text/markup-processor-helper-functions.cpp
    ${toolkit_src_dir}/text/multi-language-support.cpp
    ${toolkit_src_dir}/text/hidden-text.cpp
@@ -178,6 +178,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/rendering/text-backend-impl.cpp
    ${toolkit_src_dir}/text/rendering/text-typesetter.cpp
    ${toolkit_src_dir}/text/rendering/view-model.cpp
+   ${toolkit_src_dir}/transition/fade-impl.cpp
    ${toolkit_src_dir}/transition/transition-base-impl.cpp
    ${toolkit_src_dir}/transition/transition-impl.cpp
    ${toolkit_src_dir}/transition/transition-lifecycle-controller.cpp
diff --git a/dali-toolkit/internal/focus-manager/focus-finder-impl.cpp b/dali-toolkit/internal/focus-manager/focus-finder-impl.cpp
deleted file mode 100644 (file)
index 93f1d65..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-/*\r
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- *\r
- */\r
-\r
-/*\r
- * Copyright (C) 2017 The Android Open Source Project\r
- *\r
- * Modified by joogab yun(joogab.yun@samsung.com)\r
- */\r
-\r
-// CLASS HEADER\r
-#include "focus-finder-impl.h"\r
-\r
-// INTERNAL INCLUDES\r
-#include <dali/devel-api/actors/actor-devel.h>\r
-\r
-// EXTERNAL INCLUDES\r
-#include <dali/integration-api/adaptor-framework/adaptor.h>\r
-#include <dali/integration-api/adaptor-framework/scene-holder.h>\r
-#include <dali/integration-api/debug.h>\r
-#include <dali/public-api/actors/layer.h>\r
-#include <math.h>\r
-\r
-namespace\r
-{\r
-static int MajorAxisDistanceRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
-  switch(direction)\r
-  {\r
-    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
-    {\r
-      return source.left - dest.right;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
-    {\r
-      return dest.left - source.right;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
-    {\r
-      return source.top - dest.bottom;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
-    {\r
-      return dest.top - source.bottom;\r
-    }\r
-    default:\r
-    {\r
-      return 0;\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
- * @return The distance from the edge furthest in the given direction\r
- *   of source to the edge nearest in the given direction of dest.\r
- *   If the dest is not in the direction from source, return 0.\r
- */\r
-static int MajorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
-  return std::max(0, MajorAxisDistanceRaw(direction, source, dest));\r
-}\r
-\r
-static int MajorAxisDistanceToFarEdgeRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
-  switch(direction)\r
-  {\r
-    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
-    {\r
-      return source.left - dest.left;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
-    {\r
-      return dest.right - source.right;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
-    {\r
-      return source.top - dest.top;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
-    {\r
-      return dest.bottom - source.bottom;\r
-    }\r
-    default:\r
-    {\r
-      return 0;\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
- * @return The distance along the major axis w.r.t the direction from the\r
- *   edge of source to the far edge of dest.\r
- *   If the dest is not in the direction from source, return 1\r
- */\r
-static int MajorAxisDistanceToFarEdge(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
-  return std::max(1, MajorAxisDistanceToFarEdgeRaw(direction, source, dest));\r
-}\r
-\r
-/**\r
- * Find the distance on the minor axis w.r.t the direction to the nearest\r
- * edge of the destination rectangle.\r
- * @param direction the direction (up, down, left, right)\r
- * @param source The source rect.\r
- * @param dest The destination rect.\r
- * @return The distance.\r
- */\r
-static int MinorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
-  switch(direction)\r
-  {\r
-    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
-    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
-    {\r
-      // the distance between the center verticals\r
-      return std::abs(\r
-        (((source.top + source.bottom) * 0.5f) -\r
-         (((dest.top + dest.bottom) * 0.5f))));\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
-    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
-    {\r
-      // the distance between the center horizontals\r
-      return std::abs(\r
-        (((source.left + source.right) * 0.5f) -\r
-         (((dest.left + dest.right) * 0.5f))));\r
-    }\r
-    default:\r
-    {\r
-      return 0;\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
- * Calculate distance given major and minor axis distances.\r
- * @param majorAxisDistance The majorAxisDistance\r
- * @param minorAxisDistance The minorAxisDistance\r
- * @return The distance\r
- */\r
-static int GetWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance)\r
-{\r
-  return 13 * majorAxisDistance * majorAxisDistance + minorAxisDistance * minorAxisDistance;\r
-}\r
-\r
-/**\r
- * Convert x,y,width,height coordinates into left, right, bottom, top coordinates.\r
- * @param[in,out] rect The rect\r
- */\r
-static void ConvertCoordinate(Dali::Rect<float>& rect)\r
-{\r
-  // convert x, y, width, height -> left, right, bottom, top\r
-  float left   = rect.x;\r
-  float right  = rect.x + rect.width;\r
-  float bottom = rect.y + rect.height;\r
-  float top    = rect.y;\r
-\r
-  rect.left   = left;\r
-  rect.right  = right;\r
-  rect.bottom = bottom;\r
-  rect.top    = top;\r
-}\r
-\r
-/**\r
- * Is destRect a candidate for the next focus given the direction?\r
- * @param srcRect The source rect.\r
- * @param destRect The dest rect.\r
- * @param direction The direction (up, down, left, right)\r
- * @return Whether destRect is a candidate.\r
- */\r
-static bool IsCandidate(Dali::Rect<float> srcRect, Dali::Rect<float> destRect, Dali::Toolkit::Control::KeyboardFocus::Direction direction)\r
-{\r
-  switch(direction)\r
-  {\r
-    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
-    {\r
-      return (srcRect.right > destRect.right || srcRect.left >= destRect.right) && srcRect.left > destRect.left;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
-    {\r
-      return (srcRect.left < destRect.left || srcRect.right <= destRect.left) && srcRect.right < destRect.right;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
-    {\r
-      return (srcRect.bottom > destRect.bottom || srcRect.top >= destRect.bottom) && srcRect.top > destRect.top;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
-    {\r
-      return (srcRect.top < destRect.top || srcRect.bottom <= destRect.top) && srcRect.bottom < destRect.bottom;\r
-    }\r
-    default:\r
-    {\r
-      return false;\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-/**\r
- * Is dest in a given direction from src?\r
- * @param direction the direction (up, down, left, right)\r
- * @param src The source rect\r
- * @param dest The dest rect\r
- */\r
-static bool IsToDirectionOf(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> src, Dali::Rect<float> dest)\r
-{\r
-  switch(direction)\r
-  {\r
-    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
-    {\r
-      return src.left >= dest.right;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
-    {\r
-      return src.right <= dest.left;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
-    {\r
-      return src.top >= dest.bottom;\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
-    {\r
-      return src.bottom <= dest.top;\r
-    }\r
-    default:\r
-    {\r
-      return false;\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
- * Do the given direction's axis of rect1 and rect2 overlap?\r
- * @param direction the direction (up, down, left, right)\r
- * @param rect1 The first rect\r
- * @param rect2 The second rect\r
- * @return whether the beams overlap\r
- */\r
-static bool BeamsOverlap(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
-{\r
-  switch(direction)\r
-  {\r
-    case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
-    case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
-    {\r
-      return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom);\r
-    }\r
-    case Dali::Toolkit::Control::KeyboardFocus::UP:\r
-    case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
-    {\r
-      return (rect2.right >= rect1.left) && (rect2.left <= rect1.right);\r
-    }\r
-    default:\r
-    {\r
-      return false;\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
- * One rectangle may be another candidate than another by virtue of being exclusively in the beam of the source rect.\r
- * @param direction The direction (up, down, left, right)\r
- * @param source The source rect\r
- * @param rect1 The first rect\r
- * @param rect2 The second rect\r
- * @return Whether rect1 is a better candidate than rect2 by virtue of it being in src's beam\r
- */\r
-static bool BeamBeats(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
-{\r
-  const bool rect1InSrcBeam = BeamsOverlap(direction, source, rect1);\r
-  const bool rect2InSrcBeam = BeamsOverlap(direction, source, rect2);\r
-  // if rect1 isn't exclusively in the src beam, it doesn't win\r
-  if(rect2InSrcBeam || !rect1InSrcBeam)\r
-  {\r
-    return false;\r
-  }\r
-  // we know rect1 is in the beam, and rect2 is not\r
-  // if rect1 is to the direction of, and rect2 is not, rect1 wins.\r
-  // for example, for direction left, if rect1 is to the left of the source\r
-  // and rect2 is below, then we always prefer the in beam rect1, since rect2\r
-  // could be reached by going down.\r
-  if(!IsToDirectionOf(direction, source, rect2))\r
-  {\r
-    return true;\r
-  }\r
-  // for horizontal directions, being exclusively in beam always wins\r
-  if((direction == Dali::Toolkit::Control::KeyboardFocus::LEFT || direction == Dali::Toolkit::Control::KeyboardFocus::RIGHT))\r
-  {\r
-    return true;\r
-  }\r
-  // for vertical directions, beams only beat up to a point:\r
-  // now, as long as rect2 isn't completely closer, rect1 wins\r
-  // e.g for direction down, completely closer means for rect2's top\r
-  // edge to be closer to the source's top edge than rect1's bottom edge.\r
-  return (MajorAxisDistance(direction, source, rect1) < MajorAxisDistanceToFarEdge(direction, source, rect2));\r
-}\r
-\r
-} // unnamed namespace\r
-\r
-namespace Dali\r
-{\r
-namespace Toolkit\r
-{\r
-namespace Internal\r
-{\r
-FocusFinder::FocusFinder()\r
-{\r
-}\r
-\r
-FocusFinder::~FocusFinder()\r
-{\r
-}\r
-\r
-Actor FocusFinder::GetNearestFocusableActor(Actor& focusedActor, Toolkit::Control::KeyboardFocus::Direction direction)\r
-{\r
-  Actor nearestActor;\r
-  if(!focusedActor)\r
-  {\r
-    return nearestActor;\r
-  }\r
-\r
-  Rect<float> focusedRect = DevelActor::CalculateScreenExtents(focusedActor);\r
-\r
-  // initialize the best candidate to something impossible\r
-  // (so the first plausible actor will become the best choice)\r
-  Rect<float> bestCandidateRect = focusedRect;\r
-  switch(direction)\r
-  {\r
-    case Toolkit::Control::KeyboardFocus::LEFT:\r
-    {\r
-      bestCandidateRect.x += 1;\r
-      break;\r
-    }\r
-    case Toolkit::Control::KeyboardFocus::RIGHT:\r
-    {\r
-      bestCandidateRect.x -= 1;\r
-      break;\r
-    }\r
-    case Toolkit::Control::KeyboardFocus::UP:\r
-    {\r
-      bestCandidateRect.y += 1;\r
-      break;\r
-    }\r
-    case Toolkit::Control::KeyboardFocus::DOWN:\r
-    {\r
-      bestCandidateRect.y -= 1;\r
-      break;\r
-    }\r
-    default:\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  ConvertCoordinate(bestCandidateRect);\r
-\r
-  ConvertCoordinate(focusedRect);\r
-\r
-  Integration::SceneHolder window = Integration::SceneHolder::Get(focusedActor);\r
-  if(window)\r
-  {\r
-    Actor rootActor = window.GetRootLayer();\r
-    nearestActor    = FindNextFocus(rootActor, focusedActor, focusedRect, bestCandidateRect, direction);\r
-  }\r
-  return nearestActor;\r
-}\r
-\r
-Actor FocusFinder::FindNextFocus(Actor& actor, Actor& focusedActor, Rect<float>& focusedRect, Rect<float>& bestCandidateRect, Toolkit::Control::KeyboardFocus::Direction direction)\r
-{\r
-  Actor nearestActor;\r
-  if(actor)\r
-  {\r
-    // Recursively children\r
-    const auto childCount = actor.GetChildCount();\r
-    for(auto i = 0u; i < childCount; ++i)\r
-    {\r
-      Dali::Actor child = actor.GetChildAt(i);\r
-      if(child && child != focusedActor && child.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))\r
-      {\r
-        Rect<float> candidateRect = DevelActor::CalculateScreenExtents(child);\r
-\r
-        // convert x, y, width, height -> left, right, bottom, top\r
-        ConvertCoordinate(candidateRect);\r
-\r
-        if(IsBetterCandidate(direction, focusedRect, candidateRect, bestCandidateRect))\r
-        {\r
-          bestCandidateRect = candidateRect;\r
-          nearestActor      = child;\r
-        }\r
-      }\r
-      Actor nextActor = FindNextFocus(child, focusedActor, focusedRect, bestCandidateRect, direction);\r
-      if(nextActor)\r
-      {\r
-        nearestActor = nextActor;\r
-      }\r
-    }\r
-  }\r
-  return nearestActor;\r
-}\r
-\r
-bool FocusFinder::IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect<float>& focusedRect, Rect<float>& candidateRect, Rect<float>& bestCandidateRect) const\r
-{\r
-  // to be a better candidate, need to at least be a candidate in the first place\r
-  if(!IsCandidate(focusedRect, candidateRect, direction))\r
-  {\r
-    return false;\r
-  }\r
-  // we know that candidateRect is a candidate.. if bestCandidateRect is not a candidate,\r
-  // candidateRect is better\r
-  if(!IsCandidate(focusedRect, bestCandidateRect, direction))\r
-  {\r
-    return true;\r
-  }\r
-  // if candidateRect is better by beam, it wins\r
-  if(BeamBeats(direction, focusedRect, candidateRect, bestCandidateRect))\r
-  {\r
-    return true;\r
-  }\r
-  // if bestCandidateRect is better, then candidateRect cant' be :)\r
-  if(BeamBeats(direction, focusedRect, bestCandidateRect, candidateRect))\r
-  {\r
-    return false;\r
-  }\r
-\r
-  // otherwise, do fudge-tastic comparison of the major and minor axis\r
-  return (GetWeightedDistanceFor(\r
-            MajorAxisDistance(direction, focusedRect, candidateRect),\r
-            MinorAxisDistance(direction, focusedRect, candidateRect)) < GetWeightedDistanceFor(MajorAxisDistance(direction, focusedRect, bestCandidateRect),\r
-                                                                                               MinorAxisDistance(direction, focusedRect, bestCandidateRect)));\r
-}\r
-\r
-} // namespace Internal\r
-\r
-} // namespace Toolkit\r
-\r
-} // namespace Dali\r
diff --git a/dali-toolkit/internal/focus-manager/focus-finder-impl.h b/dali-toolkit/internal/focus-manager/focus-finder-impl.h
deleted file mode 100644 (file)
index 012b1aa..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H\r
-#define DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H\r
-\r
-/*\r
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- *\r
- */\r
-\r
-// EXTERNAL INCLUDES\r
-#include <dali/public-api/object/base-object.h>\r
-\r
-// INTERNAL INCLUDES\r
-#include <dali-toolkit/devel-api/focus-manager/focus-finder.h>\r
-\r
-namespace Dali\r
-{\r
-namespace Integration\r
-{\r
-class SceneHolder;\r
-\r
-} // namespace Integration\r
-\r
-namespace Toolkit\r
-{\r
-namespace Internal\r
-{\r
-class FocusFinder;\r
-\r
-/**\r
- * @copydoc Toolkit::FocusFinder\r
- */\r
-class FocusFinder : public Dali::BaseObject\r
-{\r
-public:\r
-  /**\r
-   * Construct a new FocusFinder.\r
-   */\r
-  FocusFinder();\r
-\r
-  /**\r
-   * @copydoc Toolkit::GetNearestFocusableActor\r
-   */\r
-  Actor GetNearestFocusableActor(Actor& focusedActor, Toolkit::Control::KeyboardFocus::Direction direction);\r
-\r
-protected:\r
-  /**\r
-   * Destructor\r
-   */\r
-  virtual ~FocusFinder();\r
-\r
-private:\r
-  /**\r
-   * Find the next actor to take focus in root's descendants, starting from the actor.\r
-   * @param[in] actor The root actor.\r
-   * @param[in] focusedActor The current focused actor.\r
-   * @param[in] focusedRect The rect of current focused actor.\r
-   * @param[in] bestCandidateRect The current best candidate.\r
-   * @param[in] direction The direction.\r
-   * @return nearest Actor.\r
-   */\r
-  Actor FindNextFocus(Actor& actor, Actor& focusedActor, Rect<float>& focusedRect, Rect<float>& bestCandidateRect, Toolkit::Control::KeyboardFocus::Direction direction);\r
-\r
-  /**\r
-   * Is rect1 a better candidate than rect2 for a focus search in a particular\r
-   * direction from a source rect?  This is the core routine that determines\r
-   * the order of focus searching.\r
-   * @param direction The direction (up, down, left, right)\r
-   * @param candidateRect The candidate rectangle\r
-   * @param bestCandidateRect The current best candidate.\r
-   * @return Whether the candidate is the new best.\r
-   */\r
-  bool IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect<float>& focusedRect, Rect<float>& candidateRect, Rect<float>& bestCandidateRect) const;\r
-\r
-private:\r
-  // Undefined\r
-  FocusFinder(const FocusFinder&);\r
-\r
-  FocusFinder& operator=(const FocusFinder& rhs);\r
-};\r
-\r
-} // namespace Internal\r
-\r
-inline Internal::FocusFinder& GetImpl(Dali::Toolkit::FocusFinder& obj)\r
-{\r
-  DALI_ASSERT_ALWAYS(obj);\r
-\r
-  Dali::BaseObject& handle = obj.GetBaseObject();\r
-\r
-  return static_cast<Internal::FocusFinder&>(handle);\r
-}\r
-\r
-inline const Internal::FocusFinder& GetImpl(const Dali::Toolkit::FocusFinder& obj)\r
-{\r
-  DALI_ASSERT_ALWAYS(obj);\r
-\r
-  const Dali::BaseObject& handle = obj.GetBaseObject();\r
-\r
-  return static_cast<const Internal::FocusFinder&>(handle);\r
-}\r
-\r
-} // namespace Toolkit\r
-\r
-} // namespace Dali\r
-\r
-#endif // DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H\r
index 0aa9ed1..8dadb11 100644 (file)
@@ -500,7 +500,7 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction
       else
       {
         // We should find it among the actors nearby.
-        nextFocusableActor = Toolkit::FocusFinder::Get().GetNearestFocusableActor(currentFocusActor, direction);
+        nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(currentFocusActor, direction);
       }
     }
 
index bf93629..92b29a6 100644 (file)
@@ -156,8 +156,8 @@ mediump float calculateCornerOpacity()
   // calculate borderline opacity by potential
   if(potential > gMaxOutlinePotential)
   {
-    // potential is out of borderline range
-    opacity = 0.0;
+    // potential is out of borderline range. just discard here
+    discard;
   }
   else if(potential > gMinOutlinePotential)
   {
index 305ff92..9c897b4 100644 (file)
@@ -155,8 +155,8 @@ mediump float calculateCornerOpacity()
   // calculate borderline opacity by potential
   if(potential > gMaxOutlinePotential)
   {
-    // potential is out of borderline range
-    opacity = 0.0;
+    // potential is out of borderline range. just discard here
+    discard;
   }
   else if(potential > gMinOutlinePotential)
   {
index e83d463..b0dcfec 100644 (file)
@@ -177,8 +177,8 @@ mediump float calculateCornerOpacity()
   // calculate borderline opacity by potential
   if(potential > gMaxOutlinePotential)
   {
-    // potential is out of borderline range
-    opacity = 0.0;
+    // potential is out of borderline range. just discard here
+    discard;
   }
   else if(potential > gMinOutlinePotential)
   {
diff --git a/dali-toolkit/internal/text/markup-processor-background.cpp b/dali-toolkit/internal/text/markup-processor-background.cpp
new file mode 100644 (file)
index 0000000..8a9910e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 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/markup-processor-background.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const std::string XHTML_COLOR_ATTRIBUTE("color");
+} // namespace
+
+void ProcessBackground(const Tag& tag, ColorRun& colorRun)
+{
+  for(auto&& attribute : tag.attributes)
+  {
+    if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+    {
+      ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor-background.h b/dali-toolkit/internal/text/markup-processor-background.h
new file mode 100644 (file)
index 0000000..331d2c8
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
+
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct ColorRun;
+
+/**
+ * @brief Retrieves the @e background from the @p tag.
+ *
+ * @param[in] tag The background tag and its attributes.
+ * @param[in,out] colorRun The color run to be filled.
+ */
+void ProcessBackground(const Tag& tag, ColorRun& colorRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
\ No newline at end of file
index ea7f869..6fef092 100644 (file)
@@ -26,6 +26,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/markup-processor-anchor.h>
+#include <dali-toolkit/internal/text/markup-processor-background.h>
 #include <dali-toolkit/internal/text/markup-processor-color.h>
 #include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
 #include <dali-toolkit/internal/text/markup-processor-font.h>
@@ -53,6 +54,7 @@ const std::string XHTML_GLOW_TAG("glow");
 const std::string XHTML_OUTLINE_TAG("outline");
 const std::string XHTML_ITEM_TAG("item");
 const std::string XHTML_ANCHOR_TAG("a");
+const std::string XHTML_BACKGROUND_TAG("background");
 
 const char LESS_THAN      = '<';
 const char GREATER_THAN   = '>';
@@ -631,12 +633,14 @@ void ProcessAnchorTag(
  * @param[in] fontRunIndex The font run index
  * @param[in] colorRunIndex The color run index
  * @param[in] underlinedCharacterRunIndex The underlined character run index
+ * @param[in] backgroundRunIndex The background run index
  */
-void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex)
+void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex, const StyleStack::RunIndex backgroundRunIndex)
 {
   markupProcessData.fontRuns.Resize(fontRunIndex);
   markupProcessData.colorRuns.Resize(colorRunIndex);
   markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex);
+  markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex);
 
 #ifdef DEBUG_ENABLED
   for(unsigned int i = 0; i < colorRunIndex; ++i)
@@ -753,21 +757,24 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   StyleStack styleStack;
 
   // Points the next free position in the vector of runs.
-  StyleStack::RunIndex colorRunIndex                = 0u;
-  StyleStack::RunIndex fontRunIndex                 = 0u;
-  StyleStack::RunIndex underlinedCharacterRunIndex  = 0u;
+  StyleStack::RunIndex colorRunIndex               = 0u;
+  StyleStack::RunIndex fontRunIndex                = 0u;
+  StyleStack::RunIndex underlinedCharacterRunIndex = 0u;
+  StyleStack::RunIndex backgroundRunIndex          = 0u;
 
   // check tag reference
-  int colorTagReference = 0u;
-  int fontTagReference  = 0u;
-  int iTagReference     = 0u;
-  int bTagReference     = 0u;
-  int uTagReference     = 0u;
+  int colorTagReference      = 0u;
+  int fontTagReference       = 0u;
+  int iTagReference          = 0u;
+  int bTagReference          = 0u;
+  int uTagReference          = 0u;
+  int backgroundTagReference = 0u;
 
   // Give an initial default value to the model's vectors.
   markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE);
   markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE);
   markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
+  markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE);
 
   // Get the mark-up string buffer.
   const char*       markupStringBuffer    = markupString.c_str();
@@ -798,8 +805,8 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
       else if(TokenComparison(XHTML_U_TAG, tag.buffer, tag.length))
       {
         ProcessTagForRun<UnderlinedCharacterRun>(
-          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {  });
-      }  // <u></u>
+          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {});
+      } // <u></u>
       else if(TokenComparison(XHTML_B_TAG, tag.buffer, tag.length))
       {
         ProcessTagForRun<FontDescriptionRun>(
@@ -844,6 +851,11 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
       {
         ProcessItemTag(markupProcessData, tag, characterIndex);
       }
+      else if(TokenComparison(XHTML_BACKGROUND_TAG, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<ColorRun>(
+          markupProcessData.backgroundColorRuns, styleStack, tag, characterIndex, backgroundRunIndex, backgroundTagReference, [](const Tag& tag, ColorRun& run) { ProcessBackground(tag, run); });
+      }
     } // end if( IsTag() )
     else if(markupStringBuffer < markupStringEndBuffer)
     {
@@ -852,7 +864,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
   }
 
   // Resize the model's vectors.
-  ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex);
+  ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, backgroundRunIndex);
 }
 
 } // namespace Text
index ec45957..e84b892 100644 (file)
@@ -40,16 +40,18 @@ namespace Text
  */
 struct MarkupProcessData
 {
-  MarkupProcessData(Vector<ColorRun>&           colorRuns,
-                    Vector<FontDescriptionRun>& fontRuns,
-                    Vector<EmbeddedItem>&       items,
-                    Vector<Anchor>&             anchors,
-                    Vector<UnderlinedCharacterRun>& underlinedCharacterRuns)
+  MarkupProcessData(Vector<ColorRun>&               colorRuns,
+                    Vector<FontDescriptionRun>&     fontRuns,
+                    Vector<EmbeddedItem>&           items,
+                    Vector<Anchor>&                 anchors,
+                    Vector<UnderlinedCharacterRun>& underlinedCharacterRuns,
+                    Vector<ColorRun>&               backgroundColorRuns)
   : colorRuns(colorRuns),
     fontRuns(fontRuns),
     items(items),
     anchors(anchors),
     underlinedCharacterRuns(underlinedCharacterRuns),
+    backgroundColorRuns(backgroundColorRuns),
     markupProcessedText()
   {
   }
@@ -59,6 +61,7 @@ struct MarkupProcessData
   Vector<EmbeddedItem>&           items;                   ///< The embedded items.
   Vector<Anchor>&                 anchors;                 ///< The anchors.
   Vector<UnderlinedCharacterRun>& underlinedCharacterRuns; ///< The underlined character runs.
+  Vector<ColorRun>&               backgroundColorRuns;     ///< The background color runs.
   std::string                     markupProcessedText;     ///< The mark-up string.
 };
 
index 83d67d5..17a5c61 100644 (file)
@@ -417,6 +417,116 @@ void DrawBackgroundColor(
   }
 }
 
+Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuffer& buffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, int horizontalOffset, int verticalOffset)
+{
+  // Retrieve lines, glyphs, positions and colors from the view model.
+  const Length            modelNumberOfLines           = model->GetNumberOfLines();
+  const LineRun* const    modelLinesBuffer             = model->GetLines();
+  const Length            numberOfGlyphs               = model->GetNumberOfGlyphs();
+  const GlyphInfo* const  glyphsBuffer                 = model->GetGlyphs();
+  const Vector2* const    positionBuffer               = model->GetLayout();
+  const Vector4* const    backgroundColorsBuffer       = model->GetBackgroundColors();
+  const ColorIndex* const backgroundColorIndicesBuffer = model->GetBackgroundColorIndices();
+
+  // Create and initialize the pixel buffer.
+  GlyphData glyphData;
+  glyphData.verticalOffset   = verticalOffset;
+  glyphData.width            = bufferWidth;
+  glyphData.height           = bufferHeight;
+  glyphData.bitmapBuffer     = buffer;
+  glyphData.horizontalOffset = 0;
+
+  ColorIndex prevBackgroundColorIndex = 0;
+  ColorIndex backgroundColorIndex     = 0;
+
+  // Traverses the lines of the text.
+  for(LineIndex lineIndex = 0u; lineIndex < modelNumberOfLines; ++lineIndex)
+  {
+    const LineRun& line = *(modelLinesBuffer + lineIndex);
+
+    // Sets the horizontal offset of the line.
+    glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast<int>(line.alignmentOffset);
+    glyphData.horizontalOffset += horizontalOffset;
+
+    // Increases the vertical offset with the line's ascender.
+    glyphData.verticalOffset += static_cast<int>(line.ascender);
+
+    // Include line spacing after first line
+    if(lineIndex > 0u)
+    {
+      glyphData.verticalOffset += static_cast<int>(line.lineSpacing);
+    }
+
+    float left     = bufferWidth;
+    float right    = 0.0f;
+    float baseline = 0.0f;
+
+    // Traverses the glyphs of the line.
+    const GlyphIndex endGlyphIndex = std::min(numberOfGlyphs, line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs);
+    for(GlyphIndex glyphIndex = line.glyphRun.glyphIndex; glyphIndex < endGlyphIndex; ++glyphIndex)
+    {
+      // Retrieve the glyph's info.
+      const GlyphInfo* const glyphInfo = glyphsBuffer + glyphIndex;
+
+      if((glyphInfo->width < Math::MACHINE_EPSILON_1000) ||
+         (glyphInfo->height < Math::MACHINE_EPSILON_1000))
+      {
+        // Nothing to do if default background color, the glyph's width or height is zero.
+        continue;
+      }
+
+      backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + glyphIndex);
+
+      if((backgroundColorIndex != prevBackgroundColorIndex) &&
+         (prevBackgroundColorIndex != 0u))
+      {
+        const Vector4& backgroundColor = *(backgroundColorsBuffer + prevBackgroundColorIndex - 1u);
+        DrawBackgroundColor(backgroundColor, bufferWidth, bufferHeight, glyphData, baseline, line, left, right);
+      }
+
+      if(backgroundColorIndex == 0u)
+      {
+        prevBackgroundColorIndex = backgroundColorIndex;
+        //if background color is the default do nothing
+        continue;
+      }
+
+      // Retrieves the glyph's position.
+      const Vector2* const position = positionBuffer + glyphIndex;
+
+      if(baseline < position->y + glyphInfo->yBearing)
+      {
+        baseline = position->y + glyphInfo->yBearing;
+      }
+
+      // Calculate the positions of leftmost and rightmost glyphs in the current line
+      if((position->x < left) || (backgroundColorIndex != prevBackgroundColorIndex))
+      {
+        left = position->x - glyphInfo->xBearing;
+      }
+
+      if(position->x + glyphInfo->width > right)
+      {
+        right = position->x - glyphInfo->xBearing + glyphInfo->advance;
+      }
+
+      prevBackgroundColorIndex = backgroundColorIndex;
+    }
+
+    //draw last background at line end if not default
+    if(backgroundColorIndex != 0u)
+    {
+      const Vector4& backgroundColor = *(backgroundColorsBuffer + backgroundColorIndex - 1u);
+      DrawBackgroundColor(backgroundColor, bufferWidth, bufferHeight, glyphData, baseline, line, left, right);
+    }
+
+    // Increases the vertical offset with the line's descender.
+    glyphData.verticalOffset += static_cast<int>(-line.descender);
+  }
+
+  return glyphData.bitmapBuffer;
+}
+
 } // namespace
 
 TypesetterPtr Typesetter::New(const ModelInterface* const model)
@@ -587,10 +697,25 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
     }
 
     // Generate the background if enabled
-    const bool backgroundEnabled = mModel->IsBackgroundEnabled();
-    if(backgroundEnabled)
+    const bool backgroundEnabled   = mModel->IsBackgroundEnabled();
+    const bool backgroundMarkupSet = mModel->IsMarkupBackgroundColorSet();
+    if(backgroundEnabled || backgroundMarkupSet)
     {
-      Devel::PixelBuffer backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+      Devel::PixelBuffer backgroundImageBuffer;
+
+      if(backgroundEnabled)
+      {
+        backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+      }
+      else
+      {
+        backgroundImageBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat);
+      }
+
+      if(backgroundMarkupSet)
+      {
+        DrawGlyphsBackground(mModel, backgroundImageBuffer, bufferWidth, bufferHeight, ignoreHorizontalAlignment, penX, penY);
+      }
 
       // Combine the two buffers
       imageBuffer = CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight);
index f695cd2..4ad0b14 100644 (file)
@@ -160,6 +160,11 @@ const ColorIndex* const ViewModel::GetBackgroundColorIndices() const
   return mModel->GetBackgroundColorIndices();
 }
 
+bool const ViewModel::IsMarkupBackgroundColorSet() const
+{
+  return mModel->IsMarkupBackgroundColorSet();
+}
+
 const Vector4& ViewModel::GetDefaultColor() const
 {
   return mModel->GetDefaultColor();
index 9272956..e51a075 100644 (file)
@@ -146,6 +146,11 @@ public:
   const ColorIndex* const GetBackgroundColorIndices() const override;
 
   /**
+   * @copydoc ModelInterface::IsMarkupBackgroundColorSet()
+   */
+  bool const IsMarkupBackgroundColorSet() const override;
+
+  /**
    * @copydoc ModelInterface::GetDefaultColor()
    */
   const Vector4& GetDefaultColor() const override;
index 417eaed..b8b6f31 100644 (file)
@@ -847,7 +847,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
     mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
     mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
 
-   updated = true;
+    updated = true;
   }
 
   const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
@@ -922,8 +922,13 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
           colorRun.color                           = backgroundColor;
           colorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
           colorRun.characterRun.numberOfCharacters = numberOfIndices;
-
           mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
+
+          //Mark-up processor case
+          if(mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            CopyUnderlinedFromLogicalToVisualModels(false);
+          }
           break;
         }
         case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
@@ -933,6 +938,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
           backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
           backgroundColorRun.color                           = LIGHT_BLUE;
           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
+
+          //Mark-up processor case
+          if(mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            CopyUnderlinedFromLogicalToVisualModels(false);
+          }
           break;
         }
         case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
@@ -1056,9 +1067,9 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
   }
 
   if((NO_OPERATION != (SHAPE_TEXT & operations)) &&
-      ! ((nullptr != mEventData) &&
-         mEventData->mPreEditFlag &&
-         (0u != mModel->mVisualModel->mCharactersToGlyph.Count())))
+     !((nullptr != mEventData) &&
+       mEventData->mPreEditFlag &&
+       (0u != mModel->mVisualModel->mCharactersToGlyph.Count())))
   {
     //Mark-up processor case
     if(mModel->mVisualModel->IsMarkupProcessorEnabled())
@@ -1069,7 +1080,6 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
     updated = true;
   }
 
-
   // The estimated number of lines. Used to avoid reallocations when layouting.
   mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count());
 
@@ -2018,8 +2028,7 @@ void Controller::Impl::RequestRelayout()
 
 Actor Controller::Impl::CreateBackgroundActor()
 {
-  // NOTE: Currently we only support background color for one line left-to-right text,
-  //       so the following calculation is based on one line left-to-right text only!
+  // NOTE: Currently we only support background color for left-to-right text.
 
   Actor actor;
 
@@ -2060,8 +2069,12 @@ Actor Controller::Impl::CreateBackgroundActor()
     const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices();
     const Vector4&          defaultBackgroundColor       = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
 
-    Vector4  quad;
-    uint32_t numberOfQuads = 0u;
+    Vector4   quad;
+    uint32_t  numberOfQuads = 0u;
+    Length    yLineOffset   = 0;
+    Length    prevLineIndex = 0;
+    LineIndex lineIndex;
+    Length    numberOfLines;
 
     for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
     {
@@ -2072,6 +2085,14 @@ Actor Controller::Impl::CreateBackgroundActor()
       const ColorIndex backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + i);
       const Vector4&   backgroundColor      = (0u == backgroundColorIndex) ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
 
+      mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines);
+      Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing;
+
+      if(lineIndex != prevLineIndex)
+      {
+        yLineOffset += lineHeight;
+      }
+
       // Only create quads for glyphs with a background color
       if(backgroundColor != Color::TRANSPARENT)
       {
@@ -2080,30 +2101,30 @@ Actor Controller::Impl::CreateBackgroundActor()
         if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text
         {
           quad.x = position.x;
-          quad.y = 0.0f;
+          quad.y = yLineOffset;
           quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
-          quad.w = textSize.height;
+          quad.w = lineHeight;
         }
-        else if(i == 0u) // The first glyph in the whole text
+        else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line
         {
           quad.x = position.x;
-          quad.y = 0.0f;
+          quad.y = yLineOffset;
           quad.z = quad.x - glyph.xBearing + glyph.advance;
-          quad.w = textSize.height;
+          quad.w = quad.y + lineHeight;
         }
         else if(i == glyphSize - 1u) // The last glyph in the whole text
         {
           quad.x = position.x - glyph.xBearing;
-          quad.y = 0.0f;
+          quad.y = yLineOffset;
           quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
-          quad.w = textSize.height;
+          quad.w = quad.y + lineHeight;
         }
         else // The glyph in the middle of the text
         {
           quad.x = position.x - glyph.xBearing;
-          quad.y = 0.0f;
+          quad.y = yLineOffset;
           quad.z = quad.x + glyph.advance;
-          quad.w = textSize.height;
+          quad.w = quad.y + lineHeight;
         }
 
         BackgroundVertex vertex;
@@ -2142,6 +2163,11 @@ Actor Controller::Impl::CreateBackgroundActor()
 
         numberOfQuads++;
       }
+
+      if(lineIndex != prevLineIndex)
+      {
+        prevLineIndex = lineIndex;
+      }
     }
 
     // Only create the background actor if there are glyphs with background color
@@ -2182,28 +2208,28 @@ Actor Controller::Impl::CreateBackgroundActor()
 
 void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns)
 {
-    //Underlined character runs for markup-processor
-    const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
-    const Vector<GlyphIndex>&             charactersToGlyph       = mModel->mVisualModel->mCharactersToGlyph;
-    const Vector<Length>&                 glyphsPerCharacter      = mModel->mVisualModel->mGlyphsPerCharacter;
+  //Underlined character runs for markup-processor
+  const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
+  const Vector<GlyphIndex>&             charactersToGlyph       = mModel->mVisualModel->mCharactersToGlyph;
+  const Vector<Length>&                 glyphsPerCharacter      = mModel->mVisualModel->mGlyphsPerCharacter;
 
-    if(shouldClearPreUnderlineRuns)
-    {
-        mModel->mVisualModel->mUnderlineRuns.Clear();
-    }
+  if(shouldClearPreUnderlineRuns)
+  {
+    mModel->mVisualModel->mUnderlineRuns.Clear();
+  }
 
-    for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
+  for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
+  {
+    CharacterIndex characterIndex     = it->characterRun.characterIndex;
+    Length         numberOfCharacters = it->characterRun.numberOfCharacters;
+    for(Length index = 0u; index < numberOfCharacters; index++)
     {
-        CharacterIndex characterIndex = it->characterRun.characterIndex;
-        Length numberOfCharacters = it->characterRun.numberOfCharacters;
-        for(Length index=0u; index<numberOfCharacters; index++)
-        {
-          GlyphRun underlineGlyphRun;
-          underlineGlyphRun.glyphIndex     = charactersToGlyph[characterIndex + index];
-          underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index];
-          mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
-        }
+      GlyphRun underlineGlyphRun;
+      underlineGlyphRun.glyphIndex     = charactersToGlyph[characterIndex + index];
+      underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index];
+      mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
     }
+  }
 }
 
 } // namespace Text
index 36a2133..d946365 100644 (file)
@@ -83,7 +83,8 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
                                         logicalModel->mFontDescriptionRuns,
                                         logicalModel->mEmbeddedItems,
                                         logicalModel->mAnchors,
-                                        logicalModel->mUnderlinedCharacterRuns);
+                                        logicalModel->mUnderlinedCharacterRuns,
+                                        logicalModel->mBackgroundColorRuns);
 
     Length         textSize = 0u;
     const uint8_t* utf8     = NULL;
index 6866ff4..a863317 100644 (file)
@@ -1234,28 +1234,37 @@ void Controller::SetInputColor(const Vector4& color)
 
     if(EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState)
     {
-      const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
+      if(EventData::SELECTING == mImpl->mEventData->mState)
+      {
+        const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
+
+        // Get start and end position of selection
+        const CharacterIndex startOfSelectedText  = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
+        const Length         lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
 
-      // Get start and end position of selection
-      const CharacterIndex startOfSelectedText  = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
-      const Length         lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
+        // Add the color run.
+        const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
+        mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
 
-      // Add the color run.
-      const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
-      mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
+        ColorRun& colorRun                       = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
+        colorRun.color                           = color;
+        colorRun.characterRun.characterIndex     = startOfSelectedText;
+        colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
 
-      ColorRun& colorRun                       = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
-      colorRun.color                           = color;
-      colorRun.characterRun.characterIndex     = startOfSelectedText;
-      colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
+        mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
+        mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+        mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
+      }
+      else
+      {
+        mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
+        mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+        mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mModel->mLogicalModel->mText.Count();
+      }
 
       // Request to relayout.
       mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
       mImpl->RequestRelayout();
-
-      mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
-      mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
-      mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
     }
   }
 }
index c116f8f..928c3f0 100644 (file)
@@ -174,6 +174,13 @@ public:
   virtual const ColorIndex* const GetBackgroundColorIndices() const = 0;
 
   /**
+   * @brief checks if there is background colors set using markup.
+   *
+   * @return boolean if there is background colors set using markup .
+   */
+  virtual bool const IsMarkupBackgroundColorSet() const = 0;
+
+  /**
    * @brief Retrieves the text's default color.
    *
    * @return The default color.
index 8565eb3..3868979 100644 (file)
@@ -127,6 +127,11 @@ const ColorIndex* const Model::GetBackgroundColorIndices() const
   return mVisualModel->mBackgroundColorIndices.Begin();
 }
 
+bool const Model::IsMarkupBackgroundColorSet() const
+{
+  return (mVisualModel->mBackgroundColorIndices.Count() > 0);
+}
+
 const Vector4& Model::GetDefaultColor() const
 {
   return mVisualModel->mTextColor;
index 4faa1bc..751f230 100644 (file)
@@ -143,6 +143,11 @@ public:
   const ColorIndex* const GetBackgroundColorIndices() const override;
 
   /**
+   * @copydoc ModelInterface::IsMarkupBackgroundColorSet()
+   */
+  bool const IsMarkupBackgroundColorSet() const override;
+
+  /**
    * @copydoc ModelInterface::GetDefaultColor()
    */
   const Vector4& GetDefaultColor() const override;
index 63f7fd4..ee4c306 100644 (file)
@@ -124,6 +124,13 @@ public:
   virtual const ColorIndex* const GetBackgroundColorIndices() const = 0;
 
   /**
+   * @brief checks if there is background colors set using markup.
+   *
+   * @return boolean if there is background colors set using markup .
+   */
+  virtual bool const IsMarkupBackgroundColorSet() const = 0;
+
+  /**
    * @brief Retrieves the text color
    *
    * @return The text color
index 2f74699..74a83f5 100644 (file)
@@ -343,6 +343,16 @@ const ColorIndex* const View::GetBackgroundColorIndices() const
   return nullptr;
 }
 
+bool const View::IsMarkupBackgroundColorSet() const
+{
+  if(mImpl->mVisualModel)
+  {
+    return (mImpl->mVisualModel->mBackgroundColorIndices.Count() > 0);
+  }
+
+  return false;
+}
+
 const Vector4& View::GetTextColor() const
 {
   if(mImpl->mVisualModel)
index 3790fd0..7c61275 100644 (file)
@@ -96,6 +96,11 @@ public:
   const ColorIndex* const GetBackgroundColorIndices() const override;
 
   /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::IsMarkupBackgroundColorSet()
+   */
+  bool const IsMarkupBackgroundColorSet() const;
+
+  /**
    * @copydoc Dali::Toolkit::Text::ViewInterface::GetTextColor()
    */
   const Vector4& GetTextColor() const override;
diff --git a/dali-toolkit/internal/transition/fade-impl.cpp b/dali-toolkit/internal/transition/fade-impl.cpp
new file mode 100644 (file)
index 0000000..30edc3e
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/transition/fade-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT);
+
+} // anonymous namespace
+
+FadePtr Fade::New(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod)
+{
+  float delaySeconds = timePeriod.delaySeconds;
+  if(delaySeconds < 0.0f)
+  {
+    DALI_LOG_WARNING("delay should be greater than 0.0f.\n");
+    delaySeconds = 0.0f;
+  }
+
+  float durationSeconds = timePeriod.durationSeconds;
+  if(durationSeconds < 0.0f)
+  {
+    DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
+    durationSeconds = 0.0f;
+  }
+
+  FadePtr fade = new Fade(control, Dali::Clamp(opacity, 0.0f, 1.0f), TimePeriod(delaySeconds, durationSeconds));
+
+  // Second-phase construction
+  fade->Initialize();
+
+  return fade;
+}
+
+Fade::Fade(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod)
+: TransitionBase(),
+  mTargetControl(control),
+  mOpacity(opacity)
+{
+  SetTarget(control);
+  SetTimePeriod(timePeriod);
+}
+
+Fade::~Fade()
+{
+}
+
+void Fade::OnPlay()
+{
+  Dali::Toolkit::Control targetControl = mTargetControl.GetHandle();
+  if(!targetControl || !targetControl[Dali::Actor::Property::CONNECTED_TO_SCENE])
+  {
+    DALI_LOG_ERROR("The Control is not added on the window\n");
+    return;
+  }
+
+  Property::Map initialPropertyMap;
+  Property::Map startPropertyMap;
+  Property::Map finishPropertyMap;
+
+  if(IsAppearingTransition())
+  {
+    initialPropertyMap.Insert(Dali::Actor::Property::OPACITY, 0.0f);
+    startPropertyMap.Insert(Dali::Actor::Property::OPACITY, mOpacity);
+    finishPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
+  }
+  else
+  {
+    initialPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
+    startPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
+    finishPropertyMap.Insert(Dali::Actor::Property::OPACITY, mOpacity);
+  }
+
+  SetInitialPropertyMap(initialPropertyMap);
+  SetStartPropertyMap(startPropertyMap);
+  SetFinishPropertyMap(finishPropertyMap);
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/transition/fade-impl.h b/dali-toolkit/internal/transition/fade-impl.h
new file mode 100644 (file)
index 0000000..0ac5c73
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef DALI_TOOLKIT_INTERNAL_FADE_H
+#define DALI_TOOLKIT_INTERNAL_FADE_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/transition/transition-base-impl.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/public-api/transition/fade.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/weak-handle.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+using FadePtr = IntrusivePtr<Fade>;
+
+class Fade : public TransitionBase
+{
+public:
+  /**
+   * @brief Create a new Fade object.
+   * @param[in] control A control of this transition.
+   * @param[in] opacity opacity value the control Opacity property will be changed from/to.
+   * @param[in] timePeriod The duration of the animation.
+   * @return A smart-pointer to the newly allocated Fade.
+   */
+  static FadePtr New(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod);
+
+protected:
+  /**
+   * @copydoc Dali::Toolkit::Fade::OnPlay()
+   */
+  void OnPlay() override;
+
+protected:
+  /**
+   * @brief Construct a new Fade.
+   */
+  Fade(Dali::Toolkit::Control control,
+       float                  opacity,
+       TimePeriod             timePeriod);
+
+  /**
+   * @brief A reference counted object may only be deleted by calling Unreference()
+   */
+  ~Fade() override;
+
+private:
+  // Undefined
+  Fade(const Fade&);
+
+  // Undefined
+  Fade& operator=(const Fade& rhs);
+
+private:
+  WeakHandle<Dali::Toolkit::Control> mTargetControl;
+  float mOpacity;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::Fade& GetImplementation(Dali::Toolkit::Fade& fade)
+{
+  DALI_ASSERT_ALWAYS(fade && "Fade handle is empty");
+
+  BaseObject& handle = fade.GetBaseObject();
+
+  return static_cast<Internal::Fade&>(handle);
+}
+
+inline const Internal::Fade& GetImplementation(const Dali::Toolkit::Fade& fade)
+{
+  DALI_ASSERT_ALWAYS(fade && "Fade handle is empty");
+
+  const BaseObject& handle = fade.GetBaseObject();
+
+  return static_cast<const Internal::Fade&>(handle);
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_FADE_H
index 42fb10d..241eb06 100644 (file)
@@ -104,7 +104,8 @@ TransitionBase::TransitionBase()
 : mAlphaFunction(DEFAULT_ALPHA_FUNCTION),
   mTimePeriod(TimePeriod(0.0f)),
   mTransitionWithChild(false),
-  mMoveTargetChildren(false)
+  mMoveTargetChildren(false),
+  mIsAppearingTransition(true)
 {
 }
 
index 84ef316..b3289ec 100644 (file)
@@ -92,6 +92,15 @@ public:
    */
   void TransitionFinished();
 
+  /**
+   * @brief Set this transition is appearing transition or not.
+   * @param[in] appearingTransition True if this transition is appearing transition.
+   */
+  void SetAppearingTransition(bool appearingTransition)
+  {
+    mIsAppearingTransition = appearingTransition;
+  }
+
 protected:
   /**
    * @brief Set property map which will be used as a initial properties.
@@ -151,11 +160,19 @@ protected:
   /**
    * @brief Returns whether this transition will be applied to children of target or not.
    */
-  bool IsTransitionWithChild()
+  bool IsTransitionWithChild() const
   {
     return mTransitionWithChild;
   }
 
+  /**
+   * @brief Returns whether this transition is appearing transition or not
+   */
+  bool IsAppearingTransition() const
+  {
+    return mIsAppearingTransition;
+  }
+
 protected:
   /**
    * Construct a new TransitionBase.
@@ -234,6 +251,7 @@ private:
   bool                         mTransitionWithChild; ///< True, if mTarget transition is inherit to its child Actors.
                                                      ///< If this is false, the child Actors are moved to the child of mCopiedActor that will have original properties of target Actor during Transition.
   bool mMoveTargetChildren;                          ///< Flag, if mTransitionWithChild is false and mTarget has children than True.
+  bool mIsAppearingTransition;                       ///< True, if this transition is appearing transition.
 };
 
 } // namespace Internal
index ef193f6..a465433 100644 (file)
@@ -79,37 +79,39 @@ Transition::~Transition()
 
 void Transition::OnPlay()
 {
-  if(!mSourceControl[Dali::Actor::Property::CONNECTED_TO_SCENE] ||
-     !mDestinationControl[Dali::Actor::Property::CONNECTED_TO_SCENE])
+  Dali::Toolkit::Control sourceControl = mSourceControl.GetHandle();
+  Dali::Toolkit::Control destinationControl = mDestinationControl.GetHandle();
+  if(!sourceControl || !sourceControl[Dali::Actor::Property::CONNECTED_TO_SCENE] ||
+     !destinationControl || !destinationControl[Dali::Actor::Property::CONNECTED_TO_SCENE])
   {
     DALI_LOG_ERROR("The source or destination is not added on the window\n");
     return;
   }
 
   //Make startPropertyMap and finishPropertyMap to use for property animation.
-  Matrix     sourceWorldTransform = mSourceControl[Dali::Actor::Property::WORLD_MATRIX];
+  Matrix     sourceWorldTransform = sourceControl[Dali::Actor::Property::WORLD_MATRIX];
   Vector3    sourcePosition, sourceScale;
   Quaternion sourceOrientation;
   sourceWorldTransform.GetTransformComponents(sourcePosition, sourceOrientation, sourceScale);
 
-  Matrix     destinationWorldTransform = GetWorldTransform(mDestinationControl);
+  Matrix     destinationWorldTransform = GetWorldTransform(destinationControl);
   Vector3    destinationPosition, destinationScale;
   Quaternion destinationOrientation;
   destinationWorldTransform.GetTransformComponents(destinationPosition, destinationOrientation, destinationScale);
 
-  Vector3       targetSize  = mDestinationControl[Dali::Actor::Property::SIZE];
-  Vector4       targetColor = GetWorldColor(mDestinationControl);
+  Vector3       targetSize  = destinationControl[Dali::Actor::Property::SIZE];
+  Vector4       targetColor = GetWorldColor(destinationControl);
   Property::Map startPropertyMap;
   Property::Map finishPropertyMap;
 
   // Use world transform if this transition requires animation of transform.
-  mDestinationControl[Dali::Actor::Property::ANCHOR_POINT]               = AnchorPoint::CENTER;
-  mDestinationControl[Dali::Actor::Property::PARENT_ORIGIN]              = ParentOrigin::CENTER;
-  mDestinationControl[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT] = true;
-  mDestinationControl[Dali::Actor::Property::INHERIT_POSITION]           = false;
-  mDestinationControl[Dali::Actor::Property::INHERIT_ORIENTATION]        = false;
-  mDestinationControl[Dali::Actor::Property::INHERIT_SCALE]              = false;
-  mDestinationControl[Dali::Actor::Property::COLOR_MODE]                 = Dali::ColorMode::USE_OWN_COLOR;
+  destinationControl[Dali::Actor::Property::ANCHOR_POINT]               = AnchorPoint::CENTER;
+  destinationControl[Dali::Actor::Property::PARENT_ORIGIN]              = ParentOrigin::CENTER;
+  destinationControl[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT] = true;
+  destinationControl[Dali::Actor::Property::INHERIT_POSITION]           = false;
+  destinationControl[Dali::Actor::Property::INHERIT_ORIENTATION]        = false;
+  destinationControl[Dali::Actor::Property::INHERIT_SCALE]              = false;
+  destinationControl[Dali::Actor::Property::COLOR_MODE]                 = Dali::ColorMode::USE_OWN_COLOR;
 
   // Set animation of Transform
   startPropertyMap.Insert(Dali::Actor::Property::POSITION, sourcePosition);
@@ -121,12 +123,12 @@ void Transition::OnPlay()
   startPropertyMap.Insert(Dali::Actor::Property::SCALE, sourceScale);
   finishPropertyMap.Insert(Dali::Actor::Property::SCALE, destinationScale);
 
-  Vector4 sourceColor = mSourceControl.GetCurrentProperty<Vector4>(Dali::Actor::Property::WORLD_COLOR);
+  Vector4 sourceColor = sourceControl.GetCurrentProperty<Vector4>(Dali::Actor::Property::WORLD_COLOR);
   startPropertyMap.Insert(Dali::Actor::Property::COLOR, sourceColor);
   finishPropertyMap.Insert(Dali::Actor::Property::COLOR, targetColor);
 
   // Set animation for other properties if source and destination is different.
-  Vector3 sourceSize = mSourceControl.GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE);
+  Vector3 sourceSize = sourceControl.GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE);
   if(sourceSize != targetSize)
   {
     startPropertyMap.Insert(Dali::Actor::Property::SIZE, sourceSize);
@@ -139,11 +141,11 @@ void Transition::OnPlay()
   // source View becomes transparent during transition.
   if(IsTransitionWithChild())
   {
-    mSourceControl[Dali::Actor::Property::VISIBLE] = false;
+    sourceControl[Dali::Actor::Property::VISIBLE] = false;
   }
   else
   {
-    GetImplementation(mSourceControl).SetTransparent(true);
+    GetImplementation(sourceControl).SetTransparent(true);
   }
 
   Dali::Animation animation = GetAnimation();
@@ -152,18 +154,24 @@ void Transition::OnPlay()
     DALI_LOG_ERROR("animation is still not initialized\n");
     return;
   }
-  Dali::Toolkit::DevelControl::CreateTransitions(mDestinationControl, animation, mSourceControl, GetAlphaFunction(), GetTimePeriod());
+  Dali::Toolkit::DevelControl::CreateTransitions(destinationControl, animation, sourceControl, GetAlphaFunction(), GetTimePeriod());
 }
 
 void Transition::OnFinished()
 {
+  Dali::Toolkit::Control sourceControl = mSourceControl.GetHandle();
+  if(!sourceControl)
+  {
+    return;
+  }
+
   if(IsTransitionWithChild())
   {
-    mSourceControl[Dali::Actor::Property::VISIBLE] = true;
+    sourceControl[Dali::Actor::Property::VISIBLE] = true;
   }
   else
   {
-    GetImplementation(mSourceControl).SetTransparent(false);
+    GetImplementation(sourceControl).SetTransparent(false);
   }
 }
 
index d9120bf..6aa1374 100644 (file)
@@ -23,6 +23,9 @@
 #include <dali-toolkit/public-api/controls/control.h>
 #include <dali-toolkit/public-api/transition/transition.h>
 
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/weak-handle.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -38,7 +41,7 @@ public:
    * @brief Create a new Transition object.
    * @param[in] source A source control of this transition.
    * @param[in] destination A destination control of this transition.
-   * @param[in] durationSeconds The duration of the animation.
+   * @param[in] timePeriod The timePeriod of the animation.
    * @return A smart-pointer to the newly allocated Transition.
    */
   static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod);
@@ -75,8 +78,8 @@ private:
   Transition& operator=(const Transition& rhs);
 
 private:
-  Dali::Toolkit::Control mSourceControl;
-  Dali::Toolkit::Control mDestinationControl;
+  WeakHandle<Dali::Toolkit::Control> mSourceControl;
+  WeakHandle<Dali::Toolkit::Control> mDestinationControl;
 };
 
 } // namespace Internal
index 89f0ec4..abb7fa8 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 30;
+const unsigned int TOOLKIT_MICRO_VERSION = 31;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 071b602..895bfc7 100644 (file)
@@ -31,6 +31,7 @@ SET( public_api_src_files
   ${public_api_src_dir}/image-loader/async-image-loader.cpp
   ${public_api_src_dir}/image-loader/sync-image-loader.cpp
   ${public_api_src_dir}/styling/style-manager.cpp
+  ${public_api_src_dir}/transition/fade.cpp
   ${public_api_src_dir}/transition/transition-base.cpp
   ${public_api_src_dir}/transition/transition-set.cpp
   ${public_api_src_dir}/transition/transition.cpp
@@ -147,6 +148,7 @@ SET( public_api_visuals_header_files
 )
 
 SET( public_api_transition_header_files
+  ${public_api_src_dir}/transition/fade.h
   ${public_api_src_dir}/transition/transition-base.h
   ${public_api_src_dir}/transition/transition-set.h
   ${public_api_src_dir}/transition/transition.h
diff --git a/dali-toolkit/public-api/transition/fade.cpp b/dali-toolkit/public-api/transition/fade.cpp
new file mode 100644 (file)
index 0000000..b5e54dc
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/public-api/transition/fade.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/transition/fade-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+Fade::Fade() = default;
+
+Fade::Fade(Internal::Fade* fade)
+: TransitionBase(fade)
+{
+}
+
+Fade Fade::New(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod)
+{
+  Internal::FadePtr internal = Dali::Toolkit::Internal::Fade::New(control, opacity, timePeriod);
+
+  return Fade(internal.Get());
+}
+
+Fade Fade::DownCast(BaseHandle handle)
+{
+  return Fade(dynamic_cast<Dali::Toolkit::Internal::Fade*>(handle.GetObjectPtr()));
+}
+
+Fade::~Fade() = default;
+
+Fade::Fade(const Fade& handle) = default;
+
+Fade& Fade::operator=(const Fade& rhs) = default;
+
+Fade::Fade(Fade&& rhs) = default;
+
+Fade& Fade::operator=(Fade&& rhs) = default;
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/public-api/transition/fade.h b/dali-toolkit/public-api/transition/fade.h
new file mode 100644 (file)
index 0000000..dbafb7b
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_TOOLKIT_FADE_H
+#define DALI_TOOLKIT_FADE_H
+
+/*
+ * Copyright (c) 2021 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/controls/control.h>
+#include <dali-toolkit/public-api/transition/transition-base.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal DALI_INTERNAL
+{
+class Fade;
+}
+
+/**
+ * @brief Fade provides smoothly appearing/disappearing effects for target Control.
+ */
+class DALI_TOOLKIT_API Fade : public TransitionBase
+{
+public:
+  /**
+   * @brief Creates an uninitialized Fade; this can be initialized with Fade::New().
+   *
+   * Calling member functions with an uninitialized Fade handle is not allowed.
+   */
+  Fade();
+
+  /**
+   * @brief Creates an initialized Fade.
+   *
+   * @param[in] control A control of this transition.
+   * @param[in] opacity opacity value the control Opacity property will be changed from/to. Opacity must be between [0, 1].
+   * @param[in] timePeriod The duration of the animation.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static Fade New(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod);
+
+  /**
+   * @brief Downcasts a handle to Fade handle.
+   *
+   * If handle points to an Fade object, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @param[in] handle Handle to an object
+   * @return Handle to an Fade object or an uninitialized handle
+   */
+  static Fade DownCast(BaseHandle handle);
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~Fade();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @param[in] handle A reference to the copied handle
+   */
+  Fade(const Fade& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @param[in] rhs A reference to the copied handle
+   * @return A reference to this
+   */
+  Fade& operator=(const Fade& rhs);
+
+  /**
+   * @brief Move constructor.
+   *
+   * @param[in] rhs A reference to the moved handle
+   */
+  Fade(Fade&& rhs);
+
+  /**
+   * @brief Move assignment operator.
+   *
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this handle
+   */
+  Fade& operator=(Fade&& rhs);
+
+public: // Not intended for use by Application developers
+  /// @cond internal
+  /**
+   * @brief This constructor is used by Fade::New() methods.
+   * @param[in] fade A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL Fade(Internal::Fade* fade);
+  /// @endcond
+};
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_FADE_H
index 5e70e21..6b88c84 100644 (file)
@@ -76,7 +76,12 @@ AlphaFunction TransitionBase::GetAlphaFunction() const
 
 void TransitionBase::TransitionWithChild(bool transitionWithChild)
 {
-  return GetImplementation(*this).TransitionWithChild(transitionWithChild);
+  GetImplementation(*this).TransitionWithChild(transitionWithChild);
+}
+
+void TransitionBase::SetAppearingTransition(bool appearingTransition)
+{
+  GetImplementation(*this).SetAppearingTransition(appearingTransition);
 }
 
 } // namespace Toolkit
index 9a274ac..6deaeff 100644 (file)
@@ -131,10 +131,17 @@ public:
   AlphaFunction GetAlphaFunction() const;
 
   /**
-   * @brief A View could be transition with its child Views or without them.
+   * @brief A Control could be transition with its child Controls or without them.
+   * @param[in] transitionWithChild True if the Control is transitioned with children.
    */
   void TransitionWithChild(bool transitionWithChild);
 
+  /**
+   * @brief Set this transition is appearing transition or not.
+   * @param[in] appearingTransition True if this transition is appearing transition.
+   */
+  void SetAppearingTransition(bool appearingTransition);
+
 public: // Not intended for use by Application developers
   /// @cond internal
   /**
index 7609a2c..7c53805 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.0.30
+Version:    2.0.31
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT