[dali_2.1.25] Merge branch 'devel/master' 77/275777/1
authorRichard Huang <r.huang@samsung.com>
Wed, 1 Jun 2022 10:16:00 +0000 (11:16 +0100)
committerRichard Huang <r.huang@samsung.com>
Wed, 1 Jun 2022 10:16:00 +0000 (11:16 +0100)
Change-Id: I8502ea9b30dc5ada3575bd029bfd2cd6703a11cf

41 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
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/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-Visual.cpp
automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp
dali-toolkit/devel-api/visuals/image-visual-properties-devel.h
dali-toolkit/internal/file.list
dali-toolkit/internal/graphics/shaders/image-visual-shader.frag
dali-toolkit/internal/graphics/shaders/image-visual-shader.vert
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/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/rendering/text-typesetter.cpp
dali-toolkit/internal/text/strikethrough-character-run.h
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/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/visual-factory-cache.h
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
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 b6b45a6..80836e3 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;
@@ -894,7 +968,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 +1011,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..120f570 100644 (file)
@@ -3655,9 +3655,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 +3687,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;
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 bd3469a..175e834 100644 (file)
@@ -441,7 +441,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();
@@ -3764,7 +3767,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 +3787,6 @@ int UtcDaliSvgVisualCustomShader(void)
 
 int UtcDaliVisualRoundedCorner(void)
 {
-  ToolkitTestApplication application;
   tet_infoline("UtcDaliVisualRoundedCorner");
 
   static std::vector<UniformData> customUniforms =
@@ -3792,11 +3795,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 +3835,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 +3872,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 +3909,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 +3947,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 +3998,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 +4037,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 +4063,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 +4076,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 +4118,6 @@ int UtcDaliVisualRoundedCorner(void)
 
 int UtcDaliVisualBorderline(void)
 {
-  ToolkitTestApplication application;
   tet_infoline("UtcDaliVisualBorderline");
 
   static std::vector<UniformData> customUniforms =
@@ -4097,11 +4129,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 +4178,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 +4221,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 +4259,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 +4300,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 +4358,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 +4400,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 +4430,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 +4447,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 +5332,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();
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 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 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 703c649..c2324e7 100644 (file)
@@ -4,6 +4,9 @@
 #ifndef IS_REQUIRED_BORDERLINE
 #define IS_REQUIRED_BORDERLINE 0
 #endif
+#ifndef IS_REQUIRED_ALPHA_MASKING
+#define IS_REQUIRED_ALPHA_MASKING 0
+#endif
 #ifndef ATLAS_DEFAULT_WARP
 #define ATLAS_DEFAULT_WARP 0
 #endif
@@ -22,6 +25,12 @@ INPUT mediump vec4 vCornerRadius;
 #endif
 
 uniform sampler2D sTexture;
+
+#if IS_REQUIRED_ALPHA_MASKING
+uniform sampler2D sMaskTexture;
+INPUT mediump vec2 vMaskTexCoord;
+#endif
+
 #if ATLAS_DEFAULT_WARP
 uniform mediump vec4 uAtlasRect;
 #elif ATLAS_CUSTOM_WARP
@@ -228,6 +237,12 @@ void main()
 
   lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ) * uColor;
 
+#if IS_REQUIRED_ALPHA_MASKING
+  mediump float maskAlpha = TEXTURE(sMaskTexture, vMaskTexCoord).a;
+  textureColor.a *= maskAlpha;
+  textureColor.rgb *= mix(1.0, maskAlpha, preMultipliedAlpha);
+#endif
+
 #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
   // skip most potential calculate for performance
   if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
index 21d4084..d563c78 100644 (file)
@@ -4,6 +4,9 @@
 #ifndef IS_REQUIRED_BORDERLINE
 #define IS_REQUIRED_BORDERLINE 0
 #endif
+#ifndef IS_REQUIRED_ALPHA_MASKING
+#define IS_REQUIRED_ALPHA_MASKING 0
+#endif
 
 INPUT mediump vec2 aPosition;
 OUTPUT mediump vec2 vTexCoord;
@@ -34,6 +37,11 @@ uniform mediump float borderlineOffset;
 uniform mediump vec4 cornerRadius;
 uniform mediump float cornerRadiusPolicy;
 #endif
+#if IS_REQUIRED_ALPHA_MASKING
+OUTPUT  mediump vec2  vMaskTexCoord;
+uniform lowp    float cropToMask;
+uniform mediump vec2  maskTextureRatio;
+#endif
 uniform mediump vec2 extraSize;
 
 vec4 ComputeVertexPosition()
@@ -68,7 +76,18 @@ vec4 ComputeVertexPosition()
   mediump vec2 vPosition = aPosition * visualSize;
 #endif
 
-  vTexCoord = pixelArea.xy + pixelArea.zw * (vPosition.xy / max(vec2(1.0), visualSize) + vec2(0.5));
+  vec4 finalPixelArea = pixelArea;
+#if 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);
 }
 
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
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 826e894..b1502a9 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>
@@ -486,6 +487,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 +510,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 +576,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 +853,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 +1020,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 +1032,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());
@@ -1357,7 +1333,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 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 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..445ad65 100644 (file)
@@ -113,14 +113,18 @@ TextureManager::MaskingData::MaskingData()
 : mAlphaMaskUrl(),
   mAlphaMaskId(INVALID_TEXTURE_ID),
   mContentScaleFactor(1.0f),
-  mCropToMask(true)
+  mCropToMask(true),
+  mPreappliedMasking(true),
+  mMaskImageLoadingFailed(false)
 {
 }
 
 TextureManager::TextureManager()
 : mTextureCacheManager(),
-  mAsyncLocalLoaders(GetNumberOfLocalLoaderThreads(), [&]() { return TextureAsyncLoadingHelper(*this); }),
-  mAsyncRemoteLoaders(GetNumberOfRemoteLoaderThreads(), [&]() { return TextureAsyncLoadingHelper(*this); }),
+  mAsyncLocalLoaders(GetNumberOfLocalLoaderThreads(), [&]()
+                     { return TextureAsyncLoadingHelper(*this); }),
+  mAsyncRemoteLoaders(GetNumberOfRemoteLoaderThreads(), [&]()
+                      { return TextureAsyncLoadingHelper(*this); }),
   mLifecycleObservers(),
   mLoadQueue(),
   mRemoveQueue(),
@@ -166,12 +170,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 +205,10 @@ TextureSet TextureManager::LoadAnimatedImageTexture(
         texture.Upload(pixelData);
         textureSet = TextureSet::New();
         textureSet.SetTexture(0u, texture);
+        if(maskTexture)
+        {
+          textureSet.SetTexture(1u, maskTexture);
+        }
       }
     }
   }
@@ -201,13 +219,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 +402,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 +505,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(
@@ -519,7 +538,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     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;
@@ -645,19 +664,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 +700,10 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 
         // Upload texture
         UploadTexture(pixelBuffer, textureInfo);
+        if(maskTexture && textureInfo.textureSet)
+        {
+          textureInfo.textureSet.SetTexture(1u, maskTexture);
+        }
       }
     }
   }
@@ -928,10 +963,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 +1013,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 +1024,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 +1058,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..a334e2f 100644 (file)
@@ -46,7 +46,7 @@ namespace Internal
 {
 namespace
 {
-const int CUSTOM_PROPERTY_COUNT(3); // ltr, wrap, pixel area,
+const int CUSTOM_PROPERTY_COUNT(10); // ltr, wrap, pixel area, crop to mask, mask texture ratio + border/corner
 
 // stop behavior
 DALI_ENUM_TO_STRING_TABLE_BEGIN(STOP_BEHAVIOR)
@@ -83,6 +83,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
@@ -317,6 +319,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 +449,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 +627,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 +708,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;
 }
 
@@ -728,6 +748,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 +768,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 +819,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 +861,7 @@ void AnimatedImageVisual::FrameReady(TextureSet textureSet, uint32_t interval)
         mFrameDelayTimer.SetInterval(interval);
       }
       mImpl->mRenderer.SetTextures(textureSet);
+      CheckMaskTexture();
     }
   }
 }
@@ -887,6 +930,7 @@ bool AnimatedImageVisual::DisplayNextFrame()
       if(mImpl->mRenderer)
       {
         mImpl->mRenderer.SetTextures(textureSet);
+        CheckMaskTexture();
       }
       mFrameDelayTimer.SetInterval(mImageCache->GetFrameInterval(frameIndex));
     }
@@ -931,6 +975,24 @@ void AnimatedImageVisual::AllocateMaskData()
   }
 }
 
+void AnimatedImageVisual::CheckMaskTexture()
+{
+  if(mMaskingData && !mMaskingData->mPreappliedMasking)
+  {
+    bool maskLoadFailed = true;
+    TextureSet textures = mImpl->mRenderer.GetTextures();
+    if(textures && textures.GetTextureCount() >= TEXTURE_COUNT_FOR_GPU_ALPHA_MASK)
+    {
+      maskLoadFailed = false;
+    }
+    if(mMaskingData->mMaskImageLoadingFailed != maskLoadFailed)
+    {
+      mMaskingData->mMaskImageLoadingFailed = maskLoadFailed;
+      UpdateShader();
+    }
+  }
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 4acb736..8fc0f59 100644 (file)
@@ -247,6 +247,12 @@ private:
    */
   void AllocateMaskData();
 
+  /**
+   * @brief Check whether the mask texture is loaded or not.
+   * If MaskingType is MASKING_ON_LOADING and mask texture is failed to load, update shader.
+   */
+  void CheckMaskTexture();
+
   // Undefined
   AnimatedImageVisual(const AnimatedImageVisual& animatedImageVisual);
 
index f5753fa..16ba9ca 100644 (file)
@@ -43,6 +43,28 @@ static std::string gFragmentShaderNoAtlas;
 
 const int NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMAGE_SHADER - VisualFactoryCache::ShaderType::IMAGE_SHADER;
 
+// enum of required list when we select shader
+enum class ImageVisualRequireFlag : uint32_t
+{
+  DEFAULT        = 0,
+  ROUNDED_CORNER = 1 << 0,
+  BORDERLINE     = 1 << 1,
+  ALPHA_MASKING  = 1 << 2,
+};
+
+static constexpr auto SHADER_TYPE_COUNT = 8u;
+VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
+{
+  VisualFactoryCache::IMAGE_SHADER,
+  VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+  VisualFactoryCache::IMAGE_SHADER_BORDERLINE,
+  VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE,
+  VisualFactoryCache::IMAGE_SHADER_MASKING,
+  VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+  VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
+  VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING
+};
+
 } // unnamed namespace
 
 namespace ImageVisualShaderFeature
@@ -72,6 +94,11 @@ FeatureBuilder& FeatureBuilder::SetTextureForFragmentShaderCheck(const Dali::Tex
   mTexture = texture;
   return *this;
 }
+FeatureBuilder& FeatureBuilder::EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering)
+{
+  mAlphaMaskingOnRendering = (enableAlphaMaskingOnRendering ? AlphaMaskingOnRendering::ENABLED : AlphaMaskingOnRendering::DISABLED);
+  return *this;
+}
 } // namespace ImageVisualShaderFeature
 
 ImageVisualShaderFactory::ImageVisualShaderFactory()
@@ -88,13 +115,14 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
   Shader shader;
   VisualFactoryCache::ShaderType shaderType = VisualFactoryCache::IMAGE_SHADER;
 
-  const auto& atlasing               = featureBuilder.mTextureAtlas;
-  const auto& defaultTextureWrapping = featureBuilder.mDefaultTextureWrapMode;
-  const auto& roundedCorner          = featureBuilder.mRoundedCorner;
-  const auto& borderline             = featureBuilder.mBorderline;
-  const auto& changeFragmentShader   = (featureBuilder.mTexture && DevelTexture::IsNative(featureBuilder.mTexture))
-                                       ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE
-                                       : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
+  const auto& atlasing                = featureBuilder.mTextureAtlas;
+  const auto& defaultTextureWrapping  = featureBuilder.mDefaultTextureWrapMode;
+  const auto& roundedCorner           = featureBuilder.mRoundedCorner;
+  const auto& borderline              = featureBuilder.mBorderline;
+  const auto& alphaMaskingOnRendering = featureBuilder.mAlphaMaskingOnRendering;
+  const auto& changeFragmentShader    = (featureBuilder.mTexture && DevelTexture::IsNative(featureBuilder.mTexture))
+                                          ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE
+                                          : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
 
   if(atlasing == ImageVisualShaderFeature::TextureAtlas::ENABLED)
   {
@@ -109,24 +137,20 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
   }
   else
   {
+    uint32_t shaderTypeFlag = static_cast<uint32_t>(ImageVisualRequireFlag::DEFAULT);
     if(roundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
     {
-      if(borderline == ImageVisualShaderFeature::Borderline::ENABLED)
-      {
-        shaderType = VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE;
-      }
-      else
-      {
-        shaderType = VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER;
-      }
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ROUNDED_CORNER);
     }
-    else
+    if(borderline == ImageVisualShaderFeature::Borderline::ENABLED)
     {
-      if(borderline == ImageVisualShaderFeature::Borderline::ENABLED)
-      {
-        shaderType = VisualFactoryCache::IMAGE_SHADER_BORDERLINE;
-      }
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::BORDERLINE);
+    }
+    if(alphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
+    {
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ALPHA_MASKING);
     }
+    shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
   }
 
   if(changeFragmentShader == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE &&
@@ -164,6 +188,11 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
         vertexShaderPrefixList   += "#define IS_REQUIRED_BORDERLINE 1\n";
         fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
       }
+      if(alphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
+      {
+        vertexShaderPrefixList   += "#define IS_REQUIRED_ALPHA_MASKING 1\n";
+        fragmentShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING 1\n";
+      }
     }
 
     std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix()   + vertexShaderPrefixList   + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
index 1459614..e0070ed 100644 (file)
@@ -96,6 +96,18 @@ enum Type
 };
 } // namespace ChangeFragmentShader
 
+namespace AlphaMaskingOnRendering
+{
+/**
+ * @brief Whether use runtime alpha masking in shader, or not
+ */
+enum Type
+{
+  DISABLED = 0, ///< Image visual doesn't use runtime alpha masking
+  ENABLED       ///< Image visual uses runtime alpha masking
+};
+} // namespace AlphaMaskingOnRendering
+
 /**
  * @brief Collection of current image visual feature. Only use for ImageVisualShaderFactory::GetShader()
  */
@@ -106,6 +118,7 @@ struct FeatureBuilder
     mDefaultTextureWrapMode(DefaultTextureWrapMode::APPLY),
     mRoundedCorner(RoundedCorner::DISABLED),
     mBorderline(Borderline::DISABLED),
+    mAlphaMaskingOnRendering(AlphaMaskingOnRendering::DISABLED),
     mTexture()
   {
   }
@@ -115,15 +128,17 @@ struct FeatureBuilder
   FeatureBuilder& EnableRoundedCorner(bool enableRoundedCorner);
   FeatureBuilder& EnableBorderline(bool enableBorderline);
   FeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
-
-  TextureAtlas::Type           mTextureAtlas : 2;           ///< Whether use texture with atlas, or not. default as TextureAtlas::DISABLED
-  DefaultTextureWrapMode::Type mDefaultTextureWrapMode : 2; ///< Whether apply to texture wraping in default, or not. default as DefaultTextureWrapMode::APPLY
-  RoundedCorner::Type          mRoundedCorner : 2;          ///< Whether use rounded corner, or not. default as RoundedCorner::DISABLED
-  Borderline::Type             mBorderline : 2;             ///< Whether use borderline, or not. default as Borderline::DISABLED
-  Dali::Texture                mTexture;                    ///< Texture to check whether we need to change fragment shader or not
+  FeatureBuilder& EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering);
+
+  TextureAtlas::Type            mTextureAtlas : 2;            ///< Whether use texture with atlas, or not. default as TextureAtlas::DISABLED
+  DefaultTextureWrapMode::Type  mDefaultTextureWrapMode : 2;  ///< Whether apply to texture wraping in default, or not. default as DefaultTextureWrapMode::APPLY
+  RoundedCorner::Type           mRoundedCorner : 2;           ///< Whether use rounded corner, or not. default as RoundedCorner::DISABLED
+  Borderline::Type              mBorderline : 2;              ///< Whether use borderline, or not. default as Borderline::DISABLED
+  AlphaMaskingOnRendering::Type mAlphaMaskingOnRendering : 2; ///< Whether use runtime alpha masking, or not. default as AlphaMaskingOnRendering::DISABLED
+  Dali::Texture                 mTexture;                     ///< Texture to check whether we need to change fragment shader or not
 };
 
-} // namespace ImageVisualShaderFactoryFeature
+} // namespace ImageVisualShaderFeature
 
 /**
  * ImageVisualShaderFactory is an object that provides and shares shaders between image visuals
index e3aa797..44c9fac 100644 (file)
@@ -51,7 +51,7 @@ namespace Internal
 {
 namespace
 {
-const int CUSTOM_PROPERTY_COUNT(9); // wrap, pixel area, atlas, pixalign, + border/corner
+const int CUSTOM_PROPERTY_COUNT(12); // ltr, wrap, pixel area, atlas, pixalign, crop to mask, mask texture ratio + border/corner
 
 // fitting modes
 DALI_ENUM_TO_STRING_TABLE_BEGIN(FITTING_MODE)
@@ -99,6 +99,8 @@ const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
 const float PIXEL_ALIGN_ON  = 1.0f;
 const float PIXEL_ALIGN_OFF = 0.0f;
 
+constexpr uint32_t TEXTURE_COUNT_FOR_GPU_ALPHA_MASK = 2u;
+
 Geometry CreateGeometry(VisualFactoryCache& factoryCache, ImageDimensions gridSize)
 {
   Geometry geometry;
@@ -274,6 +276,10 @@ void ImageVisual::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);
@@ -426,6 +432,17 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va
       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;
@@ -481,11 +498,9 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
     auto textureSet = mImpl->mRenderer.GetTextures();
     if(textureSet && textureSet.GetTextureCount())
     {
-      auto texture = textureSet.GetTexture(0);
-      if(texture)
+      if(mTextureSize != Vector2::ZERO)
       {
-        naturalSize.x = texture.GetWidth();
-        naturalSize.y = texture.GetHeight();
+        naturalSize = mTextureSize;
         return;
       }
     }
@@ -574,6 +589,11 @@ void ImageVisual::OnInitialize()
   mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
 
   EnablePreMultipliedAlpha(IsPreMultipliedAlphaEnabled());
+
+  if(mMaskingData)
+  {
+    mImpl->mRenderer.RegisterProperty(CROP_TO_MASK_NAME, static_cast<float>(mMaskingData->mCropToMask));
+  }
 }
 
 void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection, TextureManager::ReloadPolicy forceReload)
@@ -661,6 +681,8 @@ void ImageVisual::InitializeRenderer()
   if(mTextures)
   {
     mImpl->mRenderer.SetTextures(mTextures);
+    ComputeTextureSize();
+    CheckMaskTexture();
     if(DevelTexture::IsNative(mTextures.GetTexture(0)))
     {
       UpdateShader();
@@ -745,6 +767,7 @@ void ImageVisual::DoSetOffScene(Actor& actor)
 
     TextureSet textureSet = TextureSet::New();
     mImpl->mRenderer.SetTextures(textureSet);
+    ComputeTextureSize();
 
     mLoadState = TextureManager::LoadState::NOT_STARTED;
   }
@@ -780,6 +803,7 @@ void ImageVisual::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);
@@ -879,6 +903,8 @@ void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureIn
       sampler.SetWrapMode(mWrapModeU, mWrapModeV);
       textureInformation.textureSet.SetSampler(0u, sampler);
       mImpl->mRenderer.SetTextures(textureInformation.textureSet);
+      ComputeTextureSize();
+      CheckMaskTexture();
     }
 
     if(actor)
@@ -967,6 +993,60 @@ void ImageVisual::RemoveTexture()
   }
 }
 
+void ImageVisual::ComputeTextureSize()
+{
+  if(mImpl->mRenderer)
+  {
+    auto textureSet = mImpl->mRenderer.GetTextures();
+    if(textureSet && textureSet.GetTextureCount())
+    {
+      auto texture = textureSet.GetTexture(0);
+      if(texture)
+      {
+        mTextureSize.x = texture.GetWidth();
+        mTextureSize.y = texture.GetHeight();
+        if(textureSet.GetTextureCount() > 1u && mMaskingData && !mMaskingData->mPreappliedMasking && mMaskingData->mCropToMask)
+        {
+          Texture maskTexture = textureSet.GetTexture(1);
+          if(maskTexture)
+          {
+            mTextureSize.x = std::min(static_cast<uint32_t>(mTextureSize.x * mMaskingData->mContentScaleFactor), maskTexture.GetWidth());
+            mTextureSize.y = std::min(static_cast<uint32_t>(mTextureSize.y * mMaskingData->mContentScaleFactor), maskTexture.GetHeight());
+          }
+        }
+      }
+    }
+  }
+}
+
+Vector2 ImageVisual::ComputeMaskTextureRatio()
+{
+  Vector2 maskTextureRatio;
+  if(mImpl->mRenderer)
+  {
+    auto textureSet = mImpl->mRenderer.GetTextures();
+    if(textureSet && textureSet.GetTextureCount())
+    {
+      auto texture = textureSet.GetTexture(0);
+      if(texture)
+      {
+        if(textureSet.GetTextureCount() > 1u && mMaskingData && !mMaskingData->mPreappliedMasking && mMaskingData->mCropToMask)
+        {
+          Texture maskTexture = textureSet.GetTexture(1);
+          if(maskTexture)
+          {
+            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);
+            maskTextureRatio    = Vector2(std::min(static_cast<float>(maskTexture.GetWidth()), textureWidth) / textureWidth,
+                                       std::min(static_cast<float>(maskTexture.GetHeight()), textureHeight) / textureHeight);
+          }
+        }
+      }
+    }
+  }
+  return maskTextureRatio;
+}
+
 Shader ImageVisual::GenerateShader() const
 {
   Shader shader;
@@ -977,6 +1057,7 @@ Shader ImageVisual::GenerateShader() const
 
   if(useStandardShader)
   {
+    bool   requiredAlphaMaskingOnRendering = (mMaskingData && !mMaskingData->mMaskImageLoadingFailed) ? !mMaskingData->mPreappliedMasking : false;
     // Create and cache the standard shader
     shader = mImageVisualShaderFactory.GetShader(
       mFactoryCache,
@@ -985,7 +1066,8 @@ Shader ImageVisual::GenerateShader() const
         .ApplyDefaultTextureWrapMode(mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE)
         .EnableRoundedCorner(IsRoundedCornerRequired())
         .EnableBorderline(IsBorderlineRequired())
-        .SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture()));
+        .SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture())
+        .EnableAlphaMaskingOnRendering(requiredAlphaMaskingOnRendering));
   }
   else
   {
@@ -1047,6 +1129,29 @@ Shader ImageVisual::GenerateShader() const
   return shader;
 }
 
+void ImageVisual::CheckMaskTexture()
+{
+  if(mMaskingData && !mMaskingData->mPreappliedMasking)
+  {
+    bool maskLoadFailed = true;
+    TextureSet textures = mImpl->mRenderer.GetTextures();
+    if(textures && textures.GetTextureCount() >= TEXTURE_COUNT_FOR_GPU_ALPHA_MASK)
+    {
+      if(mMaskingData->mCropToMask)
+      {
+        mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, ComputeMaskTextureRatio());
+      }
+      maskLoadFailed = false;
+    }
+
+    if(mMaskingData->mMaskImageLoadingFailed != maskLoadFailed)
+    {
+      mMaskingData->mMaskImageLoadingFailed = maskLoadFailed;
+      UpdateShader();
+    }
+  }
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 0cbc3ba..17d5a6e 100644 (file)
@@ -299,12 +299,29 @@ private:
   void RemoveTexture();
 
   /**
+   * @brief Compute texture size
+   */
+  void ComputeTextureSize();
+
+  /**
+   * @brief Compute mask texture ratio
+   * @return The Mask Texture Ratio
+   */
+  Vector2 ComputeMaskTextureRatio();
+
+  /**
    * Helper method to set individual values by index key.
    * @param[in] index The index key of the value
    * @param[in] value The value
    */
   void DoSetProperty(Property::Index index, const Property::Value& value);
 
+  /**
+   * @brief Check whether the mask texture is loaded or not.
+   * If MaskingType is MASKING_ON_LOADING and mask texture is failed to load, update shader.
+   */
+  void CheckMaskTexture();
+
 private:
   Vector4                            mPixelArea;
   WeakHandle<Actor>                  mPlacementActor;
@@ -314,6 +331,7 @@ private:
   Dali::ImageDimensions     mDesiredSize;
   TextureManager::TextureId mTextureId;
   TextureSet                mTextures;
+  Vector2                   mTextureSize;
 
   ImageVisualShaderFactory& mImageVisualShaderFactory;
 
index 417f4d4..193799c 100644 (file)
@@ -84,12 +84,20 @@ public:
     IMAGE_SHADER_ROUNDED_CORNER,
     IMAGE_SHADER_BORDERLINE,
     IMAGE_SHADER_ROUNDED_BORDERLINE,
+    IMAGE_SHADER_MASKING,
+    IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+    IMAGE_SHADER_BORDERLINE_MASKING,
+    IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
     IMAGE_SHADER_ATLAS_DEFAULT_WRAP,
     IMAGE_SHADER_ATLAS_CUSTOM_WRAP,
     NATIVE_IMAGE_SHADER,
     NATIVE_IMAGE_SHADER_ROUNDED_CORNER,
     NATIVE_IMAGE_SHADER_BORDERLINE,
     NATIVE_IMAGE_SHADER_ROUNDED_BORDERLINE,
+    NATIVE_IMAGE_SHADER_MASKING,
+    NATIVE_IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+    NATIVE_IMAGE_SHADER_BORDERLINE_MASKING,
+    NATIVE_IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
     NINE_PATCH_SHADER,
     NINE_PATCH_MASK_SHADER,
     TEXT_SHADER_MULTI_COLOR_TEXT,
index 643fb21..c79c9a6 100644 (file)
@@ -122,6 +122,8 @@ const char* const IMAGE_DESIRED_WIDTH("desiredWidth");
 const char* const IMAGE_DESIRED_HEIGHT("desiredHeight");
 const char* const ALPHA_MASK_URL("alphaMaskUrl");
 const char* const REDRAW_IN_SCALING_DOWN_NAME("redrawInScalingDown");
+const char* const MASKING_TYPE_NAME("maskingType");
+const char* const MASK_TEXTURE_RATIO_NAME("maskTextureRatio");
 
 // Text visual
 const char* const TEXT_PROPERTY("text");
index 1544206..b65292f 100644 (file)
@@ -106,6 +106,8 @@ extern const char* const IMAGE_DESIRED_WIDTH;
 extern const char* const IMAGE_DESIRED_HEIGHT;
 extern const char* const ALPHA_MASK_URL;
 extern const char* const REDRAW_IN_SCALING_DOWN_NAME;
+extern const char* const MASKING_TYPE_NAME;
+extern const char* const MASK_TEXTURE_RATIO_NAME;
 
 // Text visual
 extern const char* const TEXT_PROPERTY;
index d463d90..55c9919 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 24;
+const unsigned int TOOLKIT_MICRO_VERSION = 25;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index b0b28d4..29b9409 100644 (file)
@@ -226,7 +226,7 @@ enum
    * @details Name "cropToMask", type Property::BOOLEAN, True if the image should
    * be cropped to match the mask size, or false if the image should remain the same size.
    * @SINCE_1_2.60
-   * @note Optional.
+   * @note Optional, Default true
    * @note If this is false, then the mask is scaled to fit the image before being applied.
    */
   CROP_TO_MASK,
index 49be95c..b644874 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.1.24
+Version:    2.1.25
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT