Fix behaviour when PreeditStyle is REVERSE 15/260515/7
authorBowon Ryu <bowon.ryu@samsung.com>
Mon, 28 Jun 2021 05:31:57 +0000 (14:31 +0900)
committerBowon Ryu <bowon.ryu@samsung.com>
Thu, 1 Jul 2021 03:24:04 +0000 (12:24 +0900)
In REVERSE case, TextColor uses text's background color.
but in most cases, there is no text's background color
and the the default alpha value is 0.
So in this case, the text is not visible. (text color's alpah value becomes 0)

To solve this, if there is no text's background, the control's color is used.
And if there is no control's color, set white or black according to the contrast.
In this case, the color is determined based on W3C recommendations.
(https://www.w3.org/TR/WCAG20/)

Change-Id: I251ec3283d761e08bb8214f4e53b0da05ad9ba4f
Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-editable-control-interface.h

index 1d394e6..024942f 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -386,6 +386,50 @@ int UtcDaliTextControllerImfPreeditStyle(void)
   END_TEST;
 }
 
   END_TEST;
 }
 
+int UtcDaliTextControllerImfPreeditStyleReverse(void)
+{
+  tet_infoline(" UtcDaliTextControllerImfPreeditStyleReverse");
+  ToolkitTestApplication application;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  std::string text;
+  InputMethodContext::EventData imfEvent;
+
+  DALI_TEST_CHECK(controller);
+
+  // Configures the text controller similarly to the text-field.
+  ConfigureTextField(controller);
+
+  InputMethodContext inputMethodContext = InputMethodContext::New();
+
+  // Send PRE_EDIT event
+  imfEvent = InputMethodContext::EventData(InputMethodContext::PRE_EDIT, "Reverse", 0, 7);
+  controller->OnInputMethodContextEvent(inputMethodContext, imfEvent);
+
+  // For coverage, mEditableControlInterface is required.
+  // Creates a temporary text-field to use mEditableControlInterface.
+  TextField field = TextField::New();
+  Toolkit::Internal::TextField& fieldImpl = GetImpl(field);
+  ControllerPtr fieldController = fieldImpl.getController();
+  Controller::Impl& fieldControllerImpl = Controller::Impl::GetImplementation(*fieldController.Get());
+  Controller::Impl& controllerImpl = Controller::Impl::GetImplementation(*controller.Get());
+
+  // For coverage, mEditableControlInterface is required.
+  controllerImpl.mEditableControlInterface = fieldControllerImpl.mEditableControlInterface;
+
+  // Set the preedit style as REVERSE
+  inputMethodContext.SetPreeditStyle(InputMethodContext::PreeditStyle::REVERSE);
+  controller->GetNaturalSize();
+
+  controller->GetText(text);
+  DALI_TEST_EQUALS("Reverse", text, TEST_LOCATION);
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
 int UtcDaliTextControllerTextPopupButtonTouched(void)
 {
   tet_infoline(" UtcDaliTextControllerTextPopupButtonTouched");
 int UtcDaliTextControllerTextPopupButtonTouched(void)
 {
   tet_infoline(" UtcDaliTextControllerTextPopupButtonTouched");
index 09c5078..4aff653 100755 (executable)
@@ -262,4 +262,39 @@ int UtcDaliTextEditorTextWithSpan(void)
   DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
 
   END_TEST;
   DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
 
   END_TEST;
+}
+
+int UtcDaliTextEditorControlBackgroundColor(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextEditorControlBackgroundColor\n");
+
+  TextEditor editor = TextEditor::New();
+  DALI_TEST_CHECK(editor);
+
+  Vector4 backgroundColor;
+
+  editor.SetProperty(TextEditor::Property::TEXT, "Background Color");
+  application.GetScene().Add(editor);
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextEditor& editorImpl = GetImpl(editor);
+  ControllerPtr controller = editorImpl.getController();
+  Controller::Impl& controllerImpl = Controller::Impl::GetImplementation(*controller.Get());
+
+  // Default color is transparent
+  controllerImpl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+  DALI_TEST_EQUALS(backgroundColor, Color::TRANSPARENT, TEST_LOCATION);
+
+  // Set background color to red
+  editor.SetBackgroundColor(Color::RED);
+  application.SendNotification();
+  application.Render();
+
+  // Should be red
+  controllerImpl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+  DALI_TEST_EQUALS(backgroundColor, Color::RED, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
 }
\ No newline at end of file
index 1fbc13e..65de962 100755 (executable)
@@ -346,4 +346,39 @@ int UtcDaliTextFieldTextWithSpan(void)
   DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
 
   END_TEST;
   DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
 
   END_TEST;
+}
+
+int UtcDaliTextFieldControlBackgroundColor(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextFieldControlBackgroundColor\n");
+
+  TextField field = TextField::New();
+  DALI_TEST_CHECK(field);
+
+  Vector4 backgroundColor;
+
+  field.SetProperty(TextField::Property::TEXT, "Background Color");
+  application.GetScene().Add(field);
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextField& fieldImpl = GetImpl(field);
+  ControllerPtr controller = fieldImpl.getController();
+  Controller::Impl& controllerImpl = Controller::Impl::GetImplementation(*controller.Get());
+
+  // Default color is transparent
+  controllerImpl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+  DALI_TEST_EQUALS(backgroundColor, Color::TRANSPARENT, TEST_LOCATION);
+
+  // Set background color to red
+  field.SetBackgroundColor(Color::RED);
+  application.SendNotification();
+  application.Render();
+
+  // Should be red
+  controllerImpl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+  DALI_TEST_EQUALS(backgroundColor, Color::RED, TEST_LOCATION);
+
+  END_TEST;
 }
\ No newline at end of file
 }
\ No newline at end of file
index 56f43ff..af27bd1 100644 (file)
@@ -1949,6 +1949,18 @@ Uint32Pair TextEditor::GetTextSelectionRange() const
   return range;
 }
 
   return range;
 }
 
+void TextEditor::GetControlBackgroundColor(Vector4& color) const
+{
+  Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
+  Property::Map*  resultMap = propValue.GetMap();
+
+  Property::Value* colorValue = nullptr;
+  if(resultMap && (colorValue = resultMap->Find(ColorVisual::Property::MIX_COLOR)))
+  {
+    colorValue->Get(color);
+  }
+}
+
 void TextEditor::UpdateScrollBar()
 {
   using namespace Dali;
 void TextEditor::UpdateScrollBar()
 {
   using namespace Dali;
index 424cda5..9a034a1 100644 (file)
@@ -238,6 +238,11 @@ private: // From Control
    */
   void InputFiltered(Toolkit::InputFilter::Property::Type type) override;
 
    */
   void InputFiltered(Toolkit::InputFilter::Property::Type type) override;
 
+  /**
+   * @copydoc Text::EditableControlInterface::GetControlBackgroundColor()
+   */
+  void GetControlBackgroundColor(Vector4& color) const override;
+
   // From SelectableControlInterface
 public:
   /**
   // From SelectableControlInterface
 public:
   /**
index dbf5624..27eae92 100644 (file)
@@ -1859,6 +1859,18 @@ void TextField::AddDecoration(Actor& actor, bool needsClipping)
   }
 }
 
   }
 }
 
+void TextField::GetControlBackgroundColor(Vector4& color) const
+{
+  Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
+  Property::Map*  resultMap = propValue.GetMap();
+
+  Property::Value* colorValue = nullptr;
+  if(resultMap && (colorValue = resultMap->Find(ColorVisual::Property::MIX_COLOR)))
+  {
+    colorValue->Get(color);
+  }
+}
+
 void TextField::OnSceneConnect(Dali::Actor actor)
 {
   if(mHasBeenStaged)
 void TextField::OnSceneConnect(Dali::Actor actor)
 {
   if(mHasBeenStaged)
@@ -2203,8 +2215,8 @@ Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
   return states;
 }
 
   return states;
 }
 
-bool TextField::AccessibleImpl::InsertText(size_t startPosition,
-                                            std::string text)
+bool TextField::AccessibleImpl::InsertText(size_t      startPosition,
+                                           std::string text)
 {
   auto slf = Toolkit::TextField::DownCast(Self());
   auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 {
   auto slf = Toolkit::TextField::DownCast(Self());
   auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
index d1a2671..ae73c30 100644 (file)
@@ -231,6 +231,11 @@ private: // From Control
    */
   void InputFiltered(Toolkit::InputFilter::Property::Type type) override;
 
    */
   void InputFiltered(Toolkit::InputFilter::Property::Type type) override;
 
+  /**
+   * @copydoc Text::EditableControlInterface::GetControlBackgroundColor()
+   */
+  void GetControlBackgroundColor(Vector4& color) const override;
+
   // From SelectableControlInterface
 public:
   /**
   // From SelectableControlInterface
 public:
   /**
index b8b6f31..12cdae7 100644 (file)
 #include <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
 #include <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+#include <dali-toolkit/internal/text/text-enumerations-impl.h>
 #include <dali-toolkit/internal/text/text-run-container.h>
 #include <dali-toolkit/internal/text/text-selection-handle-controller.h>
 
 #include <dali-toolkit/internal/text/text-run-container.h>
 #include <dali-toolkit/internal/text/text-selection-handle-controller.h>
 
-#include <dali-toolkit/internal/text/text-enumerations-impl.h>
-
 using namespace Dali;
 
 namespace
 using namespace Dali;
 
 namespace
@@ -60,6 +60,14 @@ struct BackgroundMesh
   Vector<unsigned short>   mIndices;  ///< container of indices
 };
 
   Vector<unsigned short>   mIndices;  ///< container of indices
 };
 
+// The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B)
+// based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
+const float         BRIGHTNESS_THRESHOLD = 0.179f;
+const float         CONSTANT_R           = 0.2126f;
+const float         CONSTANT_G           = 0.7152f;
+const float         CONSTANT_B           = 0.0722f;
+const Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f);
+const Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f);
 const Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
 const Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
 const Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
 const Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
 const Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
 const Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
@@ -915,7 +923,23 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
           backgroundColorRun.color                           = textColor;
           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
 
           backgroundColorRun.color                           = textColor;
           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
 
-          Vector4          backgroundColor = mModel->mVisualModel->GetBackgroundColor();
+          Vector4 backgroundColor = mModel->mVisualModel->GetBackgroundColor();
+          if(backgroundColor.a == 0) // There is no text background color.
+          {
+            // Try use the control's background color.
+            if(nullptr != mEditableControlInterface)
+            {
+              mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+              if(backgroundColor.a == 0) // There is no control background color.
+              {
+                // Determines black or white color according to text color.
+                // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
+                float L         = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
+                backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
+              }
+            }
+          }
+
           Vector<ColorRun> colorRuns;
           colorRuns.Resize(1u);
           ColorRun& colorRun                       = *(colorRuns.Begin());
           Vector<ColorRun> colorRuns;
           colorRuns.Resize(1u);
           ColorRun& colorRun                       = *(colorRuns.Begin());
index af2abd0..e128ac4 100644 (file)
@@ -93,6 +93,13 @@ public:
   virtual void AddDecoration(Actor& actor, bool needsClipping) = 0;
 
   /**
   virtual void AddDecoration(Actor& actor, bool needsClipping) = 0;
 
   /**
+   * @brief Gets the color of the control.
+   *
+   * @param[out] The color of the control.
+   */
+  virtual void GetControlBackgroundColor(Vector4& color) const = 0;
+
+  /**
    * @brief Editable status (on/off).
    *
    * @return true if it can be edit, else false.
    * @brief Editable status (on/off).
    *
    * @return true if it can be edit, else false.