From: Shinwoo Kim Date: Mon, 28 Feb 2022 07:52:13 +0000 (+0900) Subject: [AT-SPI] text: add "GetRangeExtents" interface X-Git-Tag: dali_2.1.13~5^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=8cf6ed1255128c422ebe51a090cb3df76c1e05d9 [AT-SPI] text: add "GetRangeExtents" interface This interface will be used for getting MBR(Minimum Bounding Rectangle) with following usage on the AT client side. cc = atspi_text_get_character_count(text, NULL); rect = atspi_text_get_range_extents(text, 0, cc, ATSPI_COORD_TYPE_WINDOW, NULL); Change-Id: Ib8c91c56f44de5fda65fc2bc28c363601b6afccb --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Text.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Text.cpp index ab7f8bf..073138a 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Text.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Text.cpp @@ -199,6 +199,59 @@ int utcDaliAccessibilityTextEditorRemoveSelection(void) END_TEST; } +int utcDaliAccessibilityTextEditorGetRangeExtents(void) +{ + ToolkitTestApplication application; + + auto editor = Dali::Toolkit::TextEditor::New(); + auto q = Dali::Accessibility::Accessible::Get( editor ); + auto x = dynamic_cast< Dali::Accessibility::Text* >( q ); + DALI_TEST_CHECK( x ); + + if( x ) + { + auto rangeExtents = x->GetRangeExtents( 0, 0, Dali::Accessibility::CoordinateType::WINDOW ); + DALI_TEST_EQUALS( (int)rangeExtents.x, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.y, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.width, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.height, 0, TEST_LOCATION ); + + application.GetScene().Add( editor ); + + editor.SetProperty( Toolkit::TextEditor::Property::POINT_SIZE, 7.f ); + editor.SetProperty( Actor::Property::SIZE, Vector2(200.f, 200.f) ); + editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + editor.SetProperty( Toolkit::TextEditor::Property::TEXT, "text editor test sentence" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); + + // Render and notify + application.SendNotification(); + application.Render(); + + auto characterCount = x->GetCharacterCount(); + rangeExtents = x->GetRangeExtents( 0, characterCount, Dali::Accessibility::CoordinateType::WINDOW ); + + Vector positionList = Toolkit::DevelTextEditor::GetTextPosition(editor, 0, characterCount); + Vector sizeList = Toolkit::DevelTextEditor::GetTextSize(editor, 0, characterCount); + + DALI_TEST_EQUALS(positionList.Size() == sizeList.Size(), true, TEST_LOCATION); + + unsigned int sizeListSize = sizeList.Size(); + for(unsigned int i = 0; i < sizeListSize; i++) + { + DALI_TEST_EQUALS((int)positionList[i].x >= rangeExtents.x, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)positionList[i].y >= rangeExtents.y, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)sizeList[i].x <= rangeExtents.width, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)sizeList[i].y <= rangeExtents.height, true, TEST_LOCATION); + } + } + + END_TEST; +} + int utcDaliAccessibilityTextFieldGetName(void) { ToolkitTestApplication application; @@ -390,6 +443,59 @@ int utcDaliAccessibilityTextFieldRemoveSelection(void) END_TEST; } +int utcDaliAccessibilityTextFieldGetRangeExtents(void) +{ + ToolkitTestApplication application; + + auto field = Dali::Toolkit::TextField::New(); + auto q = Dali::Accessibility::Accessible::Get( field ); + auto x = dynamic_cast< Dali::Accessibility::Text* >( q ); + DALI_TEST_CHECK( x ); + + if( x ) + { + auto rangeExtents = x->GetRangeExtents( 0, 0, Dali::Accessibility::CoordinateType::WINDOW ); + DALI_TEST_EQUALS( (int)rangeExtents.x, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.y, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.width, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.height, 0, TEST_LOCATION ); + + application.GetScene().Add( field ); + + field.SetProperty( Toolkit::TextField::Property::POINT_SIZE, 7.f ); + field.SetProperty( Actor::Property::SIZE, Vector2(200.f, 200.f) ); + field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + field.SetProperty( Toolkit::TextField::Property::TEXT, "text field test sentence" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); + + // Render and notify + application.SendNotification(); + application.Render(); + + auto characterCount = x->GetCharacterCount(); + rangeExtents = x->GetRangeExtents( 0, characterCount, Dali::Accessibility::CoordinateType::WINDOW ); + + Vector positionList = Toolkit::DevelTextField::GetTextPosition(field, 0, characterCount); + Vector sizeList = Toolkit::DevelTextField::GetTextSize(field, 0, characterCount); + + DALI_TEST_EQUALS(positionList.Size() == sizeList.Size(), true, TEST_LOCATION); + + unsigned int sizeListSize = sizeList.Size(); + for(unsigned int i = 0; i < sizeListSize; i++) + { + DALI_TEST_EQUALS((int)positionList[i].x >= rangeExtents.x, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)positionList[i].y >= rangeExtents.y, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)sizeList[i].x <= rangeExtents.width, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)sizeList[i].y <= rangeExtents.height, true, TEST_LOCATION); + } + } + + END_TEST; +} + int utcDaliAccessibilityTextLabelGetName(void) { ToolkitTestApplication application; @@ -520,3 +626,57 @@ int utcDaliAccessibilityTextLabelRemoveSelection( void ) END_TEST; } + +int utcDaliAccessibilityTextLabelGetRangeExtents(void) +{ + ToolkitTestApplication application; + + auto label = Dali::Toolkit::TextLabel::New(); + auto q = Dali::Accessibility::Accessible::Get( label ); + auto x = dynamic_cast< Dali::Accessibility::Text* >( q ); + DALI_TEST_CHECK( x ); + + if( x ) + { + auto rangeExtents = x->GetRangeExtents( 0, 0, Dali::Accessibility::CoordinateType::WINDOW ); + DALI_TEST_EQUALS( (int)rangeExtents.x, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.y, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.width, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( (int)rangeExtents.height, 0, TEST_LOCATION ); + + application.GetScene().Add( label ); + + label.SetProperty( Toolkit::TextLabel::Property::POINT_SIZE, 7.f ); + label.SetProperty( Toolkit::TextLabel::Property::MULTI_LINE, true ); + 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( Toolkit::TextLabel::Property::TEXT, "text label\n test sentence" ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); + + // Render and notify + application.SendNotification(); + application.Render(); + + auto characterCount = x->GetCharacterCount(); + rangeExtents = x->GetRangeExtents( 0, characterCount, Dali::Accessibility::CoordinateType::WINDOW ); + + Vector positionList = Toolkit::DevelTextLabel::GetTextPosition(label, 0, characterCount); + Vector sizeList = Toolkit::DevelTextLabel::GetTextSize(label, 0, characterCount); + + DALI_TEST_EQUALS(positionList.Size() == sizeList.Size(), true, TEST_LOCATION); + + unsigned int sizeListSize = sizeList.Size(); + for(unsigned int i = 0; i < sizeListSize; i++) + { + DALI_TEST_EQUALS((int)positionList[i].x >= rangeExtents.x, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)positionList[i].y >= rangeExtents.y, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)sizeList[i].x <= rangeExtents.width, true, TEST_LOCATION); + DALI_TEST_EQUALS((int)sizeList[i].y <= rangeExtents.height, true, TEST_LOCATION); + } + } + + END_TEST; +} 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 6fc1a3d..6202c8f 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -1537,6 +1537,24 @@ bool TextEditor::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size return true; } +Rect<> TextEditor::AccessibleImpl::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) +{ + if (endOffset <= startOffset || endOffset <= 0) + { + return {0, 0, 0, 0}; + } + + auto self = Toolkit::TextEditor::DownCast(Self()); + auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1); + + auto componentExtents = this->GetExtents(type); + + rect.x += componentExtents.x; + rect.y += componentExtents.y; + + return rect; +} + bool TextEditor::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition) { if(endPosition <= startPosition) 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 a2521ed..8a96a13 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -629,6 +629,11 @@ private: // Data bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override; /** + * @copydoc Dali::Accessibility::Text::GetRangeExtents() + */ + Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) override; + + /** * @copydoc Dali::Accessibility::EditableText::CopyText() */ bool CopyText(size_t startPosition, size_t endPosition) 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 f0d6c68..35d06ea 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -1404,6 +1404,24 @@ bool TextField::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_ return true; } +Rect<> TextField::AccessibleImpl::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) +{ + if (endOffset <= startOffset || endOffset <= 0) + { + return {0, 0, 0, 0}; + } + + auto self = Toolkit::TextField::DownCast(Self()); + auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1); + + auto componentExtents = this->GetExtents(type); + + rect.x += componentExtents.x; + rect.y += componentExtents.y; + + return rect; +} + bool TextField::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition) { if(endPosition <= startPosition) 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 3ba2954..c10dd51 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -578,6 +578,11 @@ protected: bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override; /** + * @copydoc Dali::Accessibility::Text::GetRangeExtents() + */ + Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) override; + + /** * @copydoc Dali::Accessibility::EditableText::CopyText() */ bool CopyText(size_t startPosition, size_t endPosition) override; 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 10b05a0..fa9c6c0 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -1379,6 +1379,24 @@ bool TextLabel::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_ return true; } +Rect<> TextLabel::AccessibleImpl::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) +{ + if (endOffset <= startOffset || endOffset <= 0) + { + return {0, 0, 0, 0}; + } + + auto self = Toolkit::TextLabel::DownCast(Self()); + auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1); + + auto componentExtents = this->GetExtents(type); + + rect.x += componentExtents.x; + rect.y += componentExtents.y; + + return rect; +} + int32_t TextLabel::AccessibleImpl::GetLinkCount() const { 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 978ad97..9cba1c4 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -293,6 +293,11 @@ protected: bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override; /** + * @copydoc Dali::Accessibility::Text::GetRangeExtents() + */ + Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) override; + + /** * @copydoc Dali::Accessibility::Text::GetNameRaw() */ std::string GetNameRaw() const override; diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 9de7dba..b0f740d 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -1391,6 +1391,34 @@ Vector Controller::GetTextPosition(CharacterIndex startIndex, Character return positionsList; } +Rect<> Controller::GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex) +{ + Vector sizeList; + Vector positionList; + + GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizeList, positionList); + + if(sizeList.Empty() || sizeList.Size() != positionList.Size()) + { + return {0, 0, 0, 0}; + } + + auto minX = positionList[0].x; + auto minY = positionList[0].y; + auto maxRight = positionList[0].x + sizeList[0].x; + auto maxBottom = positionList[0].y + sizeList[0].y; + + for(unsigned int i = 1; i < sizeList.Size(); i++) + { + minX = std::min(minX, positionList[i].x); + minY = std::min(minY, positionList[i].y); + maxRight = std::max(maxRight, positionList[i].x + sizeList[i].x); + maxBottom = std::max(maxBottom, positionList[i].y + sizeList[i].y); + } + + return {minX, minY, maxRight - minX, maxBottom - minY}; +} + 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 2a37c3b..81a0318 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -1696,6 +1696,15 @@ public: // Queries & retrieves. Vector GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex); /** + * @brief Gets the bounding box of a specific text range. + * + * @param[in] startIndex start index of the text requested to get bounding box to. + * @param[in] endIndex end index(included) of the text requested to get bounding box to. + * @return bounding box of the requested text. + */ + Rect<> GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex); + + /** * @brief Sets the layout direction changed. */ void ChangedLayoutDirection();