From: abdullah Date: Mon, 22 Nov 2021 07:10:51 +0000 (+0200) Subject: Add support for text geometry X-Git-Tag: dali_2.1.3~8^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=6d3a21eaeaae4edbc04b6e902b61439cdf029188 Add support for text geometry Added the following requested API's for text geometry : GetTextSize(); GetTextPosition(); above API's could return a list of values in case of : 1-multiline, each line in a separate value. 2-mixed text of LTR & RTL, each contiguous block of the same direction has a separate value. note that above API's returns values based on the current rendered text position/size. Change-Id: I1ee9d26954d529bb81c72647dbc9f09ccc8e35ac --- diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index b1aece3..641a9df 100755 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -135,6 +135,7 @@ SET(TEST_HARNESS_SOURCES dali-toolkit-test-utils/test-render-controller.cpp dali-toolkit-test-utils/test-trace-call-stack.cpp dali-toolkit-test-utils/test-native-image.cpp + test-text-geometry-utils.cpp ) PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED diff --git a/automated-tests/src/dali-toolkit/test-text-geometry-utils.cpp b/automated-tests/src/dali-toolkit/test-text-geometry-utils.cpp new file mode 100644 index 0000000..b2f0411 --- /dev/null +++ b/automated-tests/src/dali-toolkit/test-text-geometry-utils.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 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 "test-text-geometry-utils.h" + +namespace TestTextGeometryUtils +{ + +void CheckGeometryResult(Vector positionsList, Vector sizeList, Vector expectedPositions, Vector expectedSizes) +{ + unsigned int expectedCount = expectedSizes.Size(); + + for(unsigned int i = 0; i < expectedCount; i++) + { + DALI_TEST_EQUALS((int)positionsList[i].x, (int)expectedPositions[i].x, TEST_LOCATION); + DALI_TEST_EQUALS((int)positionsList[i].y, (int)expectedPositions[i].y, TEST_LOCATION); + + DALI_TEST_EQUALS((int)sizeList[i].x, (int)expectedSizes[i].x, TEST_LOCATION); + DALI_TEST_EQUALS((int)sizeList[i].y, (int)expectedSizes[i].y, TEST_LOCATION); + } +} + +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/test-text-geometry-utils.h b/automated-tests/src/dali-toolkit/test-text-geometry-utils.h new file mode 100644 index 0000000..4aa2a33 --- /dev/null +++ b/automated-tests/src/dali-toolkit/test-text-geometry-utils.h @@ -0,0 +1,32 @@ +#ifndef TOOLKIT_TEXT_GEOMETRY_UTILS_H +#define TOOLKIT_TEXT_GEOMETRY_UTILS_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. + * + */ + + +#include +#include + + + +namespace TestTextGeometryUtils +{ +void CheckGeometryResult(Vector positionsList, Vector sizeList, Vector expectedPositions, Vector expectedSizes); +} + +#endif // TOOLKIT_TEXT_GEOMETRY_UTILS_H diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 02dff2e..b2a7c5f 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -29,6 +29,7 @@ #include #include #include +#include "test-text-geometry-utils.h" using namespace Dali; using namespace Toolkit; @@ -4455,6 +4456,258 @@ int utcDaliTextEditorCursorPositionChangedSignal(void) END_TEST; } +int utcDaliTextEditorGeometryEllipsisStart(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextEditorGeometryEllipsisStart"); + + TextEditor editor = TextEditor::New(); + DALI_TEST_CHECK( editor ); + + application.GetScene().Add( editor ); + + editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f ); + editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) ); + editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true ); + editor.SetProperty( DevelTextEditor::Property::ENABLE_SCROLL_BAR, false ); + editor.SetProperty( DevelTextEditor::Property::ELLIPSIS, true ); + editor.SetProperty( DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::START ); + editor.SetProperty( TextEditor::Property::TEXT, "line1 \nline2\nline 3\nline4" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 2; + unsigned int startIndex = 0; + unsigned int endIndex = 24; + + Vector positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex); + Vector sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(37, 0)); + expectedSizes.PushBack(Vector2(20, 25)); + + expectedPositions.PushBack(Vector2(-1, 25)); + expectedSizes.PushBack(Vector2(52, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + +int utcDaliTextEditorGeometryEllipsisMiddle(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextEditorGeometryEllipsisMiddle"); + + TextEditor editor = TextEditor::New(); + DALI_TEST_CHECK( editor ); + + application.GetScene().Add( editor ); + + editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f ); + editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) ); + editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true ); + editor.SetProperty( DevelTextEditor::Property::ENABLE_SCROLL_BAR, false ); + editor.SetProperty( DevelTextEditor::Property::ELLIPSIS, true ); + editor.SetProperty( DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::MIDDLE ); + editor.SetProperty( TextEditor::Property::TEXT, "line1 \nline2\nline 3\nline4" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 2; + unsigned int startIndex = 0; + unsigned int endIndex = 24; + + Vector positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex); + Vector sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(-1, 0)); + expectedSizes.PushBack(Vector2(25, 25)); + + expectedPositions.PushBack(Vector2(-1, 25)); + expectedSizes.PushBack(Vector2(52, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + +int utcDaliTextEditorGeometryEllipsisEnd(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextEditorGeometryEllipsisEnd"); + + TextEditor editor = TextEditor::New(); + DALI_TEST_CHECK( editor ); + + application.GetScene().Add( editor ); + + editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f ); + editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) ); + editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true ); + editor.SetProperty( DevelTextEditor::Property::ENABLE_SCROLL_BAR, false ); + editor.SetProperty( DevelTextEditor::Property::ELLIPSIS, true ); + editor.SetProperty( DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::END ); + editor.SetProperty( TextEditor::Property::TEXT, "line1 \nline2\nline 3\nline4" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 2; + unsigned int startIndex = 0; + unsigned int endIndex = 24; + + Vector positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex); + Vector sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(-1, 0)); + expectedSizes.PushBack(Vector2(59, 25)); + + expectedPositions.PushBack(Vector2(-1, 25)); + expectedSizes.PushBack(Vector2(25, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + +int utcDaliTextEditorGeometryRTL(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextEditorGeometryRTL"); + + TextEditor editor = TextEditor::New(); + DALI_TEST_CHECK( editor ); + + application.GetScene().Add( editor ); + + editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f ); + editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) ); + editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true ); + editor.SetProperty( TextEditor::Property::TEXT, "line1 \nline2\nline 3\nالاخيرالسطر" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 4; + unsigned int startIndex = 3; + unsigned int endIndex = 24; + + Vector positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex); + Vector sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(24, 0)); + expectedSizes.PushBack(Vector2(33, 25)); + + expectedPositions.PushBack(Vector2(-1, 25)); + expectedSizes.PushBack(Vector2(52, 25)); + + expectedPositions.PushBack(Vector2(-1, 50)); + expectedSizes.PushBack(Vector2(59, 25)); + + expectedPositions.PushBack(Vector2(61, 75)); + expectedSizes.PushBack(Vector2(37, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + +int utcDaliTextEditorGeometryGlyphMiddle(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextEditorGeometryGlyphMiddle"); + + TextEditor editor = TextEditor::New(); + DALI_TEST_CHECK( editor ); + + application.GetScene().Add( editor ); + + editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f ); + editor.SetProperty( Actor::Property::SIZE, Vector2( 150.f, 200.f ) ); + editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true ); + editor.SetProperty( TextEditor::Property::TEXT, "لا تحتوي على لا" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 1; + unsigned int startIndex = 1; + unsigned int endIndex = 13; + + Vector positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex); + Vector sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(6, 0)); + expectedSizes.PushBack(Vector2(124, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + int utcDaliTextEditorSelectionClearedSignal(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index e8bf4b6..d1a04e9 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -31,6 +31,7 @@ #include #include "toolkit-clipboard.h" #include +#include "test-text-geometry-utils.h" using namespace Dali; using namespace Toolkit; @@ -4391,6 +4392,190 @@ int utcDaliTextFieldCursorPositionChangedSignal(void) END_TEST; } +int utcDaliTextFieldGeometryEllipsisStart(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldGeometryEllipsisStart"); + + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + application.GetScene().Add( field ); + + field.SetProperty( TextField::Property::POINT_SIZE, 7.f ); + field.SetProperty( Actor::Property::SIZE, Vector2( 250.f, 50.f ) ); + field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + field.SetProperty( TextField::Property::ENABLE_MARKUP, true ); + field.SetProperty( DevelTextField::Property::ELLIPSIS, true ); + field.SetProperty( DevelTextField::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::START ); + field.SetProperty( TextField::Property::TEXT, "Hello World" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 1; + unsigned int startIndex = 0; + unsigned int endIndex = 10; + + Vector positionsList = DevelTextField::GetTextPosition(field, startIndex, endIndex); + Vector sizeList = DevelTextField::GetTextSize(field, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(14, 0)); + expectedSizes.PushBack(Vector2(106, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + +int utcDaliTextFieldGeometryEllipsisEnd(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldGeometryEllipsisEnd"); + + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + application.GetScene().Add( field ); + + field.SetProperty( TextField::Property::POINT_SIZE, 7.f ); + field.SetProperty( Actor::Property::SIZE, Vector2( 250.f, 50.f ) ); + field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + field.SetProperty( TextField::Property::ENABLE_MARKUP, true ); + field.SetProperty( DevelTextField::Property::ELLIPSIS, true ); + field.SetProperty( DevelTextField::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::END ); + field.SetProperty( TextField::Property::TEXT, "Hello World" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 1; + unsigned int startIndex = 0; + unsigned int endIndex = 10; + + Vector positionsList = DevelTextField::GetTextPosition(field, startIndex, endIndex); + Vector sizeList = DevelTextField::GetTextSize(field, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(-2, 0)); + expectedSizes.PushBack(Vector2(122, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + +int utcDaliTextFieldGeometryRTL(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldGeometryRTL"); + + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + application.GetScene().Add( field ); + + field.SetProperty( TextField::Property::POINT_SIZE, 7.f ); + field.SetProperty( Actor::Property::SIZE, Vector2( 300.f, 50.f ) ); + field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + field.SetProperty( TextField::Property::ENABLE_MARKUP, true ); + field.SetProperty( TextField::Property::TEXT, "السطر الاخير" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 1; + unsigned int startIndex = 1; + unsigned int endIndex = 7; + + Vector positionsList = DevelTextField::GetTextPosition(field, startIndex, endIndex); + Vector sizeList = DevelTextField::GetTextSize(field, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(38, 0)); + expectedSizes.PushBack(Vector2(73, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + +int utcDaliTextFieldGeometryGlyphMiddle(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldGeometryGlyphMiddle"); + + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + application.GetScene().Add( field ); + + field.SetProperty( TextField::Property::POINT_SIZE, 7.f ); + field.SetProperty( Actor::Property::SIZE, Vector2( 150.f, 200.f ) ); + field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + field.SetProperty( TextField::Property::ENABLE_MARKUP, true ); + field.SetProperty( TextField::Property::TEXT, "لا تحتوي على لا" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 1; + unsigned int startIndex = 1; + unsigned int endIndex = 13; + + Vector positionsList = DevelTextField::GetTextPosition(field, startIndex, endIndex); + Vector sizeList = DevelTextField::GetTextSize(field, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(6, 0)); + expectedSizes.PushBack(Vector2(124, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + int utcDaliTextFieldSelectionClearedSignal(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index b0f9764..c060743 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -30,6 +30,7 @@ #include #include #include +#include "test-text-geometry-utils.h" using namespace Dali; using namespace Toolkit; @@ -2017,6 +2018,106 @@ int utcDaliTextLabelGetHeightForWidthChangeLineCountWhenTextChanged(void) END_TEST; } +int utcDaliTextLabelGeometryRTL(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextLabelGeometryRTL"); + + TextLabel label = TextLabel::New(); + DALI_TEST_CHECK( label ); + + application.GetScene().Add( label ); + + label.SetProperty( TextLabel::Property::POINT_SIZE, 7.f ); + label.SetProperty( Actor::Property::SIZE, Vector2( 150.f, 100.f ) ); + label.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + label.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + label.SetProperty( TextLabel::Property::ENABLE_MARKUP, true ); + label.SetProperty( TextLabel::Property::MULTI_LINE, true); + label.SetProperty( TextLabel::Property::TEXT, "line1 \nline2\nline 3\nالاخيرالسطر" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 4; + unsigned int startIndex = 3; + unsigned int endIndex = 24; + + Vector positionsList = DevelTextLabel::GetTextPosition(label, startIndex, endIndex); + Vector sizeList = DevelTextLabel::GetTextSize(label, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(24, 0)); + expectedSizes.PushBack(Vector2(33, 25)); + + expectedPositions.PushBack(Vector2(-1, 25)); + expectedSizes.PushBack(Vector2(52, 25)); + + expectedPositions.PushBack(Vector2(-1, 50)); + expectedSizes.PushBack(Vector2(59, 25)); + + expectedPositions.PushBack(Vector2(73, 75)); + expectedSizes.PushBack(Vector2(37, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + +int utcDaliTextLabelGeometryGlyphMiddle(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextLabelGeometryGlyphMiddle"); + + TextLabel label = TextLabel::New(); + DALI_TEST_CHECK( label ); + + application.GetScene().Add( label ); + + label.SetProperty( TextLabel::Property::POINT_SIZE, 7.f ); + label.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + label.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + label.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + label.SetProperty( TextLabel::Property::ENABLE_MARKUP, true ); + label.SetProperty( TextLabel::Property::TEXT, "لا تحتوي على لا" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + unsigned int expectedCount = 1; + unsigned int startIndex = 1; + unsigned int endIndex = 13; + + Vector positionsList = DevelTextLabel::GetTextPosition(label, startIndex, endIndex); + Vector sizeList = DevelTextLabel::GetTextSize(label, startIndex, endIndex); + + DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION); + DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION); + + Vector expectedSizes; + Vector expectedPositions; + + expectedPositions.PushBack(Vector2(12, 0)); + expectedSizes.PushBack(Vector2(118, 25)); + + TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes); + + END_TEST; +} + int UtcDaliToolkitTextlabelEllipsisPositionProperty(void) { ToolkitTestApplication application; diff --git a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp index f3f073b..a7b4ae4 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp @@ -80,6 +80,16 @@ void ScrollBy(TextEditor textEditor, Vector2 scroll) GetImpl(textEditor).ScrollBy(scroll); } +Vector GetTextSize(TextEditor textEditor, const uint32_t startIndex, const uint32_t endIndex) +{ + return GetImpl(textEditor).GetTextSize(startIndex, endIndex); +} + +Vector GetTextPosition(TextEditor textEditor, const uint32_t startIndex, const uint32_t endIndex) +{ + return GetImpl(textEditor).GetTextPosition(startIndex, endIndex); +} + string CopyText(TextEditor textEditor) { return GetImpl(textEditor).CopyText(); diff --git a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h index 177be64..74c19df 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h @@ -451,6 +451,30 @@ DALI_TOOLKIT_API void SelectText(TextEditor textEditor, const uint32_t start, co DALI_TOOLKIT_API void ScrollBy(TextEditor textEditor, Vector2 scroll); /** + * @brief Get the rendered size of a specific text range. + * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction. + * + * @param[in] textEditor The instance of TextEditor. + * @param[in] startIndex start index of the text requested to calculate size for. + * @param[in] endIndex end index(included) of the text requested to calculate size for. + * @return list of sizes of the reuested text. + */ +DALI_TOOLKIT_API Vector GetTextSize(TextEditor textEditor, const uint32_t startIndex, const uint32_t endIndex); + +/** + * @brief Get the top/left rendered position of a specific text range. + * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction. + * + * @param[in] textEditor The instance of TextEditor. + * @param[in] startIndex start index of the text requested to get position to. + * @param[in] endIndex end index(included) of the text requested to get position to. + * @return list of positions of the requested text. + */ +DALI_TOOLKIT_API Vector GetTextPosition(TextEditor textEditor, const uint32_t startIndex, const uint32_t endIndex); + +/** * @brief Copy and return the selected text of TextEditor. * * @param[in] textEditor The instance of TextEditor. diff --git a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp index e5abdfa..fce7819 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp @@ -70,6 +70,16 @@ void SelectText(TextField textField, const uint32_t start, const uint32_t end) GetImpl(textField).SelectText(start, end); } +Vector GetTextSize(TextField textField, const uint32_t startIndex, const uint32_t endIndex) +{ + return GetImpl(textField).GetTextSize(startIndex, endIndex); +} + +Vector GetTextPosition(TextField textField, const uint32_t startIndex, const uint32_t endIndex) +{ + return GetImpl(textField).GetTextPosition(startIndex, endIndex); +} + string CopyText(TextField textField) { return GetImpl(textField).CopyText(); diff --git a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h index 10d79e8..7498110 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h @@ -336,6 +336,30 @@ using SelectionClearedSignalType = Signal; DALI_TOOLKIT_API SelectionClearedSignalType& SelectionClearedSignal(TextField textField); /** + * @brief Get the rendered size of a specific text range. + * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction. + * + * @param[in] textField The instance of TextField. + * @param[in] startIndex start index of the text requested to calculate size for. + * @param[in] endIndex end index(included) of the text requested to calculate size for. + * @return list of sizes of the reuested text. + */ +DALI_TOOLKIT_API Vector GetTextSize(TextField textField, const uint32_t startIndex, const uint32_t endIndex); + +/** + * @brief Get the top/left rendered position of a specific text range. + * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction. + * + * @param[in] textField The instance of TextField. + * @param[in] startIndex start index of the text requested to get position to. + * @param[in] endIndex end index(included) of the text requested to get position to. + * @return list of positions of the requested text. + */ +DALI_TOOLKIT_API Vector GetTextPosition(TextField textField, const uint32_t startIndex, const uint32_t endIndex); + +/** * @brief Select the whole text of TextField. * * @param[in] textField The instance of TextField. diff --git a/dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp b/dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp index c117152..5e6bc02 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-label-devel.cpp @@ -35,6 +35,16 @@ TextFitChangedSignalType& TextFitChangedSignal(TextLabel textLabel) return GetImpl(textLabel).TextFitChangedSignal(); } +Vector GetTextSize(TextLabel textLabel, const uint32_t startIndex, const uint32_t endIndex) +{ + return GetImpl(textLabel).GetTextSize(startIndex, endIndex); +} + +Vector GetTextPosition(TextLabel textLabel, const uint32_t startIndex, const uint32_t endIndex) +{ + return GetImpl(textLabel).GetTextPosition(startIndex, endIndex); +} + } // namespace DevelTextLabel } // namespace Toolkit diff --git a/dali-toolkit/devel-api/controls/text-controls/text-label-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-label-devel.h index 6bcbdd0..17a808f 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-label-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-label-devel.h @@ -167,6 +167,30 @@ enum Type } // namespace Property /** + * @brief Get the rendered size of a specific text range. + * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction. + * + * @param[in] textLabel The instance of TextLabel. + * @param[in] startIndex start index of the text requested to calculate size for. + * @param[in] endIndex end index(included) of the text requested to calculate size for. + * @return list of sizes of the reuested text. + */ +DALI_TOOLKIT_API Vector GetTextSize(TextLabel textLabel, const uint32_t startIndex, const uint32_t endIndex); + +/** + * @brief Get the top/left rendered position of a specific text range. + * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction. + * + * @param[in] textLabel The instance of TextLabel. + * @param[in] startIndex start index of the text requested to get position to. + * @param[in] endIndex end index(included) of the text requested to get position to. + * @return list of positions of the requested text. + */ +DALI_TOOLKIT_API Vector GetTextPosition(TextLabel textLabel, const uint32_t startIndex, const uint32_t endIndex); + +/** * @brief Anchor clicked signal type. * * @note Signal 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 44c1176..5e9e7d9 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -341,6 +341,16 @@ float TextEditor::GetVerticalScrollPosition() return 0; } +Vector TextEditor::GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const +{ + return mController->GetTextSize(startIndex, endIndex); +} + +Vector TextEditor::GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const +{ + return mController->GetTextPosition(startIndex, endIndex); +} + string TextEditor::GetSelectedText() const { string selectedText = ""; 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 e4b5fa5..9d41735 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -317,6 +317,28 @@ public: float GetVerticalScrollPosition(); /** + * @brief Get the rendered size of a specific text range. + * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction. + * + * @param[in] startIndex start index of the text requested to calculate size for. + * @param[in] endIndex end index(included) of the text requested to calculate size for. + * @return list of sizes of the reuested text. + */ + Vector GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const; + + /** + * @brief Get the top/left rendered position of a specific text range. + * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction. + * + * @param[in] startIndex start index of the text requested to get position to. + * @param[in] endIndex end index(included) of the text requested to get position to. + * @return list of positions of the requested text. + */ + Vector GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const; + + /** * @copydoc Text::SelectableControlInterface::GetSelectedText() */ string GetSelectedText() const override; diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index 2f4ef60..9cefc6c 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -204,8 +204,8 @@ Toolkit::TextField::InputStyle::Mask ConvertInputStyle(Text::InputStyle::Mask in bool IsHiddenInput(Toolkit::TextField textField) { Property::Map hiddenInputSettings = textField.GetProperty(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS); - auto mode = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE); - if (mode && (mode->Get() != Toolkit::HiddenInput::Mode::HIDE_NONE)) + auto mode = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE); + if(mode && (mode->Get() != Toolkit::HiddenInput::Mode::HIDE_NONE)) { return true; } @@ -215,8 +215,8 @@ bool IsHiddenInput(Toolkit::TextField textField) char GetSubstituteCharacter(Toolkit::TextField textField) { Property::Map hiddenInputSettings = textField.GetProperty(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS); - auto substChar = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER); - if (substChar) + auto substChar = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER); + if(substChar) { return static_cast(substChar->Get()); } @@ -1128,10 +1128,20 @@ TextField::~TextField() } } +Vector TextField::GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const +{ + return mController->GetTextSize(startIndex, endIndex); +} + +Vector TextField::GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const +{ + return mController->GetTextPosition(startIndex, endIndex); +} + std::string TextField::AccessibleImpl::GetName() { auto self = Toolkit::TextField::DownCast(Self()); - if (IsHiddenInput(self)) + if(IsHiddenInput(self)) { return {}; } @@ -1193,8 +1203,8 @@ bool TextField::AccessibleImpl::SetCursorOffset(size_t offset) Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset( size_t offset, Dali::Accessibility::TextBoundary boundary) { - auto self = Toolkit::TextField::DownCast(Self()); - auto range = Dali::Accessibility::Range{}; + auto self = Toolkit::TextField::DownCast(Self()); + auto range = Dali::Accessibility::Range{}; if(IsHiddenInput(self)) { @@ -1297,14 +1307,14 @@ Dali::Accessibility::Range TextField::AccessibleImpl::GetRangeOfSelection(size_t return {}; } - auto self = Toolkit::TextField::DownCast(Self()); + auto self = Toolkit::TextField::DownCast(Self()); auto controller = Dali::Toolkit::GetImpl(self).GetTextController(); - auto indices = controller->GetSelectionIndexes(); + auto indices = controller->GetSelectionIndexes(); auto startOffset = static_cast(indices.first); - auto endOffset = static_cast(indices.second); + auto endOffset = static_cast(indices.second); - if (IsHiddenInput(self)) + if(IsHiddenInput(self)) { return {startOffset, endOffset, std::string(endOffset - startOffset, GetSubstituteCharacter(self))}; } diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h index 7e18a82..1f97263 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -325,6 +325,28 @@ public: */ void AnchorClicked(const std::string& href) override; + /** + * @brief Get the rendered size of a specific text range. + * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction. + * + * @param[in] startIndex start index of the text requested to calculate size for. + * @param[in] endIndex end index(included) of the text requested to calculate size for. + * @return list of sizes of the reuested text. + */ + Vector GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const; + + /** + * @brief Get the top/left rendered position of a specific text range. + * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction. + * + * @param[in] startIndex start index of the text requested to get position to. + * @param[in] endIndex end index(included) of the text requested to get position to. + * @return list of positions of the requested text. + */ + Vector GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const; + private: // Implementation /** * @copydoc Dali::Toolkit::Text::Controller::(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent) diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index 22990d9..9e15b34 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -30,6 +30,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -37,7 +38,6 @@ #include #include #include -#include #include #include @@ -729,10 +729,10 @@ Property::Value TextLabel::GetProperty(BaseObject* object, Property::Index index } case Toolkit::DevelTextLabel::Property::TEXT_FIT: { - const bool enabled = impl.mController->IsTextFitEnabled(); - const float minSize = impl.mController->GetTextFitMinSize(); - const float maxSize = impl.mController->GetTextFitMaxSize(); - const float stepSize = impl.mController->GetTextFitStepSize(); + const bool enabled = impl.mController->IsTextFitEnabled(); + const float minSize = impl.mController->GetTextFitMinSize(); + const float maxSize = impl.mController->GetTextFitMaxSize(); + const float stepSize = impl.mController->GetTextFitStepSize(); const float pointSize = impl.mController->GetTextFitPointSize(); Property::Map map; @@ -1136,6 +1136,16 @@ TextLabel::~TextLabel() { } +Vector TextLabel::GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const +{ + return mController->GetTextSize(startIndex, endIndex); +} + +Vector TextLabel::GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const +{ + return mController->GetTextPosition(startIndex, endIndex); +} + std::string TextLabel::AccessibleImpl::GetNameRaw() { auto self = Toolkit::TextLabel::DownCast(Self()); diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.h b/dali-toolkit/internal/controls/text-controls/text-label-impl.h index 5c9a6b1..d776c32 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -98,6 +98,28 @@ public: */ Text::ControllerPtr GetTextController(); + /** + * @brief Get the rendered size of a specific text range. + * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction. + * + * @param[in] startIndex start index of the text requested to calculate size for. + * @param[in] endIndex end index(included) of the text requested to calculate size for. + * @return list of sizes of the reuested text. + */ + Vector GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const; + + /** + * @brief Get the top/left rendered position of a specific text range. + * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction. + * + * @param[in] startIndex start index of the text requested to get position to. + * @param[in] endIndex end index(included) of the text requested to get position to. + * @return list of positions of the requested text. + */ + Vector GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const; + private: // From Control /** * @copydoc Control::OnInitialize() @@ -209,7 +231,7 @@ private: // Data std::vector mAnchorActors; // Signals - Toolkit::DevelTextLabel::AnchorClickedSignalType mAnchorClickedSignal; + Toolkit::DevelTextLabel::AnchorClickedSignalType mAnchorClickedSignal; Toolkit::DevelTextLabel::TextFitChangedSignalType mTextFitChangedSignal; int mRenderingBackend; diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 8438261..0ad41cd 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -208,6 +208,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/xhtml-entities.cpp ${toolkit_src_dir}/drag-drop-detector/drag-and-drop-detector-impl.cpp ${toolkit_src_dir}/text/emoji-helper.cpp + ${toolkit_src_dir}/text/text-geometry.cpp ) SET( SOURCES ${SOURCES} diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 757d54a..be985d1 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -37,6 +37,7 @@ #include #include #include +#include namespace { @@ -116,7 +117,6 @@ void UpdateCursorPosition(Dali::Toolkit::Text::EventData* eventData) namespace Dali::Toolkit::Text { - void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext) { if(!decorator) @@ -1234,6 +1234,24 @@ void Controller::RequestRelayout() mImpl->RequestRelayout(); } +Vector Controller::GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex) +{ + Vector sizesList; + Vector positionsList; + + GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList); + return sizesList; +} + +Vector Controller::GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex) +{ + Vector sizesList; + Vector positionsList; + + GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList); + return positionsList; +} + bool Controller::IsInputStyleChangedSignalsQueueEmpty() { return mImpl->IsInputStyleChangedSignalsQueueEmpty(); diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index a582110..b16186b 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -23,9 +23,9 @@ #include // INTERNAL INCLUDES +#include #include #include -#include #include #include #include @@ -1516,6 +1516,28 @@ public: // Queries & retrieves. Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const; /** + * @brief Get the rendered size of a specific text range. + * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction. + * + * @param[in] startIndex start index of the text requested to calculate size for. + * @param[in] endIndex end index(included) of the text requested to calculate size for. + * @return list of sizes of the reuested text. + */ + Vector GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex); + + /** + * @brief Get the top/left rendered position of a specific text range. + * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction. + * + * @param[in] startIndex start index of the text requested to get position to. + * @param[in] endIndex end index(included) of the text requested to get position to. + * @return list of positions of the requested text. + */ + Vector GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex); + + /** * @brief Sets the layout direction changed. */ void ChangedLayoutDirection(); diff --git a/dali-toolkit/internal/text/text-geometry.cpp b/dali-toolkit/internal/text/text-geometry.cpp new file mode 100644 index 0000000..e599922 --- /dev/null +++ b/dali-toolkit/internal/text/text-geometry.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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +using namespace Dali; + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, GlyphIndex& lastGlyphOfLine, Length numberOfLines) +{ + if(index == lastGlyphOfLine) + { + ++lineIndex; + if(lineIndex < numberOfLines) + { + ++lineRun; + return true; + } + } + + return false; +} + +void UpdateLineInfo(const LineRun* lineRun, float& currentLineOffset, float& currentLineHeight, GlyphIndex& lastGlyphOfLine) +{ + lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u; + currentLineOffset = currentLineOffset + currentLineHeight; + currentLineHeight = GetLineHeight(*lineRun); +} + +void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterIndex endIndex, Vector& sizesList, Vector& positionsList) +{ + VisualModelPtr& visualModel = textModel->mVisualModel; + LogicalModelPtr& logicalModel = textModel->mLogicalModel; + + const GlyphIndex* const charactersToGlyphBuffer = visualModel->mCharactersToGlyph.Begin(); + const Length* const glyphsPerCharacterBuffer = visualModel->mGlyphsPerCharacter.Begin(); + const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); + const Vector2* const positionsBuffer = visualModel->mGlyphPositions.Begin(); + const Length* const charactersPerGlyphBuffer = visualModel->mCharactersPerGlyph.Begin(); + const CharacterIndex* const glyphToCharacterBuffer = visualModel->mGlyphsToCharacters.Begin(); + const CharacterDirection* const modelCharacterDirectionsBuffer = (0u != logicalModel->mCharacterDirections.Count()) ? logicalModel->mCharacterDirections.Begin() : NULL; + + if((startIndex < 0 && endIndex < 0) || (startIndex >= logicalModel->mText.Count() && endIndex >= logicalModel->mText.Count())) + return; + + if(startIndex < 0) + startIndex = 0; + + if(endIndex < 0) + endIndex = 0; + + if(startIndex >= logicalModel->mText.Count()) + startIndex = logicalModel->mText.Count() - 1; + + if(endIndex >= logicalModel->mText.Count()) + endIndex = logicalModel->mText.Count() - 1; + + if(startIndex > endIndex) + { + std::swap(startIndex, endIndex); + } + + LineRun* lineRun = visualModel->mLines.Begin(); + GlyphIndex glyphStart = *(charactersToGlyphBuffer + startIndex); + + //if glyph not in the first line (in some ellipsis cases) + if(glyphStart < lineRun->glyphRun.glyphIndex) + { + glyphStart = lineRun->glyphRun.glyphIndex; + startIndex = *(glyphToCharacterBuffer + glyphStart); + + if(startIndex > endIndex) + { + std::swap(startIndex, endIndex); + } + } + + const Length numberOfGlyphs = *(glyphsPerCharacterBuffer + endIndex); + GlyphIndex glyphEnd = *(charactersToGlyphBuffer + endIndex) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u); + LineIndex lineIndex = visualModel->GetLineOfCharacter(startIndex); + Length numberOfLines = visualModel->GetTotalNumberOfLines(); + + LineIndex firstLineIndex = lineIndex; + Size textInLineSize; + Vector2 textInLinePosition; + + lineRun += firstLineIndex; + + //get the first line and its vertical offset + float currentLineOffset = CalculateLineOffset(visualModel->mLines, firstLineIndex); + float currentLineHeight = GetLineHeight(*lineRun); + GlyphIndex lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1; + + // Check if the first/last glyph is a ligature that needs be splitted like English fi or Arabic ﻻ. + const Length numberOfCharactersStart = *(charactersPerGlyphBuffer + glyphStart); + const Length numberOfCharactersEnd = *(charactersPerGlyphBuffer + glyphEnd); + + bool splitStartGlyph = (numberOfCharactersStart > 1u) && HasLigatureMustBreak(logicalModel->GetScript(startIndex)); + bool splitEndGlyph = (glyphStart != glyphEnd) && (numberOfCharactersEnd > 1u) && HasLigatureMustBreak(logicalModel->GetScript(endIndex)); + + Vector2 currentSize; + Vector2 currentPosition; + Vector2 blockSize; + Vector2 blockPos; + CharacterDirection isCurrentRightToLeft; + + CharacterDirection isPrevoiusRightToLeft = (nullptr != modelCharacterDirectionsBuffer ? *(modelCharacterDirectionsBuffer + startIndex) : false); + const bool isEllipsisEnabled = textModel->mElideEnabled; + const GlyphIndex startIndexOfGlyphs = textModel->GetStartIndexOfElidedGlyphs(); + const GlyphIndex endIndexOfGlyphs = textModel->GetEndIndexOfElidedGlyphs(); + const GlyphIndex firstMiddleIndexOfElidedGlyphs = textModel->GetFirstMiddleIndexOfElidedGlyphs(); + const GlyphIndex secondMiddleIndexOfElidedGlyphs = textModel->GetSecondMiddleIndexOfElidedGlyphs(); + const DevelText::EllipsisPosition::Type ellipsisPosition = textModel->GetEllipsisPosition(); + + for(GlyphIndex index = glyphStart; index <= glyphEnd; ++index) + { + if(isEllipsisEnabled) + { + if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE) + { + if(index >= firstMiddleIndexOfElidedGlyphs && + index < secondMiddleIndexOfElidedGlyphs) + { + if((index - 1 == firstMiddleIndexOfElidedGlyphs) && (firstMiddleIndexOfElidedGlyphs != 0)) + { + sizesList.PushBack(blockSize); + positionsList.PushBack(blockPos); + } + + if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines)) + { + UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine); + } + // Ignore any glyph that was removed + continue; + } + } + else + { + if((ellipsisPosition == DevelText::EllipsisPosition::END) && (index >= endIndexOfGlyphs)) + { + //skip remaining elided glyphs + break; + } + else if((ellipsisPosition == DevelText::EllipsisPosition::START) && (index <= startIndexOfGlyphs)) + { + if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines)) + { + UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine); + } + + continue; + } + } + } + + const GlyphInfo& glyph = *(glyphsBuffer + index); + const Vector2& position = *(positionsBuffer + index); + + // If NULL, means all of the characters is left to right. + isCurrentRightToLeft = (nullptr != modelCharacterDirectionsBuffer ? *(modelCharacterDirectionsBuffer + *(glyphToCharacterBuffer + index)) : false); + + if(splitStartGlyph && (index == glyphStart)) + { + // If the first glyph is a ligature that needs to be splitted, we may need only to add part of the glyph. + const float glyphAdvance = glyph.advance / static_cast(numberOfCharactersStart); + const CharacterIndex interGlyphIndex = startIndex - *(glyphToCharacterBuffer + glyphStart); + const Length numberOfCharacters = (glyphStart == glyphEnd) ? (endIndex - startIndex) + 1 : (numberOfCharactersStart - interGlyphIndex); + + currentPosition.x = lineRun->alignmentOffset + position.x - glyph.xBearing + textModel->mScrollPosition.x + glyphAdvance * static_cast(isCurrentRightToLeft ? (numberOfCharactersStart - interGlyphIndex - numberOfCharacters) : interGlyphIndex); + currentPosition.y = currentLineOffset + textModel->mScrollPosition.y; + currentSize.x = static_cast(numberOfCharacters) * glyphAdvance; + currentSize.y = currentLineHeight; + splitStartGlyph = false; + } + else if(splitEndGlyph && (index == glyphEnd)) + { + const float glyphAdvance = glyph.advance / static_cast(numberOfCharactersEnd); + const CharacterIndex interGlyphIndex = endIndex - *(glyphToCharacterBuffer + glyphEnd); + const Length numberOfCharacters = numberOfCharactersEnd - interGlyphIndex - 1; + + currentPosition.x = lineRun->alignmentOffset + position.x - glyph.xBearing + textModel->mScrollPosition.x + (isCurrentRightToLeft ? (glyphAdvance * static_cast(numberOfCharacters)) : 0.f); + currentPosition.y = currentLineOffset + textModel->mScrollPosition.y; + currentSize.x = static_cast(interGlyphIndex + 1) * glyphAdvance; + currentSize.y = currentLineHeight; + splitEndGlyph = false; + } + else + { + currentPosition.x = lineRun->alignmentOffset + position.x - glyph.xBearing + textModel->mScrollPosition.x; + currentPosition.y = currentLineOffset + textModel->mScrollPosition.y; + currentSize.x = glyph.advance; + currentSize.y = currentLineHeight; + + // if there is next line to retrieve. + if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines)) + { + UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine); + } + } + + if((index == glyphStart) || (isEllipsisEnabled && (((ellipsisPosition == DevelText::EllipsisPosition::MIDDLE) && (index == secondMiddleIndexOfElidedGlyphs)) || ((ellipsisPosition == DevelText::EllipsisPosition::START) && (index - 1 == startIndexOfGlyphs))))) + { + blockPos = currentPosition; + blockSize = currentSize; + } + else if((isPrevoiusRightToLeft != isCurrentRightToLeft) || (blockPos.y != currentPosition.y)) //new direction or new line + { + sizesList.PushBack(blockSize); + positionsList.PushBack(blockPos); + + blockPos = currentPosition; + blockSize = currentSize; + } + else + { + if(isCurrentRightToLeft) + { + blockPos.x -= currentSize.x; + } + + blockSize.x += currentSize.x; + } + + isPrevoiusRightToLeft = isCurrentRightToLeft; + } + + //add last block + sizesList.PushBack(blockSize); + positionsList.PushBack(blockPos); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-geometry.h b/dali-toolkit/internal/text/text-geometry.h new file mode 100644 index 0000000..fb118f0 --- /dev/null +++ b/dali-toolkit/internal/text/text-geometry.h @@ -0,0 +1,49 @@ +#ifndef DALI_TOOLKIT_TEXT_GEOMETRY_H +#define DALI_TOOLKIT_TEXT_GEOMETRY_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 + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Get the rendered size & position of a specific text range. + * if the requested text is at multilines, multiple sizes/positions will be returned for each text located in a separate line. + * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction. + * + * @param[in] textModel text model containing text info. + * @param[in] startIndex start index of the text requested to get position/size for. + * @param[in] endIndex end index(included) of the text requested to get position/size for. + * @param[in] sizesList list of sizes for the reuested text. + * @param[in] positionsList list of positions for the requested text + */ +void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterIndex endIndex, Vector& sizesList, Vector& positionsList); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_GEOMETRY_H diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index 5fa3843..9c57494 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -204,6 +204,11 @@ void VisualModel::GetGlyphPositions(Vector2* glyphPositions, memcpy(glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof(Vector2)); } +Length VisualModel::GetTotalNumberOfLines() const +{ + return mLines.Size(); +} + void VisualModel::GetNumberOfLines(GlyphIndex glyphIndex, Length numberOfGlyphs, LineIndex& firstLine, diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index 359b695..ac9b12d 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -120,6 +120,13 @@ public: // Line interface. /** + * @brief Retrieves the total number of lines. + * + * @return The number of lines. + */ + Length GetTotalNumberOfLines() const; + + /** * @brief Retrieves the number of lines and the index to the first line where the given range of glyphs is laid out. * * @param[in] glyphIndex Index to the first glyph.