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