[dali_2.1.28] Merge branch 'devel/master' 96/276796/1 master
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 24 Jun 2022 13:09:32 +0000 (14:09 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 24 Jun 2022 13:09:32 +0000 (14:09 +0100)
Change-Id: I7fb722f798cabfbf10e2e08917edb27a1db690b5

99 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-LineHelperFunctions.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-AbstractStyleCharacterRun.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-CharacterSpacing.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Ellipsis.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp [changed mode: 0755->0644]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp
automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-Control.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp
automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp
build/tizen/dali-scene-loader/CMakeLists.txt
dali-scene-loader/public-api/dli-loader.cpp
dali-toolkit/devel-api/focus-manager/focus-finder.cpp
dali-toolkit/devel-api/styling/style-manager-devel.cpp
dali-toolkit/devel-api/styling/style-manager-devel.h
dali-toolkit/devel-api/text/text-utils-devel.cpp
dali-toolkit/devel-api/visuals/image-visual-properties-devel.h
dali-toolkit/internal/controls/text-controls/common-text-utils.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/graphics/shaders/animated-gradient-visual-shader.vert
dali-toolkit/internal/graphics/shaders/arc-visual-shader.vert
dali-toolkit/internal/graphics/shaders/border-visual-shader.vert
dali-toolkit/internal/graphics/shaders/color-visual-shader.frag
dali-toolkit/internal/graphics/shaders/color-visual-shader.vert
dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag
dali-toolkit/internal/graphics/shaders/gradient-visual-shader.vert
dali-toolkit/internal/graphics/shaders/image-visual-shader.frag
dali-toolkit/internal/graphics/shaders/image-visual-shader.vert
dali-toolkit/internal/graphics/shaders/mesh-visual-normal-map-shader.vert
dali-toolkit/internal/graphics/shaders/mesh-visual-shader.vert
dali-toolkit/internal/graphics/shaders/mesh-visual-simple-shader.vert
dali-toolkit/internal/graphics/shaders/npatch-visual-3x3-shader.vert
dali-toolkit/internal/graphics/shaders/npatch-visual-shader.vert
dali-toolkit/internal/graphics/shaders/primitive-visual-shader.vert
dali-toolkit/internal/graphics/shaders/text-scroller-shader.vert
dali-toolkit/internal/graphics/shaders/text-visual-shader.vert
dali-toolkit/internal/graphics/shaders/wireframe-visual-shader.vert
dali-toolkit/internal/styling/style-manager-impl.cpp
dali-toolkit/internal/styling/style-manager-impl.h
dali-toolkit/internal/text/abstract-style-character-run.cpp [new file with mode: 0644]
dali-toolkit/internal/text/abstract-style-character-run.h [new file with mode: 0644]
dali-toolkit/internal/text/bounded-paragraph-run.h
dali-toolkit/internal/text/character-spacing-character-run.h
dali-toolkit/internal/text/color-run.h
dali-toolkit/internal/text/font-description-run.h
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/line-helper-functions.cpp [new file with mode: 0644]
dali-toolkit/internal/text/line-helper-functions.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor.cpp
dali-toolkit/internal/text/multi-language-support-impl.cpp
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/rendering/view-model.cpp
dali-toolkit/internal/text/strikethrough-character-run.h
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller-relayouter.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/underlined-character-run.h
dali-toolkit/internal/texture-manager/texture-cache-manager.cpp
dali-toolkit/internal/texture-manager/texture-cache-manager.h
dali-toolkit/internal/texture-manager/texture-manager-impl.cpp
dali-toolkit/internal/texture-manager/texture-manager-impl.h
dali-toolkit/internal/texture-manager/texture-manager-type.h
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.h
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/color/color-visual.cpp
dali-toolkit/internal/visuals/color/color-visual.h
dali-toolkit/internal/visuals/gradient/gradient-visual.cpp
dali-toolkit/internal/visuals/image-visual-shader-factory.cpp
dali-toolkit/internal/visuals/image-visual-shader-factory.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/visual-base-data-impl.cpp
dali-toolkit/internal/visuals/visual-base-data-impl.h
dali-toolkit/internal/visuals/visual-base-impl.cpp
dali-toolkit/internal/visuals/visual-base-impl.h
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-string-constants.cpp
dali-toolkit/internal/visuals/visual-string-constants.h
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/public-api/visuals/image-visual-properties.h
packaging/dali-toolkit.spec

index 035f6c3..ed393f0 100755 (executable)
@@ -16,8 +16,10 @@ SET(TC_SOURCES
  utc-Dali-Dictionary.cpp
  utc-Dali-FeedbackStyle.cpp
  utc-Dali-ItemView-internal.cpp
+ utc-Dali-LineHelperFunctions.cpp
  utc-Dali-LogicalModel.cpp
  utc-Dali-PropertyHelper.cpp
+ utc-Dali-Text-AbstractStyleCharacterRun.cpp
  utc-Dali-Text-Characters.cpp
  utc-Dali-Text-CharacterSetConversion.cpp
  utc-Dali-Text-Circular.cpp
index e8bbb21..5b8469d 100644 (file)
@@ -351,11 +351,13 @@ void CreateTextModel(const std::string&                text,
   layoutParameters.startLineIndex         = 0u;
   layoutParameters.estimatedNumberOfLines = logicalModel->mParagraphInfo.Count();
 
-  bool isAutoScroll = false;
+  bool isAutoScroll                   = false;
+  bool isAutoScrollMaxTextureExceeded = false;
   layoutEngine.LayoutText(layoutParameters,
                           layoutSize,
                           false,
                           isAutoScroll,
+                          isAutoScrollMaxTextureExceeded,
                           ellipsisPosition);
 
   if(options.align)
index df21268..29aa513 100644 (file)
@@ -598,6 +598,16 @@ int UtcDaliAccessibilityTextField(void)
   DALI_TEST_EQUALS( text->SetRangeOfSelection( 1, 0, 1 ), false, TEST_LOCATION );
   DALI_TEST_EQUALS( text->RemoveSelection( 1 ), false, TEST_LOCATION );
 
+  // Insert into empty field
+  DALI_TEST_EQUALS(editabletext->SetTextContents(""), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(editabletext->InsertText(1, "xyz"), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(editabletext->InsertText(0, "abc"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(text->GetText(0, 3), "abc", TEST_LOCATION);
+
+  // Append at end
+  DALI_TEST_EQUALS(editabletext->InsertText(3, "xyz"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(text->GetText(0, 6), "abcxyz", TEST_LOCATION);
+
   DALI_TEST_EQUALS(editabletext->SetTextContents("adef"), true, TEST_LOCATION);
   DALI_TEST_EQUALS(editabletext->InsertText(1, "bc"), true, TEST_LOCATION);
   DALI_TEST_EQUALS(text->GetText(0, 6), "abcdef", TEST_LOCATION);
@@ -699,6 +709,16 @@ int UtcDaliAccessibilityTextEditor(void)
   DALI_TEST_EQUALS( text->SetRangeOfSelection( 1, 0, 1 ), false, TEST_LOCATION );
   DALI_TEST_EQUALS( text->RemoveSelection( 1 ), false, TEST_LOCATION );
 
+  // Insert into empty field
+  DALI_TEST_EQUALS(editabletext->SetTextContents(""), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(editabletext->InsertText(1, "xyz"), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(editabletext->InsertText(0, "abc"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(text->GetText(0, 3), "abc", TEST_LOCATION);
+
+  // Append at end
+  DALI_TEST_EQUALS(editabletext->InsertText(3, "xyz"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(text->GetText(0, 6), "abcxyz", TEST_LOCATION);
+
   DALI_TEST_EQUALS(editabletext->SetTextContents("adef"), true, TEST_LOCATION);
   DALI_TEST_EQUALS(editabletext->InsertText(1, "bc"), true, TEST_LOCATION);
   DALI_TEST_EQUALS(text->GetText(0, 6), "abcdef", TEST_LOCATION);
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-LineHelperFunctions.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-LineHelperFunctions.cpp
new file mode 100644 (file)
index 0000000..2930c6d
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2020 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 <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/internal/text/line-helper-functions.h>
+#include <dali-toolkit/internal/text/rendering/text-typesetter.h>
+#include <dali-toolkit/internal/text/rendering/view-model.h>
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <toolkit-text-utils.h>
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+int UtcDaliGetPreOffsetVerticalLineAlignmentWithNegativeLineSpacing(void)
+{
+  tet_infoline(" UtcDaliGetPreOffsetVerticalLineAlignmentWithNegativeLineSpacing ");
+  ToolkitTestApplication application;
+
+  uint32_t expectedNumberOfLines = 2u;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-label.
+  ConfigureTextLabel(controller);
+
+  // Sets the text.
+  controller->SetMarkupProcessorEnabled(true);
+  controller->SetTextElideEnabled(false);
+  controller->SetText("<p rel-line-height=0.5>Line one Line two</p>");
+
+  // Creates the text's model and relais-out the text.
+  const Size relayoutSize(120.f, 100.f);
+  controller->Relayout(relayoutSize);
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+  DALI_TEST_CHECK(model);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(model->GetNumberOfLines(), expectedNumberOfLines, TEST_LOCATION);
+  DALI_TEST_CHECK(model->GetLines());
+
+  const LineRun& lineOne = *(model->GetLines() + 0u);
+  const LineRun& lineTwo = *(model->GetLines() + 1u);
+
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliGetPreOffsetVerticalLineAlignmentWithPositiveLineSpacing(void)
+{
+  tet_infoline(" UtcDaliGetPreOffsetVerticalLineAlignmentWithPositiveLineSpacing ");
+  ToolkitTestApplication application;
+
+  uint32_t expectedNumberOfLines = 2u;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-label.
+  ConfigureTextLabel(controller);
+
+  // Sets the text.
+  controller->SetMarkupProcessorEnabled(true);
+  controller->SetTextElideEnabled(false);
+  controller->SetText("<p rel-line-height=2.0>Line one Line two</p>");
+
+  // Creates the text's model and relais-out the text.
+  const Size relayoutSize(120.f, 100.f);
+  controller->Relayout(relayoutSize);
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+  DALI_TEST_CHECK(model);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(model->GetNumberOfLines(), expectedNumberOfLines, TEST_LOCATION);
+  DALI_TEST_CHECK(model->GetLines());
+
+  const LineRun& lineOne = *(model->GetLines() + 0u);
+  const LineRun& lineTwo = *(model->GetLines() + 1u);
+
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 9.5f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 19.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliGetPostOffsetVerticalLineAlignmentWithNegativeLineSpacing(void)
+{
+  tet_infoline(" UtcDaliGetPostOffsetVerticalLineAlignmentWithNegativeLineSpacing ");
+  ToolkitTestApplication application;
+
+  uint32_t expectedNumberOfLines = 2u;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-label.
+  ConfigureTextLabel(controller);
+
+  // Sets the text.
+  controller->SetMarkupProcessorEnabled(true);
+  controller->SetTextElideEnabled(false);
+  controller->SetText("<p rel-line-height=0.5>Line one Line two</p>");
+
+  // Creates the text's model and relais-out the text.
+  const Size relayoutSize(120.f, 100.f);
+  controller->Relayout(relayoutSize);
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+  DALI_TEST_CHECK(model);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(model->GetNumberOfLines(), expectedNumberOfLines, TEST_LOCATION);
+  DALI_TEST_CHECK(model->GetLines());
+
+  const LineRun& lineOne = *(model->GetLines() + 0u);
+  const LineRun& lineTwo = *(model->GetLines() + 1u);
+
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), -9.5f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), -9.5f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), -9.5f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliGetPostOffsetVerticalLineAlignmentWithPositiveLineSpacing(void)
+{
+  tet_infoline(" UtcDaliGetPostOffsetVerticalLineAlignmentWithPositiveLineSpacing ");
+  ToolkitTestApplication application;
+
+  uint32_t expectedNumberOfLines = 2u;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-label.
+  ConfigureTextLabel(controller);
+
+  // Sets the text.
+  controller->SetMarkupProcessorEnabled(true);
+  controller->SetTextElideEnabled(false);
+  controller->SetText("<p rel-line-height=2.0>Line one Line two</p>");
+
+  // Creates the text's model and relais-out the text.
+  const Size relayoutSize(120.f, 100.f);
+  controller->Relayout(relayoutSize);
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+  DALI_TEST_CHECK(model);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(model->GetNumberOfLines(), expectedNumberOfLines, TEST_LOCATION);
+  DALI_TEST_CHECK(model->GetLines());
+
+  const LineRun& lineOne = *(model->GetLines() + 0u);
+  const LineRun& lineTwo = *(model->GetLines() + 1u);
+
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 19.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 9.5f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-AbstractStyleCharacterRun.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-AbstractStyleCharacterRun.cpp
new file mode 100644 (file)
index 0000000..f6d1827
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2022 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 <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-character-run.h>
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/strikethrough-character-run.h>
+#include <dali-toolkit/internal/text/underlined-character-run.h>
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions for AbstractStyleCharacterRun.
+//  CharacterIndex GetStartCharacterIndex() const;
+//  Length GetNumberOfCharacters() const;
+//  CharacterIndex GetEndCharacterIndex() const;
+
+template<typename TYPE_OF_RUN>
+void TestAbstractStyleCharacterRunEmptyCharacterRun(std::string test_name)
+{
+  tet_infoline(" TestAbstractStyleCharacterRunEmptyCharacterRun ");
+  std::cout << "  testing " << test_name << std::endl;
+
+  tet_infoline(" Default Constructor ");
+  TYPE_OF_RUN abstractStyleCharacterRun;
+
+  tet_infoline(" AbstractStyleCharacterRun_GetStartCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetStartCharacterIndex(), 0u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetNumberOfCharacters ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetNumberOfCharacters(), 0u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetEndCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetEndCharacterIndex(), 0u, TEST_LOCATION);
+}
+
+template<typename TYPE_OF_RUN>
+void TestAbstractStyleCharacterRunOneCharacter(std::string test_name)
+{
+  tet_infoline(" TestAbstractStyleCharacterRunOneCharacter ");
+  std::cout << "  testing " << test_name << std::endl;
+
+  TYPE_OF_RUN abstractStyleCharacterRun;
+  abstractStyleCharacterRun.characterRun.numberOfCharacters = 1u;
+  tet_infoline(" AbstractStyleCharacterRun_GetStartCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetStartCharacterIndex(), 0u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetNumberOfCharacters ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetNumberOfCharacters(), 1u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetEndCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetEndCharacterIndex(), 0u, TEST_LOCATION);
+
+  abstractStyleCharacterRun.characterRun.characterIndex = 5u;
+  tet_infoline(" AbstractStyleCharacterRun_GetStartCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetStartCharacterIndex(), 5u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetNumberOfCharacters ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetNumberOfCharacters(), 1u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetEndCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetEndCharacterIndex(), 5u, TEST_LOCATION);
+}
+
+template<typename TYPE_OF_RUN>
+void TestAbstractStyleCharacterRunMoreThanOneCharacter(std::string test_name)
+{
+  tet_infoline(" TestAbstractStyleCharacterRunOneCharacter ");
+  std::cout << "  testing " << test_name << std::endl;
+
+  TYPE_OF_RUN abstractStyleCharacterRun;
+  abstractStyleCharacterRun.characterRun.numberOfCharacters = 15u;
+  tet_infoline(" AbstractStyleCharacterRun_GetStartCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetStartCharacterIndex(), 0u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetNumberOfCharacters ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetNumberOfCharacters(), 15u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetEndCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetEndCharacterIndex(), 14u, TEST_LOCATION);
+
+  abstractStyleCharacterRun.characterRun.characterIndex = 5u;
+  tet_infoline(" AbstractStyleCharacterRun_GetStartCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetStartCharacterIndex(), 5u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetNumberOfCharacters ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetNumberOfCharacters(), 15u, TEST_LOCATION);
+
+  tet_infoline(" AbstractStyleCharacterRun_GetEndCharacterIndex ");
+  DALI_TEST_EQUALS(abstractStyleCharacterRun.GetEndCharacterIndex(), 19u, TEST_LOCATION);
+}
+
+int UtcDaliTextAbstractStyleCharacterRun(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAbstractStyleCharacterRun");
+
+  TestAbstractStyleCharacterRunEmptyCharacterRun<Dali::Toolkit::Text::ColorRun>("ColorRun");
+  TestAbstractStyleCharacterRunEmptyCharacterRun<Dali::Toolkit::Text::CharacterSpacingCharacterRun>("CharacterSpacingCharacterRun");
+  TestAbstractStyleCharacterRunEmptyCharacterRun<Dali::Toolkit::Text::FontDescriptionRun>("FontDescriptionRun");
+  TestAbstractStyleCharacterRunEmptyCharacterRun<Dali::Toolkit::Text::UnderlinedCharacterRun>("UnderlinedCharacterRun");
+  TestAbstractStyleCharacterRunEmptyCharacterRun<Dali::Toolkit::Text::StrikethroughCharacterRun>("StrikethroughCharacterRun");
+  TestAbstractStyleCharacterRunEmptyCharacterRun<Dali::Toolkit::Text::BoundedParagraphRun>("BoundedParagraphRun");
+
+  TestAbstractStyleCharacterRunOneCharacter<Dali::Toolkit::Text::ColorRun>("ColorRun");
+  TestAbstractStyleCharacterRunOneCharacter<Dali::Toolkit::Text::CharacterSpacingCharacterRun>("CharacterSpacingCharacterRun");
+  TestAbstractStyleCharacterRunOneCharacter<Dali::Toolkit::Text::FontDescriptionRun>("FontDescriptionRun");
+  TestAbstractStyleCharacterRunOneCharacter<Dali::Toolkit::Text::UnderlinedCharacterRun>("UnderlinedCharacterRun");
+  TestAbstractStyleCharacterRunOneCharacter<Dali::Toolkit::Text::StrikethroughCharacterRun>("StrikethroughCharacterRun");
+  TestAbstractStyleCharacterRunOneCharacter<Dali::Toolkit::Text::BoundedParagraphRun>("BoundedParagraphRun");
+
+  TestAbstractStyleCharacterRunMoreThanOneCharacter<Dali::Toolkit::Text::ColorRun>("ColorRun");
+  TestAbstractStyleCharacterRunMoreThanOneCharacter<Dali::Toolkit::Text::CharacterSpacingCharacterRun>("CharacterSpacingCharacterRun");
+  TestAbstractStyleCharacterRunMoreThanOneCharacter<Dali::Toolkit::Text::FontDescriptionRun>("FontDescriptionRun");
+  TestAbstractStyleCharacterRunMoreThanOneCharacter<Dali::Toolkit::Text::UnderlinedCharacterRun>("UnderlinedCharacterRun");
+  TestAbstractStyleCharacterRunMoreThanOneCharacter<Dali::Toolkit::Text::StrikethroughCharacterRun>("StrikethroughCharacterRun");
+  TestAbstractStyleCharacterRunMoreThanOneCharacter<Dali::Toolkit::Text::BoundedParagraphRun>("BoundedParagraphRun");
+
+  END_TEST;
+}
index f636a19..5a15b09 100644 (file)
@@ -180,11 +180,13 @@ bool LayoutTextTest(const LayoutTextData& data)
 
   layoutSize = Vector2::ZERO;
 
-  bool       isAutoScroll = false;
-  const bool updated      = engine.LayoutText(layoutParameters,
+  bool       isAutoScroll                   = false;
+  bool       isAutoScrollMaxTextureExceeded = false;
+  const bool updated                        = engine.LayoutText(layoutParameters,
                                          layoutSize,
                                          data.ellipsis,
                                          isAutoScroll,
+                                         isAutoScrollMaxTextureExceeded,
                                          DevelText::EllipsisPosition::END);
 
   // 4) Compare the results.
index bab8800..75d8bb4 100755 (executable)
@@ -74,7 +74,7 @@ namespace
     ControllerPtr controller = Controller::New();
 
     // Tests the rendering controller has been created.
-    TypesetterPtr typesetter = Typesetter::New( controller->GetTextModel() );
+    TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
     DALI_TEST_CHECK(typesetter);
 
     // Tests the view model has been created.
@@ -91,7 +91,7 @@ namespace
     controller->SetLineWrapMode( (Text::LineWrap::Mode)(data.lineWrapMode) );
     controller->SetEllipsisPosition( data.ellipsisPosition );
 
-    controller->SetText( data.text );
+    controller->SetText(data.text);
     controller->Relayout( data.size );
 
     // Elide the glyphs.
@@ -532,780 +532,736 @@ int UtcDaliTextLabelElideTextLocation(void)
   Size  textSize36( 120.0f, 30.0f );
   float positions36[] = { 0.0f, 10.0f, 21.0f, 25.0f, 28.0f, 38.0f, 44.0f, 55.0f };
 
+  Size  textSize37(145.0f, 30.0f);
+  float positions37[] = {131.0f, 126.0f, 121.0f, 116.0f, 108.0f, 103.0f, 93.0f, 88.0f, 20.0f, 29.0f, 34.0f, 42.0f, 48.0f, 57.0f, 67.0f};
+
+  Size  textSize38(145.0f, 30.0f);
+  float positions38[] = {51.0f, 66.0f, 71.0f, 79.0f, 85.0f, 94.0f, 103.0f, 109.0f, 119.0f, 51.0f, 37.0f, 32.0f, 27.0f, 23.0f, 14.0f, 10.0f, 0.0f};
+
   struct ElideData data[] =
-  {
     {
-      "void text",
-      "",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize00,
-      0u,
-      0u,
-      nullptr
-    },
+      {"void text",
+       "",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize00,
+       0u,
+       0u,
+       nullptr},
+
+      {"void text",
+       "",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize00,
+       0u,
+       0u,
+       nullptr},
+
+      {"void text",
+       "",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize00,
+       0u,
+       0u,
+       nullptr},
+
+      //END LTR cases
+      {
+        "EllipsisPosition: TextLabel: Basic case SingleLine LTR END",
+        "A0123456789 B0123456789 C0123456789 D0123456789 ",
+        false,
+        DevelText::LineWrap::WORD,
+        DevelText::EllipsisPosition::END,
+        false,
+        textSize01,
+        1u,
+        10u,
+        positions01},
+
+      {"EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR END",
+       "A0123456789 B0123456789 C0123456789 D0123456789 ",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize02,
+       2u,
+       22u,
+       positions02},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR END",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize03,
+       3u,
+       29u,
+       positions03},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR END",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::CHARACTER,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize04,
+       3u,
+       40u,
+       positions04},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR END",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::HYPHENATION,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize05,
+       3u,
+       32u,
+       positions05},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR END",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::MIXED,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize06,
+       3u,
+       28u,
+       positions06},
+
+      //START LTR cases
+      {
+        "EllipsisPosition: TextLabel: Basic case SingleLine LTR START",
+        "A0123456789 B0123456789 C0123456789 D0123456789 ",
+        false,
+        DevelText::LineWrap::WORD,
+        DevelText::EllipsisPosition::START,
+        false,
+        textSize07,
+        1u,
+        11u,
+        positions07,
+
+      },
+
+      {"EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR START",
+       "A0123456789 B0123456789 C0123456789 D0123456789 ",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize08,
+       2u,
+       23u,
+       positions08},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR START",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize09,
+       3u,
+       33u,
+       positions09},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR START",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::CHARACTER,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize10,
+       3u,
+       37u,
+       positions10},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR START",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::HYPHENATION,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize11,
+       3u,
+       25u,
+       positions11},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR START",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::MIXED,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize12,
+       3u,
+       25u,
+       positions12},
+
+      //END RTL cases
+      {
+        "EllipsisPosition: TextLabel: SingleLine RTL END",
+        "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+        false,
+        DevelText::LineWrap::WORD,
+        DevelText::EllipsisPosition::END,
+        false,
+        textSize13,
+        1u,
+        14u,
+        positions13},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL END",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize14,
+       3u,
+       42u,
+       positions14},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL END",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::CHARACTER,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize15,
+       3u,
+       44u,
+       positions15},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL END",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::HYPHENATION,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize16,
+       3u,
+       39u,
+       positions16},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL END",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::MIXED,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize17,
+       3u,
+       39u,
+       positions17},
+
+      //START RTL cases
+      {
+        "EllipsisPosition: TextLabel: SingleLine RTL START",
+        "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+        false,
+        DevelText::LineWrap::WORD,
+        DevelText::EllipsisPosition::START,
+        false,
+        textSize18,
+        1u,
+        13u,
+        positions18},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL START",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize19,
+       3u,
+       33u,
+       positions19},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL START",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::CHARACTER,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize20,
+       3u,
+       30u,
+       positions20},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL START",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::HYPHENATION,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize21,
+       3u,
+       33u,
+       positions21},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL START",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::MIXED,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize22,
+       3u,
+       33u,
+       positions22},
+
+      //MIDDLE LTR cases
+      {
+        "EllipsisPosition: TextLabel: Basic case SingleLine LTR MIDDLE",
+        "ABCDEFGHIJKLMNPQRSTUVWXYZ abcdefghijklmnpqrstuvwxyz",
+        false,
+        DevelText::LineWrap::WORD,
+        DevelText::EllipsisPosition::MIDDLE,
+        false,
+        textSize23,
+        1u,
+        10u,
+        positions23},
+
+      {"EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR MIDDLE",
+       "A0123456789 B0123456789 C0123456789 D0123456789 ",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize24,
+       2u,
+       22u,
+       positions24},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR MIDDLE",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize25,
+       3u,
+       24u,
+       positions25},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR MIDDLE",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye",
+       true,
+       DevelText::LineWrap::CHARACTER,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize26,
+       3u,
+       36u,
+       positions26},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR MIDDLE",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye",
+       true,
+       DevelText::LineWrap::HYPHENATION,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize27,
+       3u,
+       27u,
+       positions27},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR MIDDLE",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye",
+       true,
+       DevelText::LineWrap::MIXED,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize28,
+       3u,
+       24u,
+       positions28},
+
+      //MIDDLE RTL cases
+      {
+        "EllipsisPosition: TextLabel: SingleLine RTL MIDDLE",
+        "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+        false,
+        DevelText::LineWrap::WORD,
+        DevelText::EllipsisPosition::MIDDLE,
+        false,
+        textSize29,
+        1u,
+        13u,
+        positions29},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL MIDDLE",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize30,
+       3u,
+       31u,
+       positions30},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL MIDDLE",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::CHARACTER,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize31,
+       3u,
+       29u,
+       positions31},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL MIDDLE",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::HYPHENATION,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize32,
+       3u,
+       31u,
+       positions32},
+
+      {"EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL MIDDLE",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       true,
+       DevelText::LineWrap::MIXED,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize33,
+       3u,
+       31u,
+       positions33},
+
+      {"EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR END",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize34,
+       1u,
+       13u,
+       positions34},
+
+      {"EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR START",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize35,
+       1u,
+       11u,
+       positions35},
+
+      {"EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR MIDDLE",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       true,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize36,
+       1u,
+       12u,
+       positions36},
+
+      {"EllipsisPosition: TextLabel: Mixed Directions Languages END",
+       "سیٹنگیں Projector سیٹنگیں",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize37,
+       1u,
+       16u,
+       positions37},
+
+      {"EllipsisPosition: TextLabel: Mixed Directions Languages START",
+       "سیٹنگیں Projector سیٹنگیں",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize38,
+       1u,
+       17u,
+       positions38},
+
+    };
+  const unsigned int numberOfTests = 41u;
 
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !ElideTestViewModel( data[index] ) )
     {
-      "void text",
-      "",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize00,
-      0u,
-      0u,
-      nullptr
-    },
+      tet_result(TET_FAIL);
+    }
+  }
 
-    {
-      "void text",
-      "",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize00,
-      0u,
-      0u,
-      nullptr
-    },
+  tet_result(TET_PASS);
+  END_TEST;
+}
 
-   //END LTR cases
-    {
-      "EllipsisPosition: TextLabel: Basic case SingleLine LTR END",
-      "A0123456789 B0123456789 C0123456789 D0123456789 ",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize01,
-      1u,
-      10u,
-      positions01
-    },
 
-    {
-      "EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR END",
-      "A0123456789 B0123456789 C0123456789 D0123456789 ",
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize02,
-      2u,
-      22u,
-      positions02
-    },
+int UtcDaliTextFieldlElideTextLocation(void)
+{
+  tet_infoline(" UtcDaliTextFieldlElideTextLocation ");
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR END",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize03,
-      3u,
-      29u,
-      positions03
-    },
+  Size textSize00( 100.f, 100.f );
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR END",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::CHARACTER,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize04,
-      3u,
-      40u,
-      positions04
-    },
+  Size  textSize01( 120.0f, 50.0f );
+  float positions01[] = { 0.0f, 11.0f, 21.0f, 31.0f, 41.0f, 50.0f, 60.0f, 70.0f, 80.0f, 91.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR END",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::HYPHENATION,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize05,
-      3u,
-      32u,
-      positions05
-    },
+  Size  textSize02( 120.0f, 50.0f );
+  float positions02[] = { 0.0f, 10.0f, 21.0f, 25.0f, 28.0f, 38.0f, 44.0f, 55.0f, 59.0f, 65.0f, 73.0f, 84.0f, 93.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR END",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::MIXED,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize06,
-      3u,
-      28u,
-      positions06
-    },
+  Size  textSize03( 120.0f, 50.0f );
+  float positions03[] = { 117.0f, 111.0f, 97.0f, 88.0f, 80.0f, 74.0f, 64.0f, 59.0f, 54.0f, 45.0f, 37.0f, 31.0f, 22.0f, 7.0f };
 
-   //START LTR cases
-    {
-      "EllipsisPosition: TextLabel: Basic case SingleLine LTR START",
-      "A0123456789 B0123456789 C0123456789 D0123456789 ",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize07,
-      1u,
-      11u,
-      positions07
-    },
+  Size  textSize04( 120.0f, 50.0f );
+  float positions04[] = { 5.0f, 21.0f, 31.0f, 41.0f, 50.0f, 61.0f, 71.0f, 80.0f, 90.0f, 100.0f, 109.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR START",
-      "A0123456789 B0123456789 C0123456789 D0123456789 ",
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize08,
-      2u,
-      23u,
-      positions08
-    },
+  Size  textSize05( 120.0f, 50.0f );
+  float positions05[] = { 8.0f, 24.0f, 35.0f, 44.0f, 49.0f, 63.0f, 74.0f, 77.0f, 85.0f, 96.0f, 110.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR START",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize09,
-      3u,
-      33u,
-      positions09
-    },
+  Size  textSize06( 120.0f, 50.0f );
+  float positions06[] = { 90.0f, 79.0f, 70.0f, 68.0f, 62.0f, 56.0f, 51.0f, 42.0f, 29.0f, 26.0f, 15.0f, 7.0f, 0.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR START",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::CHARACTER,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize10,
-      3u,
-      37u,
-      positions10
-    },
+  Size  textSize07( 120.0f, 50.0f );
+  float positions07[] = { 0.0f, 11.0f, 21.0f, 31.0f, 41.0f, 53.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR START",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::HYPHENATION,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize11,
-      3u,
-      25u,
-      positions11
-    },
+  Size  textSize08( 120.0f, 50.0f );
+  float positions08[] = { 0.0f, 10.0f, 21.0f, 25.0f, 28.0f, 38.0f, 44.0f, 55.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR START",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::MIXED,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize12,
-      3u,
-      25u,
-      positions12
-    },
+  Size  textSize09( 120.0f, 50.0f );
+  float positions09[] = { 116.0f, 109.0f, 96.0f, 87.0f, 79.0f, 73.0f, 63.0f };
 
-  //END RTL cases
-    {
-      "EllipsisPosition: TextLabel: SingleLine RTL END",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize13,
-      1u,
-      14u,
-      positions13
-    },
+  Size  textSize10( 120.0f, 50.0f );
+  float positions10[] = { 121.0f, 116.0f, 111.0f, 106.0f, 101.0f, 96.0f, 92.0f, 87.0f, 83.0f, 77.0f, 63.0f, 55.0f, 46.0f, 40.0f, 30.0f, 16.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL END",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize14,
-      3u,
-      42u,
-      positions14
-    },
+  Size  textSize11( 120.0f, 50.0f );
+  float positions11[] = { 93.0f, 77.0f, 74.0f, 63.0f, 56.0f, 49.0f, 44.0f, 39.0f, 34.0f, 29.0f, 24.0f, 19.0f, 14.0f, 9.0f, 5.0f };
 
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL END",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::CHARACTER,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize15,
-      3u,
-      44u,
-      positions15
-    },
+  Size  textSize12( 120.0f, 50.0f );
+  float positions12[] = { 117.0f, 112.0f, 107.0f, 102.0f, 97.0f, 92.0f, 87.0f, 82.0f, 79.0f, 72.0f };
 
+  Size  textSize13(145.0f, 30.0f);
+  float positions13[] = {131.0f, 126.0f, 121.0f, 117.0f, 108.0f, 104.0f, 94.0f, 88.0f, 20.0f, 29.0f, 34.0f, 42.0f, 48.0f, 57.0f, 67.0f};
+
+  Size  textSize14(145.0f, 30.0f);
+  float positions14[] = {51.0f, 66.0f, 71.0f, 80.0f, 85.0f, 94.0f, 103.0f, 109.0f, 119.0f, 51.0f, 37.0f, 32.0f, 28.0f, 23.0f, 14.0f, 10.0f, 0.0f};
+
+  struct ElideData data[] =
     {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL END",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::HYPHENATION,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize16,
-      3u,
-      39u,
-      positions16
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL END",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::MIXED,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize17,
-      3u,
-      39u,
-      positions17
-    },
-
-   //START RTL cases
-    {
-      "EllipsisPosition: TextLabel: SingleLine RTL START",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize18,
-      1u,
-      13u,
-      positions18
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL START",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize19,
-      3u,
-      33u,
-      positions19
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL START",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::CHARACTER,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize20,
-      3u,
-      30u,
-      positions20
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL START",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::HYPHENATION,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize21,
-      3u,
-      33u,
-      positions21
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL START",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::MIXED,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize22,
-      3u,
-      33u,
-      positions22
-    },
-
-  //MIDDLE LTR cases
-    {
-      "EllipsisPosition: TextLabel: Basic case SingleLine LTR MIDDLE",
-      "ABCDEFGHIJKLMNPQRSTUVWXYZ abcdefghijklmnpqrstuvwxyz",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize23,
-      1u,
-      10u,
-      positions23
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR MIDDLE",
-      "A0123456789 B0123456789 C0123456789 D0123456789 ",
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize24,
-      2u,
-      22u,
-      positions24
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR MIDDLE",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize25,
-      3u,
-      24u,
-      positions25
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR MIDDLE",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
-      true,
-      DevelText::LineWrap::CHARACTER,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize26,
-      3u,
-      36u,
-      positions26
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR MIDDLE",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
-      true,
-      DevelText::LineWrap::HYPHENATION,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize27,
-      3u,
-      27u,
-      positions27
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR MIDDLE",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
-      true,
-      DevelText::LineWrap::MIXED,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize28,
-      3u,
-      24u,
-      positions28
-    },
-
-//MIDDLE RTL cases
-    {
-      "EllipsisPosition: TextLabel: SingleLine RTL MIDDLE",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize29,
-      1u,
-      13u,
-      positions29
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL MIDDLE",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize30,
-      3u,
-      31u,
-      positions30
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL MIDDLE",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::CHARACTER,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize31,
-      3u,
-      29u,
-      positions31
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL MIDDLE",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::HYPHENATION,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize32,
-      3u,
-      31u,
-      positions32
-    },
-
-    {
-      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL MIDDLE",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      true,
-      DevelText::LineWrap::MIXED,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize33,
-      3u,
-      31u,
-      positions33
-    },
-
-    {
-      "EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR END",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize34,
-      1u,
-      13u,
-      positions34
-    },
-
-    {
-      "EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR START",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize35,
-      1u,
-      11u,
-      positions35
-    },
-
-    {
-      "EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR MIDDLE",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      true,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize36,
-      1u,
-      12u,
-      positions36
-    },
-
-  };
-  const unsigned int numberOfTests = 39u;
-
-  for( unsigned int index = 0u; index < numberOfTests; ++index )
-  {
-    ToolkitTestApplication application;
-    if( !ElideTestViewModel( data[index] ) )
-    {
-      tet_result(TET_FAIL);
-    }
-  }
-
-  tet_result(TET_PASS);
-  END_TEST;
-}
-
-
-int UtcDaliTextFieldlElideTextLocation(void)
-{
-  tet_infoline(" UtcDaliTextFieldlElideTextLocation ");
-
-  Size textSize00( 100.f, 100.f );
-
-  Size  textSize01( 120.0f, 50.0f );
-  float positions01[] = { 0.0f, 11.0f, 21.0f, 31.0f, 41.0f, 50.0f, 60.0f, 70.0f, 80.0f, 91.0f };
-
-  Size  textSize02( 120.0f, 50.0f );
-  float positions02[] = { 0.0f, 10.0f, 21.0f, 25.0f, 28.0f, 38.0f, 44.0f, 55.0f, 59.0f, 65.0f, 73.0f, 84.0f, 93.0f };
-
-  Size  textSize03( 120.0f, 50.0f );
-  float positions03[] = { 117.0f, 111.0f, 97.0f, 88.0f, 80.0f, 74.0f, 64.0f, 59.0f, 54.0f, 45.0f, 37.0f, 31.0f, 22.0f, 7.0f };
-
-  Size  textSize04( 120.0f, 50.0f );
-  float positions04[] = { 5.0f, 21.0f, 31.0f, 41.0f, 50.0f, 61.0f, 71.0f, 80.0f, 90.0f, 100.0f, 109.0f };
-
-  Size  textSize05( 120.0f, 50.0f );
-  float positions05[] = { 8.0f, 24.0f, 35.0f, 44.0f, 49.0f, 63.0f, 74.0f, 77.0f, 85.0f, 96.0f, 110.0f };
-
-  Size  textSize06( 120.0f, 50.0f );
-  float positions06[] = { 90.0f, 79.0f, 70.0f, 68.0f, 62.0f, 56.0f, 51.0f, 42.0f, 29.0f, 26.0f, 15.0f, 7.0f, 0.0f };
-
-  Size  textSize07( 120.0f, 50.0f );
-  float positions07[] = { 0.0f, 11.0f, 21.0f, 31.0f, 41.0f, 53.0f };
-
-  Size  textSize08( 120.0f, 50.0f );
-  float positions08[] = { 0.0f, 10.0f, 21.0f, 25.0f, 28.0f, 38.0f, 44.0f, 55.0f };
-
-  Size  textSize09( 120.0f, 50.0f );
-  float positions09[] = { 116.0f, 109.0f, 96.0f, 87.0f, 79.0f, 73.0f, 63.0f };
-
-  Size  textSize10( 120.0f, 50.0f );
-  float positions10[] = { 121.0f, 116.0f, 111.0f, 106.0f, 101.0f, 96.0f, 92.0f, 87.0f, 83.0f, 77.0f, 63.0f, 55.0f, 46.0f, 40.0f, 30.0f, 16.0f };
-
-  Size  textSize11( 120.0f, 50.0f );
-  float positions11[] = { 93.0f, 77.0f, 74.0f, 63.0f, 56.0f, 49.0f, 44.0f, 39.0f, 34.0f, 29.0f, 24.0f, 19.0f, 14.0f, 9.0f, 5.0f };
-
-  Size  textSize12( 120.0f, 50.0f );
-  float positions12[] = { 117.0f, 112.0f, 107.0f, 102.0f, 97.0f, 92.0f, 87.0f, 82.0f, 79.0f, 72.0f };
-
-  struct ElideData data[] =
-  {
-    {
-      "void text",
-      "",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize00,
-      0u,
-      0u,
-      nullptr
-    },
-
-    {
-      "void text",
-      "",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize00,
-      0u,
-      0u,
-      nullptr
-    },
-
-    {
-      "void text",
-      "",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize00,
-      0u,
-      0u,
-      nullptr
-    },
-
-    {
-      "EllipsisPosition: TextField: Basic case SingleLine LTR END",
-      "A0123456789 B0123456789 C0123456789 D0123456789 ",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize01,
-      1u,
-      10u,
-      positions01
-    },
-
-    {
-      "EllipsisPosition: TextField: SingleLine LTR END",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize02,
-      1u,
-      13u,
-      positions02
-    },
-
-    {
-      "EllipsisPosition: TextField: SingleLine RTL END",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize03,
-      1u,
-      14u,
-      positions03
-    },
-
-    {
-      "EllipsisPosition: TextField: Basic case SingleLine LTR START",
-      "A0123456789 B0123456789 C0123456789 D0123456789 ",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize04,
-      1u,
-      11u,
-      positions04
-    },
-
-    {
-      "EllipsisPosition: TextField: SingleLine LTR START",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize05,
-      1u,
-      11u,
-      positions05
-    },
-
-    {
-      "EllipsisPosition: TextField: SingleLine RTL START",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize06,
-      1u,
-      13u,
-      positions06
-    },
-
-    {
-      "EllipsisPosition: TextField: Basic case SingleLine LTR MIDDLE",
-      "A0123456789 B0123456789 C0123456789 D0123456789 ",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize07,
-      1u,
-      11u,
-      positions07
-    },
-
-    {
-      "EllipsisPosition: TextField: SingleLine LTR MIDDLE",
-      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize08,
-      1u,
-      13u,
-      positions08
-    },
-
-    {
-      "EllipsisPosition: TextField: SingleLine RTL MIDDLE",
-      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize09,
-      1u,
-      13u,
-      positions09
-    },
-
-    {
-      "EllipsisPosition: TextField: Head and Tail whitespaces RTL END",
-      "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::END,
-      false,
-      textSize10,
-      1u,
-      16u,
-      positions10
-    },
-
-    {
-      "EllipsisPosition: TextField: Head and Tail whitespaces RTL START",
-      "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::START,
-      false,
-      textSize11,
-      1u,
-      15u,
-      positions11
-    },
-
-    {
-      "EllipsisPosition: TextField: Head and Tail whitespaces RTL MIDDLE",
-      "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
-      false,
-      DevelText::LineWrap::WORD,
-      DevelText::EllipsisPosition::MIDDLE,
-      false,
-      textSize12,
-      1u,
-      20u,
-      positions12
-    },
-
-  };
-
-  const unsigned int numberOfTests = 15u;
+      {"void text",
+       "",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize00,
+       0u,
+       0u,
+       nullptr},
+
+      {"void text",
+       "",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize00,
+       0u,
+       0u,
+       nullptr},
+
+      {"void text",
+       "",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize00,
+       0u,
+       0u,
+       nullptr},
+
+      {"EllipsisPosition: TextField: Basic case SingleLine LTR END",
+       "A0123456789 B0123456789 C0123456789 D0123456789 ",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize01,
+       1u,
+       10u,
+       positions01},
+
+      {"EllipsisPosition: TextField: SingleLine LTR END",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize02,
+       1u,
+       13u,
+       positions02},
+
+      {"EllipsisPosition: TextField: SingleLine RTL END",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize03,
+       1u,
+       14u,
+       positions03},
+
+      {"EllipsisPosition: TextField: Basic case SingleLine LTR START",
+       "A0123456789 B0123456789 C0123456789 D0123456789 ",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize04,
+       1u,
+       11u,
+       positions04},
+
+      {"EllipsisPosition: TextField: SingleLine LTR START",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Welcome",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize05,
+       1u,
+       11u,
+       positions05},
+
+      {"EllipsisPosition: TextField: SingleLine RTL START",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize06,
+       1u,
+       13u,
+       positions06},
+
+      {"EllipsisPosition: TextField: Basic case SingleLine LTR MIDDLE",
+       "A0123456789 B0123456789 C0123456789 D0123456789 ",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize07,
+       1u,
+       11u,
+       positions07},
+
+      {"EllipsisPosition: TextField: SingleLine LTR MIDDLE",
+       "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize08,
+       1u,
+       13u,
+       positions08},
+
+      {"EllipsisPosition: TextField: SingleLine RTL MIDDLE",
+       "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize09,
+       1u,
+       13u,
+       positions09},
+
+      {"EllipsisPosition: TextField: Head and Tail whitespaces RTL END",
+       "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize10,
+       1u,
+       16u,
+       positions10},
+
+      {"EllipsisPosition: TextField: Head and Tail whitespaces RTL START",
+       "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize11,
+       1u,
+       15u,
+       positions11},
+
+      {"EllipsisPosition: TextField: Head and Tail whitespaces RTL MIDDLE",
+       "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::MIDDLE,
+       false,
+       textSize12,
+       1u,
+       20u,
+       positions12},
+
+      {"EllipsisPosition: TextField: Mixed Directions Languages END",
+       "سیٹنگیں Projector سیٹنگیں",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::END,
+       false,
+       textSize13,
+       1u,
+       16,
+       positions13},
+
+      {"EllipsisPosition: TextField: Mixed Directions Languages START",
+       "سیٹنگیں Projector سیٹنگیں",
+       false,
+       DevelText::LineWrap::WORD,
+       DevelText::EllipsisPosition::START,
+       false,
+       textSize14,
+       1u,
+       17,
+       positions14},
+
+    };
+
+  const unsigned int numberOfTests = 17u;
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
old mode 100755 (executable)
new mode 100644 (file)
index 9b71156..6ec3bfe
@@ -180,11 +180,13 @@ bool LayoutTextTest(const LayoutTextData& data)
 
   layoutSize = Vector2::ZERO;
 
-  bool       isAutoScroll = false;
-  const bool updated      = engine.LayoutText(layoutParameters,
+  bool       isAutoScroll                   = false;
+  bool       isAutoScrollMaxTextureExceeded = false;
+  const bool updated                        = engine.LayoutText(layoutParameters,
                                          layoutSize,
                                          data.ellipsis,
                                          isAutoScroll,
+                                         isAutoScrollMaxTextureExceeded,
                                          data.ellipsisPosition);
 
   // 4) Compare the results.
index 80624a8..301f191 100755 (executable)
@@ -87,7 +87,7 @@ bool IsEqualGlyph(const GlyphInfoData& glyphData, const GlyphInfo& glyph)
   {
     return false;
   }
-  if(fabsf(glyphData.advance - floor(glyph.advance)) > Math::MACHINE_EPSILON_1000)
+  if(glyphData.advance >= 0.0f && fabsf(glyphData.advance - floor(glyph.advance)) > Math::MACHINE_EPSILON_1000)
   {
     return false;
   }
@@ -961,9 +961,10 @@ int UtcDaliTextShapeEmojiSequences(void)
   bool sizeDefined   = false;
 
   // variation selector 16 (Emoji)
+  // Note : Non-scalable font's advance value is undefined. See https://github.com/harfbuzz/harfbuzz/discussions/3023. 2022-06-03 updated.
   struct GlyphInfoData glyphsVS16[] =
     {
-      {2u, 74u, 0.f, 0.f, 0.f, 0.f, 39.0f, 0.f, false, false},
+      {2u, 74u, 0.f, 0.f, 0.f, 0.f, -1.0f /* Special value that we don't check it */, 0.f, false, false},
     };
   CharacterIndex characterIndicesVS16[]   = {0u, 1u};
   Length         charactersPerGlyphVS16[] = {2u};
index b6b45a6..6e8c9d7 100644 (file)
@@ -82,6 +82,7 @@ int UtcDaliAnimatedImageVisualGetPropertyMap01(void)
       .Add(ImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME)
       .Add(ImageVisual::Property::MASK_CONTENT_SCALE, 1.6f)
       .Add(ImageVisual::Property::CROP_TO_MASK, true)
+      .Add(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING)
       .Add(DevelVisual::Property::CORNER_RADIUS, 22.2f)
       .Add(DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::ABSOLUTE)
       .Add(DevelVisual::Property::BORDERLINE_WIDTH, 33.3f)
@@ -132,6 +133,10 @@ int UtcDaliAnimatedImageVisualGetPropertyMap01(void)
   DALI_TEST_CHECK(value);
   DALI_TEST_EQUALS(value->Get<bool>(), true, TEST_LOCATION);
 
+  value = resultMap.Find(DevelImageVisual::Property::MASKING_TYPE, Property::INTEGER);
+  DALI_TEST_CHECK(value);
+  DALI_TEST_CHECK(value->Get<int>() == DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+
   Vector2 naturalSize;
   animatedImageVisual.GetNaturalSize(naturalSize);
   DALI_TEST_EQUALS(naturalSize, Vector2(100, 100), TEST_LOCATION);
@@ -176,6 +181,7 @@ int UtcDaliAnimatedImageVisualGetPropertyMap02(void)
       .Add("alphaMaskUrl", TEST_MASK_IMAGE_FILE_NAME)
       .Add("maskContentScale", 1.6f)
       .Add("cropToMask", true)
+      .Add(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING)
       .Add("cornerRadius", Vector4(50.0f, 25.0f, 12.5f, 33.0f))
       .Add("cornerRadiusPolicy", Visual::Transform::Policy::RELATIVE)
       .Add("borderlineWidth", 20.0f)
@@ -248,6 +254,10 @@ int UtcDaliAnimatedImageVisualGetPropertyMap02(void)
   DALI_TEST_CHECK(value);
   DALI_TEST_EQUALS(value->Get<bool>(), true, TEST_LOCATION);
 
+  value = resultMap.Find(DevelImageVisual::Property::MASKING_TYPE, Property::INTEGER);
+  DALI_TEST_CHECK(value);
+  DALI_TEST_CHECK(value->Get<int>() == DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+
   END_TEST;
 }
 
@@ -275,6 +285,7 @@ int UtcDaliAnimatedImageVisualGetPropertyMap03(void)
       .Add("alphaMaskUrl", TEST_MASK_IMAGE_FILE_NAME)
       .Add("maskContentScale", 1.6f)
       .Add("cropToMask", true)
+      .Add(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING)
       .Add("cornerRadius", 50.5f));
 
   Property::Map resultMap;
@@ -343,6 +354,10 @@ int UtcDaliAnimatedImageVisualGetPropertyMap03(void)
   DALI_TEST_CHECK(value);
   DALI_TEST_EQUALS(value->Get<bool>(), true, TEST_LOCATION);
 
+  value = resultMap.Find(DevelImageVisual::Property::MASKING_TYPE, Property::INTEGER);
+  DALI_TEST_CHECK(value);
+  DALI_TEST_CHECK(value->Get<bool>() == DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+
   END_TEST;
 }
 
@@ -525,10 +540,11 @@ int UtcDaliAnimatedImageVisualSynchronousLoading(void)
   END_TEST;
 }
 
-int UtcDaliAnimatedImageVisualSynchronousLoadingWithAlphaMask(void)
+int UtcDaliAnimatedImageVisualSynchronousLoadingWithAlphaMask01(void)
 {
   ToolkitTestApplication application;
-  TestGlAbstraction&     gl = application.GetGlAbstraction();
+  tet_infoline("UtcDaliAnimatedImageVisualSynchronousLoadingWithAlphaMask01 for CPU Alpha Masking");
+  TestGlAbstraction& gl = application.GetGlAbstraction();
 
   {
     Property::Map propertyMap;
@@ -581,6 +597,64 @@ int UtcDaliAnimatedImageVisualSynchronousLoadingWithAlphaMask(void)
   END_TEST;
 }
 
+int UtcDaliAnimatedImageVisualSynchronousLoadingWithAlphaMask02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliAnimatedImageVisualSynchronousLoadingWithAlphaMask02 for GPU Alpha Masking");
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  {
+    Property::Map propertyMap;
+    propertyMap.Insert(Visual::Property::TYPE, Visual::ANIMATED_IMAGE);
+    propertyMap.Insert(ImageVisual::Property::URL, TEST_GIF_FILE_NAME);
+    propertyMap.Insert(ImageVisual::Property::BATCH_SIZE, 2);
+    propertyMap.Insert(ImageVisual::Property::CACHE_SIZE, 2);
+    propertyMap.Insert(ImageVisual::Property::FRAME_DELAY, 20);
+    propertyMap.Insert(ImageVisual::Property::SYNCHRONOUS_LOADING, true);
+    propertyMap.Insert(ImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME);
+    propertyMap.Insert(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+    propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, 0.23f);
+    propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::ABSOLUTE);
+
+    VisualFactory factory = VisualFactory::Get();
+    Visual::Base  visual  = factory.CreateVisual(propertyMap);
+
+    Property::Map testMap;
+    visual.CreatePropertyMap(testMap);
+    DALI_TEST_EQUALS(*testMap.Find(ImageVisual::Property::ALPHA_MASK_URL), Property::Value(TEST_MASK_IMAGE_FILE_NAME), TEST_LOCATION);
+
+    DummyControl        dummyControl = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl    = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+    dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
+
+    dummyControl.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+    application.GetScene().Add(dummyControl);
+
+    TraceCallStack& textureTrace = gl.GetTextureTrace();
+    textureTrace.Enable(true);
+
+    application.SendNotification();
+    application.Render(20);
+
+    // The first frame is loaded synchronously and load next batch with masking
+    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS(Test::GetTimerCount(), 1, TEST_LOCATION);
+    DALI_TEST_EQUALS(gl.GetNumGeneratedTextures(), 4, TEST_LOCATION);
+
+    dummyControl.Unparent();
+  }
+  tet_infoline("Test that removing the visual from stage deletes all textures");
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_EQUALS(gl.GetNumGeneratedTextures(), 0, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliAnimatedImageVisualJumpToAction(void)
 {
   ToolkitTestApplication application;
@@ -853,9 +927,8 @@ int UtcDaliAnimatedImageVisualAnimatedImage01(void)
     // Note that we only re-load 0 frame.
     DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
 
-    // To do: we need to fix caching bug in animated-visual
-    //tet_infoline("Test that we don't try to re-load new image cause it cached");
-    //DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 1), false, TEST_LOCATION);
+    tet_infoline("Test that we don't try to re-load new image cause it cached");
+    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 1), false, TEST_LOCATION);
 
     // Batch 2 frames. Now visual frame 1, 2, 3 cached and visual2 frame 0, 1 cached.
     application.SendNotification();
@@ -894,7 +967,8 @@ int UtcDaliAnimatedImageVisualAnimatedImage01(void)
 int UtcDaliAnimatedImageVisualAnimatedImageWithAlphaMask01(void)
 {
   ToolkitTestApplication application;
-  TestGlAbstraction&     gl = application.GetGlAbstraction();
+  tet_infoline("UtcDaliAnimatedImageVisualAnimatedImageWithAlphaMask01 for CPU Alpha Masking");
+  TestGlAbstraction& gl = application.GetGlAbstraction();
 
   {
     Property::Map propertyMap;
@@ -936,6 +1010,100 @@ int UtcDaliAnimatedImageVisualAnimatedImageWithAlphaMask01(void)
   END_TEST;
 }
 
+int UtcDaliAnimatedImageVisualAnimatedImageWithAlphaMask02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliAnimatedImageVisualAnimatedImageWithAlphaMask02 for GPU Alpha Masking");
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  {
+    Property::Map propertyMap;
+    propertyMap.Insert(Visual::Property::TYPE, Visual::ANIMATED_IMAGE);
+    propertyMap.Insert(ImageVisual::Property::URL, TEST_GIF_FILE_NAME);
+    propertyMap.Insert(ImageVisual::Property::BATCH_SIZE, 2);
+    propertyMap.Insert(ImageVisual::Property::CACHE_SIZE, 4);
+    propertyMap.Insert(ImageVisual::Property::FRAME_DELAY, 20);
+    propertyMap.Insert(ImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME);
+    propertyMap.Insert(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+
+    VisualFactory factory = VisualFactory::Get();
+    Visual::Base  visual  = factory.CreateVisual(propertyMap);
+
+    DummyControl        dummyControl = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl    = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+    dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
+
+    dummyControl.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+    application.GetScene().Add(dummyControl);
+
+    application.SendNotification();
+    application.Render();
+
+    // load two frame(batch size), load mask image, and request two masking
+    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(20);
+
+    DALI_TEST_EQUALS(gl.GetLastGenTextureId(), 3, TEST_LOCATION);
+
+    dummyControl.Unparent();
+  }
+  tet_infoline("Test that removing the visual from stage deletes all textures");
+  application.SendNotification();
+  application.Render(20);
+  DALI_TEST_EQUALS(gl.GetNumGeneratedTextures(), 0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimatedImageVisualAnimatedImageWithAlphaMask03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliAnimatedImageVisualAnimatedImageWithAlphaMask03 for GPU Alpha Masking with broken mask texture");
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  {
+    Property::Map propertyMap;
+    propertyMap.Insert(Visual::Property::TYPE, Visual::ANIMATED_IMAGE);
+    propertyMap.Insert(ImageVisual::Property::URL, TEST_GIF_FILE_NAME);
+    propertyMap.Insert(ImageVisual::Property::BATCH_SIZE, 2);
+    propertyMap.Insert(ImageVisual::Property::CACHE_SIZE, 4);
+    propertyMap.Insert(ImageVisual::Property::FRAME_DELAY, 20);
+    propertyMap.Insert(ImageVisual::Property::ALPHA_MASK_URL, "");
+    propertyMap.Insert(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+
+    VisualFactory factory = VisualFactory::Get();
+    Visual::Base  visual  = factory.CreateVisual(propertyMap);
+
+    DummyControl        dummyControl = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl    = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+    dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
+
+    dummyControl.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+    application.GetScene().Add(dummyControl);
+
+    application.SendNotification();
+    application.Render();
+
+    // load two frame(batch size), load mask image, and request two masking
+    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(20);
+
+    DALI_TEST_EQUALS(gl.GetLastGenTextureId(), 3, TEST_LOCATION);
+
+    dummyControl.Unparent();
+  }
+  tet_infoline("Test that removing the visual from stage deletes all textures");
+  application.SendNotification();
+  application.Render(20);
+  DALI_TEST_EQUALS(gl.GetNumGeneratedTextures(), 0, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliAnimatedImageVisualMultiImage01(void)
 {
   ToolkitTestApplication application;
index 3ae49cc..fbca3b6 100644 (file)
@@ -1074,8 +1074,8 @@ int UtcDaliControlResourcesReady02(void)
   application.SendNotification();
   application.Render();
 
-  // Wait for rasterization
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  // Wait for loading & rasterization
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
 
   DALI_TEST_EQUALS(control.IsResourceReady(), true, TEST_LOCATION);
   DALI_TEST_EQUALS(gResourceReadySignalFired, true, TEST_LOCATION);
index cb46bd4..24802c4 100644 (file)
@@ -2833,7 +2833,7 @@ int UtcDaliImageViewSVGLoadingSyncSetInvalidValue(void)
   END_TEST;
 }
 
-int UtcDaliImageViewSvgLoadingFailure(void)
+int UtcDaliImageViewSvgLoadingFailureLocalFile(void)
 {
   // Local svg file - invalid file path
   {
@@ -2941,6 +2941,11 @@ int UtcDaliImageViewSvgLoadingFailure(void)
     DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION);
   }
 
+  END_TEST;
+}
+
+int UtcDaliImageViewSvgLoadingFailureRemoteFile01(void)
+{
   // Remote svg file
   {
     ToolkitTestApplication application;
@@ -2950,7 +2955,6 @@ int UtcDaliImageViewSvgLoadingFailure(void)
     textureTrace.Enable(true);
 
     gResourceReadySignalFired = false;
-    textureTrace.Reset();
 
     ImageView imageView = ImageView::New("https://bar.org/foobar.svg");
     imageView.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
@@ -2977,6 +2981,11 @@ int UtcDaliImageViewSvgLoadingFailure(void)
     DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION);
   }
 
+  END_TEST;
+}
+
+int UtcDaliImageViewSvgLoadingFailureRemoteFile02(void)
+{
   // Remote svg file without size set
   {
     ToolkitTestApplication application;
@@ -2986,7 +2995,6 @@ int UtcDaliImageViewSvgLoadingFailure(void)
     textureTrace.Enable(true);
 
     gResourceReadySignalFired = false;
-    textureTrace.Reset();
 
     ImageView imageView = ImageView::New("https://bar.org/foobar.svg");
     imageView.ResourceReadySignal().Connect(&ResourceReadySignal);
@@ -3439,6 +3447,19 @@ void OnResourceReadySignal04(Control control)
   }
 }
 
+void OnResourceReadySignal05(Control control)
+{
+  gResourceReadySignalCounter++;
+
+  // Request load with same image
+  // NOTE : The url must not be same as gImageView1
+  const int viewCount = 4;
+  for(int i = 0; i < viewCount; ++i)
+  {
+    gImageView1.Add(ImageView::New("invalid2.jpg"));
+  }
+}
+
 } // namespace
 
 int UtcDaliImageViewSetImageOnResourceReadySignal01(void)
@@ -3655,9 +3676,9 @@ int UtcDaliImageViewCheckVariousCaseSendOnResourceReadySignal(void)
 {
   tet_infoline("Test signal handler various case.");
 
-  ToolkitTestApplication application;
+  auto TestResourceReadyUrl = [](int eventTriggerCount, bool isSynchronous, bool loadSuccess, const std::string& url, const std::string& mask, const char* location) {
+    ToolkitTestApplication application;
 
-  auto TestResourceReadyUrl = [&application](int eventTriggerCount, bool isSynchronous, bool loadSuccess, const std::string& url, const std::string& mask, const char* location) {
     gResourceReadySignalCounter = 0;
 
     Property::Map map;
@@ -3687,7 +3708,9 @@ int UtcDaliImageViewCheckVariousCaseSendOnResourceReadySignal(void)
     imageView.Unparent();
   };
 
-  auto TestAuxiliaryResourceReadyUrl = [&application](bool isSynchronous, bool loadSuccess, const std::string& url, const std::string& auxiliaryUrl, const char* location) {
+  auto TestAuxiliaryResourceReadyUrl = [](bool isSynchronous, bool loadSuccess, const std::string& url, const std::string& auxiliaryUrl, const char* location) {
+    ToolkitTestApplication application;
+
     gResourceReadySignalCounter = 0;
 
     Property::Map map;
@@ -3836,3 +3859,33 @@ int UtcDaliImageViewSetImageOnResourceReadySignal04(void)
 
   END_TEST;
 }
+int UtcDaliImageViewSetImageOnResourceReadySignal05(void)
+{
+  tet_infoline("Test multiple views with same image during ResourceReady load the image only 1 times");
+
+  ToolkitTestApplication application;
+
+  gResourceReadySignalCounter = 0;
+
+  gImageView1 = ImageView::New("invalid.jpg"); // request invalid image, to make loading failed fast.
+  gImageView1.ResourceReadySignal().Connect(&OnResourceReadySignal05);
+  application.GetScene().Add(gImageView1);
+
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline("Try to load 1 invalid.jpg image");
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(gResourceReadySignalCounter, 1, TEST_LOCATION);
+
+  tet_infoline("Try to load 1 invalid2.jpg image");
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  tet_infoline("Now we don't have any image to be loaded. Check event thread trigger failed.");
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 1), false, TEST_LOCATION);
+
+  gImageView1.Unparent();
+  gImageView1.Reset();
+
+  END_TEST;
+}
index b36457f..3f4fdba 100644 (file)
@@ -1593,7 +1593,7 @@ int UtcDaliImageVisualSetInvalidRemoteImage(void)
   END_TEST;
 }
 
-int UtcDaliImageVisualAlphaMask(void)
+int UtcDaliImageVisualAlphaMask01(void)
 {
   ToolkitTestApplication application;
   tet_infoline("Request image visual with a Property::Map containing an Alpha mask");
@@ -1647,7 +1647,127 @@ int UtcDaliImageVisualAlphaMask(void)
   END_TEST;
 }
 
-int UtcDaliImageVisualSynchronousLoadAlphaMask(void)
+int UtcDaliImageVisualAlphaMask02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("Request image visual with a Property::Map containing an Alpha mask for GPU");
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_LARGE_IMAGE_FILE_NAME);
+  propertyMap.Insert(ImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME);
+  propertyMap.Insert(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+
+  Visual::Base visual = factory.CreateVisual(propertyMap);
+  DALI_TEST_CHECK(visual);
+
+  Property::Map testMap;
+  visual.CreatePropertyMap(testMap);
+  DALI_TEST_EQUALS(*testMap.Find(ImageVisual::Property::ALPHA_MASK_URL), Property::Value(TEST_MASK_IMAGE_FILE_NAME), TEST_LOCATION);
+  DALI_TEST_EQUALS(*testMap.Find(DevelImageVisual::Property::MASKING_TYPE), Property::Value(DevelImageVisual::MaskingType::MASKING_ON_RENDERING), TEST_LOCATION);
+
+  // For tesing the LoadResourceFunc is called, a big image size should be set, so the atlasing is not applied.
+  // Image with a size smaller than 512*512 will be uploaded as a part of the atlas.
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  DummyControl      actor     = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+  actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), false, TEST_LOCATION);
+
+  application.GetScene().Add(actor);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  Renderer renderer = actor.GetRendererAt(0u);
+  TextureSet textures = renderer.GetTextures();
+  DALI_TEST_CHECK(textures);
+  DALI_TEST_EQUALS(textures.GetTextureCount(), 2u, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+
+  dummyImpl.UnregisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1);
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualAlphaMask03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("Request image visual with a Property::Map containing an Alpha mask for GPU with fail case");
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_LARGE_IMAGE_FILE_NAME);
+  propertyMap.Insert(ImageVisual::Property::ALPHA_MASK_URL, "dummy_path");
+  propertyMap.Insert(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+
+  Visual::Base visual = factory.CreateVisual(propertyMap);
+  DALI_TEST_CHECK(visual);
+
+  Property::Map testMap;
+  visual.CreatePropertyMap(testMap);
+
+  // For tesing the LoadResourceFunc is called, a big image size should be set, so the atlasing is not applied.
+  // Image with a size smaller than 512*512 will be uploaded as a part of the atlas.
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  DummyControl      actor     = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+  actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), false, TEST_LOCATION);
+
+  application.GetScene().Add(actor);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  Renderer renderer = actor.GetRendererAt(0u);
+  TextureSet textures = renderer.GetTextures();
+  DALI_TEST_CHECK(textures);
+  DALI_TEST_EQUALS(textures.GetTextureCount(), 1u, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+
+  dummyImpl.UnregisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1);
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualSynchronousLoadAlphaMask01(void)
 {
   ToolkitTestApplication application;
   tet_infoline("Request image visual with a Property::Map containing an Alpha mask with synchronous loading");
@@ -1700,6 +1820,65 @@ int UtcDaliImageVisualSynchronousLoadAlphaMask(void)
   END_TEST;
 }
 
+int UtcDaliImageVisualSynchronousLoadAlphaMask02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("Request image visual with a Property::Map containing an Alpha mask for GPU with synchronous loading");
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_LARGE_IMAGE_FILE_NAME);
+  propertyMap.Insert(ImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME);
+  propertyMap.Insert(ImageVisual::Property::SYNCHRONOUS_LOADING, true);
+  propertyMap.Insert(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+
+  Visual::Base visual = factory.CreateVisual(propertyMap);
+  DALI_TEST_CHECK(visual);
+
+  Property::Map testMap;
+  visual.CreatePropertyMap(testMap);
+  DALI_TEST_EQUALS(*testMap.Find(ImageVisual::Property::ALPHA_MASK_URL), Property::Value(TEST_MASK_IMAGE_FILE_NAME), TEST_LOCATION);
+
+  // For tesing the LoadResourceFunc is called, a big image size should be set, so the atlasing is not applied.
+  // Image with a size smaller than 512*512 will be uploaded as a part of the atlas.
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  DummyControl      actor     = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+  actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), false, TEST_LOCATION);
+
+  application.GetScene().Add(actor);
+
+  // Do not wait for any EventThreadTrigger in synchronous alpha mask.
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  Renderer renderer = actor.GetRendererAt(0u);
+  TextureSet textures = renderer.GetTextures();
+  DALI_TEST_CHECK(textures);
+  DALI_TEST_EQUALS(textures.GetTextureCount(), 2u, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+
+  dummyImpl.UnregisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1);
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliImageVisualRemoteAlphaMask(void)
 {
   ToolkitTestApplication application;
index dab40a2..2ff4a7d 100644 (file)
@@ -2087,6 +2087,13 @@ int UtcDaliToolkitTextlabelMaxTextureSet(void)
   // Check if the number of renderers is greater than 1.
   DALI_TEST_CHECK(label.GetRendererCount() > 1u);
 
+  // Coverage test for case of layoutSize is bigger than maxTextureSize
+  float max_value = static_cast<float>(std::numeric_limits<uint16_t>::max());
+  label.SetProperty(Actor::Property::SIZE, Vector2(max_value, 30.0f));
+  application.SendNotification();
+  application.Render();
+
+
   END_TEST;
 }
 
index 332e771..784af73 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali-toolkit/public-api/transition/transition-set.h>
 #include <dali-toolkit/public-api/transition/transition.h>
 #include <dali/devel-api/actors/actor-devel.h>
+#include <dali/public-api/rendering/decorated-visual-renderer.h> // for Renderer Property Index.
 #include <stdlib.h>
 #include <iostream>
 
@@ -287,18 +288,14 @@ int UtcDaliTransitionBetweenControlPair(void)
 
   DALI_TEST_NOT_EQUALS(destinationPosition, control2.GetCurrentProperty<Vector3>(Actor::Property::POSITION), 0.00001f, TEST_LOCATION);
   DALI_TEST_EQUALS(1, control2.GetRendererCount(), TEST_LOCATION);
-  Dali::Renderer  renderer = control2.GetRendererAt(0);
-  Property::Index index    = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
-  cornerRadius             = renderer.GetCurrentProperty<Vector4>(index);
+  Dali::Renderer renderer = control2.GetRendererAt(0);
+  cornerRadius            = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS);
   DALI_TEST_NOT_EQUALS(destinationRadiusV4, cornerRadius, 0.00001f, TEST_LOCATION);
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
-  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  borderlineWidth = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH);
   DALI_TEST_NOT_EQUALS(destinationBorderlineWidth, borderlineWidth, 0.00001f, TEST_LOCATION);
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
-  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR);
   DALI_TEST_NOT_EQUALS(destinationBorderlineColor, borderlineColor, 0.00001f, TEST_LOCATION);
-  index            = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
-  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  borderlineOffset = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET);
   DALI_TEST_NOT_EQUALS(destinationBorderlineOffset, borderlineOffset, 0.00001f, TEST_LOCATION);
 
   application.SendNotification();
@@ -318,17 +315,13 @@ int UtcDaliTransitionBetweenControlPair(void)
   DALI_TEST_EQUALS(destinationOpacity, control2.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
   DALI_TEST_EQUALS(1, control2.GetRendererCount(), TEST_LOCATION);
   renderer     = control2.GetRendererAt(0);
-  index        = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
-  cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+  cornerRadius = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS);
   DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
-  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  borderlineWidth = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH);
   DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
-  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR);
   DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
-  index            = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
-  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  borderlineOffset = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET);
   DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
 
   END_TEST;
@@ -431,21 +424,17 @@ int UtcDaliTransitionBetweenControlPair2(void)
   DALI_TEST_NOT_EQUALS(destinationPosition, control1.GetCurrentProperty<Vector3>(Actor::Property::POSITION), 0.00001f, TEST_LOCATION);
   DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
 
-  Dali::Renderer  renderer = control1.GetRendererAt(0);
-  Property::Index index    = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
-  cornerRadius             = renderer.GetCurrentProperty<Vector4>(index);
+  Dali::Renderer renderer = control1.GetRendererAt(0);
+  cornerRadius            = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS);
   DALI_TEST_NOT_EQUALS(destinationRadiusV4, cornerRadius, 0.00001f, TEST_LOCATION);
 
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
-  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  borderlineWidth = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH);
   DALI_TEST_NOT_EQUALS(destinationBorderlineWidth, borderlineWidth, 0.00001f, TEST_LOCATION);
 
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
-  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR);
   DALI_TEST_NOT_EQUALS(destinationBorderlineColor, borderlineColor, 0.00001f, TEST_LOCATION);
 
-  index            = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
-  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  borderlineOffset = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET);
   DALI_TEST_NOT_EQUALS(destinationBorderlineOffset, borderlineOffset, 0.00001f, TEST_LOCATION);
 
   application.SendNotification();
@@ -465,20 +454,16 @@ int UtcDaliTransitionBetweenControlPair2(void)
 
   DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
   renderer     = control1.GetRendererAt(0);
-  index        = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
-  cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+  cornerRadius = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS);
   DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
 
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
-  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  borderlineWidth = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH);
   DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
 
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
-  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR);
   DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
 
-  index            = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
-  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  borderlineOffset = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET);
   DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
 
   // every actor properties of control1 are returned to the source properties.
@@ -494,20 +479,16 @@ int UtcDaliTransitionBetweenControlPair2(void)
   // after next update, renderer properties are returned to the source properties.
   DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
   renderer     = control1.GetRendererAt(0);
-  index        = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
-  cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+  cornerRadius = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::CORNER_RADIUS);
   DALI_TEST_EQUALS(sourceRadiusV4, cornerRadius, TEST_LOCATION);
 
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
-  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  borderlineWidth = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_WIDTH);
   DALI_TEST_EQUALS(sourceBorderlineWidth, borderlineWidth, TEST_LOCATION);
 
-  index           = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
-  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(DecoratedVisualRenderer::Property::BORDERLINE_COLOR);
   DALI_TEST_EQUALS(sourceBorderlineColor, borderlineColor, TEST_LOCATION);
 
-  index            = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
-  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  borderlineOffset = renderer.GetCurrentProperty<float>(DecoratedVisualRenderer::Property::BORDERLINE_OFFSET);
   DALI_TEST_EQUALS(sourceBorderlineOffset, borderlineOffset, TEST_LOCATION);
 
   END_TEST;
index bd3469a..7c13fc1 100644 (file)
@@ -141,6 +141,38 @@ bool DaliTestCheckMaps(const Property::Map& fontStyleMapGet, const Property::Map
   return true;
 }
 
+void TestShaderCodeContainSubstrings(Control control, std::vector<std::pair<std::string, bool>> substringCheckList, const char* location)
+{
+  Renderer        renderer = control.GetRendererAt(0);
+  Shader          shader   = renderer.GetShader();
+  Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
+  Property::Map*  map      = value.GetMap();
+  DALI_TEST_CHECK(map);
+
+  Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
+  DALI_TEST_CHECK(fragment);
+  std::string fragmentShader;
+  DALI_TEST_CHECK(fragment->Get(fragmentShader));
+  for(const auto& checkPair : substringCheckList)
+  {
+    const auto& keyword = checkPair.first;
+    const auto& expect  = checkPair.second;
+    tet_printf("check [%s] %s exist in fragment shader\n", keyword.c_str(), expect ? "is" : "is not");
+    DALI_TEST_EQUALS((fragmentShader.find(keyword.c_str()) != std::string::npos), expect, location);
+  }
+
+  Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
+  std::string      vertexShader;
+  DALI_TEST_CHECK(vertex->Get(vertexShader));
+  for(const auto& checkPair : substringCheckList)
+  {
+    const auto& keyword = checkPair.first;
+    const auto& expect  = checkPair.second;
+    tet_printf("check [%s] %s exist in vertex shader\n", keyword.c_str(), expect ? "is" : "is not");
+    DALI_TEST_EQUALS((vertexShader.find(keyword.c_str()) != std::string::npos), expect, location);
+  }
+}
+
 } //namespace
 
 void dali_visual_startup(void)
@@ -441,7 +473,10 @@ int UtcDaliVisualSetOnOffScene2(void)
 
   application.SendNotification();
   application.Render(0);
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  // Wait for loading & rasterization
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
   DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
   Renderer renderer = actor.GetRendererAt(0);
   auto     textures = renderer.GetTextures();
@@ -903,7 +938,7 @@ int UtcDaliVisualGetPropertyMap6(void)
 
   value = resultMap.Find(ImageVisual::Property::BORDER, Property::RECTANGLE);
   DALI_TEST_CHECK(value);
-  DALI_TEST_CHECK(value->Get<Rect<int> >() == border);
+  DALI_TEST_CHECK(value->Get<Rect<int>>() == border);
 
   value = resultMap.Find(DevelImageVisual::Property::AUXILIARY_IMAGE, Property::STRING);
   DALI_TEST_CHECK(value);
@@ -944,7 +979,7 @@ int UtcDaliVisualGetPropertyMap6(void)
 
   value = resultMap.Find(ImageVisual::Property::BORDER, Property::RECTANGLE);
   DALI_TEST_CHECK(value);
-  DALI_TEST_CHECK(value->Get<Rect<int> >() == border);
+  DALI_TEST_CHECK(value->Get<Rect<int>>() == border);
 
   END_TEST;
 }
@@ -3764,7 +3799,8 @@ int UtcDaliSvgVisualCustomShader(void)
   application.SendNotification();
   application.Render();
 
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  // Wait for loading & rasterization
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
 
   Renderer        renderer = dummy.GetRendererAt(0);
   Shader          shader2  = renderer.GetShader();
@@ -3783,7 +3819,6 @@ int UtcDaliSvgVisualCustomShader(void)
 
 int UtcDaliVisualRoundedCorner(void)
 {
-  ToolkitTestApplication application;
   tet_infoline("UtcDaliVisualRoundedCorner");
 
   static std::vector<UniformData> customUniforms =
@@ -3792,11 +3827,12 @@ int UtcDaliVisualRoundedCorner(void)
       UniformData("cornerRadiusPolicy", Property::Type::FLOAT),
     };
 
-  TestGraphicsController& graphics = application.GetGraphicsController();
-  graphics.AddCustomUniforms(customUniforms);
-
   // image visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         cornerRadius = 30.0f;
@@ -3831,6 +3867,10 @@ int UtcDaliVisualRoundedCorner(void)
 
   // color visual 1
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         cornerRadius = 30.0f;
@@ -3864,6 +3904,10 @@ int UtcDaliVisualRoundedCorner(void)
 
   // color visual 2
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     Vector4       cornerRadius(0.5f, 0.5f, 0.5f, 0.3f);
@@ -3897,6 +3941,10 @@ int UtcDaliVisualRoundedCorner(void)
 
   // color visual 3 - invalid value
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     Vector4       cornerRadius(30.0f, 30.0f, 30.0f, 20.0f);
@@ -3931,6 +3979,10 @@ int UtcDaliVisualRoundedCorner(void)
 
   // gradient visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         cornerRadius = 30.0f;
@@ -3978,6 +4030,10 @@ int UtcDaliVisualRoundedCorner(void)
 
   // animated image visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     Vector4       cornerRadius(24.0f, 23.0f, 22.0f, 21.0f);
@@ -4013,6 +4069,10 @@ int UtcDaliVisualRoundedCorner(void)
 
   // vector image visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     Vector4       cornerRadius(27.0f, 72.0f, 11.0f, 500.5f);
@@ -4035,7 +4095,8 @@ int UtcDaliVisualRoundedCorner(void)
     application.SendNotification();
     application.Render();
 
-    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+    // Wait for loading & rasterization
+    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
 
     application.SendNotification();
     application.Render();
@@ -4047,6 +4108,10 @@ int UtcDaliVisualRoundedCorner(void)
 
   // animated vector image visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         cornerRadius = 1.3f;
@@ -4085,7 +4150,6 @@ int UtcDaliVisualRoundedCorner(void)
 
 int UtcDaliVisualBorderline(void)
 {
-  ToolkitTestApplication application;
   tet_infoline("UtcDaliVisualBorderline");
 
   static std::vector<UniformData> customUniforms =
@@ -4097,11 +4161,12 @@ int UtcDaliVisualBorderline(void)
       UniformData("borderlineOffset", Property::Type::FLOAT),
     };
 
-  TestGraphicsController& graphics = application.GetGraphicsController();
-  graphics.AddCustomUniforms(customUniforms);
-
   // image visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         cornerRadius    = 5.0f;
@@ -4145,6 +4210,10 @@ int UtcDaliVisualBorderline(void)
 
   // color visual 1
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     Vector4       cornerRadius(23.0f, 2.0f, 3.0f, 2.3f);
@@ -4184,6 +4253,10 @@ int UtcDaliVisualBorderline(void)
 
   // color visual 2, default color, default offset
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         borderlineWidth = 30.0f;
@@ -4218,6 +4291,10 @@ int UtcDaliVisualBorderline(void)
 
   // color visual 3, offset not [-1.0 ~ 1.0], but uniform value is same anyway
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         borderlineWidth = 30.0f;
@@ -4255,6 +4332,10 @@ int UtcDaliVisualBorderline(void)
 
   // gradient visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         borderlineWidth = 30.0f;
@@ -4309,6 +4390,10 @@ int UtcDaliVisualBorderline(void)
 
   // animated image visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     float         borderlineWidth  = 24.0f;
@@ -4347,6 +4432,10 @@ int UtcDaliVisualBorderline(void)
 
   // vector image visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     Vector4       cornerRadius(54.0f, 43.0f, 32.0f, 21.0f);
@@ -4373,7 +4462,8 @@ int UtcDaliVisualBorderline(void)
     application.SendNotification();
     application.Render();
 
-    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+    // Wait for loading & rasterization
+    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
 
     application.SendNotification();
     application.Render();
@@ -4389,6 +4479,10 @@ int UtcDaliVisualBorderline(void)
 
   // animated vector image visual
   {
+    ToolkitTestApplication  application;
+    TestGraphicsController& graphics = application.GetGraphicsController();
+    graphics.AddCustomUniforms(customUniforms);
+
     VisualFactory factory = VisualFactory::Get();
     Property::Map properties;
     Vector4       cornerRadius(1.3f, 0.0f, 0.4f, 0.2f);
@@ -5270,8 +5364,8 @@ int UtcDaliVisualGetVisualProperty05(void)
   application.SendNotification();
   application.Render();
 
-  // Wait for image loading
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  // Wait for loading & rasterization
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
 
   application.SendNotification();
   application.Render();
@@ -5609,27 +5703,14 @@ int UtcDaliVisualUpdatePropertyChangeShader01(void)
   application.SendNotification();
   application.Render();
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", false},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", false},
+    },
+    TEST_LOCATION);
+
   callStack.Reset();
   callStack.Enable(true);
 
@@ -5654,27 +5735,13 @@ int UtcDaliVisualUpdatePropertyChangeShader01(void)
   DALI_TEST_CHECK(cornerRadiusPolicyValue);
   DALI_TEST_EQUALS(cornerRadiusPolicyValue->Get<int>(), static_cast<int>(Toolkit::Visual::Transform::Policy::RELATIVE), TEST_LOCATION);
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", false},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", true},
+    },
+    TEST_LOCATION);
 
   // Send shader compile signal
   application.SendNotification();
@@ -5724,29 +5791,13 @@ int UtcDaliVisualUpdatePropertyChangeShader01(void)
   DALI_TEST_CHECK(borderlineOffsetValue);
   DALI_TEST_EQUALS(borderlineOffsetValue->Get<float>(), targetBorderlineOffset, TEST_LOCATION);
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos);
-    // Note : mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos);
-    // Note : mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", true},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", true}, // Note : mAlwaysUsingCornerRadius is true.
+    },
+    TEST_LOCATION);
 
   // Send shader compile signal
   application.SendNotification();
@@ -5792,29 +5843,13 @@ int UtcDaliVisualUpdatePropertyChangeShader01(void)
   DALI_TEST_CHECK(borderlineOffsetValue);
   DALI_TEST_EQUALS(borderlineOffsetValue->Get<float>(), 0.0f, TEST_LOCATION);
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    // Note : mAlwaysUsingBorderline and mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    // Note : mAlwaysUsingBorderline and mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", true},     // Note : mAlwaysUsingBorderline is true.
+      {"#define IS_REQUIRED_ROUNDED_CORNER", true}, // Note : mAlwaysUsingCornerRadius is true.
+    },
+    TEST_LOCATION);
 
   // Send shader compile signal
   application.SendNotification();
@@ -5857,27 +5892,13 @@ int UtcDaliVisualUpdatePropertyChangeShader02(void)
   application.SendNotification();
   application.Render();
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", false},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", false},
+    },
+    TEST_LOCATION);
 
   Vector4 targetCornerRadius = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
 
@@ -5898,29 +5919,13 @@ int UtcDaliVisualUpdatePropertyChangeShader02(void)
   DALI_TEST_CHECK(cornerRadiusValue);
   DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), targetCornerRadius, TEST_LOCATION);
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    // Note : corner radius is zero. so we don't change shader!
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    // Note : corner radius is zero. so we don't change shader!
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", false},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", false}, // Note : corner radius is zero. so we don't change shader!
+    },
+    TEST_LOCATION);
 
   // Send shader compile signal
   application.SendNotification();
@@ -5961,29 +5966,13 @@ int UtcDaliVisualUpdatePropertyChangeShader02(void)
   DALI_TEST_CHECK(borderlineOffsetValue);
   DALI_TEST_EQUALS(borderlineOffsetValue->Get<float>(), targetBorderlineOffset, TEST_LOCATION);
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    // Note : borderline width is zero. so we don't change shader!
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    // Note : borderline width is zero. so we don't change shader!
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", false}, // Note : borderline width is zero. so we don't change shader!
+      {"#define IS_REQUIRED_ROUNDED_CORNER", false},
+    },
+    TEST_LOCATION);
 
   // Send shader compile signal
   application.SendNotification();
@@ -6024,29 +6013,14 @@ int UtcDaliVisualUpdatePropertyChangeShader03(void)
   application.SendNotification();
   application.Render();
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BLUR 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BLUR 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BLUR", false},
+      {"#define IS_REQUIRED_BORDERLINE", false},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", false},
+    },
+    TEST_LOCATION);
 
   float   targetBlurRadius   = 15.0f;
   Vector4 targetCornerRadius = Vector4(1.0f, 0.1f, 1.1f, 0.0f);
@@ -6074,31 +6048,14 @@ int UtcDaliVisualUpdatePropertyChangeShader03(void)
   DALI_TEST_CHECK(cornerRadiusValue);
   DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), targetCornerRadius, TEST_LOCATION);
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BLUR 1") != std::string::npos);
-    // Note : We ignore borderline when blur radius occured
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BLUR 1") != std::string::npos);
-    // Note : We ignore borderline when blur radius occured
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BLUR", true},
+      {"#define IS_REQUIRED_BORDERLINE", false}, // Note : We ignore borderline when blur radius occured
+      {"#define IS_REQUIRED_ROUNDED_CORNER", true},
+    },
+    TEST_LOCATION);
 
   // Send shader compile signal
   application.SendNotification();
@@ -6131,33 +6088,14 @@ int UtcDaliVisualUpdatePropertyChangeShader03(void)
   DALI_TEST_CHECK(cornerRadiusValue);
   DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), Vector4::ZERO, TEST_LOCATION);
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    // Note : mAlwaysUsingBlurRadius and mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BLUR 1") != std::string::npos);
-    // Note : We ignore borderline when blur radius occured
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    // Note : mAlwaysUsingBlurRadius and mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BLUR 1") != std::string::npos);
-    // Note : We ignore borderline when blur radius occured
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BLUR", true},           // Note : mAlwaysUsingBlurRadius is true.
+      {"#define IS_REQUIRED_BORDERLINE", false},    // Note : We ignore borderline when blur radius occured
+      {"#define IS_REQUIRED_ROUNDED_CORNER", true}, // Note : mAlwaysUsingCornerRadius is true.
+    },
+    TEST_LOCATION);
 
   // Send shader compile signal
   application.SendNotification();
@@ -6202,27 +6140,14 @@ int UtcDaliVisualUpdatePropertyChangeShader04(void)
   application.SendNotification();
   application.Render();
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", false},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", true},
+    },
+    TEST_LOCATION);
+
   callStack.Reset();
   callStack.Enable(true);
 
@@ -6236,29 +6161,14 @@ int UtcDaliVisualUpdatePropertyChangeShader04(void)
   application.Render();
   application.Render(1001u); // End of animation
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    // Note : mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos);
-    // Note : mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", false},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", true}, // Note : mAlwaysUsingCornerRadius is true.
+    },
+    TEST_LOCATION);
+
   callStack.Enable(false);
   // Shader not changed
   DALI_TEST_CHECK(!callStack.FindMethod("CreateShader"));
@@ -6288,29 +6198,13 @@ int UtcDaliVisualUpdatePropertyChangeShader04(void)
   DALI_TEST_CHECK(borderlineWidthValue);
   DALI_TEST_EQUALS(borderlineWidthValue->Get<float>(), targetBorderlineWidth, TEST_LOCATION);
 
-  // Get shader
-  {
-    Renderer        renderer = dummyControl.GetRendererAt(0);
-    Shader          shader   = renderer.GetShader();
-    Property::Value value    = shader.GetProperty(Shader::Property::PROGRAM);
-    Property::Map*  map      = value.GetMap();
-    DALI_TEST_CHECK(map);
-
-    Property::Value* fragment = map->Find("fragment"); // fragment key name from shader-impl.cpp
-    DALI_TEST_CHECK(fragment);
-    std::string fragmentShader;
-    DALI_TEST_CHECK(fragment->Get(fragmentShader));
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos);
-    // Note : mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-
-    Property::Value* vertex = map->Find("vertex"); // vertex key name from shader-impl.cpp
-    std::string      vertexShader;
-    DALI_TEST_CHECK(vertex->Get(vertexShader));
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos);
-    // Note : mAlwaysUsingCornerRadius is true.
-    DALI_TEST_CHECK(vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos);
-  }
+  TestShaderCodeContainSubstrings(
+    dummyControl,
+    {
+      {"#define IS_REQUIRED_BORDERLINE", true},
+      {"#define IS_REQUIRED_ROUNDED_CORNER", true}, // Note : mAlwaysUsingCornerRadius is true.
+    },
+    TEST_LOCATION);
 
   // Send shader compile signal
   application.SendNotification();
index 6291e50..ae3963f 100644 (file)
@@ -1529,7 +1529,9 @@ int UtcDaliVisualFactoryGetSvgVisual(void)
   // Either application.SendNotification() or the trigger can now complete the task.
   application.SendNotification();
   application.Render();
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  // Wait for loading & rasterization
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
 
   // renderer is added to actor
   DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
@@ -1565,7 +1567,9 @@ int UtcDaliVisualFactoryGetSvgVisualLarge(void)
   // Either application.SendNotification() or the trigger can now complete the task.
   application.SendNotification();
   application.Render();
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  // Wait for loading & rasterization
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
 
   // renderer is added to actor
   DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
@@ -1609,7 +1613,9 @@ int UtcDaliVisualFactoryGetSvgVisualAtlas(void)
   DALI_TEST_CHECK(actor.GetRendererCount() == 0u);
   application.SendNotification();
   application.Render();
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  // Wait for loading & rasterization
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
 
   // renderer is added to actor
   DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
index 8891e9d..f900b5a 100644 (file)
@@ -64,7 +64,7 @@ if (ENABLE_PKG_CONFIGURE)
 
        set(PREFIX ${prefix})
        set(EXEC_PREFIX ${CMAKE_INSTALL_PREFIX})
-       set(DEV_INCLUDE_PATH ${repo_root_dir})
+       set(DEV_INCLUDE_PATH ${INCLUDE_DIR})
 
        set(core_pkg_cfg_file dali2-scene-loader.pc)
        configure_file(${CMAKE_CURRENT_LIST_DIR}/${core_pkg_cfg_file}.in ${core_pkg_cfg_file} @ONLY)
index 3031c5e..2c8bd97 100644 (file)
@@ -1263,9 +1263,10 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde
       auto& extras = nodeDef.mExtras;
       extras.reserve(eExtras->Size());
 
-      NodeDefinition::Extra e;
       for(auto i0 = eExtras->CBegin(), i1 = eExtras->CEnd(); i0 != i1; ++i0)
       {
+        NodeDefinition::Extra e;
+
         auto eExtra = *i0;
         e.mKey      = eExtra.first;
         if(e.mKey.empty())
index 2fdf285..71934f0 100644 (file)
@@ -152,9 +152,9 @@ static int MinorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction di
  * @param minorAxisDistance The minorAxisDistance\r
  * @return The distance\r
  */\r
-static int GetWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance)\r
+static uint64_t GetWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance)\r
 {\r
-  return 13 * majorAxisDistance * majorAxisDistance + minorAxisDistance * minorAxisDistance;\r
+  return 13 * static_cast<int64_t>(majorAxisDistance) * static_cast<int64_t>(majorAxisDistance) + static_cast<int64_t>(minorAxisDistance) * static_cast<int64_t>(minorAxisDistance);\r
 }\r
 \r
 /**\r
index cc96d45..d7778d8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -25,7 +25,7 @@ namespace Toolkit
 {
 namespace DevelStyleManager
 {
-const Property::Map GetConfigurations(StyleManager styleManager)
+const Property::Map& GetConfigurations(StyleManager styleManager)
 {
   return GetImpl(styleManager).GetConfigurations();
 }
index f1e05d7..23c7999 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_STYLE_MANAGER_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -46,7 +46,7 @@ using BrokenImageChangedSignalType = Signal<void(StyleManager)>;
  * @param[in] styleManager The instance of StyleManager
  * @return A property map to the currently defined configurations
 **/
-DALI_TOOLKIT_API const Property::Map GetConfigurations(StyleManager styleManager);
+DALI_TOOLKIT_API const Property::Map& GetConfigurations(StyleManager styleManager);
 
 /**
    * @brief Sets an image to be used when a visual has failed to correctly render
index c9ab7b5..d1d6900 100644 (file)
@@ -1065,11 +1065,14 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR
 
   // Update the visual model.
   Size newLayoutSize;
-  bool isAutoScrollEnabled = false;
+  bool isAutoScrollEnabled            = false;
+  bool isAutoScrollMaxTextureExceeded = false;
+
   layoutEngine.LayoutText(layoutParameters,
                           newLayoutSize,
                           textParameters.ellipsisEnabled,
                           isAutoScrollEnabled,
+                          isAutoScrollMaxTextureExceeded,
                           ellipsisPosition);
 
   return newLayoutSize;
index 413b556..7deaf7a 100644 (file)
@@ -145,7 +145,14 @@ enum Type
    * @details Name "redrawInScalingDown", type Property::BOOLEAN.
    * @note It is used in the AnimatedVectorImageVisual. The default is true.
    */
-  REDRAW_IN_SCALING_DOWN
+  REDRAW_IN_SCALING_DOWN = ORIENTATION_CORRECTION + 11,
+
+  /**
+   * @brief Whether to apply mask in loading time or rendering time.
+   * @details Name "maskingType", type PlayState::Type (Property::INTEGER).
+   * @note It is used in the ImageVisual and AnimatedImageVisual. The default is MASKING_ON_LOADING.
+   */
+  MASKING_TYPE = ORIENTATION_CORRECTION + 12
 };
 
 } //namespace Property
@@ -191,6 +198,19 @@ enum Type
 
 } // namespace LoopingMode
 
+/**
+ * @brief Enumeration for what masking type is in.
+ */
+namespace MaskingType
+{
+enum Type
+{
+  MASKING_ON_RENDERING, ///< Alpha masking is applied for each rendering time. (On GPU)
+  MASKING_ON_LOADING    ///< Alpha masking is applied when the image is loading. (On CPU)
+};
+
+}
+
 } // namespace DevelImageVisual
 
 } // namespace Toolkit
index c1f4179..646bdbf 100644 (file)
@@ -488,7 +488,7 @@ bool EditableTextControlAccessible::InsertText(std::size_t startPosition, std::s
 {
   auto text = GetWholeText();
 
-  if(!ValidateRange(text, startPosition, startPosition + 1))
+  if(!ValidateRange(text, startPosition, startPosition + 1) && !(startPosition == text.size()))
   {
     return false;
   }
index 76d0ee2..2d2368b 100644 (file)
@@ -1062,6 +1062,13 @@ void TextLabel::OnRelayout(const Vector2& size, RelayoutContainer& container)
     alignmentOffset.x = 0.0f;
     alignmentOffset.y = (contentSize.y - layoutSize.y) * VERTICAL_ALIGNMENT_TABLE[mController->GetVerticalAlignment()];
 
+    const int maxTextureSize = Dali::GetMaxTextureSize();
+    if(layoutSize.width > maxTextureSize)
+    {
+      DALI_LOG_WARNING("layoutSize(%f) > maxTextureSize(%d): To guarantee the behavior of Texture::New, layoutSize must not be bigger than maxTextureSize\n", layoutSize.width, maxTextureSize);
+      layoutSize.width = maxTextureSize;
+    }
+
     Property::Map visualTransform;
     visualTransform.Add(Toolkit::Visual::Transform::Property::SIZE, layoutSize)
       .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE))
@@ -1125,6 +1132,7 @@ void TextLabel::SetUpAutoScrolling()
     if(textNaturalSize.width > maxTextureSize)
     {
       mController->SetTextElideEnabled(true);
+      mController->SetAutoScrollMaxTextureExceeded(true);
     }
     GetHeightForWidth(maxTextureSize);
     wrapGap = std::max(maxTextureSize - textNaturalSize.width, 0.0f);
@@ -1152,6 +1160,7 @@ void TextLabel::SetUpAutoScrolling()
   Renderer renderer = static_cast<Internal::Visual::Base&>(GetImplementation(mVisual)).GetRenderer();
   mTextScroller->SetParameters(Self(), renderer, textureSet, controlSize, verifiedSize, wrapGap, direction, mController->GetHorizontalAlignment(), mController->GetVerticalAlignment());
   mController->SetTextElideEnabled(actualellipsis);
+  mController->SetAutoScrollMaxTextureExceeded(false);
 }
 
 void TextLabel::ScrollingFinished()
index 15640b7..41d8c0d 100644 (file)
@@ -139,6 +139,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/image-loader/image-load-thread.cpp
    ${toolkit_src_dir}/image-loader/image-url-impl.cpp
    ${toolkit_src_dir}/styling/style-manager-impl.cpp
+   ${toolkit_src_dir}/text/abstract-style-character-run.cpp
    ${toolkit_src_dir}/text/bidirectional-support.cpp
    ${toolkit_src_dir}/text/bounded-paragraph-helper-functions.cpp
    ${toolkit_src_dir}/text/character-set-conversion.cpp
@@ -163,6 +164,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/multi-language-support.cpp
    ${toolkit_src_dir}/text/hidden-text.cpp
    ${toolkit_src_dir}/text/input-filter.cpp
+   ${toolkit_src_dir}/text/line-helper-functions.cpp
    ${toolkit_src_dir}/text/property-string-parser.cpp
    ${toolkit_src_dir}/text/segmentation.cpp
    ${toolkit_src_dir}/text/shaper.cpp
index 4383c1a..07dc86d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -183,8 +183,10 @@ void KeyboardFocusManager::GetConfigurationFromStyleManger()
   Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
   if(styleManager)
   {
-    Property::Map config   = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
-    mAlwaysShowIndicator   = config["alwaysShowFocus"].Get<bool>() ? ALWAYS_SHOW : NONE;
+    const Property::Map& config               = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
+    const auto           alwaysShowFocusValue = config.Find("alwaysShowFocus", Property::Type::BOOLEAN);
+
+    mAlwaysShowIndicator   = (alwaysShowFocusValue && alwaysShowFocusValue->Get<bool>()) ? ALWAYS_SHOW : NONE;
     mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE;
     mClearFocusOnTouch     = (mIsFocusIndicatorShown == SHOW) ? false : true;
   }
@@ -244,14 +246,6 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
       actor.Add(GetFocusIndicatorActor());
     }
 
-    Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor);
-    if(currentlyFocusedControl)
-    {
-      // Do we need it to remember if it was previously DISABLED?
-      currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL);
-      currentlyFocusedControl.ClearKeyInputFocus();
-    }
-
     // Save the current focused actor
     mCurrentFocusActor = actor;
 
@@ -277,6 +271,14 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor)
       mFocusChangedSignal.Emit(currentFocusedActor, actor);
     }
 
+    Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor);
+    if(currentlyFocusedControl)
+    {
+      // Do we need it to remember if it was previously DISABLED?
+      currentlyFocusedControl.SetProperty(DevelControl::Property::STATE, DevelControl::NORMAL);
+      currentlyFocusedControl.ClearKeyInputFocus();
+    }
+
     Toolkit::Control newlyFocusedControl = Toolkit::Control::DownCast(actor);
     if(newlyFocusedControl)
     {
@@ -520,16 +522,16 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction
         nextFocusableActor                  = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction);
         mIsWaitingKeyboardFocusChangeCommit = false;
       }
-      else if (mEnableDefaultAlgorithm)
+      else if(mEnableDefaultAlgorithm)
       {
         Actor rootActor = mFocusFinderRootActor.GetHandle();
         if(!rootActor)
         {
-          if (currentFocusActor)
+          if(currentFocusActor)
           {
             // Find the window of the focused actor.
             Integration::SceneHolder window = Integration::SceneHolder::Get(currentFocusActor);
-            if (window)
+            if(window)
             {
               rootActor = window.GetRootLayer();
             }
@@ -799,7 +801,7 @@ Actor KeyboardFocusManager::GetFocusIndicatorActor()
 
 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
 {
-  const std::string& keyName = event.GetKeyName();
+  const std::string& keyName    = event.GetKeyName();
   const std::string& deviceName = event.GetDeviceName();
 
   if(mIsFocusIndicatorShown == UNKNOWN)
@@ -984,7 +986,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
         actor.Add(GetFocusIndicatorActor());
       }
     }
-    else
+    else if(!mEnableDefaultAlgorithm)
     {
       // No actor is focused but keyboard focus is activated by the key press
       // Let's try to move the initial focus
@@ -1045,8 +1047,8 @@ void KeyboardFocusManager::OnWheelEvent(const WheelEvent& event)
 
 bool KeyboardFocusManager::OnCustomWheelEvent(const WheelEvent& event)
 {
-  bool consumed = false;
-  Actor actor = GetCurrentFocusActor();
+  bool  consumed = false;
+  Actor actor    = GetCurrentFocusActor();
   if(actor)
   {
     // Notify the actor about the wheel event
index e5cbaa7..5faf423 100644 (file)
@@ -36,9 +36,9 @@ uniform mediump vec2 anchorPoint;
 
 vec4 ComputeVertexPosition()
 {
-  vec2 visualSize = mix( uSize.xy*size, size, offsetSizeMode.zw );
-  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy );
-  return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw );
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy );
+  return vec4( (aPosition + anchorPoint)*visualSize + visualOffset + origin * uSize.xy, 0.0, 1.0 );
 }
 
 void main()
index e063d81..4f6dab5 100644 (file)
@@ -13,10 +13,10 @@ uniform mediump vec2 anchorPoint;
 
 vec4 ComputeVertexPosition()
 {
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
-  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw );
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
   vPosition = aPosition* visualSize;
-  return vec4( vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+  return vec4( vPosition + anchorPoint*visualSize + visualOffset + origin * uSize.xy, 0.0, 1.0 );
 }
 
 void main()
index 6dc0721..6bf08fa 100644 (file)
@@ -14,9 +14,9 @@ uniform mediump vec2 anchorPoint;
 
 vec2 ComputeVertexPosition()
 {
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
-  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
-  return (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy;
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw );
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
+  return (aPosition + anchorPoint)*visualSize + visualOffset + origin * uSize.xy;
 }
 
 void main()
index 33202a2..db23361 100644 (file)
@@ -1,36 +1,26 @@
-#ifndef IS_REQUIRED_ROUNDED_CORNER
-#define IS_REQUIRED_ROUNDED_CORNER 0
-#endif
-#ifndef IS_REQUIRED_BORDERLINE
-#define IS_REQUIRED_BORDERLINE 0
-#endif
-#ifndef IS_REQUIRED_BLUR
-#define IS_REQUIRED_BLUR 0
-#endif
-
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE) || defined(IS_REQUIRED_BLUR)
 INPUT mediump vec2 vPosition;
 INPUT mediump vec2 vRectSize;
 INPUT mediump vec2 vOptRectSize;
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 INPUT mediump vec4 vCornerRadius;
 #endif
 #endif
 
 uniform lowp vec4 uColor;
 uniform lowp vec3 mixColor;
-#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+#if !defined(IS_REQUIRED_BLUR) && defined(IS_REQUIRED_BORDERLINE)
 uniform mediump float borderlineWidth;
 uniform mediump float borderlineOffset;
 uniform lowp vec4 borderlineColor;
 uniform lowp vec4 uActorColor;
 #endif
-#if IS_REQUIRED_BLUR
+#ifdef IS_REQUIRED_BLUR
 uniform mediump float blurRadius;
 #endif
 
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE) || defined(IS_REQUIRED_BLUR)
 // Global values both rounded corner and borderline use
 
 // radius of rounded corner on this quadrant
@@ -54,7 +44,7 @@ mediump float gMinInlinePotential = 0.0;
 
 void calculateCornerRadius()
 {
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
   gRadius =
   mix(
     mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
@@ -68,7 +58,7 @@ void calculatePosition()
 {
   gFragmentPosition = abs(vPosition) - vRectSize;
   gCenterPosition = -gRadius;
-#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+#if !defined(IS_REQUIRED_BLUR) && defined(IS_REQUIRED_BORDERLINE)
   gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5;
 #endif
   gDiff = gFragmentPosition - gCenterPosition;
@@ -86,7 +76,7 @@ void setupMinMaxPotential()
   gMaxOutlinePotential = gRadius + gPotentialRange;
   gMinOutlinePotential = gRadius - gPotentialRange;
 
-#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+#if !defined(IS_REQUIRED_BLUR) && defined(IS_REQUIRED_BORDERLINE)
   gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth;
   gMinInlinePotential = gMinOutlinePotential - borderlineWidth;
 #else
@@ -109,7 +99,7 @@ void PreprocessPotential()
 }
 #endif
 
-#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+#if !defined(IS_REQUIRED_BLUR) && defined(IS_REQUIRED_BORDERLINE)
 lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 {
   mediump float potential = gPotential;
@@ -173,7 +163,7 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 }
 #endif
 
-#if !IS_REQUIRED_BLUR && IS_REQUIRED_ROUNDED_CORNER
+#if !defined(IS_REQUIRED_BLUR) && defined(IS_REQUIRED_ROUNDED_CORNER)
 mediump float calculateCornerOpacity()
 {
   mediump float potential = gPotential;
@@ -195,7 +185,7 @@ mediump float calculateCornerOpacity()
 }
 #endif
 
-#if IS_REQUIRED_BLUR
+#ifdef IS_REQUIRED_BLUR
 mediump float calculateBlurOpacity()
 {
 // Don't use borderline!
@@ -203,7 +193,7 @@ mediump float calculateBlurOpacity()
   mediump float cy = gRadius + blurRadius;
   mediump float cr = gRadius + blurRadius;
 
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
   // This routine make perfect circle. If corner radius is not exist, we don't consider prefect circle.
   cy = min(cy, min(vRectSize.x, vRectSize.y) - gRadius);
 #endif
@@ -240,7 +230,7 @@ mediump float calculateBlurOpacity()
     // highest point of that circle is (x, x + r) and potential is x + r
 
     // solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
     // Note : lowspec HW cannot calculate here. need to reduce numeric error
     highp float A = (cr * cr - 2.0 * cy * cy);
     highp float B = cy * (v.x + v.y);
@@ -268,7 +258,7 @@ void main()
 {
   lowp vec4 targetColor = vec4(mixColor, 1.0) * uColor;
 
-#if IS_REQUIRED_BLUR || IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_BLUR) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   // skip most potential calculate for performance
   if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
   {
@@ -279,20 +269,20 @@ void main()
     PreprocessPotential();
 #endif
 
-#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+#if !defined(IS_REQUIRED_BLUR) && defined(IS_REQUIRED_BORDERLINE)
     targetColor = convertBorderlineColor(targetColor);
 #endif
     OUT_COLOR = targetColor;
 
-#if IS_REQUIRED_BLUR
+#ifdef IS_REQUIRED_BLUR
     mediump float opacity = calculateBlurOpacity();
     OUT_COLOR.a *= opacity;
-#elif IS_REQUIRED_ROUNDED_CORNER
+#elif defined(IS_REQUIRED_ROUNDED_CORNER)
     mediump float opacity = calculateCornerOpacity();
     OUT_COLOR.a *= opacity;
 #endif
 
-#if IS_REQUIRED_BLUR || IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_BLUR) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   }
 #endif
 }
index 2798185..f1688da 100644 (file)
@@ -1,19 +1,9 @@
-#ifndef IS_REQUIRED_ROUNDED_CORNER
-#define IS_REQUIRED_ROUNDED_CORNER 0
-#endif
-#ifndef IS_REQUIRED_BORDERLINE
-#define IS_REQUIRED_BORDERLINE 0
-#endif
-#ifndef IS_REQUIRED_BLUR
-#define IS_REQUIRED_BLUR 0
-#endif
-
 INPUT mediump vec2 aPosition;
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE) || defined(IS_REQUIRED_BLUR)
 OUTPUT mediump vec2 vPosition;
 OUTPUT mediump vec2 vRectSize;
 OUTPUT mediump vec2 vOptRectSize;
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 OUTPUT mediump vec4 vCornerRadius;
 #endif
 #endif
@@ -27,14 +17,14 @@ uniform highp vec2 size;
 uniform mediump vec4 offsetSizeMode;
 uniform mediump vec2 origin;
 uniform mediump vec2 anchorPoint;
-#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+#if !defined(IS_REQUIRED_BLUR) && defined(IS_REQUIRED_BORDERLINE)
 uniform mediump float borderlineWidth;
 uniform mediump float borderlineOffset;
 #endif
-#if IS_REQUIRED_BLUR
+#ifdef IS_REQUIRED_BLUR
 uniform mediump float blurRadius;
 #endif
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 uniform mediump vec4 cornerRadius;
 uniform mediump float cornerRadiusPolicy;
 #endif
@@ -42,16 +32,16 @@ uniform mediump vec2 extraSize;
 
 vec4 ComputeVertexPosition()
 {
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;
-  vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy);
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw ) + extraSize;
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE) || defined(IS_REQUIRED_BLUR)
   vRectSize = visualSize * 0.5;
   vOptRectSize = vRectSize;
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER
-#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_ROUNDED_CORNER
+#if !defined(IS_REQUIRED_BLUR) && defined(IS_REQUIRED_BORDERLINE)
   mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth;
 #else
   mediump float minSize = min(visualSize.x, visualSize.y);
@@ -63,18 +53,18 @@ vec4 ComputeVertexPosition()
   vOptRectSize -= 0.2929 * maxRadius + 1.0;
 #endif
 
-#if IS_REQUIRED_BLUR
+#ifdef IS_REQUIRED_BLUR
   vPosition = aPosition * (visualSize + 2.0 * blurRadius);
   vOptRectSize -= blurRadius + 1.0;
-#elif IS_REQUIRED_BORDERLINE
+#elif defined(IS_REQUIRED_BORDERLINE)
   vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0))* borderlineWidth);
   vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
-#elif IS_REQUIRED_ROUNDED_CORNER
+#elif defined(IS_REQUIRED_ROUNDED_CORNER)
   vPosition = aPosition * visualSize;
 #else
   mediump vec2 vPosition = aPosition * visualSize;
 #endif
-  return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
+  return vec4(vPosition + anchorPoint * visualSize + visualOffset + origin * uSize.xy, 0.0, 1.0);
 }
 
 void main()
index a30bf5e..febc776 100644 (file)
@@ -1,19 +1,9 @@
-#ifndef IS_REQUIRED_ROUNDED_CORNER
-#define IS_REQUIRED_ROUNDED_CORNER 0
-#endif
-#ifndef IS_REQUIRED_BORDERLINE
-#define IS_REQUIRED_BORDERLINE 0
-#endif
-#ifndef RADIAL
-#define RADIAL 0
-#endif
-
 INPUT mediump vec2 vTexCoord;
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 INPUT mediump vec2 vPosition;
 INPUT mediump vec2 vRectSize;
 INPUT mediump vec2 vOptRectSize;
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 INPUT mediump vec4 vCornerRadius;
 #endif
 #endif
@@ -21,14 +11,14 @@ INPUT mediump vec4 vCornerRadius;
 uniform sampler2D sTexture; // sampler1D?
 uniform lowp vec4 uColor;
 uniform lowp vec3 mixColor;
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
 uniform mediump float borderlineWidth;
 uniform mediump float borderlineOffset;
 uniform lowp vec4 borderlineColor;
 uniform lowp vec4 uActorColor;
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 // Global values both rounded corner and borderline use
 
 // radius of rounded corner on this quadrant
@@ -52,7 +42,7 @@ mediump float gMinInlinePotential = 0.0;
 
 void calculateCornerRadius()
 {
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
   gRadius =
   mix(
     mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
@@ -66,7 +56,7 @@ void calculatePosition()
 {
   gFragmentPosition = abs(vPosition) - vRectSize;
   gCenterPosition = -gRadius;
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
   gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5;
 #endif
   gDiff = gFragmentPosition - gCenterPosition;
@@ -84,7 +74,7 @@ void setupMinMaxPotential()
   gMaxOutlinePotential = gRadius + gPotentialRange;
   gMinOutlinePotential = gRadius - gPotentialRange;
 
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
   gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth;
   gMinInlinePotential = gMinOutlinePotential - borderlineWidth;
 #else
@@ -108,7 +98,7 @@ void PreprocessPotential()
 #endif
 
 
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
 lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 {
   mediump float potential = gPotential;
@@ -172,7 +162,7 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 }
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 mediump float calculateCornerOpacity()
 {
   mediump float potential = gPotential;
@@ -196,13 +186,13 @@ mediump float calculateCornerOpacity()
 
 void main()
 {
-#if RADIAL
+#ifdef RADIAL
   lowp vec4 textureColor = TEXTURE(sTexture, vec2(length(vTexCoord), 0.5)) * vec4(mixColor, 1.0) * uColor;
 #else
   lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y, 0.5)) * vec4(mixColor, 1.0) * uColor;
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   // skip most potential calculate for performance
   if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
   {
@@ -213,17 +203,17 @@ void main()
     PreprocessPotential();
 #endif
 
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
     textureColor = convertBorderlineColor(textureColor);
 #endif
     OUT_COLOR = textureColor;
 
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
     mediump float opacity = calculateCornerOpacity();
     OUT_COLOR *= opacity;
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   }
 #endif
 }
index edaf643..68179ab 100644 (file)
@@ -1,20 +1,10 @@
-#ifndef IS_REQUIRED_ROUNDED_CORNER
-#define IS_REQUIRED_ROUNDED_CORNER 0
-#endif
-#ifndef IS_REQUIRED_BORDERLINE
-#define IS_REQUIRED_BORDERLINE 0
-#endif
-#ifndef USER_SPACE
-#define USER_SPACE 0
-#endif
-
 INPUT mediump vec2 aPosition;
 OUTPUT mediump vec2 vTexCoord;
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 OUTPUT mediump vec2 vPosition;
 OUTPUT mediump vec2 vRectSize;
 OUTPUT mediump vec2 vOptRectSize;
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 OUTPUT mediump vec4 vCornerRadius;
 #endif
 #endif
@@ -29,27 +19,27 @@ uniform highp vec2 size;
 uniform mediump vec4 offsetSizeMode;
 uniform mediump vec2 origin;
 uniform mediump vec2 anchorPoint;
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
 uniform mediump float borderlineWidth;
 uniform mediump float borderlineOffset;
 #endif
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 uniform mediump vec4 cornerRadius;
 uniform mediump float cornerRadiusPolicy;
 #endif
 
 vec4 ComputeVertexPosition()
 {
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
-  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw );
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   vRectSize = visualSize * 0.5;
   vOptRectSize = vRectSize;
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_BORDERLINE
   mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth;
 #else
   mediump float minSize = min(visualSize.x, visualSize.y);
@@ -62,23 +52,23 @@ vec4 ComputeVertexPosition()
 #endif
 
   mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
   vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth);
   vertexPosition.xy *= (1.0 + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth / visualSize);
   vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
-#elif IS_REQUIRED_ROUNDED_CORNER
+#elif defined(IS_REQUIRED_ROUNDED_CORNER)
   vPosition = aPosition * visualSize;
 #else
   mediump vec2 vPosition = aPosition * visualSize;
 #endif
 
-#if USER_SPACE
+#ifdef USER_SPACE
   vertexPosition.xyz *= uSize;
 #endif
 
   vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
 
-  return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
+  return vec4(vPosition + anchorPoint * visualSize + visualOffset + origin * uSize.xy, 0.0, 1.0);
 }
 
 void main()
index 703c649..3694280 100644 (file)
@@ -1,30 +1,23 @@
-#ifndef IS_REQUIRED_ROUNDED_CORNER
-#define IS_REQUIRED_ROUNDED_CORNER 0
-#endif
-#ifndef IS_REQUIRED_BORDERLINE
-#define IS_REQUIRED_BORDERLINE 0
-#endif
-#ifndef ATLAS_DEFAULT_WARP
-#define ATLAS_DEFAULT_WARP 0
-#endif
-#ifndef ATLAS_CUSTOM_WARP
-#define ATLAS_CUSTOM_WARP 0
-#endif
-
 INPUT mediump vec2 vTexCoord;
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 INPUT mediump vec2 vPosition;
 INPUT mediump vec2 vRectSize;
 INPUT mediump vec2 vOptRectSize;
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 INPUT mediump vec4 vCornerRadius;
 #endif
 #endif
 
 uniform sampler2D sTexture;
-#if ATLAS_DEFAULT_WARP
+
+#ifdef IS_REQUIRED_ALPHA_MASKING
+uniform sampler2D sMaskTexture;
+INPUT mediump vec2 vMaskTexCoord;
+#endif
+
+#ifdef ATLAS_DEFAULT_WARP
 uniform mediump vec4 uAtlasRect;
-#elif ATLAS_CUSTOM_WARP
+#elif defined(ATLAS_CUSTOM_WARP)
 // WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
 uniform lowp vec2 wrapMode;
 #endif
@@ -32,14 +25,14 @@ uniform lowp vec2 wrapMode;
 uniform lowp vec4 uColor;
 uniform lowp vec3 mixColor;
 uniform lowp float preMultipliedAlpha;
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
 uniform mediump float borderlineWidth;
 uniform mediump float borderlineOffset;
 uniform lowp vec4 borderlineColor;
 uniform lowp vec4 uActorColor;
 #endif
 
-#if ATLAS_CUSTOM_WARP
+#ifdef ATLAS_CUSTOM_WARP
 mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )
 {
   mediump float coord;
@@ -51,7 +44,7 @@ mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp
 }
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 // Global values both rounded corner and borderline use
 
 // radius of rounded corner on this quadrant
@@ -75,7 +68,7 @@ mediump float gMinInlinePotential = 0.0;
 
 void calculateCornerRadius()
 {
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
   gRadius =
   mix(
     mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
@@ -89,7 +82,7 @@ void calculatePosition()
 {
   gFragmentPosition = abs(vPosition) - vRectSize;
   gCenterPosition = -gRadius;
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
   gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5;
 #endif
   gDiff = gFragmentPosition - gCenterPosition;
@@ -107,7 +100,7 @@ void setupMinMaxPotential()
   gMaxOutlinePotential = gRadius + gPotentialRange;
   gMinOutlinePotential = gRadius - gPotentialRange;
 
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
   gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth;
   gMinInlinePotential = gMinOutlinePotential - borderlineWidth;
 #else
@@ -130,7 +123,7 @@ void PreprocessPotential()
 }
 #endif
 
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
 lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 {
   mediump float potential = gPotential;
@@ -193,7 +186,7 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 }
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 mediump float calculateCornerOpacity()
 {
   mediump float potential = gPotential;
@@ -217,9 +210,9 @@ mediump float calculateCornerOpacity()
 
 void main()
 {
-#if ATLAS_DEFAULT_WARP
+#ifdef ATLAS_DEFAULT_WARP
   mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );
-#elif ATLAS_CUSTOM_WARP
+#elif defined(ATLAS_CUSTOM_WARP)
   mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ),
                                 wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );
 #else
@@ -228,7 +221,13 @@ void main()
 
   lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ) * uColor;
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_ALPHA_MASKING
+  mediump float maskAlpha = TEXTURE(sMaskTexture, vMaskTexCoord).a;
+  textureColor.a *= maskAlpha;
+  textureColor.rgb *= mix(1.0, maskAlpha, preMultipliedAlpha);
+#endif
+
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   // skip most potential calculate for performance
   if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
   {
@@ -239,18 +238,18 @@ void main()
     PreprocessPotential();
 #endif
 
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
     textureColor = convertBorderlineColor(textureColor);
 #endif
     OUT_COLOR = textureColor;
 
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
     mediump float opacity = calculateCornerOpacity();
     OUT_COLOR.a *= opacity;
     OUT_COLOR.rgb *= mix(1.0, opacity, preMultipliedAlpha);
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   }
 #endif
 }
index 21d4084..7443aa1 100644 (file)
@@ -1,17 +1,10 @@
-#ifndef IS_REQUIRED_ROUNDED_CORNER
-#define IS_REQUIRED_ROUNDED_CORNER 0
-#endif
-#ifndef IS_REQUIRED_BORDERLINE
-#define IS_REQUIRED_BORDERLINE 0
-#endif
-
 INPUT mediump vec2 aPosition;
 OUTPUT mediump vec2 vTexCoord;
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
 OUTPUT mediump vec2 vPosition;
 OUTPUT mediump vec2 vRectSize;
 OUTPUT mediump vec2 vOptRectSize;
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 OUTPUT mediump vec4 vCornerRadius;
 #endif
 #endif
@@ -26,28 +19,33 @@ uniform highp vec2 size;
 uniform mediump vec4 offsetSizeMode;
 uniform mediump vec2 origin;
 uniform mediump vec2 anchorPoint;
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
 uniform mediump float borderlineWidth;
 uniform mediump float borderlineOffset;
 #endif
-#if IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_ROUNDED_CORNER
 uniform mediump vec4 cornerRadius;
 uniform mediump float cornerRadiusPolicy;
 #endif
+#ifdef IS_REQUIRED_ALPHA_MASKING
+OUTPUT  mediump vec2  vMaskTexCoord;
+uniform lowp    float cropToMask;
+uniform mediump vec2  maskTextureRatio;
+#endif
 uniform mediump vec2 extraSize;
 
 vec4 ComputeVertexPosition()
 {
-  vec2 visualSize = mix(uSize.xy * size, size, offsetSizeMode.zw) + extraSize;
-  vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy);
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw) + extraSize;
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
 
-#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE)
   vRectSize = visualSize * 0.5;
   vOptRectSize = vRectSize;
 #endif
 
-#if IS_REQUIRED_ROUNDED_CORNER
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_ROUNDED_CORNER
+#ifdef IS_REQUIRED_BORDERLINE
   mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth;
 #else
   mediump float minSize = min(visualSize.x, visualSize.y);
@@ -59,17 +57,28 @@ vec4 ComputeVertexPosition()
   vOptRectSize -= 0.2929 * maxRadius + 1.0;
 #endif
 
-#if IS_REQUIRED_BORDERLINE
+#ifdef IS_REQUIRED_BORDERLINE
   vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth);
   vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
-#elif IS_REQUIRED_ROUNDED_CORNER
+#elif defined(IS_REQUIRED_ROUNDED_CORNER)
   vPosition = aPosition * visualSize;
 #else
   mediump vec2 vPosition = aPosition * visualSize;
 #endif
 
-  vTexCoord = pixelArea.xy + pixelArea.zw * (vPosition.xy / max(vec2(1.0), visualSize) + vec2(0.5));
-  return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
+  vec4 finalPixelArea = pixelArea;
+#ifdef IS_REQUIRED_ALPHA_MASKING
+  finalPixelArea = mix(pixelArea,
+                       vec4(
+                            vec2(0.5) + (pixelArea.xy - vec2(0.5)) * maskTextureRatio,
+                            pixelArea.zw * maskTextureRatio
+                       ),
+                       cropToMask);
+  vMaskTexCoord = pixelArea.xy + pixelArea.zw * (vPosition.xy / max(vec2(1.0), visualSize) + vec2(0.5));
+#endif
+  vTexCoord = finalPixelArea.xy + finalPixelArea.zw * (vPosition.xy / max(vec2(1.0), visualSize) + vec2(0.5));
+
+  return vec4(vPosition + anchorPoint * visualSize + visualOffset + origin * uSize.xy, 0.0, 1.0);
 }
 
 void main()
index c25a1bb..bc9ac8a 100644 (file)
@@ -24,12 +24,12 @@ uniform mediump vec2 anchorPoint;
 
 vec4 ComputeVertexPosition()
 {
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw );
   float scaleFactor = min( visualSize.x, visualSize.y );
   vec3 originFlipY =vec3(origin.x, -origin.y, 0.0);
   vec3 anchorPointFlipY = vec3( anchorPoint.x, -anchorPoint.y, 0.0);
-  vec3 offset = vec3( ( offset / uSize.xy ) * offsetSizeMode.xy + offset * (1.0-offsetSizeMode.xy), 0.0) * vec3(1.0,-1.0,1.0);
-  return vec4( (aPosition + anchorPointFlipY)*scaleFactor + (offset + originFlipY)*uSize, 1.0 );
+  vec3 visualOffset = vec3( offset * offsetSizeMode.xy + offset * uSize.xy * (1.0 - offsetSizeMode.xy), 0.0) * vec3(1.0,-1.0,1.0);
+  return vec4( (aPosition + anchorPointFlipY)*scaleFactor + visualOffset + originFlipY * uSize, 1.0 );
 }
 
 void main()
index 05b90ce..858c92d 100644 (file)
@@ -26,8 +26,8 @@ vec4 ComputeVertexPosition()
   float scaleFactor = min( visualSize.x, visualSize.y );
   vec3 originFlipY =vec3(origin.x, -origin.y, 0.0);
   vec3 anchorPointFlipY = vec3( anchorPoint.x, -anchorPoint.y, 0.0);
-  vec3 offset = vec3( ( offset / uSize.xy ) * offsetSizeMode.xy + offset * (1.0-offsetSizeMode.xy), 0.0) * vec3(1.0,-1.0,1.0);
-  return vec4( (aPosition + anchorPointFlipY)*scaleFactor + (offset + originFlipY)*uSize, 1.0 );
+  vec3 visualOffset = vec3( offset * offsetSizeMode.xy + offset * uSize.xy * (1.0-offsetSizeMode.xy), 0.0) * vec3(1.0,-1.0,1.0);
+  return vec4( (aPosition + anchorPointFlipY)*scaleFactor + visualOffset + originFlipY * uSize, 1.0 );
 }
 
 void main()
index 2a4b704..0541a16 100644 (file)
@@ -23,8 +23,8 @@ vec4 ComputeVertexPosition()
   float scaleFactor = min( visualSize.x, visualSize.y );
   vec3 originFlipY =vec3(origin.x, -origin.y, 0.0);
   vec3 anchorPointFlipY = vec3( anchorPoint.x, -anchorPoint.y, 0.0);
-  vec3 offset = vec3( ( offset / uSize.xy ) * offsetSizeMode.xy + offset * (1.0-offsetSizeMode.xy), 0.0) * vec3(1.0,-1.0,1.0);
-  return vec4( (aPosition + anchorPointFlipY)*scaleFactor + (offset + originFlipY)*uSize, 1.0 );
+  vec3 visualOffset = vec3( offset * offsetSizeMode.xy + offset * uSize.xy * (1.0-offsetSizeMode.xy), 0.0) * vec3(1.0,-1.0,1.0);
+  return vec4( (aPosition + anchorPointFlipY)*scaleFactor + visualOffset + originFlipY * uSize, 1.0 );
 }
 
 void main()
index c7b8a9f..4625b3c 100644 (file)
@@ -16,8 +16,8 @@ uniform mediump vec2 extraSize;
 
 void main()
 {
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;
-  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw ) + extraSize;
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
 
   mediump vec2 size = visualSize.xy;
 
@@ -31,7 +31,7 @@ void main()
   mediump vec4 gridPosition = vec4( fixedFactor * fixedScaleDownRate + ( size - fixedTotal * fixedScaleDownRate ) * stretch, 0.0, 1.0 );
   mediump vec4 vertexPosition = gridPosition;
   vertexPosition.xy -= size * vec2( 0.5, 0.5 );
-  vertexPosition.xy += anchorPoint*size + (visualOffset + origin)*uSize.xy;
+  vertexPosition.xy += anchorPoint*size + visualOffset + origin * uSize.xy;
 
   vertexPosition = uMvpMatrix * vertexPosition;
 
index 4cd84bc..01f6138 100644 (file)
@@ -22,8 +22,8 @@ void main()
   mediump vec2 fixedTotal = vec2( uNinePatchFactorsX[ FACTOR_SIZE_X - 1 ].x, uNinePatchFactorsY[ FACTOR_SIZE_Y - 1 ].x );
   mediump vec2 stretchTotal = vec2( uNinePatchFactorsX[ FACTOR_SIZE_X - 1 ].y, uNinePatchFactorsY[ FACTOR_SIZE_Y - 1 ].y );
 
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;
-  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw ) + extraSize;
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
 
   // Scale down if fixedTotal is bigger than visualSize
   mediump float fixedScaleDownRate = min(1.0, min(visualSize.x / fixedTotal.x, visualSize.y / fixedTotal.y));
@@ -31,7 +31,7 @@ void main()
   mediump vec4 gridPosition = vec4( fixedFactor * fixedScaleDownRate + ( visualSize.xy - fixedTotal * fixedScaleDownRate ) * stretch / stretchTotal, 0.0, 1.0 );
   mediump vec4 vertexPosition = gridPosition;
   vertexPosition.xy -= visualSize.xy * vec2( 0.5, 0.5 );
-  vertexPosition.xy += anchorPoint*visualSize + (visualOffset + origin)*uSize.xy;
+  vertexPosition.xy += anchorPoint*visualSize + visualOffset + origin * uSize.xy;
   vertexPosition = uMvpMatrix * vertexPosition;
 
   vTexCoord = ( fixedFactor + stretch ) / ( fixedTotal + stretchTotal );
index 6a1b758..1200294 100644 (file)
@@ -27,9 +27,9 @@ vec4 ComputeVertexPosition()
   float scaleFactor = min( visualSize.x / uObjectDimensions.x, visualSize.y / uObjectDimensions.y );
   vec3 originFlipY =vec3(origin.x, -origin.y, 0.0);
   vec3 anchorPointFlipY = vec3( anchorPoint.x, -anchorPoint.y, 0.0);
-  vec3 offset = vec3( ( offset / uSize.xy ) * offsetSizeMode.xy + offset * (1.0-offsetSizeMode.xy), 0.0) * vec3(1.0,-1.0,1.0);
+  vec3 visualOffset = vec3( offset * offsetSizeMode.xy + offset * uSize.xy * (1.0-offsetSizeMode.xy), 0.0) * vec3(1.0,-1.0,1.0);
 
-  return vec4( (aPosition + anchorPointFlipY)*scaleFactor + (offset + originFlipY)*uSize, 1.0 );
+  return vec4( (aPosition + anchorPointFlipY)*scaleFactor + visualOffset + originFlipY * uSize, 1.0 );
 }
 
 void main()
index 6c2cd05..c152b5e 100644 (file)
@@ -1,9 +1,9 @@
 attribute mediump vec2 aPosition;
 varying highp vec2 vTexCoord;
 uniform highp vec3 uSize;
-uniform mediump float uDelta;
+uniform highp float uDelta;
 uniform mediump vec2 uTextureSize;
-uniform mediump float uGap;
+uniform highp float uGap;
 uniform mediump float uHorizontalAlign;
 uniform mediump float uVerticalAlign;
 
@@ -18,13 +18,13 @@ uniform mediump vec2 anchorPoint;
 
 void main()
 {
-  mediump vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy );
-  mediump vec2 visualSize = mix( uSize.xy * size, size, offsetSizeMode.zw );
+  highp vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw);
+  highp vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
 
-  vTexCoord.x = ( uDelta + uHorizontalAlign * ( uTextureSize.x - visualSize.x - uGap ) + floor( aPosition.x * visualSize.x ) + 0.5 - uGap * 0.5 ) / uTextureSize.x + 0.5;
-  vTexCoord.y = ( uVerticalAlign * ( uTextureSize.y - visualSize.y ) + floor( aPosition.y * visualSize.y ) + 0.5 ) / ( uTextureSize.y ) + 0.5;
+  vTexCoord.x = ( uDelta + uHorizontalAlign * ( uTextureSize.x - visualSize.x - uGap ) + aPosition.x * visualSize.x - uGap * 0.5 ) / uTextureSize.x + 0.5;
+  vTexCoord.y = ( uVerticalAlign * ( uTextureSize.y - visualSize.y ) + aPosition.y * visualSize.y ) / ( uTextureSize.y ) + 0.5;
 
-  mediump vec4 vertexPosition = vec4( floor( ( aPosition + anchorPoint ) * visualSize + ( visualOffset + origin ) * uSize.xy ), 0.0, 1.0 );
+  highp vec4 vertexPosition = vec4( ( aPosition + anchorPoint ) * visualSize + visualOffset + origin * uSize.xy, 0.0, 1.0 );
 
   gl_Position = uMvpMatrix * vertexPosition;
 }
\ No newline at end of file
index 893d075..4cc1212 100644 (file)
@@ -14,9 +14,9 @@ uniform mediump vec2 anchorPoint;
 
 vec4 ComputeVertexPosition()
 {
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
-  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
-  return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw );
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
+  return vec4( (aPosition + anchorPoint) * visualSize + visualOffset + origin * uSize.xy, 0.0, 1.0 );
 }
 
 void main()
index 5e0bfb0..9a9975c 100644 (file)
@@ -11,9 +11,9 @@ uniform mediump vec2 anchorPoint;
 
 vec4 ComputeVertexPosition()
 {
-  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
-  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
-  return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+  vec2 visualSize = mix(size * uSize.xy, size, offsetSizeMode.zw );
+  vec2 visualOffset = mix(offset * uSize.xy, offset, offsetSizeMode.xy);
+  return vec4( (aPosition + anchorPoint)*visualSize + visualOffset + origin * uSize.xy, 0.0, 1.0 );
 }
 
 void main()
index 959724b..e6ad82f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -285,44 +285,40 @@ void StyleManager::SetTheme(const std::string& themeFile)
   }
 }
 
-const Property::Map StyleManager::GetConfigurations()
+const Property::Map& StyleManager::GetConfigurations()
 {
   DALI_LOG_STREAM(gLogFilter, Debug::Concise, "GetConfigurations()\n On entry, mThemeBuilder: " << (bool(mThemeBuilder) ? "Created" : "Empty") << "  mThemeFile: " << mThemeFile);
 
-  Property::Map result;
-  if(mThemeBuilder)
-  {
-    result = mThemeBuilder.GetConfigurations();
-  }
-  else
+  if(!mThemeBuilder)
   {
     DALI_LOG_STREAM(gLogFilter, Debug::Concise, "GetConfigurations()  Loading default theme");
 
-    bool themeLoaded = false;
-
     mThemeBuilder = CreateBuilder(mThemeBuilderConstants);
 
     // Load default theme because this is first try to load stylesheet.
-    themeLoaded = LoadJSON(mThemeBuilder, mDefaultThemeFilePath);
-    mThemeFile  = mDefaultThemeFilePath;
-
-    if(themeLoaded)
-    {
-      result = mThemeBuilder.GetConfigurations();
-    }
+#if defined(DEBUG_ENABLED)
+    bool themeLoaded = LoadJSON(mThemeBuilder, mDefaultThemeFilePath);
     DALI_LOG_STREAM(gLogFilter, Debug::Concise, "  themeLoaded" << (themeLoaded ? "success" : "failure"));
+#else
+    LoadJSON(mThemeBuilder, mDefaultThemeFilePath);
+#endif
+
+    mThemeFile = mDefaultThemeFilePath;
   }
 
+#if defined(DEBUG_ENABLED)
+  Property::Map result = mThemeBuilder.GetConfigurations();
   DALI_LOG_STREAM(gLogFilter, Debug::Concise, "GetConfigurations()\n On exit, result Count: " << (result.Count() != 0));
   DALI_LOG_STREAM(gLogFilter, Debug::Verbose, "          result: " << result);
+#endif
 
-  return result;
+  return mThemeBuilder.GetConfigurations();
 }
 
 void StyleManager::SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
 {
-  int brokenType = static_cast<int>(brokenImageType);
-  mBrokenImageUrls[brokenType] = brokenImageUrl;
+  int brokenType                     = static_cast<int>(brokenImageType);
+  mBrokenImageUrls[brokenType]       = brokenImageUrl;
   Toolkit::StyleManager styleManager = StyleManager::Get();
   mBrokenImageChangedSignal.Emit(styleManager);
 }
index 56e61f0..3aacf79 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_STYLE_MANAGER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -28,9 +28,9 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/builder/builder.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
 #include <dali-toolkit/internal/builder/style.h>
 #include <dali-toolkit/public-api/styling/style-manager.h>
-#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
 
 namespace Dali
 {
@@ -93,7 +93,7 @@ public: // Public API
   /**
    * @copydoc Toolkit::StyleManager::GetConfigurations
    */
-  const Property::Map GetConfigurations();
+  const Property::Map& GetConfigurations();
 
   /**
    * @copydoc Toolkit::DevelStyleManager::SetBrokenImageUrl
@@ -255,7 +255,7 @@ private:
 
   Toolkit::Internal::FeedbackStyle* mFeedbackStyle; ///< Feedback style
 
-  std::vector<std::string> mBrokenImageUrls;    ///< Broken Image Urls received from user
+  std::vector<std::string> mBrokenImageUrls; ///< Broken Image Urls received from user
 
   // Signals
   Toolkit::StyleManager::StyleChangedSignalType            mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
diff --git a/dali-toolkit/internal/text/abstract-style-character-run.cpp b/dali-toolkit/internal/text/abstract-style-character-run.cpp
new file mode 100644 (file)
index 0000000..60b7a8a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2022 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/abstract-style-character-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+CharacterIndex AbstractStyleCharacterRun::GetStartCharacterIndex() const
+{
+  return characterRun.characterIndex;
+}
+
+Length AbstractStyleCharacterRun::GetNumberOfCharacters() const
+{
+  return characterRun.numberOfCharacters;
+}
+
+CharacterIndex AbstractStyleCharacterRun::GetEndCharacterIndex() const
+{
+  return characterRun.GetEndCharacterIndex();
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/abstract-style-character-run.h b/dali-toolkit/internal/text/abstract-style-character-run.h
new file mode 100644 (file)
index 0000000..7822679
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef DALI_TOOLKIT_TEXT_ABSTRACT_STYLE_CHARACTER_RUN_H
+#define DALI_TOOLKIT_TEXT_ABSTRACT_STYLE_CHARACTER_RUN_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/type-traits.h>
+#include <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Run of characters with the same style.
+ */
+struct AbstractStyleCharacterRun
+{
+  CharacterRun characterRun; ///< The initial character index and the number of characters of the run.
+
+  // Constructors
+
+protected:
+  /**
+   * @brief Constructor.
+   * Default constructor to set the default values
+   */
+  AbstractStyleCharacterRun()
+  : characterRun{}
+  {
+  }
+
+  /**
+   * @brief Constructor.
+   * Default constructor to set the default values
+   *
+   * @param[in] characterRun the character run
+   */
+  AbstractStyleCharacterRun(const CharacterRun& characterRun)
+  : characterRun{characterRun}
+  {
+  }
+
+public:
+  AbstractStyleCharacterRun(const AbstractStyleCharacterRun&) = default;
+
+  AbstractStyleCharacterRun(AbstractStyleCharacterRun&&) noexcept = default;
+
+  // Operators
+
+  AbstractStyleCharacterRun& operator=(const AbstractStyleCharacterRun&) = default;
+
+  AbstractStyleCharacterRun& operator=(AbstractStyleCharacterRun&&) noexcept = default;
+
+  /**
+   * @brief Destructor.
+   */
+  virtual ~AbstractStyleCharacterRun() = default;
+
+  //Methods
+
+  /**
+  * @brief Retrive the first index in run.
+  * @return the end character index in run.
+  */
+  CharacterIndex GetStartCharacterIndex() const;
+
+  /**
+  * @brief Retrive the number of characters in the run.
+  * @return the the number of characters in run.
+  */
+  Length GetNumberOfCharacters() const;
+
+  /**
+  * @brief Calculate the end index in run.
+  * @return the end character index in run.
+  */
+  CharacterIndex GetEndCharacterIndex() const;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+// Allow AbstractStyleCharacterRun to be treated as a POD type
+template<>
+struct TypeTraits<Dali::Toolkit::Text::AbstractStyleCharacterRun> : public Dali::BasicTypes<Dali::Toolkit::Text::AbstractStyleCharacterRun>
+{
+  enum
+  {
+    IS_TRIVIAL_TYPE = true
+  };
+};
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_ABSTRACT_STYLE_CHARACTER_RUN_H
index 4b3150e..3547095 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali/public-api/math/vector2.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/abstract-style-character-run.h>
 #include <dali-toolkit/public-api/text/text-enumerations.h>
 
 namespace Dali
@@ -40,13 +40,13 @@ namespace Text
  * Bounded-paragraph could contain multi paragraphs that have been breaked by Paragraph Separators or appropriate Newline Functions.
  * This will be used to handle information for the attributes of markup tag. Like TextAlign, TextDirection, TextIndent, LineHeight, etc.
  */
-struct BoundedParagraphRun
+struct BoundedParagraphRun : public AbstractStyleCharacterRun
 {
   /**
    * Default constructor to set the default values of bitfields
    */
   BoundedParagraphRun()
-  : characterRun{},
+  : AbstractStyleCharacterRun(),
     horizontalAlignment(Text::HorizontalAlignment::BEGIN),
     relativeLineSize(1),
     horizontalAlignmentDefined{false},
@@ -54,7 +54,6 @@ struct BoundedParagraphRun
   {
   }
 
-  CharacterRun                    characterRun;                   ///< The initial character index within the whole text and the number of characters of the run.
   Text::HorizontalAlignment::Type horizontalAlignment;            ///< The paragraph horizontal alignment. Values "BEGIN" "CENTER" "END".
   float                           relativeLineSize;               ///< The relative line height to be used for this paragaraph.
   bool                            horizontalAlignmentDefined : 1; ///< Whether the horizontal alignment is defined.
@@ -65,6 +64,16 @@ struct BoundedParagraphRun
 
 } // namespace Toolkit
 
+// Allow BoundedParagraphRun to be treated as a POD type
+template<>
+struct TypeTraits<Dali::Toolkit::Text::BoundedParagraphRun> : public Dali::BasicTypes<Dali::Toolkit::Text::BoundedParagraphRun>
+{
+  enum
+  {
+    IS_TRIVIAL_TYPE = true
+  };
+};
+
 } // namespace Dali
 
 #endif // DALI_TOOLKIT_TEXT_BOUNDED_PARAGRAPH_RUN_H
index 5c4238e..f256c6a 100644 (file)
  *
  */
 
-// EXTERNAL INCLUDES
-#include <dali/public-api/math/vector4.h>
-
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/abstract-style-character-run.h>
 
 namespace Dali
 {
@@ -33,19 +30,19 @@ namespace Text
 /**
  * @brief Run of character-spacing characters with same properties.
  */
-struct CharacterSpacingCharacterRun
+struct CharacterSpacingCharacterRun : public AbstractStyleCharacterRun
 {
   /**
-   * Default constructor to set the default values of bitfields
+   * @brief Constructor.
+   * Default constructor to set the default values
    */
   CharacterSpacingCharacterRun()
-  : characterRun{},
+  : AbstractStyleCharacterRun(),
     value{0.f} //The default value is 0.f which does nothing.
   {
   }
 
-  CharacterRun characterRun; ///< The initial character index and the number of characters of the run.
-  float        value;        /// The spaces between characters in Pixels. A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed).
+  float value; /// The spaces between characters in Pixels. A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed).
 
   //TODO: Add unit property to choose between Pixel or Scale (%)
 };
@@ -54,6 +51,16 @@ struct CharacterSpacingCharacterRun
 
 } // namespace Toolkit
 
+// Allow ColorRun to be treated as a POD type
+template<>
+struct TypeTraits<Dali::Toolkit::Text::CharacterSpacingCharacterRun> : public Dali::BasicTypes<Dali::Toolkit::Text::CharacterSpacingCharacterRun>
+{
+  enum
+  {
+    IS_TRIVIAL_TYPE = true
+  };
+};
+
 } // namespace Dali
 
 #endif // DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H
index edae1e2..75bd27b 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_COLOR_RUN_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
  *
  */
 
-// EXTERNAL INCLUDES
-#include <dali/public-api/math/vector4.h>
-
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-run.h>
-#include <dali-toolkit/internal/text/glyph-run.h>
+#include <dali-toolkit/internal/text/abstract-style-character-run.h>
 
 namespace Dali
 {
@@ -34,16 +30,33 @@ namespace Text
 /**
  * @brief Run of characters with the same color.
  */
-struct ColorRun
+struct ColorRun : public AbstractStyleCharacterRun
 {
-  CharacterRun characterRun; ///< The initial character index and the number of characters of the run.
-  Vector4      color;        ///< The color of the characters.
+  /**
+   * @brief Constructor.
+   * Default constructor to set the default values
+   */
+  ColorRun()
+  : AbstractStyleCharacterRun()
+  {
+  }
+  Vector4 color; ///< The color of the characters.
 };
 
 } // namespace Text
 
 } // namespace Toolkit
 
+// Allow ColorRun to be treated as a POD type
+template<>
+struct TypeTraits<Dali::Toolkit::Text::ColorRun> : public Dali::BasicTypes<Dali::Toolkit::Text::ColorRun>
+{
+  enum
+  {
+    IS_TRIVIAL_TYPE = true
+  };
+};
+
 } // namespace Dali
 
 #endif // DALI_TOOLKIT_TEXT_COLOR_RUN_H
index 04a5e91..77b8db8 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_FONT_DESCRIPTION_RUN_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -22,7 +22,7 @@
 #include <dali/devel-api/text-abstraction/font-list.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/abstract-style-character-run.h>
 #include <dali-toolkit/internal/text/text-definitions.h>
 
 namespace Dali
@@ -34,13 +34,13 @@ namespace Text
 /**
  * @brief Run of characters with the same font.
  */
-struct FontDescriptionRun
+struct FontDescriptionRun : public AbstractStyleCharacterRun
 {
   /**
    * Default constructor to set the default values of bitfields
    */
   FontDescriptionRun()
-  : characterRun{},
+  : AbstractStyleCharacterRun(),
     familyName{nullptr},
     familyLength{0u},
     weight{FontWeight::NONE},
@@ -67,7 +67,7 @@ struct FontDescriptionRun
                      bool                widthDefined,
                      bool                slantDefined,
                      bool                sizeDefined)
-  : characterRun{characterRun},
+  : AbstractStyleCharacterRun(characterRun),
     familyName{familyName},
     familyLength{familyLength},
     weight{weight},
@@ -82,7 +82,6 @@ struct FontDescriptionRun
   {
   }
 
-  CharacterRun    characterRun; ///< The initial character index and the number of characters of the run.
   char*           familyName;   ///< The font's family name.
   Length          familyLength; ///< The length of the font's family name.
   FontWeight      weight;       ///< The font's weight.
@@ -101,6 +100,16 @@ struct FontDescriptionRun
 
 } // namespace Toolkit
 
+// Allow FontDescriptionRun to be treated as a POD type
+template<>
+struct TypeTraits<Dali::Toolkit::Text::FontDescriptionRun> : public Dali::BasicTypes<Dali::Toolkit::Text::FontDescriptionRun>
+{
+  enum
+  {
+    IS_TRIVIAL_TYPE = true
+  };
+};
+
 } // namespace Dali
 
 #endif // DALI_TOOLKIT_TEXT_FONT_DESCRIPTION_RUN_H
index 41e41a9..39af47c 100644 (file)
@@ -1260,16 +1260,22 @@ struct Engine::Impl
                     Length&                           numberOfLines,
                     float                             penY,
                     bool&                             isAutoScrollEnabled,
+                    bool                              isAutoScrollMaxTextureExceeded,
                     DevelText::EllipsisPosition::Type ellipsisPosition,
                     bool                              enforceEllipsisInSingleLine)
   {
-    const bool ellipsis    = enforceEllipsisInSingleLine || (isAutoScrollEnabled ? (penY - layout.descender > layoutParameters.boundingBox.height) : ((penY - layout.descender > layoutParameters.boundingBox.height) || ((mLayout == SINGLE_LINE_BOX) && (layout.length > layoutParameters.boundingBox.width))));
+    const bool ellipsis    = enforceEllipsisInSingleLine || (isAutoScrollEnabled ? isAutoScrollMaxTextureExceeded : ((penY - layout.descender > layoutParameters.boundingBox.height) || ((mLayout == SINGLE_LINE_BOX) && (layout.length > layoutParameters.boundingBox.width))));
     const bool isMultiline = !enforceEllipsisInSingleLine && (mLayout == MULTI_LINE_BOX);
     if(ellipsis && (ellipsisPosition == DevelText::EllipsisPosition::END || !isMultiline))
     {
-      isAutoScrollEnabled = false;
-      // Do not layout more lines if ellipsis is enabled.
+      if(penY - layout.descender > layoutParameters.boundingBox.height)
+      {
+        // Even if auto scroll is enabled and text is bigger than max texture size,
+        // if the the height is small, auto scroll should not work.
+        isAutoScrollEnabled = false;
+      }
 
+      // Do not layout more lines if ellipsis is enabled.
       // The last line needs to be completely filled with characters.
       // Part of a word may be used.
 
@@ -1601,6 +1607,7 @@ struct Engine::Impl
                   Size&                             layoutSize,
                   bool                              elideTextEnabled,
                   bool&                             isAutoScrollEnabled,
+                  bool                              isAutoScrollMaxTextureExceeded,
                   DevelText::EllipsisPosition::Type ellipsisPosition)
   {
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->LayoutText\n");
@@ -1801,7 +1808,7 @@ struct Engine::Impl
       CharacterIndex lastCharacterInParagraph = currentParagraphRun.characterRun.characterIndex + currentParagraphRun.characterRun.numberOfCharacters - 1;
 
       //check if this is the last line in paragraph, if false we should use the default relative line size (the one set using the property)
-      if(lastCharacterInParagraph >= layout.characterIndex && lastCharacterInParagraph < layout.characterIndex+layout.numberOfCharacters)
+      if(lastCharacterInParagraph >= layout.characterIndex && lastCharacterInParagraph < layout.characterIndex + layout.numberOfCharacters)
       {
         layout.relativeLineSize = mRelativeLineSize;
       }
@@ -1840,6 +1847,7 @@ struct Engine::Impl
                                 numberOfLines,
                                 penY,
                                 isAutoScrollEnabled,
+                                isAutoScrollMaxTextureExceeded,
                                 ellipsisPosition,
                                 false);
       }
@@ -1858,6 +1866,7 @@ struct Engine::Impl
                                   numberOfLines,
                                   penY,
                                   isAutoScrollEnabled,
+                                  isAutoScrollMaxTextureExceeded,
                                   ellipsisPosition,
                                   true);
         }
@@ -2252,12 +2261,14 @@ bool Engine::LayoutText(Parameters&                       layoutParameters,
                         Size&                             layoutSize,
                         bool                              elideTextEnabled,
                         bool&                             isAutoScrollEnabled,
+                        bool                              isAutoScrollMaxTextureExceeded,
                         DevelText::EllipsisPosition::Type ellipsisPosition)
 {
   return mImpl->LayoutText(layoutParameters,
                            layoutSize,
                            elideTextEnabled,
                            isAutoScrollEnabled,
+                           isAutoScrollMaxTextureExceeded,
                            ellipsisPosition);
 }
 
index 6b78e87..9fa22c6 100644 (file)
@@ -107,6 +107,7 @@ public:
    * @param[out] layoutSize The size of the text after it has been laid-out.
    * @param[in] elideTextEnabled Whether the text elide is enabled.
    * @param[in,out] isAutoScrollEnabled If the isAutoScrollEnabled is true and the height of the text exceeds the boundaries of the control the text is elided and the isAutoScrollEnabled is set to false to disable the autoscroll
+   * @param[in] isAutoScrollMaxTextureExceeded If isAutoScrollMaxTextureExceeded is true, enable ellipsis during auro scroll.
    * @param[in] ellipsisPosition The location of the text ellipsis
    *
    * @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character.
@@ -115,6 +116,7 @@ public:
                   Size&                             layoutSize,
                   bool                              elideTextEnabled,
                   bool&                             isAutoScrollEnabled,
+                  bool                              isAutoScrollMaxTextureExceeded,
                   DevelText::EllipsisPosition::Type ellipsisPosition);
 
   /**
diff --git a/dali-toolkit/internal/text/line-helper-functions.cpp b/dali-toolkit/internal/text/line-helper-functions.cpp
new file mode 100644 (file)
index 0000000..d2ffcd1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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/line-helper-functions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+float GetPreOffsetVerticalLineAlignment(const LineRun& line, const DevelText::VerticalLineAlignment::Type& verLineAlign)
+{
+  // Calculate vertical line alignment
+  float offset = 0.0f;
+
+  switch(verLineAlign)
+  {
+    case DevelText::VerticalLineAlignment::TOP:
+    {
+      break;
+    }
+    case DevelText::VerticalLineAlignment::MIDDLE:
+    {
+      offset = line.lineSpacing * 0.5f;
+      break;
+    }
+    case DevelText::VerticalLineAlignment::BOTTOM:
+    {
+      offset = line.lineSpacing;
+      break;
+    }
+  }
+
+  // Apply TOP case when the lineSpacing is less than zero.
+  offset = line.lineSpacing < 0.0f ? 0.0f : offset;
+
+  return offset;
+}
+
+float GetPostOffsetVerticalLineAlignment(const LineRun& line, const DevelText::VerticalLineAlignment::Type& verLineAlign)
+{
+  // Calculate vertical line alignment
+  float offset = 0.0f;
+
+  switch(verLineAlign)
+  {
+    case DevelText::VerticalLineAlignment::TOP:
+    {
+      offset = line.lineSpacing;
+      break;
+    }
+    case DevelText::VerticalLineAlignment::MIDDLE:
+    {
+      offset = line.lineSpacing * 0.5f;
+      break;
+    }
+    case DevelText::VerticalLineAlignment::BOTTOM:
+    {
+      break;
+    }
+  }
+
+  // Apply TOP case when the lineSpacing is less than zero.
+  offset = line.lineSpacing < 0.0f ? line.lineSpacing : offset;
+
+  return offset;
+}
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/line-helper-functions.h b/dali-toolkit/internal/text/line-helper-functions.h
new file mode 100644 (file)
index 0000000..ad94086
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef DALI_TOOLKIT_TEXT_LINE_HELPER_FUNCTIONS_H
+#define DALI_TOOLKIT_TEXT_LINE_HELPER_FUNCTIONS_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/devel-api/text/text-enumerations-devel.h>
+#include <dali-toolkit/internal/text/line-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+  * @brief Retrieves the vertical offset to shift text inside line to up by negative value and to down by positive value.
+  * The shifting depends on the vertical line alignment @p verLineAlign and lineSpacing when the lineSpacing is poistive.
+  * When the lineSpacing is negative then ignore @p verLineAlign
+  * @param[in] line the line.
+  * @param[in] line the line.
+  *
+  * @return The vertical offset before text.
+  */
+float GetPreOffsetVerticalLineAlignment(const LineRun& line, const Dali::Toolkit::DevelText::VerticalLineAlignment::Type& verLineAlign);
+
+/**
+  * @brief Retrieves the vertical offset to shift the next line to up by negative value and to down by positive value.
+  * The shifting depends on the vertical line alignment @p verLineAlign and lineSpacing when the lineSpacing is poistive.
+  * When the lineSpacing is negative then ignore @p verLineAlign
+  * @param[in] line the line.
+  * @param[in] line the line.
+  *
+  * @return The vertical offset after text.
+  */
+float GetPostOffsetVerticalLineAlignment(const LineRun& line, const Dali::Toolkit::DevelText::VerticalLineAlignment::Type& verLineAlign);
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_LINE_HELPER_FUNCTIONS_H
index 60eb03b..1047411 100644 (file)
@@ -941,7 +941,7 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData,
   markupProcessData.characterSpacingCharacterRuns.Resize(characterSpacingCharacterRunIndex);
 
 #ifdef DEBUG_ENABLED
-  for(unsigned int i = 0; i < colorRunIndex; ++i)
+  for(uint32_t i = 0; gLogFilter->IsEnabledFor(Debug::Verbose) && i < colorRunIndex; ++i)
   {
     ColorRun& run = markupProcessData.colorRuns[i];
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "run[%d] index: %d, length: %d, color %f,%f,%f,%f\n", i, run.characterRun.characterIndex, run.characterRun.numberOfCharacters, run.color.r, run.color.g, run.color.b, run.color.a);
index dbd110b..52f2b18 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -500,6 +500,7 @@ void MultilanguageSupport::ValidateFonts(const Vector<Character>&
                               scriptRunEndIt);
 
 #ifdef DEBUG_ENABLED
+    if(gLogFilter->IsEnabledFor(Debug::Verbose))
     {
       Dali::TextAbstraction::FontDescription description;
       fontClient.GetDescription(fontId, description);
@@ -716,6 +717,7 @@ void MultilanguageSupport::ValidateFonts(const Vector<Character>&
     }
 
 #ifdef DEBUG_ENABLED
+    if(gLogFilter->IsEnabledFor(Debug::Verbose))
     {
       Dali::TextAbstraction::FontDescription description;
       fontClient.GetDescription(fontId, description);
index e30564e..847954f 100644 (file)
@@ -221,7 +221,7 @@ struct AtlasRenderer::Impl
                                 glyphBufferData.width,
                                 glyphBufferData.height,
                                 glyphBufferData.format,
-                                PixelData::DELETE_ARRAY);
+                                PixelData::FREE);
 
         if(bitmap)
         {
@@ -782,7 +782,7 @@ struct AtlasRenderer::Impl
 
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "%s\n", metrics.mVerboseGlyphCounts.c_str());
 
-    for(uint32_t i = 0; i < metrics.mAtlasMetrics.mAtlasCount; ++i)
+    for(uint32_t i = 0; gLogFilter->IsEnabledFor(Debug::Verbose) && i < metrics.mAtlasMetrics.mAtlasCount; ++i)
     {
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "   Atlas [%i] %sPixels: %s Size: %ix%i, BlockSize: %ix%i, BlocksUsed: %i/%i\n", i + 1, i > 8 ? "" : " ", metrics.mAtlasMetrics.mAtlasMetrics[i].mPixelFormat == Pixel::L8 ? "L8  " : "BGRA", metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mWidth, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mHeight, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mBlockWidth, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mBlockHeight, metrics.mAtlasMetrics.mAtlasMetrics[i].mBlocksUsed, metrics.mAtlasMetrics.mAtlasMetrics[i].mTotalBlocks);
     }
index 826e894..da397ac 100644 (file)
@@ -26,6 +26,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/line-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h>
@@ -95,9 +96,9 @@ void TypesetGlyph(GlyphData&           data,
   const int32_t xOffset = data.horizontalOffset + position->x;
 
   // Whether the given glyph is a color one.
-  const bool     isColorGlyph   = data.glyphBitmap.isColorEmoji || data.glyphBitmap.isColorBitmap;
-  const uint32_t glyphPixelSize = Pixel::GetBytesPerPixel(data.glyphBitmap.format);
-  const uint32_t alphaIndex     = glyphPixelSize - 1u;
+  const bool     isColorGlyph    = data.glyphBitmap.isColorEmoji || data.glyphBitmap.isColorBitmap;
+  const uint32_t glyphPixelSize  = Pixel::GetBytesPerPixel(data.glyphBitmap.format);
+  const uint32_t glyphAlphaIndex = glyphPixelSize - 1u;
 
   // Determinate iterator range.
   const int32_t lineIndexRangeMin = std::max(0, -yOffset);
@@ -113,9 +114,9 @@ void TypesetGlyph(GlyphData&           data,
 
   if(Pixel::RGBA8888 == pixelFormat)
   {
-    const bool swapChannelsBR = Pixel::BGRA8888 == data.glyphBitmap.format;
-
     uint32_t* bitmapBuffer = reinterpret_cast<uint32_t*>(data.bitmapBuffer.GetBuffer());
+    // Skip basic line.
+    bitmapBuffer += (lineIndexRangeMin + yOffset) * static_cast<int32_t>(data.width);
 
     // Fast-cut if style is MASK or OUTLINE. Outline not shown for color glyph.
     // Just overwrite transparent color and return.
@@ -123,17 +124,17 @@ void TypesetGlyph(GlyphData&           data,
     {
       for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex)
       {
-        const int32_t yOffsetIndex   = yOffset + lineIndex;
-        const int32_t verticalOffset = yOffsetIndex * data.width;
-
         // We can use memset here.
-        memset(bitmapBuffer + verticalOffset + xOffset + indexRangeMin, 0, (indexRangeMax - indexRangeMin) * sizeof(uint32_t));
+        memset(bitmapBuffer + xOffset + indexRangeMin, 0, (indexRangeMax - indexRangeMin) * sizeof(uint32_t));
+        bitmapBuffer += data.width;
       }
       return;
     }
 
+    const bool swapChannelsBR = Pixel::BGRA8888 == data.glyphBitmap.format;
+
     // Pointer to the color glyph if there is one.
-    const uint32_t* const colorGlyphBuffer = isColorGlyph ? reinterpret_cast<uint32_t*>(data.glyphBitmap.buffer) : NULL;
+    const uint8_t* glyphBuffer = data.glyphBitmap.buffer;
 
     // Precalculate input color's packed result.
     uint32_t packedInputColor       = 0u;
@@ -144,21 +145,20 @@ void TypesetGlyph(GlyphData&           data,
     *(packedInputColorBuffer + 1u) = static_cast<uint8_t>(color->g * 255);
     *(packedInputColorBuffer)      = static_cast<uint8_t>(color->r * 255);
 
+    // Skip basic line of glyph.
+    glyphBuffer += (lineIndexRangeMin) * static_cast<int32_t>(data.glyphBitmap.width) * glyphPixelSize;
+
     // Traverse the pixels of the glyph line per line.
-    for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex)
+    if(isColorGlyph)
     {
-      const int32_t yOffsetIndex = yOffset + lineIndex;
-
-      const int32_t verticalOffset    = yOffsetIndex * data.width;
-      const int32_t glyphBufferOffset = lineIndex * static_cast<int32_t>(data.glyphBitmap.width);
-      for(int32_t index = indexRangeMin; index < indexRangeMax; ++index)
+      for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex)
       {
-        const int32_t xOffsetIndex = xOffset + index;
-
-        if(isColorGlyph)
+        for(int32_t index = indexRangeMin; index < indexRangeMax; ++index)
         {
+          const int32_t xOffsetIndex = xOffset + index;
+
           // Retrieves the color from the color glyph.
-          uint32_t packedColorGlyph       = *(colorGlyphBuffer + glyphBufferOffset + index);
+          uint32_t packedColorGlyph       = *(reinterpret_cast<const uint32_t*>(glyphBuffer + (index << 2)));
           uint8_t* packedColorGlyphBuffer = reinterpret_cast<uint8_t*>(&packedColorGlyph);
 
           // Update the alpha channel.
@@ -192,23 +192,28 @@ void TypesetGlyph(GlyphData&           data,
           }
 
           // Set the color into the final pixel buffer.
-          *(bitmapBuffer + verticalOffset + xOffsetIndex) = packedColorGlyph;
+          *(bitmapBuffer + xOffsetIndex) = packedColorGlyph;
         }
-        else
+        bitmapBuffer += data.width;
+        glyphBuffer += data.glyphBitmap.width * glyphPixelSize;
+      }
+    }
+    else
+    {
+      for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex)
+      {
+        for(int32_t index = indexRangeMin; index < indexRangeMax; ++index)
         {
-          // Pack the given color into a 32bit buffer. The alpha channel will be updated later for each pixel.
-          // The format is RGBA8888.
-          uint32_t packedColor       = 0u;
-          uint8_t* packedColorBuffer = reinterpret_cast<uint8_t*>(&packedColor);
-
           // Update the alpha channel.
-          const uint8_t alpha = *(data.glyphBitmap.buffer + glyphPixelSize * (glyphBufferOffset + index) + alphaIndex);
+          const uint8_t alpha = *(glyphBuffer + index * glyphPixelSize + glyphAlphaIndex);
 
           // Copy non-transparent pixels only
           if(alpha > 0u)
           {
+            const int32_t xOffsetIndex = xOffset + index;
+
             // Check alpha of overlapped pixels
-            uint32_t& currentColor             = *(bitmapBuffer + verticalOffset + xOffsetIndex);
+            uint32_t& currentColor             = *(bitmapBuffer + xOffsetIndex);
             uint8_t*  packedCurrentColorBuffer = reinterpret_cast<uint8_t*>(&currentColor);
 
             // For any pixel overlapped with the pixel in previous glyphs, make sure we don't
@@ -224,6 +229,11 @@ void TypesetGlyph(GlyphData&           data,
             }
             else
             {
+              // Pack the given color into a 32bit buffer. The alpha channel will be updated later for each pixel.
+              // The format is RGBA8888.
+              uint32_t packedColor       = 0u;
+              uint8_t* packedColorBuffer = reinterpret_cast<uint8_t*>(&packedColor);
+
               // Color is pre-muliplied with its alpha.
               *(packedColorBuffer + 3u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 3u), currentAlpha);
               *(packedColorBuffer + 2u) = MultiplyAndNormalizeColor(*(packedInputColorBuffer + 2u), currentAlpha);
@@ -235,35 +245,38 @@ void TypesetGlyph(GlyphData&           data,
             }
           }
         }
+        bitmapBuffer += data.width;
+        glyphBuffer += data.glyphBitmap.width * glyphPixelSize;
       }
     }
   }
-  else
+  else // Pixel::L8
   {
     // Below codes required only if not color glyph.
     if(!isColorGlyph)
     {
-      uint8_t* bitmapBuffer = reinterpret_cast<uint8_t*>(data.bitmapBuffer.GetBuffer());
+      uint8_t*       bitmapBuffer = data.bitmapBuffer.GetBuffer();
+      const uint8_t* glyphBuffer  = data.glyphBitmap.buffer;
+
+      // Skip basic line.
+      bitmapBuffer += (lineIndexRangeMin + yOffset) * static_cast<int32_t>(data.width);
+      glyphBuffer += (lineIndexRangeMin) * static_cast<int32_t>(data.glyphBitmap.width) * glyphPixelSize;
 
       // Traverse the pixels of the glyph line per line.
       for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex)
       {
-        const int32_t yOffsetIndex = yOffset + lineIndex;
-
-        const int32_t verticalOffset    = yOffsetIndex * data.width;
-        const int32_t glyphBufferOffset = lineIndex * static_cast<int32_t>(data.glyphBitmap.width);
         for(int32_t index = indexRangeMin; index < indexRangeMax; ++index)
         {
           const int32_t xOffsetIndex = xOffset + index;
 
           // Update the alpha channel.
-          const uint8_t alpha = *(data.glyphBitmap.buffer + glyphPixelSize * (glyphBufferOffset + index) + alphaIndex);
+          const uint8_t alpha = *(glyphBuffer + index * glyphPixelSize + glyphAlphaIndex);
 
           // Copy non-transparent pixels only
           if(alpha > 0u)
           {
             // Check alpha of overlapped pixels
-            uint8_t& currentAlpha = *(bitmapBuffer + verticalOffset + xOffsetIndex);
+            uint8_t& currentAlpha = *(bitmapBuffer + xOffsetIndex);
 
             // For any pixel overlapped with the pixel in previous glyphs, make sure we don't
             // overwrite a previous bigger alpha with a smaller alpha (in order to avoid
@@ -272,6 +285,9 @@ void TypesetGlyph(GlyphData&           data,
             currentAlpha = std::max(currentAlpha, alpha);
           }
         }
+
+        bitmapBuffer += data.width;
+        glyphBuffer += data.glyphBitmap.width * glyphPixelSize;
       }
     }
   }
@@ -486,6 +502,8 @@ Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuff
   const Vector4* const    backgroundColorsBuffer       = model->GetBackgroundColors();
   const ColorIndex* const backgroundColorIndicesBuffer = model->GetBackgroundColorIndices();
 
+  const DevelText::VerticalLineAlignment::Type verLineAlign = model->GetVerticalLineAlignment();
+
   // Create and initialize the pixel buffer.
   GlyphData glyphData;
   glyphData.verticalOffset   = verticalOffset;
@@ -507,13 +525,7 @@ Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuff
     glyphData.horizontalOffset += horizontalOffset;
 
     // Increases the vertical offset with the line's ascender.
-    glyphData.verticalOffset += static_cast<int32_t>(line.ascender);
-
-    // Include line spacing after first line
-    if(lineIndex > 0u)
-    {
-      glyphData.verticalOffset += static_cast<int32_t>(line.lineSpacing);
-    }
+    glyphData.verticalOffset += static_cast<int32_t>(line.ascender + GetPreOffsetVerticalLineAlignment(line, verLineAlign));
 
     float left     = bufferWidth;
     float right    = 0.0f;
@@ -579,7 +591,7 @@ Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuff
     }
 
     // Increases the vertical offset with the line's descender.
-    glyphData.verticalOffset += static_cast<int32_t>(-line.descender);
+    glyphData.verticalOffset += static_cast<int32_t>(-line.descender + GetPostOffsetVerticalLineAlignment(line, verLineAlign));
   }
 
   return glyphData.bitmapBuffer;
@@ -856,29 +868,6 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
     }
   }
 
-  // Calculate vertical line alignment
-  switch(mModel->GetVerticalLineAlignment())
-  {
-    case DevelText::VerticalLineAlignment::TOP:
-    {
-      break;
-    }
-    case DevelText::VerticalLineAlignment::MIDDLE:
-    {
-      const auto& line = *mModel->GetLines();
-      penY -= line.descender;
-      penY += static_cast<int32_t>(line.lineSpacing * 0.5f + line.descender);
-      break;
-    }
-    case DevelText::VerticalLineAlignment::BOTTOM:
-    {
-      const auto& line       = *mModel->GetLines();
-      const auto  lineHeight = line.ascender + (-line.descender) + line.lineSpacing;
-      penY += static_cast<int32_t>(lineHeight - (line.ascender - line.descender));
-      break;
-    }
-  }
-
   // Generate the image buffers of the text for each different style first,
   // then combine all of them together as one final image buffer. We try to
   // do all of these in CPU only, so that once the final texture is generated,
@@ -1046,6 +1035,8 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const uint32_t& bufferWidth, co
   const Vector<CharacterIndex>& glyphToCharacterMap       = mModel->GetGlyphsToCharacters();
   const CharacterIndex*         glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
 
+  const DevelText::VerticalLineAlignment::Type verLineAlign = mModel->GetVerticalLineAlignment();
+
   // Traverses the lines of the text.
   for(LineIndex lineIndex = 0u; lineIndex < modelNumberOfLines; ++lineIndex)
   {
@@ -1056,7 +1047,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const uint32_t& bufferWidth, co
     glyphData.horizontalOffset += horizontalOffset;
 
     // Increases the vertical offset with the line's ascender.
-    glyphData.verticalOffset += static_cast<int32_t>(line.ascender);
+    glyphData.verticalOffset += static_cast<int32_t>(line.ascender + GetPreOffsetVerticalLineAlignment(line, verLineAlign));
 
     // Retrieves the glyph's outline width
     float outlineWidth = static_cast<float>(mModel->GetOutlineWidth());
@@ -1316,8 +1307,8 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const uint32_t& bufferWidth, co
           glyphData.verticalOffset += glyphData.glyphBitmap.outlineOffsetY;
         }
 
-        // delete the glyphBitmap.buffer as it is now copied into glyphData.bitmapBuffer
-        delete[] glyphData.glyphBitmap.buffer;
+        // free the glyphBitmap.buffer as it is now copied into glyphData.bitmapBuffer
+        free(glyphData.glyphBitmap.buffer);
         glyphData.glyphBitmap.buffer = NULL;
       }
 
@@ -1357,7 +1348,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const uint32_t& bufferWidth, co
     }
 
     // Increases the vertical offset with the line's descender & line spacing.
-    glyphData.verticalOffset += static_cast<int32_t>(-line.descender + line.lineSpacing);
+    glyphData.verticalOffset += static_cast<int32_t>(-line.descender + GetPostOffsetVerticalLineAlignment(line, verLineAlign));
   }
 
   return glyphData.bitmapBuffer;
index f02bb95..9cfba93 100644 (file)
@@ -524,7 +524,71 @@ void ViewModel::ElideGlyphs()
                 // Change the 'x' and 'y' position of the ellipsis glyph.
                 if(position.x > firstPenX)
                 {
-                  position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+                  if(isTailMode)
+                  {
+                    // To handle case of the mixed languages (LTR then RTL) with
+                    // EllipsisPosition::END and the LayoutDirection::RIGHT_TO_LEFT
+                    float nextXPositions = ellipsisLine->width;
+                    if(indexOfEllipsis + 1u < numberOfGlyphs)
+                    {
+                      Vector2& positionOfNextGlyph = *(elidedPositionsBuffer + indexOfEllipsis + 1u);
+                      nextXPositions               = positionOfNextGlyph.x;
+                    }
+
+                    if(position.x > nextXPositions) // RTL language
+                    {
+                      if((indexOfEllipsis > 0u) && ((position.x - nextXPositions) > removedGlypsWidth))
+                      {
+                        // To handle mixed directions
+                        // Re-calculates the first penX which will be used if rtl text is elided.
+                        firstPenX = position.x - glyphToRemove.xBearing;
+                        if(firstPenX < -ellipsisGlyph.xBearing)
+                        {
+                          // Avoids to exceed the bounding box when rtl text is elided.
+                          firstPenX = -ellipsisGlyph.xBearing;
+                        }
+                        //Reset the width of removed glyphs
+                        removedGlypsWidth = std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width)) - ellipsisGlyph.xBearing;
+
+                        --indexOfEllipsis;
+                        continue;
+                      }
+                      else
+                      {
+                        // To handle the case of RTL language with EllipsisPosition::END
+                        position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+                      }
+                    }
+                  }
+                  else
+                  {
+                    // To handle the case of LTR language with EllipsisPosition::START
+                    position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+                  }
+                }
+                else
+                {
+                  if(!isTailMode)
+                  {
+                    // To handle case of the mixed languages (RTL then LTR) with
+                    // EllipsisPosition::START and the LayoutDirection::RIGHT_TO_LEFT
+                    float nextXPositions = ellipsisLine->width;
+                    if(indexOfEllipsis + 1u < numberOfGlyphs)
+                    {
+                      Vector2& positionOfNextGlyph = *(elidedPositionsBuffer + indexOfEllipsis + 1u);
+                      nextXPositions               = positionOfNextGlyph.x;
+                    }
+
+                    if(position.x < nextXPositions) // LTR language
+                    {
+                      position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+
+                      if((position.x + ellipsisGlyphWidth + ellipsisGlyph.xBearing) > nextXPositions)
+                      {
+                        position.x -= (position.x + ellipsisGlyphWidth + ellipsisGlyph.xBearing) - nextXPositions;
+                      }
+                    }
+                  }
                 }
 
                 position.x += ellipsisGlyph.xBearing;
index 66214b7..1d0bc87 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali/public-api/math/vector4.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/abstract-style-character-run.h>
 #include <dali-toolkit/internal/text/strikethrough-style-properties.h>
 
 namespace Dali
@@ -34,25 +34,34 @@ namespace Text
 /**
  * @brief Run of strikethrough characters with same properties.
  */
-struct StrikethroughCharacterRun
+struct StrikethroughCharacterRun : public AbstractStyleCharacterRun
 {
   /**
    * Default constructor to set the default values of bitfields
    */
   StrikethroughCharacterRun()
-  : characterRun{},
+  : AbstractStyleCharacterRun(),
     properties{}
   {
   }
 
-  CharacterRun                 characterRun; ///< The initial character index and the number of characters of the run.
-  StrikethroughStyleProperties properties;   /// The properties of strikethrough style
+  StrikethroughStyleProperties properties; /// The properties of strikethrough style
 };
 
 } // namespace Text
 
 } // namespace Toolkit
 
+// Allow StrikethroughCharacterRun to be treated as a POD type
+template<>
+struct TypeTraits<Dali::Toolkit::Text::StrikethroughCharacterRun> : public Dali::BasicTypes<Dali::Toolkit::Text::StrikethroughCharacterRun>
+{
+  enum
+  {
+    IS_TRIVIAL_TYPE = true
+  };
+};
+
 } // namespace Dali
 
 #endif // DALI_TOOLKIT_TEXT_STRIKETHROUGH_CHARACTER_RUN_H
index 5944039..7eaf5ee 100644 (file)
@@ -37,10 +37,10 @@ namespace Toolkit
 {
 namespace Text
 {
-const float DEFAULT_TEXTFIT_MIN     = 10.f;
-const float DEFAULT_TEXTFIT_MAX     = 100.f;
-const float DEFAULT_TEXTFIT_STEP    = 1.f;
-const float DEFAULT_FONT_SIZE_SCALE = 1.f;
+const float DEFAULT_TEXTFIT_MIN            = 10.f;
+const float DEFAULT_TEXTFIT_MAX            = 100.f;
+const float DEFAULT_TEXTFIT_STEP           = 1.f;
+const float DEFAULT_FONT_SIZE_SCALE        = 1.f;
 const float DEFAULT_DISABLED_COLOR_OPACITY = 0.3f;
 
 //Forward declarations
@@ -346,6 +346,7 @@ struct Controller::Impl
     mMarkupProcessorEnabled(false),
     mClipboardHideEnabled(true),
     mIsAutoScrollEnabled(false),
+    mIsAutoScrollMaxTextureExceeded(false),
     mUpdateTextDirection(true),
     mIsTextDirectionRTL(false),
     mUnderlineSetByString(false),
@@ -385,12 +386,11 @@ struct Controller::Impl
     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
     if(styleManager)
     {
-      bool          temp;
-      Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
-      if(config["clearFocusOnEscape"].Get(temp))
-      {
-        mShouldClearFocusOnEscape = temp;
-      }
+      const Property::Map& config                  = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
+      const auto           clearFocusOnEscapeValue = config.Find("clearFocusOnEscape", Property::Type::BOOLEAN);
+
+      // Default is true. If config don't have "clearFocusOnEscape" property, make it true.
+      mShouldClearFocusOnEscape = (!clearFocusOnEscapeValue || clearFocusOnEscapeValue->Get<bool>());
     }
   }
 
@@ -1001,12 +1001,13 @@ public:
   std::unique_ptr<InputFilter> mInputFilter;                ///< Avoid allocating this when the user does not specify input filter mode.
   Vector2                      mTextFitContentSize;         ///< Size of Text fit content
 
-  bool               mRecalculateNaturalSize : 1; ///< Whether the natural size needs to be recalculated.
-  bool               mMarkupProcessorEnabled : 1; ///< Whether the mark-up procesor is enabled.
-  bool               mClipboardHideEnabled : 1;   ///< Whether the ClipboardHide function work or not
-  bool               mIsAutoScrollEnabled : 1;    ///< Whether auto text scrolling is enabled.
-  bool               mUpdateTextDirection : 1;    ///< Whether the text direction needs to be updated.
-  CharacterDirection mIsTextDirectionRTL : 1;     ///< Whether the text direction is right to left or not
+  bool               mRecalculateNaturalSize : 1;         ///< Whether the natural size needs to be recalculated.
+  bool               mMarkupProcessorEnabled : 1;         ///< Whether the mark-up procesor is enabled.
+  bool               mClipboardHideEnabled : 1;           ///< Whether the ClipboardHide function work or not
+  bool               mIsAutoScrollEnabled : 1;            ///< Whether auto text scrolling is enabled.
+  bool               mIsAutoScrollMaxTextureExceeded : 1; ///< Whether auto text scrolling is exceed max texture size.
+  bool               mUpdateTextDirection : 1;            ///< Whether the text direction needs to be updated.
+  CharacterDirection mIsTextDirectionRTL : 1;             ///< Whether the text direction is right to left or not
 
   bool                  mUnderlineSetByString : 1;     ///< Set when underline is set by string (legacy) instead of map
   bool                  mShadowSetByString : 1;        ///< Set when shadow is set by string (legacy) instead of map
index 42199ad..527bb99 100644 (file)
@@ -67,7 +67,7 @@ Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Control
                                                                         SHAPE_TEXT |
                                                                         GET_GLYPH_METRICS);
 
-  const OperationsMask sizeOperations     = static_cast<OperationsMask>(LAYOUT | ALIGN | REORDER);
+  const OperationsMask sizeOperations = static_cast<OperationsMask>(LAYOUT | ALIGN | REORDER);
 
   // Set the update info to relayout the whole text.
   TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
@@ -93,6 +93,9 @@ Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Control
   {
     impl.UpdateModel(onlyOnceOperations);
 
+    // Layout the text for the new width.
+    operationsPending = static_cast<OperationsMask>(operationsPending | requestedOperationsMask);
+
     DoRelayout(impl,
                requestedControllerSize,
                static_cast<OperationsMask>(onlyOnceOperations | requestedOperationsMask),
@@ -619,12 +622,15 @@ bool Controller::Relayouter::DoRelayout(Controller::Impl& impl, const Size& size
     }
 
     // Update the visual model.
-    bool isAutoScrollEnabled = impl.mIsAutoScrollEnabled;
+    bool isAutoScrollEnabled            = impl.mIsAutoScrollEnabled;
+    bool isAutoScrollMaxTextureExceeded = impl.mIsAutoScrollMaxTextureExceeded;
+
     Size newLayoutSize;
     viewUpdated               = impl.mLayoutEngine.LayoutText(layoutParameters,
                                                 newLayoutSize,
                                                 elideTextEnabled,
                                                 isAutoScrollEnabled,
+                                                isAutoScrollMaxTextureExceeded,
                                                 ellipsisPosition);
     impl.mIsAutoScrollEnabled = isAutoScrollEnabled;
 
@@ -798,13 +804,13 @@ void Controller::Relayouter::DoRelayoutHorizontalAlignment(Controller::Impl&
 
 void Controller::Relayouter::CalculateVerticalOffset(Controller::Impl& impl, const Size& controlSize)
 {
-  ModelPtr&         model                 = impl.mModel;
-  VisualModelPtr&   visualModel           = model->mVisualModel;
-  Size              layoutSize            = model->mVisualModel->GetLayoutSize();
-  Size              oldLayoutSize         = layoutSize;
-  float             offsetY               = 0.f;
-  bool              needRecalc            = false;
-  float             defaultFontLineHeight = impl.GetDefaultFontLineHeight();
+  ModelPtr&       model                 = impl.mModel;
+  VisualModelPtr& visualModel           = model->mVisualModel;
+  Size            layoutSize            = model->mVisualModel->GetLayoutSize();
+  Size            oldLayoutSize         = layoutSize;
+  float           offsetY               = 0.f;
+  bool            needRecalc            = false;
+  float           defaultFontLineHeight = impl.GetDefaultFontLineHeight();
 
   if(fabsf(layoutSize.height) < Math::MACHINE_EPSILON_1000)
   {
index bf92f6a..7cc8831 100644 (file)
@@ -172,6 +172,11 @@ void Controller::SetAutoScrollEnabled(bool enable)
   mImpl->SetAutoScrollEnabled(enable);
 }
 
+void Controller::SetAutoScrollMaxTextureExceeded(bool exceed)
+{
+  mImpl->mIsAutoScrollMaxTextureExceeded = exceed;
+}
+
 bool Controller::IsAutoScrollEnabled() const
 {
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
index 3e987dd..0def96f 100644 (file)
@@ -257,6 +257,15 @@ public: // Configure the text controller.
   void SetAutoScrollEnabled(bool enable);
 
   /**
+   * @brief Whether the auto scrolling texture exceed max texture.
+   *
+   * By default is false.
+   *
+   * @param[in] exceed Whether the auto scrolling texture exceed max texture.
+   */
+  void SetAutoScrollMaxTextureExceeded(bool exceed);
+
+  /**
    * @brief Retrieves whether auto text scrolling is enabled.
    *
    * By default is disabled.
index 9c067de..0be5ac6 100644 (file)
@@ -376,10 +376,73 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
                 glyphInfo = ellipsisGlyph;
 
                 // Change the 'x' and 'y' position of the ellipsis glyph.
-
                 if(position.x > firstPenX)
                 {
-                  position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+                  if(isTailMode)
+                  {
+                    // To handle case of the mixed languages (LTR then RTL) with
+                    // EllipsisPosition::END and the LayoutDirection::RIGHT_TO_LEFT
+                    float nextXPositions = ellipsisLine->width;
+                    if(indexOfEllipsis + 1u < numberOfGlyphs)
+                    {
+                      Vector2& positionOfNextGlyph = *(glyphPositions + indexOfEllipsis + 1u);
+                      nextXPositions               = positionOfNextGlyph.x;
+                    }
+
+                    if(position.x > nextXPositions) // RTL language
+                    {
+                      if((indexOfEllipsis > 0u) && ((position.x - nextXPositions) > removedGlypsWidth))
+                      {
+                        // To handle mixed directions
+                        // Re-calculates the first penX which will be used if rtl text is elided.
+                        firstPenX = position.x - glyphToRemove.xBearing;
+                        if(firstPenX < -ellipsisGlyph.xBearing)
+                        {
+                          // Avoids to exceed the bounding box when rtl text is elided.
+                          firstPenX = -ellipsisGlyph.xBearing;
+                        }
+                        //Reset the width of removed glyphs
+                        removedGlypsWidth = std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width)) - ellipsisGlyph.xBearing;
+
+                        --indexOfEllipsis;
+                        continue;
+                      }
+                      else
+                      {
+                        // To handle the case of RTL language with EllipsisPosition::END
+                        position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+                      }
+                    }
+                  }
+                  else
+                  {
+                    // To handle the case of LTR language with EllipsisPosition::START
+                    position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+                  }
+                }
+                else
+                {
+                  if(!isTailMode)
+                  {
+                    // To handle case of the mixed languages (RTL then LTR) with
+                    // EllipsisPosition::START and the LayoutDirection::RIGHT_TO_LEFT
+                    float nextXPositions = ellipsisLine->width;
+                    if(indexOfEllipsis + 1u < numberOfGlyphs)
+                    {
+                      Vector2& positionOfNextGlyph = *(glyphPositions + indexOfEllipsis + 1u);
+                      nextXPositions               = positionOfNextGlyph.x;
+                    }
+
+                    if(position.x < nextXPositions) // LTR language
+                    {
+                      position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+
+                      if((position.x + ellipsisGlyphWidth + ellipsisGlyph.xBearing) > nextXPositions)
+                      {
+                        position.x -= (position.x + ellipsisGlyphWidth + ellipsisGlyph.xBearing) - nextXPositions;
+                      }
+                    }
+                  }
                 }
 
                 position.x += ellipsisGlyph.xBearing;
index 4024dff..c16bca6 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali/public-api/math/vector4.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/abstract-style-character-run.h>
 #include <dali-toolkit/internal/text/underline-style-properties.h>
 
 namespace Dali
@@ -34,25 +34,34 @@ namespace Text
 /**
  * @brief Run of underlined characters with same properties.
  */
-struct UnderlinedCharacterRun
+struct UnderlinedCharacterRun : public AbstractStyleCharacterRun
 {
   /**
    * Default constructor to set the default values of bitfields
    */
   UnderlinedCharacterRun()
-  : characterRun{},
+  : AbstractStyleCharacterRun(),
     properties{}
   {
   }
 
-  CharacterRun             characterRun; ///< The initial character index and the number of characters of the run.
-  UnderlineStyleProperties properties;   /// The properties of underline style
+  UnderlineStyleProperties properties; /// The properties of underline style
 };
 
 } // namespace Text
 
 } // namespace Toolkit
 
+// Allow UnderlinedCharacterRun to be treated as a POD type
+template<>
+struct TypeTraits<Dali::Toolkit::Text::UnderlinedCharacterRun> : public Dali::BasicTypes<Dali::Toolkit::Text::UnderlinedCharacterRun>
+{
+  enum
+  {
+    IS_TRIVIAL_TYPE = true
+  };
+};
+
 } // namespace Dali
 
 #endif // DALI_TOOLKIT_TEXT_UNDERLINED_CHARACTER_RUN_H
index 85d2e87..24a8ea2 100644 (file)
@@ -569,6 +569,7 @@ TextureCacheManager::TextureCacheIndex TextureCacheManager::FindCachedTexture(
   const Dali::FittingMode::Type&             fittingMode,
   const Dali::SamplingMode::Type&            samplingMode,
   const TextureCacheManager::UseAtlas&       useAtlas,
+  const StorageType&                         storageType,
   const TextureCacheManager::TextureId&      maskTextureId,
   const bool&                                cropToMask,
   const TextureCacheManager::MultiplyOnLoad& preMultiplyOnLoad,
@@ -593,6 +594,7 @@ TextureCacheManager::TextureCacheIndex TextureCacheManager::FindCachedTexture(
            (cropToMask == textureInfo.cropToMask) &&
            (size == textureInfo.desiredSize) &&
            (isAnimatedImage == textureInfo.isAnimatedImageFormat) &&
+           (storageType == textureInfo.storageType) &&
            (frameIndex == textureInfo.frameIndex) &&
            ((size.GetWidth() == 0 && size.GetHeight() == 0) ||
             (fittingMode == textureInfo.fittingMode &&
index ac70426..fb7dfd7 100644 (file)
@@ -230,6 +230,7 @@ public:
    * @param[in] fittingMode       The FittingMode to use
    * @param[in] samplingMode      The SamplingMode to use
    * @param[in] useAtlas          True if atlased
+   * @param[in] storageType       Whether the pixel data is stored in the cache or uploaded to the GPU
    * @param[in] maskTextureId     Optional texture ID to use to mask this image
    * @param[in] cropToMask        True if crop to mask
    * @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
@@ -244,6 +245,7 @@ public:
     const Dali::FittingMode::Type&             fittingMode,
     const Dali::SamplingMode::Type&            samplingMode,
     const TextureCacheManager::UseAtlas&       useAtlas,
+    const StorageType&                         storageType,
     const TextureCacheManager::TextureId&      maskTextureId,
     const bool&                                cropToMask,
     const TextureCacheManager::MultiplyOnLoad& preMultiplyOnLoad,
index 20aedab..92031ae 100644 (file)
@@ -113,7 +113,9 @@ TextureManager::MaskingData::MaskingData()
 : mAlphaMaskUrl(),
   mAlphaMaskId(INVALID_TEXTURE_ID),
   mContentScaleFactor(1.0f),
-  mCropToMask(true)
+  mCropToMask(true),
+  mPreappliedMasking(true),
+  mMaskImageLoadingFailed(false)
 {
 }
 
@@ -166,12 +168,22 @@ TextureSet TextureManager::LoadAnimatedImageTexture(
     }
     else
     {
+      Texture maskTexture;
       if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
       {
         Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
         if(maskPixelBuffer)
         {
-          pixelBuffer.ApplyMask(maskPixelBuffer, maskInfo->mContentScaleFactor, maskInfo->mCropToMask);
+          if(!maskInfo->mPreappliedMasking)
+          {
+            PixelData maskPixelData = Devel::PixelBuffer::Convert(maskPixelBuffer); // takes ownership of buffer
+            maskTexture             = Texture::New(Dali::TextureType::TEXTURE_2D, maskPixelData.GetPixelFormat(), maskPixelData.GetWidth(), maskPixelData.GetHeight());
+            maskTexture.Upload(maskPixelData);
+          }
+          else
+          {
+            pixelBuffer.ApplyMask(maskPixelBuffer, maskInfo->mContentScaleFactor, maskInfo->mCropToMask);
+          }
         }
         else
         {
@@ -191,6 +203,10 @@ TextureSet TextureManager::LoadAnimatedImageTexture(
         texture.Upload(pixelData);
         textureSet = TextureSet::New();
         textureSet.SetTexture(0u, texture);
+        if(maskTexture)
+        {
+          textureSet.SetTexture(1u, maskTexture);
+        }
       }
     }
   }
@@ -201,13 +217,16 @@ TextureSet TextureManager::LoadAnimatedImageTexture(
     bool      cropToMask         = false;
     if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
     {
-      maskInfo->mAlphaMaskId = RequestMaskLoad(maskInfo->mAlphaMaskUrl);
+      maskInfo->mAlphaMaskId = RequestMaskLoad(maskInfo->mAlphaMaskUrl, maskInfo->mPreappliedMasking ? StorageType::KEEP_PIXEL_BUFFER : StorageType::KEEP_TEXTURE);
       alphaMaskId            = maskInfo->mAlphaMaskId;
-      contentScaleFactor     = maskInfo->mContentScaleFactor;
-      cropToMask             = maskInfo->mCropToMask;
+      if(maskInfo->mPreappliedMasking)
+      {
+        contentScaleFactor = maskInfo->mContentScaleFactor;
+        cropToMask         = maskInfo->mCropToMask;
+      }
     }
 
-    textureId        = RequestLoadInternal(url, alphaMaskId, contentScaleFactor, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, UseAtlas::NO_ATLAS, cropToMask, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad, animatedImageLoading, frameIndex, false);
+    textureId = RequestLoadInternal(url, alphaMaskId, contentScaleFactor, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, UseAtlas::NO_ATLAS, cropToMask, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad, animatedImageLoading, frameIndex, false);
 
     TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId);
     if(loadState == TextureManager::LoadState::UPLOADED)
@@ -381,39 +400,36 @@ TextureSet TextureManager::LoadTexture(
       if(!textureSet) // big image, no atlasing or atlasing failed
       {
         atlasingStatus = false;
-        if(!maskInfo || !maskInfo->mAlphaMaskUrl.IsValid())
-        {
-          textureId = RequestLoad(
-            url,
-            desiredSize,
-            fittingMode,
-            samplingMode,
-            UseAtlas::NO_ATLAS,
-            textureObserver,
-            orientationCorrection,
-            reloadPolicy,
-            preMultiplyOnLoad,
-            synchronousLoading);
-        }
-        else
+
+        TextureId alphaMaskId        = INVALID_TEXTURE_ID;
+        float     contentScaleFactor = 1.0f;
+        bool      cropToMask         = false;
+        if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
         {
-          maskInfo->mAlphaMaskId = RequestMaskLoad(maskInfo->mAlphaMaskUrl, synchronousLoading);
-          textureId              = RequestLoad(
-            url,
-            maskInfo->mAlphaMaskId,
-            maskInfo->mContentScaleFactor,
-            desiredSize,
-            fittingMode,
-            samplingMode,
-            UseAtlas::NO_ATLAS,
-            maskInfo->mCropToMask,
-            textureObserver,
-            orientationCorrection,
-            reloadPolicy,
-            preMultiplyOnLoad,
-            synchronousLoading);
+          maskInfo->mAlphaMaskId = RequestMaskLoad(maskInfo->mAlphaMaskUrl, maskInfo->mPreappliedMasking ? StorageType::KEEP_PIXEL_BUFFER : StorageType::KEEP_TEXTURE, synchronousLoading);
+          alphaMaskId            = maskInfo->mAlphaMaskId;
+          if(maskInfo && maskInfo->mPreappliedMasking)
+          {
+            contentScaleFactor = maskInfo->mContentScaleFactor;
+            cropToMask         = maskInfo->mCropToMask;
+          }
         }
 
+        textureId = RequestLoad(
+          url,
+          alphaMaskId,
+          contentScaleFactor,
+          desiredSize,
+          fittingMode,
+          samplingMode,
+          UseAtlas::NO_ATLAS,
+          cropToMask,
+          textureObserver,
+          orientationCorrection,
+          reloadPolicy,
+          preMultiplyOnLoad,
+          synchronousLoading);
+
         TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId);
         if(loadState == TextureManager::LoadState::UPLOADED)
         {
@@ -487,11 +503,12 @@ TextureManager::TextureId TextureManager::RequestLoad(
 
 TextureManager::TextureId TextureManager::RequestMaskLoad(
   const VisualUrl& maskUrl,
+  StorageType      storageType,
   const bool&      synchronousLoading)
 {
   // Use the normal load procedure to get the alpha mask.
   auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-  return RequestLoadInternal(maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, UseAtlas::NO_ATLAS, false, StorageType::KEEP_PIXEL_BUFFER, NULL, true, TextureManager::ReloadPolicy::CACHED, preMultiply, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
+  return RequestLoadInternal(maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, UseAtlas::NO_ATLAS, false, storageType, NULL, true, TextureManager::ReloadPolicy::CACHED, preMultiply, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
 }
 
 TextureManager::TextureId TextureManager::RequestLoadInternal(
@@ -514,12 +531,12 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 {
   TextureHash       textureHash = INITIAL_HASH_NUMBER;
   TextureCacheIndex cacheIndex  = INVALID_CACHE_INDEX;
-  if(storageType != StorageType::RETURN_PIXEL_BUFFER && frameIndex == 0)
+  if(storageType != StorageType::RETURN_PIXEL_BUFFER)
   {
     textureHash = mTextureCacheManager.GenerateHash(url, desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, cropToMask, frameIndex);
 
     // Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
-    cacheIndex = mTextureCacheManager.FindCachedTexture(textureHash, url, desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, cropToMask, preMultiplyOnLoad, (animatedImageLoading) ? true : false, frameIndex);
+    cacheIndex = mTextureCacheManager.FindCachedTexture(textureHash, url, desiredSize, fittingMode, samplingMode, useAtlas, storageType, maskTextureId, cropToMask, preMultiplyOnLoad, (animatedImageLoading) ? true : false, frameIndex);
   }
 
   TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
@@ -549,7 +566,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     // Cache new texutre, and get cacheIndex.
     cacheIndex = mTextureCacheManager.AppendCache(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
 
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d, frameindex=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, frameIndex);
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d, frameindex=%d premultiply=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, frameIndex, preMultiply);
   }
 
   // The below code path is common whether we are using the cache or not.
@@ -645,19 +662,31 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
       }
       else // For the image loading.
       {
+        Texture maskTexture;
         if(maskTextureId != INVALID_TEXTURE_ID)
         {
           TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(maskTextureId);
           if(maskCacheIndex != INVALID_CACHE_INDEX)
           {
-            Devel::PixelBuffer maskPixelBuffer = mTextureCacheManager[maskCacheIndex].pixelBuffer;
-            if(maskPixelBuffer)
+            if(mTextureCacheManager[maskCacheIndex].storageType == StorageType::KEEP_TEXTURE)
             {
-              pixelBuffer.ApplyMask(maskPixelBuffer, contentScale, cropToMask);
+              TextureSet maskTextures = mTextureCacheManager[maskCacheIndex].textureSet;
+              if(maskTextures && maskTextures.GetTextureCount())
+              {
+                maskTexture = maskTextures.GetTexture(0u);
+              }
             }
-            else
+            else if(mTextureCacheManager[maskCacheIndex].storageType == StorageType::KEEP_PIXEL_BUFFER)
             {
-              DALI_LOG_ERROR("Mask image cached invalid pixel buffer!\n");
+              Devel::PixelBuffer maskPixelBuffer = mTextureCacheManager[maskCacheIndex].pixelBuffer;
+              if(maskPixelBuffer)
+              {
+                pixelBuffer.ApplyMask(maskPixelBuffer, contentScale, cropToMask);
+              }
+              else
+              {
+                DALI_LOG_ERROR("Mask image cached invalid pixel buffer!\n");
+              }
             }
           }
           else
@@ -669,6 +698,10 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 
         // Upload texture
         UploadTexture(pixelBuffer, textureInfo);
+        if(maskTexture && textureInfo.textureSet)
+        {
+          textureInfo.textureSet.SetTexture(1u, maskTexture);
+        }
       }
     }
   }
@@ -843,6 +876,12 @@ void TextureManager::ProcessLoadQueue()
       {
         EmitLoadComplete(element.mObserver, textureInfo, true);
       }
+      else if(textureInfo.loadState == LoadState::LOADING)
+      {
+        // Note : LOADING state texture cannot be queue.
+        // This case be occured when same texture id are queue in mLoadQueue.
+        ObserveTexture(textureInfo, element.mObserver);
+      }
       else
       {
         LoadTexture(textureInfo, element.mObserver);
@@ -928,10 +967,31 @@ void TextureManager::PostLoad(TextureManager::TextureInfo& textureInfo, Devel::P
           {
             textureInfo.loadState = LoadState::WAITING_FOR_MASK;
           }
-          else if(maskLoadState == LoadState::LOAD_FINISHED)
+          else if(maskLoadState == LoadState::LOAD_FINISHED || maskLoadState == LoadState::UPLOADED)
           {
             // Send New Task to Thread
-            ApplyMask(textureInfo, textureInfo.maskTextureId);
+            TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureInfo.maskTextureId);
+            if(maskCacheIndex != INVALID_CACHE_INDEX)
+            {
+              TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]);
+              if(maskTextureInfo.storageType == StorageType::KEEP_PIXEL_BUFFER)
+              {
+                // Send New Task to Thread
+                ApplyMask(textureInfo, textureInfo.maskTextureId);
+              }
+              else if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
+              {
+                // Upload image texture. textureInfo.loadState will be UPLOADED.
+                UploadTexture(textureInfo.pixelBuffer, textureInfo);
+                if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
+                {
+                  Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
+                  textureInfo.textureSet.SetTexture(1u, maskTexture);
+                }
+                // notify mask texture set.
+                NotifyObservers(textureInfo, true);
+              }
+            }
           }
           else // maskLoadState == LoadState::LOAD_FAILED
           {
@@ -957,7 +1017,7 @@ void TextureManager::PostLoad(TextureManager::TextureInfo& textureInfo, Devel::P
       {
         NotifyObservers(textureInfo, true);
       }
-      else
+      else // for the StorageType::KEEP_PIXEL_BUFFER and StorageType::KEEP_TEXTURE
       {
         // Check if there was another texture waiting for this load to complete
         // (e.g. if this was an image mask, and its load is on a different thread)
@@ -968,27 +1028,32 @@ void TextureManager::PostLoad(TextureManager::TextureInfo& textureInfo, Devel::P
   else
   {
     textureInfo.loadState = LoadState::LOAD_FAILED;
-    if(textureInfo.storageType != StorageType::KEEP_PIXEL_BUFFER)
-    {
-      NotifyObservers(textureInfo, false);
-    }
-    else // if(textureInfo.storageType == StorageType::KEEP_PIXEL_BUFFER) // image mask case
+    if(textureInfo.storageType == StorageType::KEEP_PIXEL_BUFFER || textureInfo.storageType == StorageType::KEEP_TEXTURE)
     {
       // Check if there was another texture waiting for this load to complete
       // (e.g. if this was an image mask, and its load is on a different thread)
       CheckForWaitingTexture(textureInfo);
     }
+    else
+    {
+      NotifyObservers(textureInfo, false);
+    }
   }
 }
 
 void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTextureInfo)
 {
+  if(maskTextureInfo.loadState == LoadState::LOAD_FINISHED &&
+     maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
+  {
+    // Upload mask texture. textureInfo.loadState will be UPLOADED.
+    UploadTexture(maskTextureInfo.pixelBuffer, maskTextureInfo);
+  }
+
   // Search the cache, checking if any texture has this texture id as a
   // maskTextureId:
   const std::size_t size = mTextureCacheManager.size();
 
-  const bool maskLoadSuccess = maskTextureInfo.loadState == LoadState::LOAD_FINISHED ? true : false;
-
   // TODO : Refactorize here to not iterate whole cached image.
   for(TextureCacheIndex cacheIndex = TextureCacheIndex(TextureManagerType::TEXTURE_CACHE_INDEX_TYPE_LOCAL, 0u); cacheIndex.GetIndex() < size; ++cacheIndex.detailValue.index)
   {
@@ -997,10 +1062,28 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex
     {
       TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]);
 
-      if(maskLoadSuccess)
+      if(maskTextureInfo.loadState == LoadState::LOAD_FINISHED)
+      {
+        if(maskTextureInfo.storageType == StorageType::KEEP_PIXEL_BUFFER)
+        {
+          // Send New Task to Thread
+          ApplyMask(textureInfo, maskTextureInfo.textureId);
+        }
+      }
+      else if(maskTextureInfo.loadState == LoadState::UPLOADED)
       {
-        // Send New Task to Thread
-        ApplyMask(textureInfo, maskTextureInfo.textureId);
+        if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
+        {
+          // Upload image texture. textureInfo.loadState will be UPLOADED.
+          UploadTexture(textureInfo.pixelBuffer, textureInfo);
+          if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
+          {
+            Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
+            textureInfo.textureSet.SetTexture(1u, maskTexture);
+          }
+          // notify mask texture set.
+          NotifyObservers(textureInfo, true);
+        }
       }
       else
       {
index dcd065c..4248904 100644 (file)
@@ -80,6 +80,8 @@ public:
     TextureManager::TextureId mAlphaMaskId;
     float                     mContentScaleFactor;
     bool                      mCropToMask;
+    bool                      mPreappliedMasking;
+    bool                      mMaskImageLoadingFailed;
   };
   using MaskingDataPointer = std::unique_ptr<MaskingData>;
 
@@ -416,12 +418,14 @@ public: // Load Request API
    * @brief Requests a masking image to be loaded. This mask is not uploaded to GL,
    * instead, it is stored in CPU memory, and can be used for CPU blending.
    * @param[in] maskUrl            The URL of the mask image to load
+   * @param[in] storageType,       Whether the pixel data is stored in the cache or uploaded to the GPU
    * @param[in] synchronousLoading True if the frame should be loaded synchronously. If you skip this parameter,
    *                               default is false.
    * @return                       A TextureId to use as a handle to reference this mask Texture
    */
   TextureId RequestMaskLoad(
     const VisualUrl& maskUrl,
+    StorageType      storageType,
     const bool&      synchronousLoading = false);
 
 private:
index 366e7cb..567d876 100644 (file)
@@ -175,6 +175,7 @@ enum class StorageType
   KEEP_PIXEL_BUFFER,   ///< Keep loaded pixel buffer inside of texture manager without making texture. This could be used for inside pixel process like mask image.
   RETURN_PIXEL_BUFFER, ///< Return loaded pixel buffer without making texture.
                        ///  Because a pixel buffer cannot be used multiple texture, this pixel buffer only cached during loading, and is removed after loading is finished.
+  KEEP_TEXTURE,        ///< Keep loaded texture inside of texture manager. This could be used for pixel processing like GPU masking.
   UPLOAD_TO_TEXTURE    ///< Loaded image will be uploaded to texture and the texture will be returned.
 };
 
index 2b4a3d0..382d52b 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/image-loading.h>
 #include <dali/integration-api/debug.h>
+#include <dali/public-api/rendering/decorated-visual-renderer.h>
 #include <memory>
 
 // INTERNAL INCLUDES
@@ -46,7 +47,7 @@ namespace Internal
 {
 namespace
 {
-const int CUSTOM_PROPERTY_COUNT(3); // ltr, wrap, pixel area,
+const int CUSTOM_PROPERTY_COUNT(5); // ltr, wrap, pixel area, crop to mask, mask texture ratio
 
 // stop behavior
 DALI_ENUM_TO_STRING_TABLE_BEGIN(STOP_BEHAVIOR)
@@ -83,6 +84,8 @@ static constexpr Vector4  FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
 static constexpr auto     LOOP_FOREVER = -1;
 static constexpr auto     FIRST_LOOP   = 0u;
 
+constexpr uint32_t TEXTURE_COUNT_FOR_GPU_ALPHA_MASK = 2u;
+
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE");
 #endif
@@ -175,7 +178,7 @@ void AnimatedImageVisual::CreateImageCache()
 
   if(mAnimatedImageLoading)
   {
-    mImageCache = new RollingAnimatedImageCache(textureManager, mAnimatedImageLoading, mMaskingData, *this, mCacheSize, mBatchSize, IsSynchronousLoadingRequired(),mFactoryCache.GetPreMultiplyOnLoad());
+    mImageCache = new RollingAnimatedImageCache(textureManager, mAnimatedImageLoading, mMaskingData, *this, mCacheSize, mBatchSize, IsSynchronousLoadingRequired(), mFactoryCache.GetPreMultiplyOnLoad());
   }
   else if(mImageUrls)
   {
@@ -317,6 +320,7 @@ void AnimatedImageVisual::DoCreatePropertyMap(Property::Map& map) const
     map.Insert(Toolkit::ImageVisual::Property::ALPHA_MASK_URL, mMaskingData->mAlphaMaskUrl.GetUrl());
     map.Insert(Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, mMaskingData->mContentScaleFactor);
     map.Insert(Toolkit::ImageVisual::Property::CROP_TO_MASK, mMaskingData->mCropToMask);
+    map.Insert(Toolkit::DevelImageVisual::Property::MASKING_TYPE, mMaskingData->mPreappliedMasking ? DevelImageVisual::MaskingType::MASKING_ON_LOADING : DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
   }
 
   map.Insert(Toolkit::ImageVisual::Property::LOAD_POLICY, mLoadPolicy);
@@ -446,6 +450,10 @@ void AnimatedImageVisual::DoSetProperties(const Property::Map& propertyMap)
       {
         DoSetProperty(Toolkit::ImageVisual::Property::CROP_TO_MASK, keyValue.second);
       }
+      else if(keyValue.first == MASKING_TYPE_NAME)
+      {
+        DoSetProperty(Toolkit::DevelImageVisual::Property::MASKING_TYPE, keyValue.second);
+      }
       else if(keyValue.first == LOAD_POLICY_NAME)
       {
         DoSetProperty(Toolkit::ImageVisual::Property::LOAD_POLICY, keyValue.second);
@@ -620,6 +628,17 @@ void AnimatedImageVisual::DoSetProperty(Property::Index        index,
       break;
     }
 
+    case Toolkit::DevelImageVisual::Property::MASKING_TYPE:
+    {
+      int maskingType = 0;
+      if(value.Get(maskingType))
+      {
+        AllocateMaskData();
+        mMaskingData->mPreappliedMasking = Toolkit::DevelImageVisual::MaskingType::Type(maskingType) == Toolkit::DevelImageVisual::MaskingType::MASKING_ON_LOADING ? true : false;
+      }
+      break;
+    }
+
     case Toolkit::ImageVisual::Property::RELEASE_POLICY:
     {
       int releasePolicy = 0;
@@ -690,14 +709,16 @@ void AnimatedImageVisual::UpdateShader()
 
 Shader AnimatedImageVisual::GenerateShader() const
 {
-  bool   defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE;
+  bool   defaultWrapMode                 = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE;
+  bool   requiredAlphaMaskingOnRendering = (mMaskingData && !mMaskingData->mMaskImageLoadingFailed) ? !mMaskingData->mPreappliedMasking : false;
   Shader shader;
   shader = mImageVisualShaderFactory.GetShader(
     mFactoryCache,
     ImageVisualShaderFeature::FeatureBuilder()
       .ApplyDefaultTextureWrapMode(defaultWrapMode)
       .EnableRoundedCorner(IsRoundedCornerRequired())
-      .EnableBorderline(IsBorderlineRequired()));
+      .EnableBorderline(IsBorderlineRequired())
+      .EnableAlphaMaskingOnRendering(requiredAlphaMaskingOnRendering));
   return shader;
 }
 
@@ -710,7 +731,7 @@ void AnimatedImageVisual::OnInitialize()
 
   Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
 
-  mImpl->mRenderer = VisualRenderer::New(geometry, shader);
+  mImpl->mRenderer = DecoratedVisualRenderer::New(geometry, shader);
   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
 
   // Register transform properties
@@ -728,6 +749,11 @@ void AnimatedImageVisual::OnInitialize()
     mImpl->mRenderer.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, mPixelArea);
   }
 
+  if(mMaskingData)
+  {
+    mImpl->mRenderer.RegisterProperty(CROP_TO_MASK_NAME, static_cast<float>(mMaskingData->mCropToMask));
+  }
+
   // Enable PreMultipliedAlpha if it need premultiplied
   auto preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader
                              ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
@@ -743,6 +769,7 @@ void AnimatedImageVisual::StartFirstFrame(TextureSet& textureSet, uint32_t first
   if(mImpl->mRenderer)
   {
     mImpl->mRenderer.SetTextures(textureSet);
+    CheckMaskTexture();
 
     Actor actor = mPlacementActor.GetHandle();
     if(actor)
@@ -793,6 +820,22 @@ void AnimatedImageVisual::SetImageSize(TextureSet& textureSet)
       mImageSize.SetWidth(texture.GetWidth());
       mImageSize.SetHeight(texture.GetHeight());
     }
+
+    if(textureSet.GetTextureCount() > 1u && mMaskingData && mMaskingData->mCropToMask)
+    {
+      Texture maskTexture = textureSet.GetTexture(1);
+      if(maskTexture)
+      {
+        mImageSize.SetWidth(std::min(static_cast<uint32_t>(mImageSize.GetWidth() * mMaskingData->mContentScaleFactor), maskTexture.GetWidth()));
+        mImageSize.SetHeight(std::min(static_cast<uint32_t>(mImageSize.GetHeight() * mMaskingData->mContentScaleFactor), maskTexture.GetHeight()));
+
+        float   textureWidth  = std::max(static_cast<float>(texture.GetWidth() * mMaskingData->mContentScaleFactor), Dali::Math::MACHINE_EPSILON_1);
+        float   textureHeight = std::max(static_cast<float>(texture.GetHeight() * mMaskingData->mContentScaleFactor), Dali::Math::MACHINE_EPSILON_1);
+        Vector2 textureRatio(std::min(static_cast<float>(maskTexture.GetWidth()), textureWidth) / textureWidth,
+                             std::min(static_cast<float>(maskTexture.GetHeight()), textureHeight) / textureHeight);
+        mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, textureRatio);
+      }
+    }
   }
 }
 
@@ -819,6 +862,7 @@ void AnimatedImageVisual::FrameReady(TextureSet textureSet, uint32_t interval)
         mFrameDelayTimer.SetInterval(interval);
       }
       mImpl->mRenderer.SetTextures(textureSet);
+      CheckMaskTexture();
     }
   }
 }
@@ -887,6 +931,7 @@ bool AnimatedImageVisual::DisplayNextFrame()
       if(mImpl->mRenderer)
       {
         mImpl->mRenderer.SetTextures(textureSet);
+        CheckMaskTexture();
       }
       mFrameDelayTimer.SetInterval(mImageCache->GetFrameInterval(frameIndex));