From: Richard Huang Date: Wed, 1 Jun 2022 10:16:00 +0000 (+0100) Subject: [dali_2.1.25] Merge branch 'devel/master' X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=73949ef40f8dbe1e9661ae33e2f7765c93f0b25a;hp=8f80166ff21655f688f7414eb1e4a843754dbb52 [dali_2.1.25] Merge branch 'devel/master' Change-Id: I8502ea9b30dc5ada3575bd029bfd2cd6703a11cf --- diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 035f6c3..ed393f0 100755 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -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 index 0000000..2930c6d --- /dev/null +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-LineHelperFunctions.cpp @@ -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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +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("

Line one Line two

"); + + // 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("

Line one Line two

"); + + // 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("

Line one Line two

"); + + // 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("

Line one Line two

"); + + // 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 index 0000000..f6d1827 --- /dev/null +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-AbstractStyleCharacterRun.cpp @@ -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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +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 +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 +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 +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("ColorRun"); + TestAbstractStyleCharacterRunEmptyCharacterRun("CharacterSpacingCharacterRun"); + TestAbstractStyleCharacterRunEmptyCharacterRun("FontDescriptionRun"); + TestAbstractStyleCharacterRunEmptyCharacterRun("UnderlinedCharacterRun"); + TestAbstractStyleCharacterRunEmptyCharacterRun("StrikethroughCharacterRun"); + TestAbstractStyleCharacterRunEmptyCharacterRun("BoundedParagraphRun"); + + TestAbstractStyleCharacterRunOneCharacter("ColorRun"); + TestAbstractStyleCharacterRunOneCharacter("CharacterSpacingCharacterRun"); + TestAbstractStyleCharacterRunOneCharacter("FontDescriptionRun"); + TestAbstractStyleCharacterRunOneCharacter("UnderlinedCharacterRun"); + TestAbstractStyleCharacterRunOneCharacter("StrikethroughCharacterRun"); + TestAbstractStyleCharacterRunOneCharacter("BoundedParagraphRun"); + + TestAbstractStyleCharacterRunMoreThanOneCharacter("ColorRun"); + TestAbstractStyleCharacterRunMoreThanOneCharacter("CharacterSpacingCharacterRun"); + TestAbstractStyleCharacterRunMoreThanOneCharacter("FontDescriptionRun"); + TestAbstractStyleCharacterRunMoreThanOneCharacter("UnderlinedCharacterRun"); + TestAbstractStyleCharacterRunMoreThanOneCharacter("StrikethroughCharacterRun"); + TestAbstractStyleCharacterRunMoreThanOneCharacter("BoundedParagraphRun"); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp index b6b45a6..80836e3 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp @@ -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(), true, TEST_LOCATION); + value = resultMap.Find(DevelImageVisual::Property::MASKING_TYPE, Property::INTEGER); + DALI_TEST_CHECK(value); + DALI_TEST_CHECK(value->Get() == 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(), true, TEST_LOCATION); + value = resultMap.Find(DevelImageVisual::Property::MASKING_TYPE, Property::INTEGER); + DALI_TEST_CHECK(value); + DALI_TEST_CHECK(value->Get() == 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(), true, TEST_LOCATION); + value = resultMap.Find(DevelImageVisual::Property::MASKING_TYPE, Property::INTEGER); + DALI_TEST_CHECK(value); + DALI_TEST_CHECK(value->Get() == 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(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(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(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; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index 3ae49cc..fbca3b6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -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); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp index cb46bd4..120f570 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp @@ -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; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp index b36457f..3f4fdba 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp @@ -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(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(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(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; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index bd3469a..175e834 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -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 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 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(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp index 6291e50..ae3963f 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp @@ -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); diff --git a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h index 413b556..7deaf7a 100644 --- a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h +++ b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h @@ -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 diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 15640b7..41d8c0d 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -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 diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag index 703c649..c2324e7 100644 --- a/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag @@ -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) diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert b/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert index 21d4084..d563c78 100644 --- a/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert +++ b/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert @@ -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 index 0000000..60b7a8a --- /dev/null +++ b/dali-toolkit/internal/text/abstract-style-character-run.cpp @@ -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 + +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 index 0000000..7822679 --- /dev/null +++ b/dali-toolkit/internal/text/abstract-style-character-run.h @@ -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 +#include + +// INTERNAL INCLUDES +#include + +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 : public Dali::BasicTypes +{ + enum + { + IS_TRIVIAL_TYPE = true + }; +}; + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_ABSTRACT_STYLE_CHARACTER_RUN_H diff --git a/dali-toolkit/internal/text/bounded-paragraph-run.h b/dali-toolkit/internal/text/bounded-paragraph-run.h index 4b3150e..3547095 100644 --- a/dali-toolkit/internal/text/bounded-paragraph-run.h +++ b/dali-toolkit/internal/text/bounded-paragraph-run.h @@ -22,7 +22,7 @@ #include // INTERNAL INCLUDES -#include +#include #include 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 : public Dali::BasicTypes +{ + enum + { + IS_TRIVIAL_TYPE = true + }; +}; + } // namespace Dali #endif // DALI_TOOLKIT_TEXT_BOUNDED_PARAGRAPH_RUN_H diff --git a/dali-toolkit/internal/text/character-spacing-character-run.h b/dali-toolkit/internal/text/character-spacing-character-run.h index 5c4238e..f256c6a 100644 --- a/dali-toolkit/internal/text/character-spacing-character-run.h +++ b/dali-toolkit/internal/text/character-spacing-character-run.h @@ -18,11 +18,8 @@ * */ -// EXTERNAL INCLUDES -#include - // INTERNAL INCLUDES -#include +#include 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 : public Dali::BasicTypes +{ + enum + { + IS_TRIVIAL_TYPE = true + }; +}; + } // namespace Dali #endif // DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H diff --git a/dali-toolkit/internal/text/color-run.h b/dali-toolkit/internal/text/color-run.h index edae1e2..75bd27b 100644 --- a/dali-toolkit/internal/text/color-run.h +++ b/dali-toolkit/internal/text/color-run.h @@ -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. @@ -18,12 +18,8 @@ * */ -// EXTERNAL INCLUDES -#include - // INTERNAL INCLUDES -#include -#include +#include 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 : public Dali::BasicTypes +{ + enum + { + IS_TRIVIAL_TYPE = true + }; +}; + } // namespace Dali #endif // DALI_TOOLKIT_TEXT_COLOR_RUN_H diff --git a/dali-toolkit/internal/text/font-description-run.h b/dali-toolkit/internal/text/font-description-run.h index 04a5e91..77b8db8 100644 --- a/dali-toolkit/internal/text/font-description-run.h +++ b/dali-toolkit/internal/text/font-description-run.h @@ -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 // INTERNAL INCLUDES -#include +#include #include 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 : public Dali::BasicTypes +{ + 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 index 0000000..d2ffcd1 --- /dev/null +++ b/dali-toolkit/internal/text/line-helper-functions.cpp @@ -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 + +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 index 0000000..ad94086 --- /dev/null +++ b/dali-toolkit/internal/text/line-helper-functions.h @@ -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 +#include + +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 diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index 826e894..b1502a9 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -26,6 +26,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -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(line.ascender); - - // Include line spacing after first line - if(lineIndex > 0u) - { - glyphData.verticalOffset += static_cast(line.lineSpacing); - } + glyphData.verticalOffset += static_cast(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(-line.descender); + glyphData.verticalOffset += static_cast(-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(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(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& 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(line.ascender); + glyphData.verticalOffset += static_cast(line.ascender + GetPreOffsetVerticalLineAlignment(line, verLineAlign)); // Retrieves the glyph's outline width float outlineWidth = static_cast(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(-line.descender + line.lineSpacing); + glyphData.verticalOffset += static_cast(-line.descender + GetPostOffsetVerticalLineAlignment(line, verLineAlign)); } return glyphData.bitmapBuffer; diff --git a/dali-toolkit/internal/text/strikethrough-character-run.h b/dali-toolkit/internal/text/strikethrough-character-run.h index 66214b7..1d0bc87 100644 --- a/dali-toolkit/internal/text/strikethrough-character-run.h +++ b/dali-toolkit/internal/text/strikethrough-character-run.h @@ -22,7 +22,7 @@ #include // INTERNAL INCLUDES -#include +#include #include 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 : public Dali::BasicTypes +{ + enum + { + IS_TRIVIAL_TYPE = true + }; +}; + } // namespace Dali #endif // DALI_TOOLKIT_TEXT_STRIKETHROUGH_CHARACTER_RUN_H diff --git a/dali-toolkit/internal/text/underlined-character-run.h b/dali-toolkit/internal/text/underlined-character-run.h index 4024dff..c16bca6 100644 --- a/dali-toolkit/internal/text/underlined-character-run.h +++ b/dali-toolkit/internal/text/underlined-character-run.h @@ -22,7 +22,7 @@ #include // INTERNAL INCLUDES -#include +#include #include 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 : public Dali::BasicTypes +{ + enum + { + IS_TRIVIAL_TYPE = true + }; +}; + } // namespace Dali #endif // DALI_TOOLKIT_TEXT_UNDERLINED_CHARACTER_RUN_H diff --git a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp index 85d2e87..24a8ea2 100644 --- a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp +++ b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp @@ -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 && diff --git a/dali-toolkit/internal/texture-manager/texture-cache-manager.h b/dali-toolkit/internal/texture-manager/texture-cache-manager.h index ac70426..fb7dfd7 100644 --- a/dali-toolkit/internal/texture-manager/texture-cache-manager.h +++ b/dali-toolkit/internal/texture-manager/texture-cache-manager.h @@ -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, diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp index 20aedab..445ad65 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp @@ -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 { diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.h b/dali-toolkit/internal/texture-manager/texture-manager-impl.h index dcd065c..4248904 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.h +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.h @@ -80,6 +80,8 @@ public: TextureManager::TextureId mAlphaMaskId; float mContentScaleFactor; bool mCropToMask; + bool mPreappliedMasking; + bool mMaskImageLoadingFailed; }; using MaskingDataPointer = std::unique_ptr; @@ -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: diff --git a/dali-toolkit/internal/texture-manager/texture-manager-type.h b/dali-toolkit/internal/texture-manager/texture-manager-type.h index 366e7cb..567d876 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-type.h +++ b/dali-toolkit/internal/texture-manager/texture-manager-type.h @@ -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. }; diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp index 2b4a3d0..a334e2f 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -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(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(mImageSize.GetWidth() * mMaskingData->mContentScaleFactor), maskTexture.GetWidth())); + mImageSize.SetHeight(std::min(static_cast(mImageSize.GetHeight() * mMaskingData->mContentScaleFactor), maskTexture.GetHeight())); + + float textureWidth = std::max(static_cast(texture.GetWidth() * mMaskingData->mContentScaleFactor), Dali::Math::MACHINE_EPSILON_1); + float textureHeight = std::max(static_cast(texture.GetHeight() * mMaskingData->mContentScaleFactor), Dali::Math::MACHINE_EPSILON_1); + Vector2 textureRatio(std::min(static_cast(maskTexture.GetWidth()), textureWidth) / textureWidth, + std::min(static_cast(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 diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h index 4acb736..8fc0f59 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h @@ -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); diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp index f5753fa..16ba9ca 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp +++ b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp @@ -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(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(ImageVisualRequireFlag::ROUNDED_CORNER); } - else + if(borderline == ImageVisualShaderFeature::Borderline::ENABLED) { - if(borderline == ImageVisualShaderFeature::Borderline::ENABLED) - { - shaderType = VisualFactoryCache::IMAGE_SHADER_BORDERLINE; - } + shaderTypeFlag |= static_cast(ImageVisualRequireFlag::BORDERLINE); + } + if(alphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED) + { + shaderTypeFlag |= static_cast(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()); diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.h b/dali-toolkit/internal/visuals/image-visual-shader-factory.h index 1459614..e0070ed 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-factory.h +++ b/dali-toolkit/internal/visuals/image-visual-shader-factory.h @@ -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 diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index e3aa797..44c9fac 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -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(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(mTextureSize.x * mMaskingData->mContentScaleFactor), maskTexture.GetWidth()); + mTextureSize.y = std::min(static_cast(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(texture.GetWidth() * mMaskingData->mContentScaleFactor), Dali::Math::MACHINE_EPSILON_1); + float textureHeight = std::max(static_cast(texture.GetHeight() * mMaskingData->mContentScaleFactor), Dali::Math::MACHINE_EPSILON_1); + maskTextureRatio = Vector2(std::min(static_cast(maskTexture.GetWidth()), textureWidth) / textureWidth, + std::min(static_cast(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 diff --git a/dali-toolkit/internal/visuals/image/image-visual.h b/dali-toolkit/internal/visuals/image/image-visual.h index 0cbc3ba..17d5a6e 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.h +++ b/dali-toolkit/internal/visuals/image/image-visual.h @@ -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 mPlacementActor; @@ -314,6 +331,7 @@ private: Dali::ImageDimensions mDesiredSize; TextureManager::TextureId mTextureId; TextureSet mTextures; + Vector2 mTextureSize; ImageVisualShaderFactory& mImageVisualShaderFactory; diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.h b/dali-toolkit/internal/visuals/visual-factory-cache.h index 417f4d4..193799c 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.h +++ b/dali-toolkit/internal/visuals/visual-factory-cache.h @@ -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, diff --git a/dali-toolkit/internal/visuals/visual-string-constants.cpp b/dali-toolkit/internal/visuals/visual-string-constants.cpp index 643fb21..c79c9a6 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.cpp +++ b/dali-toolkit/internal/visuals/visual-string-constants.cpp @@ -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"); diff --git a/dali-toolkit/internal/visuals/visual-string-constants.h b/dali-toolkit/internal/visuals/visual-string-constants.h index 1544206..b65292f 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.h +++ b/dali-toolkit/internal/visuals/visual-string-constants.h @@ -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; diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index d463d90..55c9919 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -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 diff --git a/dali-toolkit/public-api/visuals/image-visual-properties.h b/dali-toolkit/public-api/visuals/image-visual-properties.h index b0b28d4..29b9409 100644 --- a/dali-toolkit/public-api/visuals/image-visual-properties.h +++ b/dali-toolkit/public-api/visuals/image-visual-properties.h @@ -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, diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 49be95c..b644874 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -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