From: Paul Wisbey Date: Thu, 9 Apr 2015 12:21:16 +0000 (+0100) Subject: Merge remote-tracking branch 'origin/tizen' into new_text X-Git-Tag: dali_1.0.38~11^2~2^2~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=d04c5bdbb95cc98f90848c7a98b0b2804df6e5b8;hp=56c2c6b9998a38276bd619ef7ca4e20522cf0da8 Merge remote-tracking branch 'origin/tizen' into new_text Change-Id: Iba714851799e17a461ac18d8431204835675c67b --- diff --git a/README b/README index dc7b5af..de9499c 100644 --- a/README +++ b/README @@ -23,7 +23,10 @@ T.O.C. gbs build -A [TARGET_ARCH] --define "%enable_dali_smack_rules 1" +1.3. MOBILE Profile +------------------- + gbs build -A [TARGET_ARCH] --spec dali-toolkit-mobile.spec 2. Building for Ubuntu desktop ============================== diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 029c12d..e7dc7cb 100644 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -8,10 +8,6 @@ SET(CAPI_LIB "dali-toolkit-internal") # List of test case sources (Only these get parsed for test cases) SET(TC_SOURCES utc-Dali-PushButton.cpp - utc-Dali-TextView-HelperAndDebug.cpp - utc-Dali-TextView-Processor-Types.cpp - utc-Dali-TextView-Processor.cpp - utc-Dali-TextView-Relayout-Utilities.cpp ) # Append list of test harness files (Won't get parsed for test cases) diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp index 05ced5a..8d2734b 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp @@ -713,7 +713,7 @@ int UtcDaliPushButtonProperties(void) // Button::PROPERTY_LABEL_ACTOR { button.SetLabel( "LABEL_TEXT_CUSTOM" ); - DALI_TEST_EQUALS( "TextView", button.GetProperty( Button::Property::LABEL_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION ); + DALI_TEST_EQUALS( "TextLabel", button.GetProperty( Button::Property::LABEL_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION ); Property::Map map; map[ "type" ] = "Actor"; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-HelperAndDebug.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-HelperAndDebug.cpp deleted file mode 100644 index f5e39e6..0000000 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-HelperAndDebug.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - * 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 - -#include -#include -#include - -// Internal headers are allowed here -#include -#include -#include -#include -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Internal; - -void dali_text_view_helper_and_debug_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void dali_text_view_helper_and_debug_cleanup(void) -{ - test_return_value = TET_PASS; -} - - -namespace -{ -// Data structures used to create an 'experiment' in TET cases - -const Toolkit::Internal::TextView::LayoutParameters DEFAULT_LAYOUT_PARAMETERS; -const Toolkit::Internal::TextView::VisualParameters DEFAULT_VISUAL_PARAMETERS; - -struct GetIndicesFromGlobalCharacterIndexTest -{ - std::string description; - std::string input; - std::size_t position; - std::size_t paragraphIndex; - std::size_t wordIndex; - std::size_t characterIndex; -}; - -/** - * Gets the paragraph, word, and character indices for a given text and a given position and checks the results with the given indices. - * - * If the test fails it prints a short description and the line where this function was called. - * - * @param description Short description of the experiment. - * @param input The input text. - * @param position Global position of the character. i.e in a text with with 1000 characters, position could be any value from 0 to 1000. - * @param resultParagraphIndex Index to the paragraph where the character is located. - * @param resultWordIndex Index to the word within the paragraph where the character is located. - * @param resultCharacterIndex Index to the character within the word where the character is located. - * @param location Where this function has been called. - * - * @return \e true if the experiment is successful. Otherwise returns \e false. - */ -bool TestGetIndicesFromGlobalCharacterIndex( const std::string& description, - const std::string& input, - const std::size_t position, - const std::size_t resultParagraphIndex, - const std::size_t resultWordIndex, - const std::size_t resultCharacterIndex, - const char* location ) -{ - tet_printf( "%s", description.c_str() ); - - // Create natural size, layout and text-actor info for the input word. - Toolkit::Internal::TextView::RelayoutData relayoutData; - TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo ); - - MarkupProcessor::StyledTextArray inputStyledText; - MarkupProcessor::GetStyledTextArray( input, inputStyledText, true ); - - TextViewProcessor::CreateTextInfo( inputStyledText, - DEFAULT_LAYOUT_PARAMETERS, - relayoutData ); - - TextViewProcessor::TextInfoIndices indices; - TextViewProcessor::GetIndicesFromGlobalCharacterIndex( position, - inputLayout, - indices ); - - if( indices.mParagraphIndex != resultParagraphIndex ) - { - tet_printf( "Fail. different paragraph index. %s", location ); - return false; - } - if( indices.mWordIndex != resultWordIndex ) - { - tet_printf( "Fail. different word index. %s", location ); - return false; - } - if( indices.mCharacterIndex != resultCharacterIndex ) - { - tet_printf( "Fail. different character index. %s", location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// -} // namespace - - -int UtcDaliTextViewGetIndicesFromGlobalCharacterIndex(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewGetIndicesFromGlobalCharacterIndex : "); - struct GetIndicesFromGlobalCharacterIndexTest getIndicesFromGlobalCharacterIndexTests[] = - { - { - std::string( "Test position 0" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 0, - 0, - 0, - 0 - }, - { - std::string( "Test position 76. (just after the last \\n)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 76, - 4, - 0, - 0 - }, - { - std::string( "Test position 73. (the last \\n)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 75, - 3, - 0, - 0 - }, - { - std::string( "Test position 35. (first hebrew character)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 35, - 1, - 4, - 0 - }, - { - std::string( "Test position 3. (end of the first word)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 3, - 0, - 0, - 3 - }, - { - std::string( "Test position 33. (end of the second word of the second paragraph)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 33, - 1, - 2, - 3 - }, - { - std::string( "Test position 43. (last hebrew character)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 43, - 1, - 6, - 3 - }, - }; - const std::size_t numberOfTests( 7 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const GetIndicesFromGlobalCharacterIndexTest& test = getIndicesFromGlobalCharacterIndexTests[index]; - - if( !TestGetIndicesFromGlobalCharacterIndex( test.description, test.input, test.position, test.paragraphIndex, test.wordIndex, test.characterIndex, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewDebugCouts(void) -{ - ///////////////////////////////////////////////////// - // Text debug functions to not to penalize coverage - ///////////////////////////////////////////////////// - - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewDebugCouts : "); - - Toolkit::Internal::TextView::RelayoutData relayoutData; - - MarkupProcessor::StyledTextArray inputStyledText; - MarkupProcessor::GetStyledTextArray( std::string( "Hello world\nhello world" ), inputStyledText, true ); - - TextViewProcessor::CreateTextInfo( inputStyledText, - DEFAULT_LAYOUT_PARAMETERS, - relayoutData ); - - Actor dummy = Actor::New(); - Toolkit::Internal::SplitByNewLineChar::Relayout( dummy, - Toolkit::Internal::TextView::RELAYOUT_ALL, - DEFAULT_LAYOUT_PARAMETERS, - DEFAULT_VISUAL_PARAMETERS, - relayoutData ); - - TextViewProcessor::dbgPrint( relayoutData.mTextLayoutInfo ); - - TextStyle textStyle; - TextViewProcessor::dbgPrint( textStyle ); - - TextViewProcessor::TextInfoIndices indices; - TextViewProcessor::dbgPrint( indices ); - - TextViewProcessor::dbgPrint( inputStyledText ); - - tet_result( TET_PASS ); - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor-Types.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor-Types.cpp deleted file mode 100644 index 44e25c0..0000000 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor-Types.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - * 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 -#include -#include -#include - - -// Internal headers are allowed here -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Internal; - -void dali_text_view_processor_types_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void dali_text_view_processor_types_cleanup(void) -{ - test_return_value = TET_PASS; -} - - -namespace -{ -// Data structures used to create an 'experiment' in TET cases - -////////////////////////////////////////////////////////////////// -} // namespace - - -int UtcDaliTextViewDefaultConstructorDestructor_PT(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewDefaultConstructorDestructor : "); - - TextViewProcessor::TextInfoIndices indices; - DALI_TEST_EQUALS( indices.mParagraphIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( indices.mWordIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( indices.mCharacterIndex, 0u, TEST_LOCATION ); - - TextViewProcessor::CharacterLayoutInfo characterLayoutInfo; - DALI_TEST_EQUALS( characterLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mBearing, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mPosition, Vector3::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mOffset, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mUnderlineThickness, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mUnderlinePosition, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( !characterLayoutInfo.mGlyphActor ); - DALI_TEST_EQUALS( characterLayoutInfo.mColorAlpha, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( NULL == characterLayoutInfo.mGradientInfo ); - DALI_TEST_CHECK( characterLayoutInfo.mIsVisible ); - DALI_TEST_CHECK( !characterLayoutInfo.mSetText ); - DALI_TEST_CHECK( !characterLayoutInfo.mSetStyle ); - - TextViewProcessor::WordLayoutInfo wordLayoutInfo; - DALI_TEST_EQUALS( wordLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo.mAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo.mType, TextViewProcessor::NoSeparator, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo.mCharactersLayoutInfo.size(), 0u, TEST_LOCATION ); - - TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo; - DALI_TEST_EQUALS( paragraphLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo.mAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo.mLineHeightOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo.mWordsLayoutInfo.size(), 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo.mNumberOfCharacters, 0u, TEST_LOCATION ); - - TextViewProcessor::TextLayoutInfo textLayoutInfo; - DALI_TEST_EQUALS( textLayoutInfo.mWholeTextSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mMaxWordWidth, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mParagraphsLayoutInfo.size(), 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mNumberOfCharacters, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mMaxItalicsOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mEllipsizeLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mEllipsizeLayoutInfo.mAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mEllipsizeLayoutInfo.mType, TextViewProcessor::NoSeparator, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.size(), 0u, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliTextViewCopyConstructorOperator(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCopyConstructorOperator : "); - - TextViewProcessor::CharacterLayoutInfo characterLayoutInfo; - characterLayoutInfo.mSize = Vector2( 1.f, 1.f ); - characterLayoutInfo.mBearing = 1.f; - characterLayoutInfo.mPosition = Vector3( 1.f, 1.f, 1.f ); - characterLayoutInfo.mOffset = Vector2( 1.f, 1.f ); - characterLayoutInfo.mAscender = 1.f; - characterLayoutInfo.mUnderlineThickness = 1.f; - characterLayoutInfo.mUnderlinePosition = 1.f; - - characterLayoutInfo.mGlyphActor = TextActor::New( "Hello" ); - - TextViewProcessor::GradientInfo* info = new TextViewProcessor::GradientInfo(); - info->mGradientColor = Vector4( 1.f, 1.f, 1.f, 1.f ); - info->mStartPoint = Vector2( 1.f, 1.f ); - info->mEndPoint = Vector2( 1.f, 1.f ); - - characterLayoutInfo.mColorAlpha = 0.f; - characterLayoutInfo.mGradientInfo = info; - - characterLayoutInfo.mIsVisible = false; - characterLayoutInfo.mSetText = false; - characterLayoutInfo.mSetStyle = false; - - TextViewProcessor::CharacterLayoutInfo characterLayoutInfo1; - characterLayoutInfo1 = characterLayoutInfo; - - DALI_TEST_EQUALS( characterLayoutInfo1.mBearing, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mPosition, Vector3( 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mOffset, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( characterLayoutInfo1.mGlyphActor ); - DALI_TEST_EQUALS( characterLayoutInfo1.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mEndPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( !characterLayoutInfo1.mIsVisible ); - DALI_TEST_CHECK( !characterLayoutInfo1.mSetText ); - DALI_TEST_CHECK( !characterLayoutInfo1.mSetStyle ); - - TextViewProcessor::CharacterLayoutInfo characterLayoutInfo2( characterLayoutInfo ); - DALI_TEST_EQUALS( characterLayoutInfo2.mBearing, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mPosition, Vector3( 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mOffset, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( characterLayoutInfo2.mGlyphActor ); - DALI_TEST_EQUALS( characterLayoutInfo2.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mEndPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( !characterLayoutInfo2.mIsVisible ); - DALI_TEST_CHECK( !characterLayoutInfo2.mSetText ); - DALI_TEST_CHECK( !characterLayoutInfo2.mSetStyle ); - - // Increases coverage. - characterLayoutInfo2.mGlyphActor.Reset(); - characterLayoutInfo1 = characterLayoutInfo2; - DALI_TEST_CHECK( !characterLayoutInfo1.mGlyphActor ); - - TextViewProcessor::WordLayoutInfo wordLayoutInfo; - wordLayoutInfo.mSize = Vector2( 1.f, 1.f ); - wordLayoutInfo.mAscender = 1.f; - wordLayoutInfo.mType = TextViewProcessor::ParagraphSeparator; - - TextViewProcessor::WordLayoutInfo wordLayoutInfo1; - wordLayoutInfo1 = wordLayoutInfo; - - DALI_TEST_EQUALS( wordLayoutInfo1.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo1.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo1.mType, TextViewProcessor::ParagraphSeparator, TEST_LOCATION ); - - TextViewProcessor::WordLayoutInfo wordLayoutInfo2( wordLayoutInfo ); - - DALI_TEST_EQUALS( wordLayoutInfo2.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo2.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo2.mType, TextViewProcessor::ParagraphSeparator, TEST_LOCATION ); - - TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo; - paragraphLayoutInfo.mSize = Vector2( 1.f, 1.f ); - paragraphLayoutInfo.mAscender = 1.f; - paragraphLayoutInfo.mLineHeightOffset = 1.f; - paragraphLayoutInfo.mNumberOfCharacters = 1u; - - TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo1; - paragraphLayoutInfo1 = paragraphLayoutInfo; - - DALI_TEST_EQUALS( paragraphLayoutInfo1.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo1.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo1.mLineHeightOffset, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo1.mNumberOfCharacters, 1u, TEST_LOCATION ); - - TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo2( paragraphLayoutInfo ); - - DALI_TEST_EQUALS( paragraphLayoutInfo2.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo2.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo2.mLineHeightOffset, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo2.mNumberOfCharacters, 1u, TEST_LOCATION ); - - TextViewProcessor::TextLayoutInfo textLayoutInfo; - textLayoutInfo.mWholeTextSize = Vector2( 1.f, 1.f ); - textLayoutInfo.mMaxWordWidth = 1.f; - textLayoutInfo.mNumberOfCharacters = 1u; - textLayoutInfo.mMaxItalicsOffset = 1.f; - - TextViewProcessor::TextLayoutInfo textLayoutInfo1; - textLayoutInfo1 = textLayoutInfo; - - DALI_TEST_EQUALS( textLayoutInfo1.mWholeTextSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo1.mMaxWordWidth, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo1.mNumberOfCharacters, 1u, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo1.mMaxItalicsOffset, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - - TextViewProcessor::TextLayoutInfo textLayoutInfo2( textLayoutInfo ); - - DALI_TEST_EQUALS( textLayoutInfo2.mWholeTextSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo2.mMaxWordWidth, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo2.mNumberOfCharacters, 1u, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo2.mMaxItalicsOffset, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliTextViewEqualityOperator(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewEqualityOperator : "); - - TextViewProcessor::TextInfoIndices indices; - TextViewProcessor::TextInfoIndices indices1( 1u, 1u, 1u ); - - DALI_TEST_CHECK( !( indices == indices1 ) ); - - indices = indices1; - - DALI_TEST_CHECK( indices == indices1 ); - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor.cpp deleted file mode 100644 index 8fef857..0000000 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * 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 -#include -#include -#include - -// Internal headers are allowed here -#include -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Internal; - -void dali_text_view_processor_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void dali_text_view_processor_cleanup(void) -{ - test_return_value = TET_PASS; -} - - -namespace -{ -// Data structures used to create an 'experiment' in TET cases - -////////////////////////////////////////////////////////////////// - -struct BeginsRightToLeftCharacterTest -{ - std::string description; - std::string input; - bool result; -}; - -bool TestBeginsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location ) -{ - // Creates a text with the string. - Text text( input ); - - const bool ret = ( result == TextProcessor::BeginsRightToLeftCharacter( text ) ); - - if( !ret ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Input : %s", input.c_str() ); - } - - return ret; -} - -////////////////////////////////////////////////////////////////// - -struct ContainsRightToLeftCharacterTest -{ - std::string description; - std::string input; - bool result; -}; - -bool TestContainsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location ) -{ - // Creates a text with the string. - Text text( input ); - - const bool ret = ( result == TextProcessor::ContainsRightToLeftCharacter( text ) ); - - if( !ret ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Input : %s", input.c_str() ); - } - - return ret; -} - -////////////////////////////////////////////////////////////////// - -struct FindNearestWordTest -{ - std::string description; - std::string input; - std::size_t offset; - std::size_t start; - std::size_t end; -}; - -bool TestFindNearestWord( const std::string& description, const std::string& input, const std::size_t offset, const std::size_t startResult, const std::size_t endResult, const char* location ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( input, styledText, true ); - - std::size_t start; - std::size_t end; - TextProcessor::FindNearestWord( styledText, offset, start, end ); - - const bool ret = ( start == startResult ) && ( end == endResult ); - - if( !ret ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Input : %s, offset %d, start %d, end %d", input.c_str(), offset, start, end ); - } - - return ret; -} - -////////////////////////////////////////////////////////////////// - -struct SplitInParagraphsTest -{ - std::string inputText; - - std::size_t resultNumberOfParagraphs; -}; - -bool TestSplitInParagraphs( const SplitInParagraphsTest& test, const char* location ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( test.inputText, styledText, true ); - - std::vector paragraphs; - std::vector< Vector > styles; - - TextProcessor::SplitInParagraphs( styledText, - paragraphs, - styles ); - - if( paragraphs.size() != test.resultNumberOfParagraphs ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Different number of paragraphs, result %d, expected result %d", paragraphs.size(), test.resultNumberOfParagraphs ); - - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -struct SplitInWordsTest -{ - std::string inputText; - - std::size_t resultNumberOfSeparators; -}; - -bool TestSplitInWords( const SplitInWordsTest& test, const char* location ) -{ - // Creates a text with the string. - Text text( test.inputText ); - - Vector positions; - - TextProcessor::SplitInWords( text, - positions ); - - if( positions.Count() != test.resultNumberOfSeparators ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Different number of separators, result %d, expected result %d", positions.Count(), test.resultNumberOfSeparators ); - - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -} // namespace - - -int UtcDaliTextViewSplitInParagraphs(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewSplitInParagraphs : "); - - struct SplitInParagraphsTest splitInParagraphsTest[] = - { - { - std::string( "Hello world\nhello world." ), - 2 - }, - { - std::string( "Hello world\nhello world.\n\n" ), - 4 - } - }; - const std::size_t numberOfTests( 2 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const SplitInParagraphsTest& test = splitInParagraphsTest[index]; - - if( !TestSplitInParagraphs( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewSplitInWords(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewSplitInWords : "); - - struct SplitInWordsTest splitInWordsTest[] = - { - { - std::string( "Hello world, hello word!" ), - 3u - }, - { - std::string( "Hello world\n" ), - 2u - } - }; - const std::size_t numberOfTests( 2u ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const SplitInWordsTest& test = splitInWordsTest[index]; - - if( !TestSplitInWords( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewBeginsRightToLeftCharacter(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewBeginsRightToLeftCharacter : "); - - struct BeginsRightToLeftCharacterTest beginsRightToLeftCharacterTest[] = - { - { - std::string( "Test if it begins with a right to left character. Should return false." ), - std::string( "Hello world مرحبا العالم." ), - false - }, - { - std::string( "Test if it begins with a right to left character. Should return true." ), - std::string( "مرحبا العالم Hola mundo." ), - true - } - }; - const std::size_t numberOfTests( 2 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const BeginsRightToLeftCharacterTest& test = beginsRightToLeftCharacterTest[index]; - - if( !TestBeginsRightToLeftCharacter( test.description, test.input, test.result, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewContainsRightToLeftCharacter(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewContainsRightToLeftCharacter : "); - - struct ContainsRightToLeftCharacterTest containsRightToLeftCharacterTest[] = - { - { - std::string( "Test if it contains a right to left character. Should return true." ), - std::string( "Hello world مرحبا العالم." ), - true - }, - { - std::string( "Test if it contains a right to left character. Should return true." ), - std::string( "مرحبا العالم Hola mundo." ), - true - }, - { - std::string( "Test if it contains a right to left character. Should return false." ), - std::string( "Hello world." ), - false - }, - { - std::string( "Test if it contains a right to left character. Should return true." ), - std::string( "مرحبا العالم." ), - true - } - }; - const std::size_t numberOfTests( 4 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const ContainsRightToLeftCharacterTest& test = containsRightToLeftCharacterTest[index]; - - if( !TestContainsRightToLeftCharacter( test.description, test.input, test.result, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewFindNearestWord(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewFindNearestWord : "); - - struct FindNearestWordTest findNearestWordTest[] = - { - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 0u, - 0u, - 5u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 7u, - 6u, - 12u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 11u, - 6u, - 12u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 23u, - 18u, - 23u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 5u, - 0u, - 5u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo مرحبا العالم" ), - 24u, - 25u, - 30u - } - }; - - const std::size_t numberOfTests( 6 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const FindNearestWordTest& test = findNearestWordTest[index]; - - if( !TestFindNearestWord( test.description, test.input, test.offset, test.start, test.end, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Relayout-Utilities.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Relayout-Utilities.cpp deleted file mode 100644 index 3bf0a46..0000000 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Relayout-Utilities.cpp +++ /dev/null @@ -1,833 +0,0 @@ -/* - * 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 - -#include -#include -#include - -// Internal headers are allowed here -#include -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Internal; - -void dali_text_view_relayout_utils_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void dali_text_view_relayout_utils_cleanup(void) -{ - test_return_value = TET_PASS; -} - -namespace -{ - -const Toolkit::Internal::TextView::LayoutParameters DEFAULT_LAYOUT_PARAMETERS; - -// Data structures used to create an 'experiment' in TET cases - - -bool TestEqual( float x, float y ) -{ - return ( fabsf( x - y ) < Math::MACHINE_EPSILON_1000 ); -} - -////////////////////////////////////////////////////////////////// - -struct CalculateLineLayoutTest -{ - std::string description; - std::string inputParagraph; - float parentWidth; - std::size_t wordIndex; - std::size_t characterIndex; - std::size_t characterParagraphIndex; - TextViewRelayout::HorizontalWrapType splitPolicy; - float shrinkFactor; - - float resultLineLength; - float resultMaxCharHeight; - float resultMaxAscender; -}; - -bool TestCalculateLineLayout( const CalculateLineLayoutTest& test, const char* location ) -{ - tet_printf( "%s", test.description.c_str() ); - - // Create styled text. - MarkupProcessor::StyledTextArray inputStyledText; - MarkupProcessor::GetStyledTextArray( test.inputParagraph, inputStyledText, true ); - - // Create styled text layout info. - Toolkit::Internal::TextView::RelayoutData relayoutData; - TextViewProcessor::CreateTextInfo( inputStyledText, - DEFAULT_LAYOUT_PARAMETERS, - relayoutData ); - - // Prepare input parameters and the result structure and call the function to be tested. - - // Creaqte indices. - TextViewProcessor::TextInfoIndices indices( 0u, test.wordIndex, test.characterIndex ); - indices.mCharacterParagraphIndex = test.characterParagraphIndex; - - // Get the input paragraph. - TextViewProcessor::ParagraphLayoutInfo inputParagraphLayout; - - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - inputParagraphLayout = *relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(); - } - - // Result struct. - TextViewRelayout::LineLayoutInfo resultLayoutInfo; - - CalculateLineLayout( test.parentWidth, - indices, - inputParagraphLayout, - test.splitPolicy, - test.shrinkFactor, - resultLayoutInfo ); - - // Check results. - if( !TestEqual( test.resultLineLength, resultLayoutInfo.mLineLength ) ) - { - tet_printf( "Fail. different line length %f == %f. %s", test.resultLineLength, resultLayoutInfo.mLineLength, location ); - return false; - } - - if( !TestEqual( test.resultMaxCharHeight, resultLayoutInfo.mMaxCharHeight ) ) - { - tet_printf( "Fail. different max character height %f == %f. %s", test.resultMaxCharHeight, resultLayoutInfo.mMaxCharHeight, location ); - return false; - } - - if( !TestEqual( test.resultMaxAscender, resultLayoutInfo.mMaxAscender ) ) - { - tet_printf( "Fail. different max ascender %f == %f. %s", test.resultMaxAscender, resultLayoutInfo.mMaxAscender, location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -struct AlignmentOffsetTest -{ - Toolkit::Alignment::Type alignment; - float parentSize; - float wholeTextSize; - - float resultOffset; -}; - -bool TestAlignmentOffset( const AlignmentOffsetTest& test, const char* location ) -{ - float offset = 0.f; - - switch( test.alignment ) - { - case Toolkit::Alignment::HorizontalLeft: - case Toolkit::Alignment::HorizontalCenter: - case Toolkit::Alignment::HorizontalRight: - { - offset = TextViewRelayout::CalculateXoffset( test.alignment, test.parentSize, test.wholeTextSize ); - break; - } - case Toolkit::Alignment::VerticalTop: - case Toolkit::Alignment::VerticalCenter: - case Toolkit::Alignment::VerticalBottom: - { - offset = TextViewRelayout::CalculateYoffset( test.alignment, test.parentSize, test.wholeTextSize ); - break; - } - } - - // Check results. - if( !TestEqual( test.resultOffset, offset ) ) - { - tet_printf( "Fail. different offset %f == %f. %s", test.resultOffset, offset, location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -struct JustificationOffsetTest -{ - Toolkit::TextView::LineJustification justification; - float wholeTextWidth; - float lineLength; - - float resultOffset; -}; - -bool TestJustificationOffset( const JustificationOffsetTest& test, const char* location ) -{ - float offset = TextViewRelayout::CalculateJustificationOffset( test.justification, test.wholeTextWidth, test.lineLength ); - - // Check results. - if( !TestEqual( test.resultOffset, offset ) ) - { - tet_printf( "Fail. different offset %f == %f. %s", test.resultOffset, offset, location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -struct CalculateVisibilityTest -{ - Vector3 position; - Size size; - Size parentSize; - TextViewRelayout::VisibilityTestType type; - - bool resultVisible; -}; - -bool TestCalculateVisibility( const CalculateVisibilityTest& test, const char* location ) -{ - if( test.resultVisible != TextViewRelayout::IsVisible( test.position, test.size, test.parentSize, test.type ) ) - { - tet_printf( "Fail. different visibility. Type %d, %s", test.type, location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -} // namespace - - -int UtcDaliTextViewDefaultConstructorDestructor_RU(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewDefaultConstructorDestructor : "); - - // Test RelayoutParameters defaults. - TextViewRelayout::RelayoutParameters relayoutParameters; - - DALI_TEST_EQUALS( relayoutParameters.mPositionOffset, Vector3::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mParagraphSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mWordSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mCharacterSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mIndices.mParagraphIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mIndices.mWordIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mIndices.mCharacterIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mCharacterGlobalIndex, 0u, TEST_LOCATION ); - DALI_TEST_CHECK( !relayoutParameters.mIsFirstCharacter ); - DALI_TEST_CHECK( !relayoutParameters.mIsFirstCharacterOfWord ); - DALI_TEST_CHECK( !relayoutParameters.mIsNewLine ); - DALI_TEST_CHECK( !relayoutParameters.mIsNewParagraphCharacter ); - DALI_TEST_CHECK( !relayoutParameters.mIsWhiteSpace ); - DALI_TEST_CHECK( !relayoutParameters.mIsVisible ); - - // Test FadeParameter defaults - TextViewRelayout::FadeParameters fadeParameters; - - DALI_TEST_EQUALS( fadeParameters.mRightFadeBoundary, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mRightFadeThreshold, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mRightFadeBoundaryOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mRightFadeThresholdOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mRightAlphaCoeficients, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftFadeBoundary, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftFadeThreshold, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftFadeBoundaryOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftFadeThresholdOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftAlphaCoeficients, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopFadeBoundary, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopFadeThreshold, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopFadeBoundaryOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopFadeThresholdOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopAlphaCoeficients, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomFadeBoundary, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomFadeThreshold, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomFadeBoundaryOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomFadeThresholdOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomAlphaCoeficients, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( !fadeParameters.mIsPartiallyVisible ); - - // Test EllipsizeParameters defaults - TextViewRelayout::EllipsizeParameters ellipsizeParameters; - - DALI_TEST_EQUALS( ellipsizeParameters.mPosition, Vector3::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mLineDescender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mLineWidth, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mEllipsizeBoundary, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mFirstIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mLastIndex, 0u, TEST_LOCATION ); - DALI_TEST_CHECK( !ellipsizeParameters.mEllipsizeLine ); - DALI_TEST_CHECK( !ellipsizeParameters.mIsLineWidthFullyVisible ); - DALI_TEST_CHECK( !ellipsizeParameters.mIsLineHeightFullyVisible ); - DALI_TEST_CHECK( !ellipsizeParameters.mIsNextLineFullyVisibleHeight ); - DALI_TEST_CHECK( !ellipsizeParameters.mCreateEllipsizedTextActors ); - DALI_TEST_CHECK( !ellipsizeParameters.mLineFits ); - DALI_TEST_CHECK( !ellipsizeParameters.mWordFits ); - - // Test UnderlineInfo defaults - TextViewRelayout::UnderlineInfo underlineInfo; - - DALI_TEST_EQUALS( underlineInfo.mMaxHeight, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( underlineInfo.mMaxThickness, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( underlineInfo.mPosition, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - - // Test TextUnderlineStatus defaults - TextViewRelayout::TextUnderlineStatus textUnderlineStatus; - - DALI_TEST_CHECK( textUnderlineStatus.mUnderlineInfo.empty() ); - DALI_TEST_EQUALS( textUnderlineStatus.mCharacterGlobalIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( textUnderlineStatus.mLineGlobalIndex, 0u, TEST_LOCATION ); - DALI_TEST_CHECK( !textUnderlineStatus.mCurrentUnderlineStatus ); - - // Test LineLayoutInfo defaults - TextViewRelayout::LineLayoutInfo lineLayoutInfo; - - DALI_TEST_EQUALS( lineLayoutInfo.mLineLength, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( lineLayoutInfo.mMaxCharHeight, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( lineLayoutInfo.mMaxAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliTextViewCalculateLineLayout(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCalculateLineLayout : "); - - struct CalculateLineLayoutTest calculateLineLayoutTest[] = - { - //WrapByCharacter - { - "The paragraph is wraped by character. All characters have the same size.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices - 0, - 0, - TextViewRelayout::WrapByCharacter, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by character. There are characters with different sizes.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices - 0, - 0, - TextViewRelayout::WrapByCharacter, // split policy - 1.f, - // results - 94.835075f, // line length. (only fits 8 characters 6x11.38 + 2x13.27) - 13.276911f, // max character height - 11.949220f // max ascender - }, - { - "The paragraph is wraped by character. There are characters with different sizes. It calculates the layout for the second line.", - "Hello world hello world", // input paragraph - 100.f, // parent width - 2, // indices. The third character of the third word starts in a new line. - 2, - 8, - TextViewRelayout::WrapByCharacter, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by character. There are characters with different sizes. It calculates the layout for the third line.", - "Hello world hello world", // input paragraph - 100.f, // parent width - 4, // indices. The fifth character of the fifth word starts in a new line. - 4, - 16, - TextViewRelayout::WrapByCharacter, // split policy - 1.f, - // results - 92.938377f, // line length. (only fits 8 characters 8x11.38) - 13.276911f, // max character height - 11.949220f // max ascender - }, - - //WrapByWord - { - "The paragraph is wraped by word. All characters have the same size.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices. It shouldn't use the index character so 9999999 shouldn't make it crash. - 9999999, - 9999999, - TextViewRelayout::WrapByWord, // split policy - 1.f, - // results - 56.901047f, // line length. (only fits 5 characters 5x11.38, white space is not counted) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by word. There are characters with different sizes.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices. - 0, - 0, - TextViewRelayout::WrapByWord, // split policy - 1.f, - // results - 58.797747f, // line length. (only fits 5 characters 4x11.38 + 13.276911, white space is not counted) - 13.276911f, // max character height - 11.949220f // max ascender - }, - { - "The paragraph is wraped by word. There are characters with different sizes. It calculates the layout for the second line.", - "Hello world hello world", // input paragraph - 100.f, // parent width - 2, // indices. The third word starts in a new line. - 0, - 6, - TextViewRelayout::WrapByWord, // split policy - 1.f, - // results - 60.694449f, // line length. (only fits 5 characters 2x13.276911 + 3x11.38) - 13.276911f, // max character height - 11.949220f // max ascender - }, - { - "The paragraph is wraped by word. The word doen't fit.", - "Hello world", // input paragraph - 40.f, // parent width - 0, // indices. The third word starts in a new line. - 0, - 0, - TextViewRelayout::WrapByWord, // split policy - 1.f, - // results - 0.f, // line length. (The word doesn't fit) - 11.380209f, // max character height - 10.242188f // max ascender - }, - - //WrapByWordAndSplit - { - "The paragraph is wraped by word and by character. All characters have the same size. There is not a long word.", - "Hello world hello world", // input paragraph - 100.f, // parent width - 0, // indices. - 0, - 0, - TextViewRelayout::WrapByWordAndSplit, // split policy - 1.f, - // results - 56.901047f, // line length. (only fits 5 characters 5x11.38, white space is not counted) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by word and by character. All characters have the same size. There is a long word.", - "Helloooooooo world", // input paragraph - 100.f, // parent width - 0, // indices. - 0, - 0, - TextViewRelayout::WrapByWordAndSplit, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by word and by character. There are characters with different sizes. There is a long word. It calculates the layout for the second line.", - "Helloooooooo world", // input paragraph - 100.f, // parent width - 0, // indices. - 8, - 8, - TextViewRelayout::WrapByWordAndSplit, // split policy - 1.f, - // results - 45.520836f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by word and by character. There are characters with different sizes. There is a shrink factor.", - "Helloooooooo world", // input paragraph - 100.f, // parent width - 0, // indices. - 8, - 8, - TextViewRelayout::WrapByWordAndSplit, // split policy - 0.7f, - // results - 95.593755f, // line length. (only fits 12 characters 8x11.38) - 7.9661463f, // max character height - 7.169531f // max ascender - }, - - //WrapByParagraphCharacterAndSplit - { - "The paragraph is wraped by end of paragraph and by character. All characters have the same size.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices - 0, - 0, - TextViewRelayout::WrapByParagraphCharacterAndSplit, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph fits in the width.", - "Hello", // input paragraph - 100.f, // parent width - 0, // indices - 0, - 0, - TextViewRelayout::WrapByParagraphCharacterAndSplit, // split policy - 1.f, - // results - 56.901047f, // line length. (only fits 5 characters 5x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by end of paragraph and by character. All characters have the same size. It calculates the layout for the second line.", - "Hello world, hello world", // input paragraph - 100.f, // parent width - 2, // indices - 2, - 8, - TextViewRelayout::WrapByParagraphCharacterAndSplit, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - }; - const std::size_t numberOfTests( 15 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const CalculateLineLayoutTest& test = calculateLineLayoutTest[index]; - - if( !TestCalculateLineLayout( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewCalculateAlignmentOffsets(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCalculateAlignmentOffsets : "); - - struct AlignmentOffsetTest alignmentOffsetTest[] = - { - { - Toolkit::Alignment::HorizontalLeft, - 100.f, - 75.f, - 0.f - }, - { - Toolkit::Alignment::HorizontalCenter, - 100.f, - 75.f, - 12.5f - }, - { - Toolkit::Alignment::HorizontalRight, - 100.f, - 75.f, - 25.f - }, - { - Toolkit::Alignment::VerticalTop, - 100.f, - 75.f, - 0.f - }, - { - Toolkit::Alignment::VerticalCenter, - 100.f, - 75.f, - 12.5f - }, - { - Toolkit::Alignment::VerticalBottom, - 100.f, - 75.f, - 25.f - } - }; - const std::size_t numberOfTests( 6 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const AlignmentOffsetTest& test = alignmentOffsetTest[index]; - - if( !TestAlignmentOffset( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewCalculateJustificationOffsets(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCalculateJustificationOffsets : "); - - struct JustificationOffsetTest justificationOffsetTest[] = - { - { - Toolkit::TextView::Left, - 100.f, - 75.f, - 0.f - }, - { - Toolkit::TextView::Justified, - 100.f, - 75.f, - 0.f - }, - { - Toolkit::TextView::Center, - 100.f, - 150.f, - -25.f - }, - { - Toolkit::TextView::Right, - 100.f, - 75.f, - 25.f - }, - }; - const std::size_t numberOfTests( 4 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const JustificationOffsetTest& test = justificationOffsetTest[index]; - - if( !TestJustificationOffset( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - - -int UtcDaliTextViewCalculateVisibility(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCalculateVisibility : "); - - struct CalculateVisibilityTest calculateVisibilityTest[] = - { - { - Vector3( 0.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE, - true - }, - { - Vector3( 10.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE, - true - }, - { - Vector3( 0.f, 10.f, 0.f ), - Size( 150.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE, - false - }, - { - Vector3( 0.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE_WIDTH, - true - }, - { - Vector3( 95.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE_WIDTH, - false - }, - { - Vector3( 0.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE_HEIGHT, - true - }, - { - Vector3( 0.f, 0.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE_HEIGHT, - false - }, - { - Vector3( -10.f, 10.f, 0.f ), - Size( 150.f, 150.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE, - true - }, - { - Vector3( -100.f, -100.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE, - false - }, - { - Vector3( -10.f, 10.f, 0.f ), - Size( 50.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE_WIDTH, - true - }, - { - Vector3( 110.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE_WIDTH, - false - }, - { - Vector3( 0.f, 20.f, 0.f ), - Size( 10.f, 50.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE_HEIGHT, - true - }, - { - Vector3( 0.f, -10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE_HEIGHT, - false - }, - }; - const std::size_t numberOfTests( 13 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const CalculateVisibilityTest& test = calculateVisibilityTest[index]; - - if( !TestCalculateVisibility( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewMiscelaneousAsserts(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewMiscelaneousAsserts : "); - - float offset = 0.f; - - bool assert1 = false; - bool assert2 = false; - try - { - offset = Toolkit::Internal::TextViewRelayout::CalculateXoffset( Toolkit::Alignment::VerticalTop, 100.f, 50.f ); - } - catch( Dali::DaliException& e ) - { - DALI_TEST_PRINT_ASSERT( e ); - DALI_TEST_EQUALS( e.condition, "!\"TextViewRelayout::CalculateXoffset: Wrong horizontal text alignment. Did you set a vertical one?\"", TEST_LOCATION ); - assert1 = true; - } - catch( ... ) - { - tet_result( TET_FAIL ); - } - DALI_TEST_EQUALS( offset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - - try - { - offset = Toolkit::Internal::TextViewRelayout::CalculateYoffset( Toolkit::Alignment::HorizontalRight, 100.f, 50.f ); - } - catch( Dali::DaliException& e ) - { - DALI_TEST_PRINT_ASSERT( e ); - DALI_TEST_EQUALS( e.condition, "!\"TextViewRelayout::CalculateXoffset: Wrong vertical text alignment. Did you set an horizontal one?\"", TEST_LOCATION ); - assert2 = true; - } - catch( ... ) - { - tet_result( TET_FAIL ); - } - DALI_TEST_EQUALS( offset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - - DALI_TEST_CHECK( assert1 && assert2 ); - - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index a3f7172..5c19f09 100644 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -51,7 +51,6 @@ SET(TC_SOURCES utc-Dali-ItemLayout.cpp utc-Dali-ItemView.cpp utc-Dali-KeyboardFocusManager.cpp - utc-Dali-MarkupProcessor.cpp utc-Dali-MaskEffect.cpp utc-Dali-NinePatchMaskEffect.cpp utc-Dali-Popup.cpp diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h index 4217d55..88315d4 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h @@ -296,41 +296,6 @@ void DALI_TEST_EQUALS( const std::string &str1, const char* str2, const char* lo void DALI_TEST_EQUALS( const char* str1, const std::string &str2, const char* location); /** - * Test whether two UTF32 strings are equal. - * @param[in] str1 The first string - * @param[in] str2 The second string - * @param[in] location The TEST_LOCATION macro should be used here - */ -template<> -inline void DALI_TEST_EQUALS( const Integration::TextArray& str1, const Integration::TextArray& str2, const char* location) -{ - if( !std::equal( str1.Begin(), str1.End(), str2.Begin() ) ) - { - fprintf(stderr, "%s, checking '", location); - - for( unsigned int i = 0; i < str1.Count(); ++i ) - { - fprintf(stderr, "%c", str1[i]); - } - - fprintf(stderr, "' == '"); - - for( unsigned int i = 0; i < str2.Count(); ++i ) - { - fprintf(stderr, "%c", str2[i]); - } - - fprintf(stderr, "'\n"); - - tet_result(TET_FAIL); - } - else - { - tet_result(TET_PASS); - } -} - -/** * Test whether one unsigned integer value is greater than another. * Test succeeds if value1 > value2 * @param[in] value1 The first value diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp index e2b419e..3557c0d 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp @@ -110,8 +110,7 @@ DummyControlImplOverride::~DummyControlImplOverride() { } void DummyControlImplOverride::OnInitialize() { initializeCalled = true; } -void DummyControlImplOverride::OnThemeChange(StyleManager change) { themeChangeCalled = true;} -void DummyControlImplOverride::OnFontChange(bool defaultFontChange, bool defaultFontSizeChange) { fontChangeCalled = true; } +void DummyControlImplOverride::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) { themeChangeCalled = change.themeChange; fontChangeCalled = change.defaultFontSizeChange; } void DummyControlImplOverride::OnPinch(const PinchGesture& pinch) { pinchCalled = true; } void DummyControlImplOverride::OnPan(const PanGesture& pan) { panCalled = true; } void DummyControlImplOverride::OnTap(const TapGesture& tap) { tapCalled = true; } diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h index d923ac18..473a01d 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h @@ -102,8 +102,7 @@ private: private: // From Internal::Control virtual void OnInitialize(); - virtual void OnThemeChange( StyleManager styleManager ); - virtual void OnFontChange(bool defaultFontChange, bool defaultFontSizeChange); + virtual void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); virtual void OnPinch(const PinchGesture& pinch); virtual void OnPan(const PanGesture& pan); virtual void OnTap(const TapGesture& tap); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp index 5ab4b7d..3d4d1d5 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp @@ -80,23 +80,13 @@ void TestPlatformAbstraction::GetClosestImageSize( Integration::ResourcePointer mTrace.PushCall("GetClosestImageSize", ""); } - /** * @copydoc PlatformAbstraction::LoadResource() */ void TestPlatformAbstraction::LoadResource(const Integration::ResourceRequest& request) { std::ostringstream out; - out << "Type:"; - if( request.GetType()->id == Integration::ResourceText ) - { - out << "Text"; - } - else - { - out << request.GetType()->id; - } - out << ", Path: " << request.GetPath() << std::endl ; + out << "Type:" << request.GetType()->id << ", Path: " << request.GetPath() << std::endl; mTrace.PushCall("LoadResource", out.str()); if(mRequest != NULL) @@ -170,145 +160,20 @@ bool TestPlatformAbstraction::IsLoading() } /** - * @copydoc PlatformAbstraction::GetDefaultFontFamily() + * @copydoc PlatformAbstraction::GetDefaultFontDescription() */ -const std::string& TestPlatformAbstraction::GetDefaultFontFamily() const +void TestPlatformAbstraction::GetDefaultFontDescription( std::string& family, std::string& style ) const { - mTrace.PushCall("GetDefaultFontFamily", ""); - return mGetDefaultFontFamilyResult; + // TODO } /** * @copydoc PlatformAbstraction::GetDefaultFontSize() */ -float TestPlatformAbstraction::GetDefaultFontSize() const -{ - mTrace.PushCall("GetDefaultFontSize", ""); - return mGetDefaultFontSizeResult; -} - -PixelSize TestPlatformAbstraction::GetFontLineHeightFromCapsHeight(const std::string& fontFamily, const std::string& fontStyle, CapsHeight capsHeight) const -{ - mTrace.PushCall("GetFontLineHeightFromCapsHeight", ""); - // LineHeight will be bigger than CapsHeight, so return capsHeight + 1 - return PixelSize(capsHeight + 1); -} - -/** - * @copydoc PlatformAbstraction::GetGlyphData() - */ - -Integration::GlyphSet* TestPlatformAbstraction::GetGlyphData ( const Integration::TextResourceType& textRequest, - const std::string& fontFamily, - bool getBitmap) const -{ - if( getBitmap ) - { - mTrace.PushCall("GetGlyphData", "getBitmap:true"); - } - else - { - mTrace.PushCall("GetGlyphData", "getBitmap:false"); - } - - // It creates fake metrics for the received characters. - - Integration::GlyphSet* set = new Dali::Integration::GlyphSet(); - Integration::BitmapPtr bitmapData; - - std::set characters; - - for( Integration::TextResourceType::CharacterList::const_iterator it = textRequest.mCharacterList.begin(), endIt = textRequest.mCharacterList.end(); it != endIt; ++it ) - { - if( characters.find( it->character ) == characters.end() ) - { - characters.insert( it->character ); - Integration::GlyphMetrics character = {it->character, Integration::GlyphMetrics::LOW_QUALITY, 10.0f, 10.0f, 9.0f, 1.0f, 10.0f, it->xPosition, it->yPosition }; - - if( getBitmap ) - { - bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD); - bitmapData->GetPackedPixelsProfile()->ReserveBuffer(Pixel::A8, 64, 64); - PixelBuffer* pixelBuffer = bitmapData->GetBuffer(); - memset( pixelBuffer, it->character, 64*64 ); - } - - set->AddCharacter(bitmapData, character); - } - } - - set->mLineHeight = 10.0f; - set->mAscender = 9.0f; - set->mUnitsPerEM = 2048.0f/64.0f; - set->SetAtlasResourceId( textRequest.mTextureAtlasId ); - set->mFontHash = textRequest.mFontHash; - - return set; -} - -/** - * @copydoc PlatformAbstraction::GetCachedGlyphData() - */ - -Integration::GlyphSet* TestPlatformAbstraction::GetCachedGlyphData( const Integration::TextResourceType& textRequest, - const std::string& fontFamily ) const -{ - mTrace.PushCall("GetCachedGlyphData", ""); - - // It creates fake metrics and bitmap for received numeric characters '0' through '9'. - Integration::GlyphSet* set = new Dali::Integration::GlyphSet(); - Integration::BitmapPtr bitmapData; - - std::set characters; - - for( Integration::TextResourceType::CharacterList::const_iterator it = textRequest.mCharacterList.begin(), endIt = textRequest.mCharacterList.end(); it != endIt; ++it ) - { - if( it->character >= '0' && it->character <= '9' && characters.find( it->character ) == characters.end() ) - { - characters.insert( it->character ); - Integration::GlyphMetrics character = {it->character, Integration::GlyphMetrics::HIGH_QUALITY, 10.0f, 10.0f, 9.0f, 1.0f, 10.0f, it->xPosition, it->yPosition }; - - bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD); - bitmapData->GetPackedPixelsProfile()->ReserveBuffer(Pixel::A8, 64, 64); - PixelBuffer* pixelBuffer = bitmapData->GetBuffer(); - memset( pixelBuffer, it->character, 64*64 ); - set->AddCharacter(bitmapData, character); - } - } - - set->mLineHeight = 10.0f; - set->mAscender = 9.0f; - set->mUnitsPerEM = 2048.0f/64.0f; - set->SetAtlasResourceId( textRequest.mTextureAtlasId ); - set->mFontHash = textRequest.mFontHash; - - return set; -} - - -/** - * @copydoc PlatformAbstraction::GetGlobalMetrics() - */ -void TestPlatformAbstraction::GetGlobalMetrics( const std::string& fontFamily, - const std::string& fontStyle, - Integration::GlobalMetrics& globalMetrics ) const +int TestPlatformAbstraction::GetDefaultFontSize() const { - globalMetrics.lineHeight = 10.0f; - globalMetrics.ascender = 9.0f; - globalMetrics.unitsPerEM = 2048.0f/64.0f; - globalMetrics.underlineThickness = 2.f; - globalMetrics.underlinePosition = 1.f; -} - -/** - * @copydoc PlatformAbstraction::GetFontPath() - */ -std::string TestPlatformAbstraction::GetFontPath(const std::string& family, bool bold, bool italic) const -{ - mTrace.PushCall("GetFontPath", ""); - return mGetFontPathResult; - - // Do nothing with arguments + // TODO + return int(); } /** @@ -320,42 +185,6 @@ void TestPlatformAbstraction::SetDpi (unsigned int dpiHorizontal, unsigned int d } /** - * @copydoc PlatformAbstraction::GetFontFamilyForChars() - */ -const std::string& TestPlatformAbstraction::GetFontFamilyForChars(const Integration::TextArray& charsRequested) const -{ - mTrace.PushCall("GetFontFamilyForChars", ""); - return mGetDefaultFontFamilyResult; -} - -/** - * @copydoc PlatformAbstraction::AllGlyphsSupported() - */ -bool TestPlatformAbstraction::AllGlyphsSupported(const std::string& name, const std::string& fontStyle, const Integration::TextArray& text) const -{ - mTrace.PushCall("AllGlyphsSupported", ""); - return true; -} - -/** - * @copydoc PlatformAbstraction::ValidateFontFamilyName() - */ -bool TestPlatformAbstraction::ValidateFontFamilyName(const std::string& fontFamily, const std::string& fontStyle, bool& isDefaultSystemFont, std::string& closestMatch, std::string& closestStyleMatch) const -{ - mTrace.PushCall("ValidateFontFamilyName", ""); - return true; -} - -/** - * @copydoc PlatformAbstraction::GetFontList() - */ -void TestPlatformAbstraction::GetFontList( PlatformAbstraction::FontListMode mode, std::vector& fonstList ) const -{ - mFontListMode = mode; - mTrace.PushCall("ValidateGetFontList", ""); -} - -/** * @copydoc PlatformAbstraction::LoadFile() */ bool TestPlatformAbstraction::LoadFile( const std::string& filename, std::vector< unsigned char >& buffer ) const @@ -397,102 +226,21 @@ void TestPlatformAbstraction::JoinLoaderThreads() mTrace.PushCall("JoinLoaderThreads", ""); } -void TestPlatformAbstraction::UpdateDefaultsFromDevice() -{ - mTrace.PushCall("UpdateDefaultsFromDevice", ""); - mGetDefaultFontFamilyResult+=1.0f; -} - Integration::DynamicsFactory* TestPlatformAbstraction::GetDynamicsFactory() { mTrace.PushCall("GetDynamicsFactory", ""); return NULL; } -bool TestPlatformAbstraction::ReadGlobalMetricsFromCache( const std::string& fontFamily, - const std::string& fontStyle, - Integration::GlobalMetrics& globalMetrics ) -{ - mTrace.PushCall("ReadGlobalMetricsFromCacheFile", ""); - globalMetrics = mReadGlobalMetrics; // Want to copy contents... - return mReadGlobalMetricsResult; // Default false (will be set to true on subsequent write) -} - -void TestPlatformAbstraction::WriteGlobalMetricsToCache( const std::string& fontFamily, - const std::string& fontStyle, - const Integration::GlobalMetrics& globalMetrics ) -{ - // Copy so next read uses written values. TODO: Could add method - // to turn this behaviour off for more extensive testing. - mReadGlobalMetrics = globalMetrics; - mReadGlobalMetricsResult = true; - - mTrace.PushCall("WriteGlobalMetricsToCacheFile", ""); -} - -bool TestPlatformAbstraction::ReadMetricsFromCache( const std::string& fontFamily, - const std::string& fontStyle, - std::vector& glyphMetricsContainer ) -{ - mTrace.PushCall("ReadMetricsFromCacheFile", ""); - glyphMetricsContainer = mReadMetrics; - return mReadMetricsResult; // Default false (will be set to true on subsequent write) -} - -void TestPlatformAbstraction::WriteMetricsToCache( const std::string& fontFamily, - const std::string& fontStyle, - const Integration::GlyphSet& glyphSet ) -{ - // Copy so next read uses written values. TODO: Could add method - // to turn this behaviour off for more extensive testing. - const Integration::GlyphSet::CharacterList& charList = glyphSet.GetCharacterList(); - mReadMetrics.clear(); - for(std::size_t i=0, end=charList.size(); i& fileNames ) -{ - fileNames.push_back( std::string( "u1f004.png" ) ); - fileNames.push_back( std::string( "u1f0cf.png" ) ); - fileNames.push_back( std::string( "u1f170.png" ) ); - fileNames.push_back( std::string( "u1f601.png" ) ); -} - - -Integration::BitmapPtr TestPlatformAbstraction::GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character ) const -{ - Integration::BitmapPtr image = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD ); - image->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 1, 1 ); - - mTrace.PushCall("GetGlyphImage", ""); - - return image; -} - - /** Call this every test */ void TestPlatformAbstraction::Initialize() { mTrace.Reset(); mTrace.Enable(true); memset(&mResources, 0, sizeof(Resources)); - memset(&mReadGlobalMetrics, 0, sizeof(Integration::GlobalMetrics)); mSeconds=0; mMicroSeconds=0; mIsLoadingResult=false; - mGetDefaultFontFamilyResult = "HelveticaNeue"; - mGetDefaultFontSizeResult=12.0f; - mGetFontPathResult="helvetica-12"; - mReadMetricsResult=false; - mReadGlobalMetricsResult=false; if(mRequest) { @@ -517,24 +265,9 @@ bool TestPlatformAbstraction::WasCalled(TestFuncEnum func) case CancelLoadFunc: return mTrace.FindMethod("CancelLoad"); case GetResourcesFunc: return mTrace.FindMethod("GetResources"); case IsLoadingFunc: return mTrace.FindMethod("IsLoading"); - case GetDefaultFontFamilyFunc: return mTrace.FindMethod("GetDefaultFontFamily"); - case GetDefaultFontSizeFunc: return mTrace.FindMethod("GetDefaultFontSize"); - case GetFontLineHeightFromCapsHeightFunc: return mTrace.FindMethod("GetFontLineHeightFromCapsHeight"); - case GetGlyphDataFunc: return mTrace.FindMethod("GetGlyphData"); - case GetCachedGlyphDataFunc: return mTrace.FindMethod("GetCachedGlyphData"); - case GetFontPathFunc: return mTrace.FindMethod("GetFontPath"); case SetDpiFunc: return mTrace.FindMethod("SetDpi"); case JoinLoaderThreadsFunc: return mTrace.FindMethod("JoinLoaderThreads"); - case GetFontFamilyForCharsFunc: return mTrace.FindMethod("GetFontFamilyForChars"); - case AllGlyphsSupportedFunc: return mTrace.FindMethod("AllGlyphsSupported"); - case ValidateFontFamilyNameFunc: return mTrace.FindMethod("ValidateFontFamilyName"); - case UpdateDefaultsFromDeviceFunc: return mTrace.FindMethod("UpdateDefaultsFromDevice"); case GetDynamicsFactoryFunc: return mTrace.FindMethod("GetDynamicsFactory"); - case ValidateGetFontListFunc: return mTrace.FindMethod("ValidateGetFontList"); - case ReadGlobalMetricsFromCacheFileFunc: return mTrace.FindMethod("ReadGlobalMetricsFromCacheFile"); - case WriteGlobalMetricsToCacheFileFunc: return mTrace.FindMethod("WriteGlobalMetricsToCacheFile"); - case ReadMetricsFromCacheFileFunc: return mTrace.FindMethod("ReadMetricsFromCacheFile"); - case WriteMetricsToCacheFileFunc: return mTrace.FindMethod("WriteMetricsToCacheFile"); } return false; } @@ -559,21 +292,6 @@ void TestPlatformAbstraction::SetIsLoadingResult(bool result) mIsLoadingResult = result; } -void TestPlatformAbstraction::SetGetDefaultFontFamilyResult(std::string result) -{ - mGetDefaultFontFamilyResult = result; -} - -void TestPlatformAbstraction::SetGetDefaultFontSizeResult(float result) -{ - mGetDefaultFontSizeResult = result; -} - -void TestPlatformAbstraction::SetGetFontPathResult(std::string& result) -{ - mGetFontPathResult = result; -} - void TestPlatformAbstraction::ClearReadyResources() { memset(&mResources, 0, sizeof(Resources)); @@ -643,21 +361,4 @@ void TestPlatformAbstraction::SetSaveFileResult( bool result ) mSaveFileResult = result; } -Integration::PlatformAbstraction::FontListMode TestPlatformAbstraction::GetLastFontListMode( ) -{ - return mFontListMode; -} - -void TestPlatformAbstraction::SetReadGlobalMetricsResult( bool success, Integration::GlobalMetrics& globalMetrics ) -{ - mReadGlobalMetricsResult = success; - mReadGlobalMetrics = globalMetrics; -} - -void TestPlatformAbstraction::SetReadMetricsResult( bool success, std::vector& glyphMetricsContainer ) -{ - mReadMetricsResult = success; - mReadMetrics = glyphMetricsContainer; // copy -} - } // namespace Dali diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h index 41b06cd..a4ec8d3 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h @@ -26,7 +26,6 @@ #include #include -#include #include "test-trace-call-stack.h" @@ -137,71 +136,19 @@ public: virtual bool IsLoading(); /** - * @copydoc PlatformAbstraction::GetDefaultFontFamily() + * @copydoc PlatformAbstraction::GetDefaultFontDescription() */ - virtual const std::string& GetDefaultFontFamily() const; + virtual void GetDefaultFontDescription( std::string& family, std::string& style ) const; /** * @copydoc PlatformAbstraction::GetDefaultFontSize() */ - virtual float GetDefaultFontSize() const; - - /** - * @copydoc PlatformAbstraction::GetFontLineHeightFromCapsHeight() - */ - virtual Dali::PixelSize GetFontLineHeightFromCapsHeight(const std::string& fontFamily, const std::string& fontStyle, CapsHeight capsHeight) const; - - /** - * @copydoc PlatformAbstraction::GetGlyphData() - */ - virtual Integration::GlyphSet* GetGlyphData ( const Integration::TextResourceType& textRequest, - const std::string& fontFamily, - bool getBitmap) const; - - /** - * @copydoc PlatformAbstraction::GetCachedGlyphData() - */ - virtual Integration::GlyphSet* GetCachedGlyphData( const Integration::TextResourceType& textRequest, - const std::string& fontFamily ) const; - - - /** - * @copydoc PlatformAbstraction::GetGlobalMetrics() - */ - virtual void GetGlobalMetrics( const std::string& fontFamily, - const std::string& fontStyle, - Integration::GlobalMetrics& globalMetrics ) const; - - /** - * @copydoc PlatformAbstraction::GetFontPath() - */ - virtual std::string GetFontPath(const std::string& family, bool bold, bool italic) const; + virtual int GetDefaultFontSize() const; /** * @copydoc PlatformAbstraction::SetDpi() */ virtual void SetDpi (unsigned int dpiHorizontal, unsigned int dpiVertical); - - /** - * @copydoc PlatformAbstraction::GetFontFamilyForChars() - */ - virtual const std::string& GetFontFamilyForChars(const Integration::TextArray& charsRequested) const; - - /** - * @copydoc PlatformAbstraction::AllGlyphsSupported() - */ - virtual bool AllGlyphsSupported(const std::string& name, const std::string& fontStyle, const Integration::TextArray& text) const; - - /** - * @copydoc PlatformAbstraction::ValidateFontFamilyName() - */ - virtual bool ValidateFontFamilyName(const std::string& fontFamily, const std::string& fontStyle, bool& isDefaultSystemFont, std::string& closestMatch, std::string& closestStyleMatch) const; - - /** - * @copydoc PlatformAbstraction::GetFontList() - */ - virtual void GetFontList( PlatformAbstraction::FontListMode mode, std::vector& fontList ) const; - /** * @copydoc PlatformAbstraction::LoadFile() */ @@ -219,31 +166,8 @@ public: virtual void JoinLoaderThreads(); - virtual void UpdateDefaultsFromDevice(); - virtual Integration::DynamicsFactory* GetDynamicsFactory(); - virtual bool ReadGlobalMetricsFromCache( const std::string& fontFamily, - const std::string& fontStyle, - Integration::GlobalMetrics& globalMetrics ); - - virtual void WriteGlobalMetricsToCache( const std::string& fontFamily, - const std::string& fontStyle, - const Integration::GlobalMetrics& globalMetrics ); - - virtual bool ReadMetricsFromCache( const std::string& fontFamily, - const std::string& fontStyle, - std::vector& glyphMetricsContainer ); - virtual void WriteMetricsToCache( const std::string& fontFamily, - const std::string& fontStyle, - const Integration::GlyphSet& glyphSet ); - - - virtual void GetFileNamesFromDirectory( const std::string& directoryName, - std::vector& fileNames ); - - virtual Integration::BitmapPtr GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character ) const; - public: // TEST FUNCTIONS // Enumeration of Platform Abstraction methods @@ -260,24 +184,9 @@ public: // TEST FUNCTIONS CancelLoadFunc, GetResourcesFunc, IsLoadingFunc, - GetDefaultFontFamilyFunc, - GetDefaultFontSizeFunc, - GetFontLineHeightFromCapsHeightFunc, - GetGlyphDataFunc, - GetCachedGlyphDataFunc, SetDpiFunc, - GetFontPathFunc, JoinLoaderThreadsFunc, - GetFontFamilyForCharsFunc, - AllGlyphsSupportedFunc, - ValidateFontFamilyNameFunc, - UpdateDefaultsFromDeviceFunc, GetDynamicsFactoryFunc, - ValidateGetFontListFunc, - ReadGlobalMetricsFromCacheFileFunc, - WriteGlobalMetricsToCacheFileFunc, - ReadMetricsFromCacheFileFunc, - WriteMetricsToCacheFileFunc, } TestFuncEnum; /** Call this every test */ @@ -326,33 +235,18 @@ public: // TEST FUNCTIONS void SetSaveFileResult( bool result ); - PlatformAbstraction::FontListMode GetLastFontListMode( ); - - void SetReadGlobalMetricsResult( bool success, Integration::GlobalMetrics& globalMetrics ); - - void SetReadMetricsResult( bool success, std::vector& glyphMetricsContainer ); - - private: mutable TraceCallStack mTrace; size_t mSeconds; size_t mMicroSeconds; bool mIsLoadingResult; - std::string mGetDefaultFontFamilyResult; - float mGetDefaultFontSizeResult; - std::string mGetFontPathResult; Resources mResources; Integration::ResourceRequest* mRequest; Vector2 mSize; Vector2 mClosestSize; - bool mReadGlobalMetricsResult; - bool mReadMetricsResult; - Integration::GlobalMetrics mReadGlobalMetrics; - std::vector mReadMetrics; LoadFileResult mLoadFileResult; bool mSaveFileResult; - mutable FontListMode mFontListMode; }; } // Dali diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp index d403477..cc03bb1 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp @@ -26,131 +26,6 @@ using namespace Toolkit; namespace { -// -// Note: To avoid escaping double quotes single quotes are used and then replaced -// before parsing. JSON uses double quotes -// - - std::string JSON_TEXT_ACTOR("\ -{ \ - 'templates': \ - { \ - 'basic-text': \ - { \ - 'type':'TextActor', \ - 'text':'Template Hello', \ - 'size': [150,170,1], \ - 'position':[-10,10,0] \ - } \ - }, \ - 'styles': \ - { \ - 'basic-text': \ - { \ - 'text':'Hello', \ - 'font':'', \ - 'parent-origin':[0.0,0.0,0], \ - 'anchor-point' :[0.5,0.5,0], \ - 'size': [150,170,1], \ - 'position':[-10,10,0] \ - } \ - }, \ - 'animations': \ - { \ - 'rotate': \ - { \ - 'duration': 10, \ - 'properties': \ - [ \ - { \ - 'actor':'text', \ - 'property':'orientation', \ - 'value':[0, 3, 0, 0], \ - 'alpha-function': 'EASE_IN_OUT', \ - 'time-period': {'delay': 0, 'duration': 3 } \ - } \ - ] \ - } \ - }, \ - 'stage': \ - [ \ - { \ - 'name':'text', \ - 'type':'basic-text', \ - 'text':'Hello' \ - }, \ - { \ - 'name':'text2', \ - 'type':'basic-text', \ - 'text':'Hello', \ - 'signals': \ - [ \ - { 'name': 'on-stage', 'action':'set', 'actor':'text2', 'property':'text', 'value':'Jaylo' } \ - ] \ - } \ - ], \ - 'other': \ - [ \ - { \ - 'name':'other-text', \ - 'type':'basic-text', \ - 'text':'Hello' \ - } \ - ] \ -} \ -"); - - - std::string JSON_CORE_ACTOR_TREE("\ -{ \ - 'templates': \ - { \ - 'my-camera': { \ - 'type':'CameraActor', \ - 'camera-type':'FreeLook', \ - 'field-of-view': 0.125, \ - 'aspect-ratio':5.0, \ - 'near-plane-distance': 100, \ - 'far-plane-distance': 200 \ - }, \ - 'basic-text': { \ - 'type':'TextActor', \ - 'text':'Hello', \ - 'font':'Freesans', \ - 'smooth-edge':0.2, \ - 'position': [-10.0, 10.0, -1000.0], \ - 'size': [300.0, 250.0, 0.0] \ - } \ - }, \ - 'styles': \ - { \ - 'theme2-text': { \ - 'type':'TextActor', \ - 'text':'Hello', \ - 'font':'Freesans', \ - 'smooth-edge':0.8 \ - } \ - }, \ - 'stage': \ - [ \ - {'name':'txt1', \ - 'type':'TextActor', \ - 'text':'Hello World', \ - 'font':'freesans', \ - 'parent-origin':'CENTER', \ - 'actors': \ - [ \ - { 'type':'basic-text', 'text':'Hello', 'position-y':50 }, \ - { 'type':'basic-text', 'text':'Hello', 'position-y':100 }, \ - { 'type':'basic-text', 'text':'Hello', 'position-y':150 }, \ - { 'type':'basic-text', 'text':'Hello', 'position-y':200 }, \ - { 'type':'basic-text', 'text':'Hello', 'position-y':250 } \ - ] \ - } \ - ] \ -} \ -"); - std::string ReplaceQuotes(const std::string &in_s) { @@ -189,263 +64,6 @@ void builder_cleanup(void) test_return_value = TET_PASS; } -int UtcDaliBuilderTextActorCreate(void) -{ - ToolkitTestApplication application; - Stage stage = Stage::GetCurrent(); - - tet_infoline(" UtcDaliBuilderTextActorCreate"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - TextActor actor( TextActor::DownCast( builder.Create("basic-text") ) ); - - DALI_TEST_CHECK( actor ); - - stage.GetRootLayer().Add( actor ); - - application.SendNotification(); - application.Render(); - - Vector3 v; - - v = actor.GetCurrentPosition(); - DALI_TEST_CHECK(v.x == -10.0); - DALI_TEST_CHECK(v.y == 10.0); - DALI_TEST_CHECK(v.z == 0.0); - - v = actor.GetCurrentSize(); - DALI_TEST_CHECK(v.x == 150.0); - DALI_TEST_CHECK(v.y == 170.0); - DALI_TEST_CHECK(v.z == 1.0); - - DALI_TEST_CHECK(actor.GetText() == "Template Hello"); - - actor = TextActor::DownCast( builder.Create("*(&^") ); - DALI_TEST_CHECK(!actor); - - END_TEST; -} - -int UtcDaliBuilderTextActorCreateAnimation(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderTextActorCreateAnimation"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - builder.AddActors( Stage::GetCurrent().GetRootLayer() ); - - Animation anim = builder.CreateAnimation("rotate"); - DALI_TEST_CHECK( anim ); - - DALI_TEST_CHECK( 10.0f == anim.GetDuration() ); - - END_TEST; -} - -int UtcDaliBuilderTextActorApplyFromStyle(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderTextActorApplyFromStyle"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - TextActor actor = TextActor::New("a"); - - builder.ApplyStyle("basic-text", actor); - - DALI_TEST_CHECK( actor ); - - Stage::GetCurrent().GetRootLayer().Add( actor ); - - application.SendNotification(); - application.Render(); - - Vector3 v; - - v = actor.GetCurrentPosition(); - DALI_TEST_CHECK(v.x == -10.0); - DALI_TEST_CHECK(v.y == 10.0); - DALI_TEST_CHECK(v.z == 0.0); - - v = actor.GetCurrentSize(); - DALI_TEST_CHECK(v.x == 150.0); - DALI_TEST_CHECK(v.y == 170.0); - DALI_TEST_CHECK(v.z == 1.0); - - DALI_TEST_CHECK(actor.GetText() == "Hello"); - - END_TEST; -} - -int UtcDaliBuilderAddActors(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderAddActors"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - builder.AddActors( Stage::GetCurrent().GetRootLayer() ); - - application.SendNotification(); - application.Render(); - - TextActor actor = TextActor::DownCast( Stage::GetCurrent().GetRootLayer().FindChildByName("text") ); - - DALI_TEST_CHECK( actor ); - DALI_TEST_CHECK(actor.GetText() == "Hello"); - - END_TEST; -} - -int UtcDaliBuilderAddActorsOther(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderAddActorsOther"); - - Actor rootActor = Stage::GetCurrent().GetRootLayer(); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - builder.AddActors( "other", rootActor ); - - application.SendNotification(); - application.Render(); - - TextActor actor = TextActor::DownCast( Stage::GetCurrent().GetRootLayer().FindChildByName("other-text") ); - - DALI_TEST_CHECK( actor ); - DALI_TEST_CHECK(actor.GetText() == "Hello"); - - END_TEST; -} - - -int UtcDaliBuilderStyles(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderStyles"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_CORE_ACTOR_TREE)); - - BaseHandle handle = builder.Create("my-camera"); - CameraActor camera = CameraActor::DownCast(handle); - - DALI_TEST_CHECK(camera); - - Property::Value v; - - v = camera.GetProperty( camera.GetPropertyIndex("field-of-view") ); - DALI_TEST_CHECK( 0.125f == v.Get() ); - - v = camera.GetProperty( camera.GetPropertyIndex("aspect-ratio") ); - DALI_TEST_CHECK( 5.0f == v.Get() ); - - handle = builder.Create("basic-text"); - TextActor textActor = TextActor::DownCast(handle); - - v = textActor.GetProperty( textActor.GetPropertyIndex("smooth-edge") ); - - DALI_TEST_CHECK( 0.2f == v.Get() ); - - // test ApplyStyle another - builder.ApplyStyle("theme2-text", textActor); - - v = textActor.GetProperty( textActor.GetPropertyIndex("smooth-edge") ); - DALI_TEST_CHECK( 0.8f == v.Get() ); - - END_TEST; -} - -int UtcDaliBuilderSetProperty(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderSetProperty"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - builder.AddActors( Stage::GetCurrent().GetRootLayer() ); - - application.SendNotification(); - application.Render(); - - TextActor actor = TextActor::DownCast( Stage::GetCurrent().GetRootLayer().FindChildByName("text2") ); - - DALI_TEST_CHECK( actor ); - DALI_TEST_CHECK( actor.GetText() == "Jaylo" ); - - END_TEST; -} - -int UtcDaliBuilderCreateFromJson(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderCreateFromJson"); - - Builder builder = Builder::New(); - - TextActor actor = TextActor::DownCast( builder.CreateFromJson("foobar") ); - - DALI_TEST_CHECK( !actor ); - - actor = TextActor::DownCast( - builder.CreateFromJson( - ReplaceQuotes("{'type':'TextActor','text':'Hi'}") ) ); - - DALI_TEST_CHECK( actor ); - - DALI_TEST_CHECK( actor.GetText() == "Hi" ); - - END_TEST; -} - -int UtcDaliBuilderApplyFromJson(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderApplyFromJson"); - - Builder builder = Builder::New(); - - TextActor actor = TextActor::DownCast( - builder.CreateFromJson( - ReplaceQuotes("{'type':'TextActor','text':'Hi'}") ) ); - - DALI_TEST_CHECK( actor ); - - DALI_TEST_CHECK( actor.GetText() == "Hi" ); - - DALI_TEST_CHECK( !builder.ApplyFromJson(actor, ReplaceQuotes("foobar") ) ); - - builder.ApplyFromJson(actor, ReplaceQuotes("{'text':'low'}") ); - - DALI_TEST_CHECK( actor.GetText() == "low" ); - - END_TEST; -} - int UtcDaliBuilderQuitSignal(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-MarkupProcessor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-MarkupProcessor.cpp deleted file mode 100644 index d2317a7..0000000 --- a/automated-tests/src/dali-toolkit/utc-Dali-MarkupProcessor.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * 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 -#include - -// Need to override adaptor classes for toolkit test harness, so include -// test harness headers before dali headers. -#include - -#include -#include - -using namespace Dali; - -void utc_dali_toolkit_markup_processor_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void utc_dali_toolkit_markup_processor_cleanup(void) -{ - test_return_value = TET_PASS; -} - -namespace -{ - -struct MarkupStringTest -{ - std::string input; - std::string expectedResult; -}; - -bool TestMarkupString( const std::string& input, const std::string& expectedResult, std::string& result ) -{ - Toolkit::MarkupProcessor::StyledTextArray styledTextArray; - - GetStyledTextArray( input, styledTextArray, true ); - GetMarkupString( styledTextArray, result ); - - return expectedResult == result; -} - -} // namespace - - -// Positive test case for a method -int UtcDaliMarkupProcessor(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliMarkupProcessor "); - - const std::string text1( "Text" ); - const std::string text2( "< font face ='FreeSerif' color= 'green' >t< / font >" ); - const std::string text3( "< font face = 'FreeSerif' size= '16' style = 'Bold' color='red'>< i>Styled< / u> Text< /i >< / font >< br / >" ); - const std::string text4( "Styled Text< br/>" ); - const std::string text5( "< shadow color = 'blue' paramx = '1' paramy = '0.75' >Shadow< / shadow>
" ); - const std::string text6( "< glow color = 'red' param = '0.1' >Glow< br />" ); - const std::string text7( "< outline color = 'red' paramx = '0.7' paramy = '0.7' >Outline< / outline >< /font >< br / >" ); - const std::string text8( "Smooth< br / >" ); - const std::string text9( "\\<" ); - const std::string text10( "\\>" ); - - char crlf[2]; - crlf[0] = 0x0D; - crlf[1] = 0x0A; - const std::string text11( crlf, 2 ); - - const std::string result1( text1 ); - const std::string result2( "t" ); - const std::string result3( "Styled Text
" ); - const std::string result4( "Styled Text
" ); - const std::string result5( "Shadow
" ); - const std::string result6( "Glow
" ); - const std::string result7( "Outline
" ); - const std::string result8( "Smooth
" ); - const std::string result9( text9 ); - const std::string result10( text10 ); - const std::string result11( "
" ); - - std::string markupString; - Toolkit::MarkupProcessor::StyledTextArray styledTextArray; - - GetStyledTextArray( text1, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result1, markupString, TEST_LOCATION ); - - GetStyledTextArray( text2, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result2, markupString, TEST_LOCATION ); - - GetStyledTextArray( text3, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result3, markupString, TEST_LOCATION ); - - GetStyledTextArray( text4, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result4, markupString, TEST_LOCATION ); - - GetStyledTextArray( text5, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result5, markupString, TEST_LOCATION ); - - GetStyledTextArray( text6, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result6, markupString, TEST_LOCATION ); - - GetStyledTextArray( text7, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result7, markupString, TEST_LOCATION ); - - GetStyledTextArray( text8, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result8, markupString, TEST_LOCATION ); - - GetStyledTextArray( text9, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result9, markupString, TEST_LOCATION ); - - GetStyledTextArray( text10, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result10, markupString, TEST_LOCATION ); - - GetStyledTextArray( text11, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result11, markupString, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliMarkupProcessorSetTextStyle01(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliMarkupProcessorSetTextStyle01 "); - - const std::string text1( "Text with no defined style" ); - const std::string result1( "Text with no defined style" ); - const std::string result2( "Text with no defined style" ); - - std::string markupString; - Toolkit::MarkupProcessor::StyledTextArray styledTextArray; - - GetStyledTextArray( text1, styledTextArray, true ); - - TextStyle style; - style.SetItalics( true ); - style.SetTextColor( Color::GREEN ); - - SetTextStyle( styledTextArray, style ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result1, markupString, TEST_LOCATION ); - - styledTextArray.clear(); - SetTextStyle( text1, styledTextArray, style ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result1, markupString, TEST_LOCATION ); - - GetStyledTextArray( text1, styledTextArray, true ); - SetTextStyleToRange( styledTextArray, style, TextStyle::ALL, 0, text1.size() - 1 ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result1, markupString, TEST_LOCATION ); - - GetStyledTextArray( text1, styledTextArray, true ); - SetTextStyleToRange( styledTextArray, style, TextStyle::ALL, 10, 19 ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result2, markupString, TEST_LOCATION ); - - std::string plainString; - GetPlainString( styledTextArray, plainString ); - - DALI_TEST_EQUALS( text1, plainString, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliMarkupProcessorSetTextStyle02(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliMarkupProcessorSetTextStyle02 "); - - Toolkit::MarkupProcessor::StyledTextArray styledTextArray; - - // Test style applied to and empty string doesn't crash - - TextStyle style; - style.SetItalics( true ); - style.SetTextColor( Color::GREEN ); - - bool fails = false; - try - { - SetTextStyle( styledTextArray, style ); - } - catch( ... ) - { - fails = true; - } - - DALI_TEST_CHECK( !fails ); - END_TEST; -} - -int UtcDaliMarkupProcessorTestColors(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliMarkupProcessorTestColors "); - - struct MarkupStringTest colorTests[] = - { - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "white" ), - std::string( "white" ) - }, - { - std::string( "red" ), - std::string( "red" ) - }, - { - std::string( "green" ), - std::string( "green" ) - }, - { - std::string( "blue" ), - std::string( "blue" ) - }, - { - std::string( "yellow" ), - std::string( "yellow" ) - }, - { - std::string( "magenta" ), - std::string( "magenta" ) - }, - { - std::string( "cyan" ), - std::string( "cyan" ) - }, - { - std::string( "transparent" ), - std::string( "transparent" ) - }, - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "white" ), - std::string( "white" ) - }, - { - std::string( "red" ), - std::string( "red" ) - }, - { - std::string( "green" ), - std::string( "green" ) - }, - { - std::string( "blue" ), - std::string( "blue" ) - }, - { - std::string( "yellow" ), - std::string( "yellow" ) - }, - { - std::string( "magenta" ), - std::string( "magenta" ) - }, - { - std::string( "cyan" ), - std::string( "cyan" ) - }, - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "white" ), - std::string( "white" ) - }, - { - std::string( "red" ), - std::string( "red" ) - }, - { - std::string( "green" ), - std::string( "green" ) - }, - { - std::string( "blue" ), - std::string( "blue" ) - }, - { - std::string( "yellow" ), - std::string( "yellow" ) - }, - { - std::string( "magenta" ), - std::string( "magenta" ) - }, - { - std::string( "cyan" ), - std::string( "cyan" ) - }, - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "white" ), - std::string( "white" ) - }, - { - std::string( "red" ), - std::string( "red" ) - }, - { - std::string( "green" ), - std::string( "green" ) - }, - { - std::string( "blue" ), - std::string( "blue" ) - }, - { - std::string( "yellow" ), - std::string( "yellow" ) - }, - { - std::string( "magenta" ), - std::string( "magenta" ) - }, - { - std::string( "cyan" ), - std::string( "cyan" ) - }, - { - std::string( "transparent" ), - std::string( "transparent" ) - }, - { - std::string( "outline" ), - std::string( "outline" ) - }, - }; - - const std::size_t numberOfTests( 36 ); - - bool fails = false; - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const MarkupStringTest& test = colorTests[index]; - - std::string result; - if( !TestMarkupString( test.input, test.expectedResult, result ) ) - { - TestMarkupString( test.input, test.expectedResult, result ); - tet_printf( "%s\n input : %s\nexpected result : %s\n result : %s\n", TEST_LOCATION, test.input.c_str(), test.expectedResult.c_str(), result.c_str() ); - - fails = true; - } - } - - DALI_TEST_CHECK( !fails ); - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-NavigationControl.cpp b/automated-tests/src/dali-toolkit/utc-Dali-NavigationControl.cpp index a2c7d54..4e81bf6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-NavigationControl.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-NavigationControl.cpp @@ -327,13 +327,12 @@ int UtcDaliNavigationControlCreateNavigationTitleBar(void) tet_infoline( "UtcDaliNavigationControlCreateNavigationTitleBar" ); ImageActor background = CreateSolidColorActor( Color::RED ); - TextStyle textStyle; Stage stage = Stage::GetCurrent(); NavigationControl naviControl = NavigationControl::New(); stage.Add( naviControl ); - Toolkit::NaviTitleBarStyle titleBarStyle( background, textStyle, textStyle, 720, 111, 68, 48, 34, 16, 11, 45, 63, 26, 14, 22 ); + Toolkit::NaviTitleBarStyle titleBarStyle( background, 720, 111, 68, 48, 34, 16, 11, 45, 63, 26, 14, 22 ); naviControl.CreateNavigationTitleBar( titleBarStyle, titleBarStyle ); Page naviItem = Page::New(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Popup.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Popup.cpp index 0ba0800..0aaf295 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Popup.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Popup.cpp @@ -168,7 +168,7 @@ int UtcDaliPopoupSetProperty(void) //Test properties std::string testString = "Hello World"; popup.SetProperty(popup.GetPropertyIndex("title"), testString); - DALI_TEST_EQUALS( testString, popup.GetTitle().GetText(), TEST_LOCATION ); + DALI_TEST_EQUALS( testString, popup.GetTitle(), TEST_LOCATION ); END_TEST; } @@ -200,54 +200,10 @@ int UtcDaliPopupSetTitle(void) // Put in show state so it's layer is connected to popup (for ancestor check). popup.SetState(Popup::POPUP_SHOW, 0.0f); - TextView titleActor = TextView::New(); - titleActor.SetText("title"); - - DALI_TEST_CHECK( !popup.GetTitle() ); - popup.SetTitle(titleActor); - DALI_TEST_CHECK( popup.GetTitle() == titleActor ); - DALI_TEST_CHECK( (popup.GetTitle()) && (popup.GetTitle().GetText() == "title") ); - // verify titleActor is actually inside popup, and not elsewhere on stage, or off even. - DALI_TEST_CHECK( HasAncestor(titleActor, popup) ); - - TextView titleActor2 = TextView::New(); - titleActor2.SetText("anothertitle"); - popup.SetTitle(titleActor2); - DALI_TEST_CHECK( popup.GetTitle() != titleActor ); - DALI_TEST_CHECK( popup.GetTitle() == titleActor2 ); - DALI_TEST_CHECK( (popup.GetTitle()) && (popup.GetTitle().GetText() == "anothertitle") ); - // verify titleActor is actually inside popup, and not elsewhere on stage, or off even. - DALI_TEST_CHECK( HasAncestor(titleActor2, popup) ); - END_TEST; -} - -int UtcDaliPopupSetTitleText(void) -{ - ToolkitTestApplication application; // Exceptions require ToolkitTestApplication - tet_infoline(" UtcDaliPopupSetTitleText"); + popup.SetTitle("title"); - // Create the Popup actor - Popup popup = Popup::New(); - Stage::GetCurrent().Add( popup ); - // Put in show state so it's layer is connected to popup (for ancestor check). - popup.SetState(Popup::POPUP_SHOW, 0.0f); + DALI_TEST_CHECK( popup.GetTitle() == "title" ); - TextView titleActor = TextView::New(); - titleActor.SetText("title"); - - DALI_TEST_CHECK( !popup.GetTitle() ); - popup.SetTitle(titleActor); - DALI_TEST_CHECK( popup.GetTitle() == titleActor ); - DALI_TEST_CHECK( (popup.GetTitle()) && (popup.GetTitle().GetText() == "title") ); - // verify titleActor is actually inside popup, and not elsewhere on stage, or off even. - DALI_TEST_CHECK( HasAncestor(titleActor, popup) ); - - // this text should replace titleImage actor. - popup.SetTitle("newtext"); - DALI_TEST_CHECK( popup.GetTitle() != titleActor ); - DALI_TEST_CHECK( (popup.GetTitle()) && (popup.GetTitle().GetText() == "newtext") ); - // verify titleActor is no longer inside popup. (been displaced by newtext actor) - DALI_TEST_CHECK( !HasAncestor(titleActor, popup) ); END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-PushButton.cpp b/automated-tests/src/dali-toolkit/utc-Dali-PushButton.cpp index 84a020e..0d259d9 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-PushButton.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-PushButton.cpp @@ -314,18 +314,11 @@ int UtcDaliPushButtonSetLabelText(void) application.SendNotification(); application.Render(); - TextView textView; - pushButton.SetLabel( STR ); - textView = TextView::DownCast( pushButton.GetLabel() ); - DALI_TEST_CHECK( STR == textView.GetText() ); - - TextView text = TextView::New( STR ); - pushButton.SetLabel( text ); + TextLabel label = TextLabel::DownCast( pushButton.GetLabel() ); + DALI_TEST_CHECK( STR == label.GetProperty( TextLabel::Property::TEXT ) ); - textView = TextView::DownCast( pushButton.GetLabel() ); - DALI_TEST_CHECK( STR == textView.GetText() ); END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-RadioButton.cpp b/automated-tests/src/dali-toolkit/utc-Dali-RadioButton.cpp index d53084c..c20a167 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-RadioButton.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-RadioButton.cpp @@ -105,12 +105,12 @@ int UtcDaliRadioButtonLabelActor(void) { ToolkitTestApplication application; - TextView actor1 = TextView::New( "test actor 1" ); + TextLabel actor1 = TextLabel::New( "test actor 1" ); RadioButton radioButton = RadioButton::New( actor1 ); DALI_TEST_CHECK( actor1 == radioButton.GetLabel() ); - TextView actor2 = TextView::New( "test actor 2" ); + TextLabel actor2 = TextLabel::New( "test actor 2" ); radioButton.SetLabel( actor2 ); DALI_TEST_CHECK( actor2 == radioButton.GetLabel() ); diff --git a/build/tizen/configure.ac b/build/tizen/configure.ac index 1e94aa3..006e192 100644 --- a/build/tizen/configure.ac +++ b/build/tizen/configure.ac @@ -30,7 +30,6 @@ AC_SUBST(DALI_TOOLKIT_VERSION) PKG_CHECK_MODULES(DALICORE, dali-core) PKG_CHECK_MODULES(DALI, dali) -PKG_CHECK_MODULES(FRIBIDI, fribidi) DALI_TOOLKIT_CFLAGS=-DPLATFORM_TIZEN @@ -90,6 +89,10 @@ else dataReadOnlyDir=${prefix}/share/dali/ fi +DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -DDALI_PROFILE_${enable_profile}" +AM_CONDITIONAL([COMMON_PROFILE], [test x$enable_profile = xCOMMON]) +AM_CONDITIONAL([MOBILE_PROFILE], [test x$enable_profile = xMOBILE]) + # v8 version 4+ requires c++11 PKG_CHECK_MODULES(V8, v8 = 3.32.7, [ pkg_check_v8=yes ], [ pkg_check_v8=no ] ) diff --git a/build/tizen/dali-toolkit/Makefile.am b/build/tizen/dali-toolkit/Makefile.am index e966482..18ed54d 100644 --- a/build/tizen/dali-toolkit/Makefile.am +++ b/build/tizen/dali-toolkit/Makefile.am @@ -18,10 +18,15 @@ toolkit_images_dir = ../../../dali-toolkit/images toolkit_sounds_dir = ../../../dali-toolkit/sounds -toolkit_styles_dir = ../../../dali-toolkit/styles toolkit_src_dir = ../../../dali-toolkit/internal public_api_src_dir = ../../../dali-toolkit/public-api +if MOBILE_PROFILE +toolkit_styles_dir = ../../../dali-toolkit/styles/mobile +else +toolkit_styles_dir = ../../../dali-toolkit/styles +endif + include ../../../dali-toolkit/images/file.list include ../../../dali-toolkit/sounds/file.list include ../../../dali-toolkit/styles/file.list @@ -99,19 +104,17 @@ publicapishadowviewdir = $(publicapicontrolsdir)/shadow-view publicapisliderdir = $(publicapicontrolsdir)/slider publicapisuperblurviewdir = $(publicapicontrolsdir)/super-blur-view publicapitableviewdir = $(publicapicontrolsdir)/table-view -publicapitextviewdir = $(publicapicontrolsdir)/text-view -publicapitextinputdir = $(publicapicontrolsdir)/text-input +publicapitextcontrolsdir = $(publicapidir)/controls/text-controls publicapitoolbardir = $(publicapicontrolsdir)/tool-bar publicapiviewdir = $(publicapicontrolsdir)/view - publicapibuilderdir = $(publicapidir)/builder publicapifocusmanagerdir = $(publicapidir)/focus-manager -publicapimarkupprocessordir = $(publicapidir)/markup-processor publicapishadereffectsdir = $(publicapidir)/shader-effects publicapibubbleeffectdir = $(publicapidir)/shader-effects/bubble-effect publicapistylingdir = $(publicapidir)/styling publicapitransitioneffectsdir = $(publicapidir)/transition-effects publicapiscriptingdir = $(publicapidir)/scripting +publicapirenderingbackenddir = $(publicapidir)/text publicapi_HEADERS = $(public_api_header_files) publicapicontrols_HEADERS = $(public_api_controls_header_files) @@ -139,17 +142,15 @@ publicapishadowview_HEADERS = $(public_api_shadow_view_header_files) publicapislider_HEADERS = $(public_api_slider_header_files) publicapisuperblurview_HEADERS = $(public_api_super_blur_view_header_files) publicapitableview_HEADERS = $(public_api_table_view_header_files) -publicapitextview_HEADERS = $(public_api_text_view_header_files) -publicapitextinput_HEADERS = $(public_api_text_input_header_files) +publicapitextcontrols_HEADERS = $(public_api_text_controls_header_files) publicapitoolbar_HEADERS = $(public_api_tool_bar_header_files) publicapiview_HEADERS = $(public_api_view_header_files) - publicapibuilder_HEADERS = $(public_api_builder_header_files) publicapifocusmanager_HEADERS = $(public_api_focus_manager_header_files) -publicapimarkupprocessor_HEADERS = $(public_api_markup_processor_header_files) publicapishadereffects_HEADERS = $(public_api_shader_effects_header_files) publicapibubbleeffect_HEADERS = $(public_api_bubble_effect_header_files) publicapistyling_HEADERS = $(public_api_styling_header_files) publicapitransitioneffects_HEADERS = $(public_api_transition_effects_header_files) publicapiscripting_HEADERS = $(public_api_scripting_header_files) +publicapirenderingbackend_HEADERS = $(public_api_rendering_backend_header_files) diff --git a/dali-toolkit/dali-toolkit.h b/dali-toolkit/dali-toolkit.h index ea7bec4..0e705e2 100644 --- a/dali-toolkit/dali-toolkit.h +++ b/dali-toolkit/dali-toolkit.h @@ -73,8 +73,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -82,11 +82,11 @@ #include #include -#include - #include #include +#include + #include #include #include @@ -118,6 +118,8 @@ #include #include +#include + #include #include #include diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp new file mode 100644 index 0000000..83bb423 --- /dev/null +++ b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp @@ -0,0 +1,851 @@ +/* + * Copyright (c) 2015 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 INCLUDE +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + const Vector2 DEFAULT_ATLAS_SIZE( 512.0f, 512.0f ); + const Vector2 DEFAULT_BLOCK_SIZE( 32.0f, 32.0f ); + const uint32_t SINGLE_PIXEL_PADDING( 1u ); + const uint32_t DOUBLE_PIXEL_PADDING( SINGLE_PIXEL_PADDING << 1 ); + const uint32_t FILLED_PIXEL( -1 ); +} + +AtlasManager::AtlasManager() +: mNewAtlasSize( DEFAULT_ATLAS_SIZE ), + mNewBlockSize( DEFAULT_BLOCK_SIZE ), + mAddFailPolicy( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES ), + mFilledPixel( FILLED_PIXEL ) +{ +} + +AtlasManagerPtr AtlasManager::New() +{ + AtlasManagerPtr internal = new AtlasManager(); + return internal; +} + +AtlasManager::~AtlasManager() +{ + for ( uint32_t i = 0; i < mAtlasList.size(); ++i ) + { + delete[] mAtlasList[ i ].mStripBuffer; + } +} + +Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( SizeType width, + SizeType height, + SizeType blockWidth, + SizeType blockHeight, + Pixel::Format pixelformat ) +{ + // Check to see if the atlas is large enough to hold a single block even ? + if ( blockWidth > width || blockHeight > height ) + { + DALI_LOG_ERROR("Atlas %i x %i too small. Dimensions need to be at least %ix%i\n", + width, height, blockWidth, blockHeight ); + return 0; + } + + Dali::Atlas atlas = Dali::Atlas::New( width, height, pixelformat ); + AtlasDescriptor atlasDescriptor; + atlasDescriptor.mAtlas = atlas; + atlasDescriptor.mWidth = width; + atlasDescriptor.mHeight = height; + atlasDescriptor.mBlockWidth = blockWidth; + atlasDescriptor.mBlockHeight = blockHeight; + atlasDescriptor.mPixelFormat = pixelformat; + std::stringstream materialLabel; + materialLabel << "Atlas Material - "; + materialLabel << mAtlasList.size(); + atlasDescriptor.mMaterial = Material::New( materialLabel.str() ); + atlasDescriptor.mMaterial.SetDiffuseTexture( atlas ); + atlasDescriptor.mNextFreeBlock = 1u; // indicate next free block will be the first ( +1 ) + + // What size do we need for this atlas' strip buffer ( assume 32bit pixel format )? + uint32_t neededStripSize =( blockWidth > blockHeight - DOUBLE_PIXEL_PADDING ? blockWidth : blockHeight - DOUBLE_PIXEL_PADDING ) << 2; + atlasDescriptor.mStripBuffer = new PixelBuffer[ neededStripSize ]; + memset( atlasDescriptor.mStripBuffer, 0, neededStripSize ); + + atlasDescriptor.mHorizontalStrip = BufferImage::New( atlasDescriptor.mStripBuffer, + blockWidth, + SINGLE_PIXEL_PADDING, + pixelformat ); + + atlasDescriptor.mVerticalStrip = BufferImage::New( atlasDescriptor.mStripBuffer, + SINGLE_PIXEL_PADDING, + blockHeight - DOUBLE_PIXEL_PADDING, + pixelformat ); + atlasDescriptor.mFilledPixelImage = BufferImage::New( reinterpret_cast< PixelBuffer* >( &mFilledPixel ), 1, 1, pixelformat ); + atlas.Upload( atlasDescriptor.mFilledPixelImage, 0, 0 ); + mAtlasList.push_back( atlasDescriptor ); + return mAtlasList.size(); +} + +void AtlasManager::SetAddPolicy( Toolkit::AtlasManager::AddFailPolicy policy ) +{ + mAddFailPolicy = policy; +} + +void AtlasManager::Add( const BufferImage& image, + Toolkit::AtlasManager::AtlasSlot& slot, + Toolkit::AtlasManager::AtlasId atlas ) +{ + // See if there's a slot in an atlas that matches the requirements of this image + // A bitmap must be sliceable into a single atlas + Pixel::Format pixelFormat = image.GetPixelFormat(); + SizeType width = image.GetWidth(); + SizeType height = image.GetHeight(); + SizeType blockArea = 0; + SizeType totalBlocks = 0; + SizeType foundAtlas = 0; + SizeType index = 0; + slot.mImageId = 0; + + AtlasSlotDescriptor desc; + + // If there is a preferred atlas then check for room in that first + if ( atlas-- ) + { + foundAtlas = CheckAtlas( atlas, width, height, pixelFormat, blockArea, totalBlocks ); + } + + // Search current atlases to see if there is a good match + + while( !foundAtlas && index < mAtlasList.size() ) + { + foundAtlas = CheckAtlas( index, width, height, pixelFormat, blockArea, totalBlocks ); + ++index; + } + + // If we can't find a suitable atlas then check the policy to determine action + if ( !foundAtlas-- ) + { + if ( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES == mAddFailPolicy ) + { + SizeType newAtlas = CreateAtlas( mNewAtlasSize.x, mNewAtlasSize.y, mNewBlockSize.x, mNewBlockSize.y, pixelFormat ); + if ( !newAtlas-- ) + { + return; + } + else + { + foundAtlas = CheckAtlas( newAtlas, width, height, pixelFormat, blockArea, totalBlocks ); + } + } + + if ( Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy || !foundAtlas-- ) + { + // Haven't found an atlas for this image!!!!!! + return; + } + } + + // Work out where the blocks are we're going to use + for ( SizeType i = 0; i < blockArea; ++i ) + { + // Is there currently a next free block available ? + if ( mAtlasList[ foundAtlas ].mNextFreeBlock ) + { + // Yes, so use this for our next block + SizeType selectedBlock = mAtlasList[ foundAtlas ].mNextFreeBlock - 1u; + desc.mBlocksList.PushBack( selectedBlock ); + + // Any blocks going to be available after this one (adjust to store +1 )? + selectedBlock++; + selectedBlock++; + if ( selectedBlock > totalBlocks ) + { + // No so start trying to use free blocks list + selectedBlock = 0; + } + mAtlasList[ foundAtlas ].mNextFreeBlock = selectedBlock; + } + else + { + // Our next block must be from the free list, fetch from the start of the list + desc.mBlocksList.PushBack( mAtlasList[ foundAtlas ].mFreeBlocksList[ 0 ] ); + mAtlasList[ foundAtlas ].mFreeBlocksList.Remove( mAtlasList[ foundAtlas ].mFreeBlocksList.Begin() ); + } + } + + desc.mImageWidth = width; + desc.mImageHeight = height; + desc.mAtlasId = foundAtlas + 1u; + desc.mCount = 1u; + + // See if there's a previously freed image ID that we can assign to this new image + uint32_t imageId = 0; + for ( uint32_t i = 0; i < mImageList.size(); ++i ) + { + if ( !mImageList[ i ].mCount ) + { + imageId = i + 1u; + break; + } + } + if ( !imageId ) + { + mImageList.push_back( desc ); + slot.mImageId = mImageList.size(); + } + else + { + mImageList[ imageId - 1u ] = desc; + slot.mImageId = imageId; + } + slot.mAtlasId = foundAtlas + 1u; + UploadImage( image, desc ); +} + +AtlasManager::SizeType AtlasManager::CheckAtlas( SizeType atlas, + SizeType width, + SizeType height, + Pixel::Format pixelFormat, + SizeType& blockArea, + SizeType& totalBlocks ) +{ + if ( pixelFormat == mAtlasList[ atlas ].mPixelFormat ) + { + // Check to see if there are any unused blocks in this atlas to accomodate our image + SizeType blocksInX = mAtlasList[ atlas ].mWidth / mAtlasList[ atlas ].mBlockWidth; + SizeType blocksInY = mAtlasList[ atlas ].mHeight / mAtlasList[ atlas ].mBlockHeight; + totalBlocks = blocksInX * blocksInY; + SizeType blocksFree = mAtlasList[ atlas ].mNextFreeBlock ? + totalBlocks - mAtlasList[ atlas ].mNextFreeBlock + 1u : + mAtlasList[ atlas ].mFreeBlocksList.Size(); + + // Check to see if the image will fit in these blocks, if not we'll need to create a new atlas + if ( blocksFree + && width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mBlockWidth + && height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mBlockHeight ) + { + blockArea = 1u; + return ( atlas + 1u ); + } + } + return 0; +} + +void AtlasManager::CreateMesh( SizeType atlas, + SizeType imageWidth, + SizeType imageHeight, + const Vector2& position, + SizeType widthInBlocks, + SizeType heightInBlocks, + Dali::MeshData& meshData, + AtlasSlotDescriptor& desc ) +{ + Dali::MeshData::Vertex vertex; + Dali::MeshData::VertexContainer vertices; + Dali::MeshData::FaceIndices faces; + Dali::MeshData::FaceIndex faceIndex = 0; + meshData.SetHasNormals( false ); + meshData.SetHasColor( true ); + meshData.SetHasTextureCoords( true ); + + SizeType blockWidth = mAtlasList[ atlas ].mBlockWidth; + SizeType blockHeight = mAtlasList[ atlas ].mBlockHeight; + + float vertexBlockWidth = static_cast< float >( blockWidth ); + float vertexBlockHeight = static_cast< float >( blockHeight ); + + SizeType width = mAtlasList[ atlas ].mWidth; + SizeType height = mAtlasList[ atlas ].mHeight; + + SizeType atlasWidthInBlocks = width / blockWidth; + + // Get the normalized size of a texel in both directions + // TODO when texture resizing and passing texture size via uniforms is available, + // we will encode pixel positions into the vertex data rather than normalized + // meaning that geometry needn't be changed on an atlas resize + float texelX = 1.0f / static_cast< float >( width ); + float texelY = 1.0f / static_cast< float >( height ); + + // Get the normalized size of a block in texels + float texelBlockWidth = texelX * vertexBlockWidth; + float texelBlockHeight = texelY * vertexBlockHeight; + + // Get partial block space + float vertexEdgeWidth = static_cast< float >( imageWidth % blockWidth ); + float vertexEdgeHeight = static_cast< float >( imageHeight % blockHeight ); + + // And in texels + float texelEdgeWidth = vertexEdgeWidth * texelX; + float texelEdgeHeight = vertexEdgeHeight * texelY; + + // Block by block create the two triangles for the quad + SizeType blockIndex = 0; + float ndcWidth; + float ndcHeight; + float ndcVWidth; + float ndcVHeight; + + Vector2 topLeft = position; + + for ( SizeType y = 0; y < heightInBlocks; ++y ) + { + + float currentX = position.x; + + if ( ( heightInBlocks - 1u ) == y && vertexEdgeHeight > 0.0f ) + { + ndcHeight = texelEdgeHeight; + ndcVHeight = vertexEdgeHeight; + } + else + { + ndcHeight = texelBlockHeight; + ndcVHeight = vertexBlockHeight; + } + + for ( SizeType x = 0; x < widthInBlocks; ++x ) + { + SizeType block = desc.mBlocksList[ blockIndex++ ]; + + float fBlockX = texelBlockWidth * static_cast< float >( block % atlasWidthInBlocks ); + float fBlockY = texelBlockHeight * static_cast< float >( block / atlasWidthInBlocks ); + + // Add on texture filtering compensation + fBlockX += texelX; + fBlockY += texelY; + + if ( ( widthInBlocks - 1u ) == x && vertexEdgeWidth > 0.0f ) + { + ndcWidth = texelEdgeWidth; + ndcVWidth = vertexEdgeWidth; + } + else + { + ndcWidth = texelBlockWidth; + ndcVWidth = vertexBlockWidth; + } + + // Top left + vertex.x = topLeft.x; + vertex.y = topLeft.y; + vertex.z = 0.0f; + vertex.u = fBlockX; + vertex.v = fBlockY; + + vertices.push_back( vertex ); + + // Top Right + vertex.x = topLeft.x + ndcVWidth; + vertex.y = topLeft.y; + vertex.z = 0.0f; + vertex.u = fBlockX + ndcWidth; + vertex.v = fBlockY; + + vertices.push_back( vertex ); + + // Bottom Left + vertex.x = topLeft.x; + vertex.y = topLeft.y + ndcVHeight; + vertex.z = 0.0f; + vertex.u = fBlockX; + vertex.v = fBlockY + ndcHeight; + + vertices.push_back( vertex ); + + // Bottom Right + topLeft.x += ndcVWidth; + vertex.x = topLeft.x; + vertex.y = topLeft.y + ndcVHeight; + vertex.z = 0.0f; + vertex.u = fBlockX + ndcWidth; + vertex.v = fBlockY + ndcHeight; + + vertices.push_back( vertex ); + + // Six indices in counter clockwise winding + faces.push_back( faceIndex + 1u ); + faces.push_back( faceIndex ); + faces.push_back( faceIndex + 2u ); + faces.push_back( faceIndex + 2u ); + faces.push_back( faceIndex + 3u ); + faces.push_back( faceIndex + 1u ); + faceIndex += 4; + } + + // Move down a row + topLeft.x = currentX; + topLeft.y += vertexBlockHeight; + } + + // If there's only one block then skip this next vertex optimisation + if ( widthInBlocks * heightInBlocks > 1 ) + { + Dali::MeshData::VertexContainer optimizedVertices; + OptimizeVertices( vertices, faces, optimizedVertices ); + meshData.SetVertices( optimizedVertices ); + } + else + { + meshData.SetVertices( vertices ); + } + + meshData.SetFaceIndices( faces ); + meshData.SetMaterial( mAtlasList[ atlas ].mMaterial ); +} + +void AtlasManager::PrintMeshData( const MeshData& meshData ) +{ + std::cout << "\nMesh Data for Image: VertexCount = " << meshData.GetVertexCount(); + std::cout << ", Triangles = " << meshData.GetFaceCount() << std::endl; + + Dali::MeshData::VertexContainer vertices = meshData.GetVertices(); + Dali::MeshData::FaceIndices faces = meshData.GetFaces(); + + for ( SizeType v = 0; v < vertices.size(); ++v ) + { + std::cout << " Vertex(" << v << ") x = " << vertices[v].x << ", "; + std::cout << "y = " << vertices[v].y << ", " << "z = " << vertices[v].z << ", "; + std::cout << "u = " << vertices[v].u << ", " << "v = " << vertices[v].v << std::endl; + } + + std::cout << "\n Indices: "; + for ( SizeType i = 0; i < faces.size(); ++i ) + { + std::cout << " " << faces[ i ]; + } + std::cout << std::endl; +} + +void AtlasManager::OptimizeVertices( const MeshData::VertexContainer& in, + MeshData::FaceIndices& faces, + MeshData::VertexContainer& out ) +{ + unsigned short vertexIndex = 0; + + // We could check to see if blocks are next to each other, but it's probably just as quick to compare verts + for ( SizeType i = 0; i < faces.size(); ++i ) + { + // Fetch a vertex, has it already been assigned? + bool foundVertex = false; + Dali::MeshData::Vertex v = in[ faces [ i ] ]; + for ( SizeType j = 0; j < vertexIndex; ++j ) + { + if ( v.x == out[ j ].x && v.y == out[ j ].y && v.z == out[ j ].z && + v.u == out[ j ].u && v.v == out[ j ].v && v.nX == out[ j ].nX && + v.nY == out[ j ].nY && v.nZ == out[ j ].nZ ) + { + // Yes, so store this down as the vertex to use + faces[ i ] = j; + foundVertex = true; + break; + } + } + + // Did we find a vertex ? + if ( !foundVertex ) + { + // Add a new vertex + faces[ i ] = vertexIndex++; + out.push_back( v ); + } + } +} + +void AtlasManager::StitchMesh( MeshData& first, + const MeshData& second, + bool optimize ) +{ + + // Would be much quicker to be able to get a non-const reference to these containers and update in situ + MeshData::VertexContainer v1 = first.GetVertices(); + MeshData::VertexContainer v2 = second.GetVertices(); + MeshData::FaceIndices f1 = first.GetFaces(); + MeshData::FaceIndices f2 = second.GetFaces(); + + uint32_t vc1 = first.GetVertexCount(); + uint32_t vc2 = second.GetVertexCount(); + + for ( uint32_t v = 0; v < vc2; ++v ) + { + v1.push_back( v2[ v ] ); + } + + for ( uint32_t f = 0; f < f2.size(); ++f ) + { + f1.push_back( f2[ f ] + vc1 ); + } + + if ( optimize ) + { + MeshData::VertexContainer optimizedVertices; + OptimizeVertices( v1, f1, optimizedVertices ); + first.SetVertices( optimizedVertices ); + } + else + { + first.SetVertices( v1 ); + } + + first.SetFaceIndices( f1 ); +} + +void AtlasManager::StitchMesh( const MeshData& first, + const MeshData& second, + MeshData& out, + bool optimize ) +{ + MeshData::VertexContainer v1 = first.GetVertices(); + MeshData::VertexContainer v2 = second.GetVertices(); + MeshData::FaceIndices f1 = first.GetFaces(); + MeshData::FaceIndices f2 = second.GetFaces(); + + uint32_t vc1 = first.GetVertexCount(); + uint32_t vc2 = second.GetVertexCount(); + + MeshData::VertexContainer vertices; + + MeshData::FaceIndices faces; + + MeshData::Vertex vertex; + + for ( uint32_t v = 0; v < vc1; ++v ) + { + vertices.push_back( v1[ v ] ); + } + + for ( uint32_t v = 0; v < vc2; ++v ) + { + vertices.push_back( v2[ v ] ); + } + + for ( uint32_t f = 0; f < f1.size(); ++f ) + { + faces.push_back( f1[ f ] ); + } + + for ( uint32_t f = 0; f < f2.size(); ++f ) + { + faces.push_back( f2[ f ] + vc1 ); + } + + if ( optimize ) + { + MeshData::VertexContainer optimizedVertices; + OptimizeVertices( vertices, faces, optimizedVertices ); + out.SetVertices( optimizedVertices ); + } + else + { + out.SetVertices( vertices ); + } + + out.SetMaterial( first.GetMaterial() ); + out.SetFaceIndices( faces ); +} + +void AtlasManager::UploadImage( const BufferImage& image, + const AtlasSlotDescriptor& desc ) +{ + // Get the atlas to upload the image to + SizeType atlas = desc.mAtlasId - 1u; + + // Check to see that the pixel formats are compatible + if ( image.GetPixelFormat() != mAtlasList[ atlas ].mPixelFormat ) + { + DALI_LOG_ERROR("Cannot upload an image with a different PixelFormat to the Atlas.\n"); + return; + } + + SizeType atlasBlockWidth = mAtlasList[ atlas ].mBlockWidth; + SizeType atlasBlockHeight = mAtlasList[ atlas ].mBlockHeight; + SizeType atlasWidthInBlocks = mAtlasList[ atlas ].mWidth / mAtlasList[ atlas ].mBlockWidth; + + SizeType block = desc.mBlocksList[ 0 ]; + SizeType blockX = block % atlasWidthInBlocks; + SizeType blockY = block / atlasWidthInBlocks; + SizeType blockOffsetX = blockX * atlasBlockWidth; + SizeType blockOffsetY = blockY * atlasBlockHeight; + + SizeType width = image.GetWidth(); + SizeType height = image.GetHeight(); + + // Blit image 1 pixel to the right and down into the block to compensate for texture filtering + if ( !mAtlasList[ atlas ].mAtlas.Upload( image, + blockOffsetX + SINGLE_PIXEL_PADDING, + blockOffsetY + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading image to Atlas Failed!.\n"); + } + + // If this is the first block then we need to keep the first pixel free for underline texture + if ( block ) + { + + // Blit top strip + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip, + blockOffsetX, + blockOffsetY ) ) + { + DALI_LOG_ERROR("Uploading top strip to Atlas Failed!\n"); + } + + // Blit left strip + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip, + blockOffsetX, + blockOffsetY + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n"); + } + } + + // Blit bottom strip + if ( blockOffsetY + height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mHeight ) + { + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip, + blockOffsetX, + blockOffsetY + height + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading bottom strip to Atlas Failed!.\n"); + } + } + + // Blit right strip + if ( blockOffsetX + width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mWidth ) + { + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip, + blockOffsetX + width + SINGLE_PIXEL_PADDING, + blockOffsetY + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading right strip to Atlas Failed!.\n"); + } + } +} + +void AtlasManager::GenerateMeshData( ImageId id, + const Vector2& position, + MeshData& meshData ) +{ + // Read the atlas Id to use for this image + SizeType imageId = id - 1u; + SizeType atlas = mImageList[ imageId ].mAtlasId - 1u; + SizeType width = mImageList[ imageId ].mImageWidth; + SizeType height = mImageList[ imageId ].mImageHeight; + + SizeType widthInBlocks = width / mAtlasList[ atlas ].mBlockWidth; + if ( width % mAtlasList[ atlas ].mBlockWidth ) + { + widthInBlocks++; + } + SizeType heightInBlocks = height / mAtlasList[ atlas ].mBlockHeight; + if ( height % mAtlasList[ atlas ].mBlockHeight ) + { + heightInBlocks++; + } + + CreateMesh( atlas, width, height, position, widthInBlocks, heightInBlocks, meshData, mImageList[ imageId ] ); + + // Mesh created so increase the reference count + mImageList[ imageId ].mCount++; +} + +Dali::Atlas AtlasManager::GetAtlasContainer( AtlasId atlas ) const +{ + Dali::Atlas null; + if ( !atlas || atlas > mAtlasList.size( ) ) + { + + DALI_LOG_ERROR("Cannot get Atlas from AtlasID ( doesn't exist ).\n"); + return null; + } + return mAtlasList[ atlas -1u ].mAtlas; +} + +bool AtlasManager::Remove( ImageId id ) +{ + // Decrements the reference count of this image, and removes the blocks if zero. + SizeType imageId = id - 1u; + bool removed = false; + + if ( id > mImageList.size() ) + { + DALI_LOG_ERROR("Atlas was asked to free an invalid imageID: %i\n", id ); + return false; + } + + // If we attempt to free an image that is already freed then do nothing, other than log + if ( !mImageList[ imageId ].mCount ) + { + DALI_LOG_ERROR("Atlas was asked to free an imageID: %i, that has already been freed!\n", id ); + return false; + } + + if ( 1u == --mImageList[ imageId ].mCount ) + { + // 'Remove the blocks' from this image and add to the atlas' freelist + removed = true; + mImageList[ imageId ].mCount = 0; + SizeType atlas = mImageList[ imageId ].mAtlasId - 1u; + for ( uint32_t i = 0; i < mImageList[ imageId ].mBlocksList.Size(); ++i ) + { + mAtlasList[ atlas ].mFreeBlocksList.PushBack( mImageList[ imageId ].mBlocksList[ i ] ); + } + } + return removed; +} + +AtlasManager::AtlasId AtlasManager::GetAtlas( ImageId id ) const +{ + if ( id && id <= mImageList.size() ) + { + return mImageList[ id - 1u ].mAtlasId; + } + else + { + return 0; + } +} + +void AtlasManager::SetNewAtlasSize( const Vector2& size, + const Vector2& blockSize ) +{ + mNewAtlasSize = size; + mNewBlockSize = blockSize; +} + +Vector2 AtlasManager::GetBlockSize( AtlasId atlas ) +{ + if ( atlas && atlas <= mAtlasList.size() ) + { + return Vector2( static_cast< float >( mAtlasList[ atlas - 1u ].mBlockWidth ), + static_cast< float >( mAtlasList[ atlas - 1u ].mBlockHeight) ); + } + else + { + return Vector2::ZERO; + } +} + +Vector2 AtlasManager::GetAtlasSize( AtlasId atlas ) +{ + if ( atlas && atlas <= mAtlasList.size() ) + { + return Vector2( static_cast< float >( mAtlasList[ atlas - 1u ].mWidth ), + static_cast< float >( mAtlasList[ atlas - 1u ].mHeight ) ); + } + else + { + return Vector2::ZERO; + } +} + +AtlasManager::SizeType AtlasManager::GetFreeBlocks( AtlasId atlas ) const +{ + if ( atlas && atlas <= mAtlasList.size() ) + { + uint32_t index = atlas - 1u; + uint32_t width = mAtlasList[ index ].mWidth; + uint32_t height = mAtlasList[ index ].mHeight; + uint32_t blockWidth = mAtlasList[ index ].mBlockWidth; + uint32_t blockHeight = mAtlasList[ index ].mBlockHeight; + + SizeType widthInBlocks = width / blockWidth; + SizeType heightInBlocks = height / blockHeight; + uint32_t blockCount = widthInBlocks * heightInBlocks; + + // Check free previously unallocated blocks and any free blocks + blockCount -= mAtlasList[ index ].mNextFreeBlock - mAtlasList[ index ].mFreeBlocksList.Size(); + return blockCount; + } + else + { + return 0; + } +} + +AtlasManager::SizeType AtlasManager::GetAtlasCount() const +{ + return mAtlasList.size(); +} + +Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas ) +{ + if ( !atlas || atlas > mAtlasList.size( ) ) + { + + DALI_LOG_ERROR("Cannot get Atlas from AtlasID ( doesn't exist ).\n"); + return Pixel::L8; + } + return mAtlasList[ atlas -1u ].mPixelFormat; +} + +void AtlasManager::GetMetrics( Toolkit::AtlasManager::Metrics& metrics ) +{ + Toolkit::AtlasManager::AtlasMetricsEntry entry; + uint32_t textureMemoryUsed = 0; + uint32_t atlasCount = mAtlasList.size(); + metrics.mAtlasCount = atlasCount; + metrics.mAtlasMetrics.Resize(0); + + for ( uint32_t i = 0; i < atlasCount; ++i ) + { + SizeType width = mAtlasList[ i ].mWidth; + SizeType height = mAtlasList[ i ].mHeight; + SizeType blockWidth = mAtlasList[ i ].mBlockWidth; + SizeType blockHeight = mAtlasList[ i ].mBlockHeight; + + entry.mWidth = width; + entry.mHeight = height; + entry.mBlockWidth = blockWidth; + entry.mBlockHeight = blockHeight; + entry.mTotalBlocks = ( width / blockWidth ) * ( height / blockHeight ); + uint32_t reuseBlocks = mAtlasList[ i ].mFreeBlocksList.Size(); + entry.mBlocksUsed = mAtlasList[ i ].mNextFreeBlock ? mAtlasList[ i ].mNextFreeBlock - reuseBlocks - 1u: entry.mTotalBlocks - reuseBlocks; + entry.mPixelFormat = GetPixelFormat( i + 1 ); + + metrics.mAtlasMetrics.PushBack( entry ); + + uint32_t size = width * height; + if ( entry.mPixelFormat == Pixel::BGRA8888 ) + { + size <<= 2; + } + + textureMemoryUsed += size; + + } + metrics.mTextureMemoryUsed = textureMemoryUsed; +} + + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + + diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h new file mode 100644 index 0000000..0656da7 --- /dev/null +++ b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h @@ -0,0 +1,249 @@ +#ifndef __DALI_TOOLKIT_ATLAS_MANAGER_IMPL_H__ +#define __DALI_TOOLKIT_ATLAS_MANAGER_IMPL_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +class AtlasManager; + +} // namespace Toolkit + +namespace Toolkit +{ + +namespace Internal +{ + +typedef Dali::Vector< Toolkit::AtlasManager::AtlasSlot > slotContainer; + +class AtlasManager; +typedef IntrusivePtr AtlasManagerPtr; + +class AtlasManager : public Dali::BaseObject +{ +public: + + typedef uint32_t SizeType; + typedef SizeType AtlasId; + typedef SizeType ImageId; + + /** + * @brief Internal storage of atlas attributes and image upload results + */ + struct AtlasDescriptor + { + Dali::Atlas mAtlas; // atlas image + SizeType mWidth; // width of atlas + SizeType mHeight; // height of atlas + SizeType mBlockWidth; // width of a block in atlas + SizeType mBlockHeight; // height of a block in atlas + Pixel::Format mPixelFormat; // pixel format used by atlas + BufferImage mHorizontalStrip; // Image used to pad upload + BufferImage mVerticalStrip; // Image used to pad upload + BufferImage mFilledPixelImage; // Image used by atlas for operations such as underline + PixelBuffer* mStripBuffer; // Blank image buffer used to pad upload + Material mMaterial; // material used for atlas texture + SizeType mNextFreeBlock; // next free block will be placed here ( actually +1 ) + Dali::Vector< SizeType > mFreeBlocksList; // unless there are any previously freed blocks + }; + + struct AtlasSlotDescriptor + { + SizeType mCount; // Reference count for this slot + SizeType mImageWidth; // Width of image stored + SizeType mImageHeight; // Height of image stored + AtlasId mAtlasId; // Image is stored in this Atlas + Dali::Vector< SizeType > mBlocksList; // List of blocks within atlas used for image + }; + + AtlasManager(); + + /** + * Create a new AtlasManager + */ + static AtlasManagerPtr New(); + + virtual ~AtlasManager(); + + /** + * @copydoc: Toolkit::AtlasManager::CreateAtlas + */ + AtlasId CreateAtlas( SizeType width, + SizeType height, + SizeType blockWidth, + SizeType blockHeight, + Pixel::Format pixelformat ); + + /** + * @copydoc Toolkit::AtlasManager::SetAddPolicy + */ + void SetAddPolicy( Toolkit::AtlasManager::AddFailPolicy policy ); + + /** + * @copydoc Toolkit::AtlasManager::Add + */ + void Add( const BufferImage& image, + Toolkit::AtlasManager::AtlasSlot& slot, + Toolkit::AtlasManager::AtlasId atlas ); + + /** + * @copydoc Toolkit::AtlasManager::GenerateMeshData + */ + void GenerateMeshData( ImageId id, + const Vector2& position, + MeshData& mesh ); + + /** + * @copydoc Toolkit::AtlasManager::StitchMesh + */ + void StitchMesh( MeshData& first, + const MeshData& second, + bool optimize ); + + /** + * @copydoc Toolkit::AtlasManager::StitchMesh + */ + void StitchMesh( const MeshData& first, + const MeshData& second, + MeshData& out, bool optimize ); + + /** + * @copydoc Toolkit::AtlasManager::Remove + */ + bool Remove( ImageId id ); + + /** + * @copydoc Toolkit::AtlasManager::GetAtlasContainer + */ + Dali::Atlas GetAtlasContainer( AtlasId atlas ) const; + + /** + * @copydoc Toolkit::AtlasManager::GetAtlas + */ + AtlasId GetAtlas( ImageId id ) const; + + /** + * @copydoc Toolkit::AtlasManager::SetNewAtlasSize + */ + void SetNewAtlasSize( const Vector2& size, + const Vector2& blockSize ); + + /** + * @copydoc Toolkit::AtlasManager::GetAtlasSize + */ + Vector2 GetAtlasSize( AtlasId atlas ); + + /** + * @copydoc Toolkit::AtlasManager::GetBlockSize + */ + Vector2 GetBlockSize( AtlasId atlas ); + + /** + * @copydoc Toolkit::AtlasManager::GetFreeBlocks + */ + SizeType GetFreeBlocks( AtlasId atlas ) const; + + /* + * @copydoc Toolkit::AtlasManager::GetAtlasCount + */ + SizeType GetAtlasCount() const; + + /** + * @copydoc Toolkit::AtlasManager::GetPixelFormat + */ + Pixel::Format GetPixelFormat( AtlasId atlas ); + + /** + * @copydoc Toolkit::AtlasManager::GetMetrics + */ + void GetMetrics( Toolkit::AtlasManager::Metrics& metrics ); + +private: + + std::vector< AtlasDescriptor > mAtlasList; // List of atlases created + std::vector< AtlasSlotDescriptor > mImageList; // List of bitmaps store in atlases + + SizeType CheckAtlas( SizeType atlas, + SizeType width, + SizeType height, + Pixel::Format pixelFormat, + SizeType& blockArea, + SizeType& totalBlocks ); + + void CreateMesh( SizeType atlas, + SizeType imageWidth, + SizeType imageHeight, + const Vector2& position, + SizeType widthInBlocks, + SizeType heightInBlocks, + Dali::MeshData& meshData, + AtlasSlotDescriptor& desc ); + + void OptimizeVertices( const MeshData::VertexContainer& in, + MeshData::FaceIndices& faces, + MeshData::VertexContainer& out ); + + void UploadImage( const BufferImage& image, + const AtlasSlotDescriptor& desc ); + + void PrintMeshData( const MeshData& meshData ); + + Vector2 mNewAtlasSize; + Vector2 mNewBlockSize; + Toolkit::AtlasManager::AddFailPolicy mAddFailPolicy; + uint32_t mFilledPixel; +}; + +} // namespace Internal + +inline const Internal::AtlasManager& GetImplementation(const Toolkit::AtlasManager& manager) +{ + DALI_ASSERT_ALWAYS( manager && "AtlasManager handle is empty" ); + + const BaseObject& handle = manager.GetBaseObject(); + + return static_cast(handle); +} + +inline Internal::AtlasManager& GetImplementation(Toolkit::AtlasManager& manager) +{ + DALI_ASSERT_ALWAYS( manager && "AtlasManager handle is empty" ); + + BaseObject& handle = manager.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + + + #endif // __DALI_TOOLKIT_ATLAS_MANAGER_IMPL_H__ \ No newline at end of file diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager.cpp b/dali-toolkit/internal/atlas-manager/atlas-manager.cpp new file mode 100644 index 0000000..6d21245 --- /dev/null +++ b/dali-toolkit/internal/atlas-manager/atlas-manager.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015 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 +{ + +AtlasManager::AtlasManager() +{ +} + +AtlasManager::~AtlasManager() +{ +} + +AtlasManager AtlasManager::New() +{ + Internal::AtlasManagerPtr internal = Internal::AtlasManager::New(); + return AtlasManager(internal.Get()); +} + +AtlasManager::AtlasManager(Internal::AtlasManager *impl) + : BaseHandle(impl) +{ +} + +AtlasManager::AtlasId AtlasManager::CreateAtlas( SizeType width, + SizeType height, + SizeType blockWidth, + SizeType blockHeight, + Pixel::Format pixelformat ) +{ + return GetImplementation(*this).CreateAtlas( width, height, blockWidth, blockHeight, pixelformat ); +} + +void AtlasManager::SetAddPolicy( AddFailPolicy policy ) +{ + GetImplementation(*this).SetAddPolicy( policy ); +} + +void AtlasManager::Add( const BufferImage& image, + AtlasManager::AtlasSlot& slot, + AtlasManager::AtlasId atlas ) +{ + GetImplementation(*this).Add( image, slot, atlas ); +} + +bool AtlasManager::Remove( ImageId id ) +{ + return GetImplementation(*this).Remove( id ); +} + +void AtlasManager::GenerateMeshData( ImageId id, + const Vector2& position, + MeshData& meshData) +{ + GetImplementation(*this).GenerateMeshData( id, + position, + meshData ); +} + +void AtlasManager::StitchMesh( MeshData& first, + const MeshData& second, + bool optimize ) +{ + GetImplementation(*this).StitchMesh( first, second, optimize ); +} + +void AtlasManager::StitchMesh( const MeshData& first, + const MeshData& second, + MeshData& out, + bool optimize ) +{ + GetImplementation(*this).StitchMesh( first, second, out, optimize ); +} + +Dali::Atlas AtlasManager::GetAtlasContainer( AtlasId atlas ) const +{ + return GetImplementation(*this).GetAtlasContainer( atlas ); +} + +AtlasManager::AtlasId AtlasManager::GetAtlas( ImageId id ) +{ + return GetImplementation(*this).GetAtlas( id ); +} + +Vector2 AtlasManager::GetBlockSize( AtlasId atlas ) +{ + return GetImplementation(*this).GetBlockSize( atlas ); +} + +Vector2 AtlasManager::GetAtlasSize( AtlasId atlas ) +{ + return GetImplementation(*this).GetAtlasSize( atlas ); +} + +AtlasManager::SizeType AtlasManager::GetFreeBlocks( AtlasId atlas ) +{ + return GetImplementation(*this).GetFreeBlocks( atlas ); +} + +void AtlasManager::SetNewAtlasSize( const Vector2& size, + const Vector2& blockSize ) +{ + GetImplementation(*this).SetNewAtlasSize( size, blockSize ); +} + +AtlasManager::SizeType AtlasManager::GetAtlasCount() const +{ + return GetImplementation(*this).GetAtlasCount(); +} + +Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas ) +{ + return GetImplementation(*this).GetPixelFormat( atlas ); +} + +void AtlasManager::GetMetrics( Metrics& metrics ) +{ + return GetImplementation(*this).GetMetrics( metrics ); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager.h b/dali-toolkit/internal/atlas-manager/atlas-manager.h new file mode 100644 index 0000000..9263ea4 --- /dev/null +++ b/dali-toolkit/internal/atlas-manager/atlas-manager.h @@ -0,0 +1,396 @@ +#ifndef __DALI_TOOLKIT_ATLAS_MANAGER_H__ +#define __DALI_TOOLKIT_ATLAS_MANAGER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal DALI_INTERNAL +{ + +class AtlasManager; + +} // namespace Internal + +/** + * AtlasManager + * ------------ + * + * Creates and manages additions and removals of images from Texture Atlases + * + * The AtlasManager will match pixeltype and optimal block use to determine + * the appropriate atlas to upload an image to. + * + * A policy can be specified to determine the action the AtlasManager will carry + * out, should it not be able to add an image. This can return an error, or create + * a new atlas of pre-determined dimensions to accomodate the new image. + * + * Images are referenced by an ImageId once they have been successfully uploaded. + * + * Once an image has been successfully uploaded, Geometry can be generated by passing + * the ImageId to the GenerateMeshData method and geometry can be consolidated via + * the StitchMesh method. + * + * Images are reference counted once mesh data has been generated. An image is removed + * from the Atlas via the Remove( ImageId ) method. This unreferences the image and only + * physically removes it from the atlas once all references have been freed. + * + * If the AddPolicy is set to generate and error if an image can't be uploaded, then it + * is the applications responsibility to deal with the situation. An error will be indicated + * with an ImageId of 0. + * + * Examples using the AtlasManager + * + * Create or obtain the AtlasManager + * @code + * + * AtlasManager manager = AtlasManager::Get(); + * + * @endcode + * + * Set the AtlasManager AddPolicy + * + * @code + * + * // Tell the atlas manager to create a new atlas, if it needs to + * manager.SetAddPolicy( FAIL_ON_ADD_CREATES ); + * + * // Tell the atlas manager to return an error, if it can't add an image + * manager.SetAddPolicy( FAIL_ON_ADD_FAILS ); + * + * @endcode + * + * Simple add and removal of BufferImage to and from an atlas + * + * @code + * + * // Structure returned by AtlasManager operations + * AtlasSlot slot; + * + * // Add image to an atlas ( will be created if none suitable exists ) + * manager.Add( bitmapImage, slot ); + * + * // slot.mImage returns the imageId for the bitmap, slot.mAtlas indicates the atlasId + * // that the image was added to. The imageId is used to communicate with the AtlasManager + * uint32_t imageId = slot.mImage; + * if ( !imageId ) + * { + * // Addition has failed..... + * } + * ... + * ... + * // Done with image, so remove from atlas, if not being used elsewhere + * manager.Remove( imageId ); + * + * @endcode + * + * Create a Specific Atlas for adding BufferImages to + * + * @code + * + * // Create an RGB888 atlas of 2048x2848, with a blocksize of 128x128 + * uint32_t atlas = manager.CreateAtlas( 2048u, 2048u, 128u, 128u, Pixel::RGB888 ); + * + * // Add an image to a preferred atlas ( note not specifying atlas may still result + * // in the bitmap being added to the atlas above ) + * manager.Add( bitmapImage, slot, atlas ); + * + * @endcode + * + * Create Geometry for a previously added image + * + * @code + * + * // Top left corner of geometry to be generated + * Vector2 position( 1.0f, 1.0f ); + * + * // Geometry will end up here! + * MeshData meshData; + * manager.GenerateMeshData( imageId, position, meshData ); + * + * @endcode + * + * Generating Geometry from multiple images in the same atlas + * + * @code + * + * MeshData firstMesh; + * MeshData secondMesh; + * manager.GenerateMeshData( imageid_1, position_1, firstMesh ); + * manager.GenerateMeshData( imageid_2, position_2, secondMesh ); + * + * // Combine the two meshes. Passing MESH_OPTIMIZE as an optional third parameter will remove duplicate vertices + * manager.StitchMesh( first, second ); + * + * @endcode + * + */ + +class AtlasManager : public BaseHandle +{ +public: + + typedef uint32_t SizeType; + typedef SizeType AtlasId; + typedef SizeType ImageId; + static const bool MESH_OPTIMIZE = true; + + /** + * Metrics structures to describe Atlas Manager state + * + */ + struct AtlasMetricsEntry + { + SizeType mWidth; // width of the atlas in pixels + SizeType mHeight;; // height of the atlas in pixels + SizeType mBlockWidth; // width of a block in pixels + SizeType mBlockHeight; // height of a block in pixels + SizeType mBlocksUsed; // number of blocks used in the atlas + SizeType mTotalBlocks; // total blocks used by atlas + Pixel::Format mPixelFormat; // pixel format of the atlas + }; + + struct Metrics + { + SizeType mAtlasCount; // number of atlases + SizeType mTextureMemoryUsed; // texture memory used by atlases + Dali::Vector< AtlasMetricsEntry > mAtlasMetrics; // container of atlas information + }; + + /** + * Create an AtlasManager handle; this can be initialised with AtlasManager::New() + * Calling member functions with an uninitialised handle is not allowed. + */ + AtlasManager(); + + /** + * @brief Get new instance of AtlasManager object. + * + * @return A handle to the AtlasManager control. + */ + static AtlasManager New(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~AtlasManager(); + + /** + * Policy on failing to add an image + */ + enum AddFailPolicy + { + FAIL_ON_ADD_FAILS, + FAIL_ON_ADD_CREATES + }; + + /** + * @brief Container to hold result of placing texture into atlas + */ + struct AtlasSlot + { + ImageId mImageId; // Id of stored Image + AtlasId mAtlasId; // Id of Atlas containing this slot + }; + + typedef Dali::Vector< AtlasManager::AtlasSlot > slotContainer; + + /** + * @brief Create a blank atlas of specific dimensions and pixel format with a certain block size + * + * @param[in] width desired atlas width in pixels + * @param[in] height desired atlas height in pixels + * @param[in] blockWidth block width to use in atlas in pixels + * @param[in] blockHeight block height to use in atlas in pixels + * @param[in] pixelformat format of a pixel in atlas + * + * @return atlas Id + */ + AtlasId CreateAtlas( SizeType width, + SizeType height, + SizeType blockWidth, + SizeType blockHeight, + Pixel::Format pixelformat = Pixel::RGBA8888 ); + + /** + * @brief Set the policy on failure to add an image to an atlas + * + * @param policy policy to carry out if add fails + */ + void SetAddPolicy( AddFailPolicy policy ); + + /** + * @brief Attempts to add an image to the most suitable atlas + * + * @details Add Policy may dictate that a new atlas is created if it can't presently be placed. + * If an add is made before an atlas is created under this policy, + * then a default size atlas will be created + * + * @param[in] image reference to a bitmapimage + * @param[out] slot result of add operation + * @param[in] atlas optional preferred atlas + */ + void Add( const BufferImage& image, + AtlasSlot& slot, + AtlasId atlas = 0 ); + + /** + * @brief Remove previously added bitmapimage from atlas + * + * @param[in] id ImageId returned in the AtlasSlot from the add operation + * + * @return if true then image has been removed from the atlas + */ + bool Remove( ImageId id ); + + /** + * @brief Generate mesh data for a previously added image + * + * @param[in] id Image Id returned in the AtlasSlot from the add operation + * @param[in] position position of the resulting mesh in model space + * @param[out] mesh Mesh Data Object to populate with mesh data + */ + void GenerateMeshData( ImageId id, + const Vector2& position, + MeshData& mesh ); + + /** + * @brief Append second mesh to the first mesh + * + * @param[in] first First mesh + * @param[in] second Second mesh + * @param[in] optimize should we optimize vertex data + */ + void StitchMesh( MeshData& first, + const MeshData& second, + bool optimize = false ); + + /** + * @brief Combine two meshes, outputting the result into a new mesh + * + * @param[in] first First mesh + * @param[in] second Second mesh + * @param[in] optimize should we optimize vertex data + * @param[out] out resulting mesh + */ + void StitchMesh( const MeshData& first, + const MeshData& second, + MeshData& out, + bool optimize = false ); + + /** + * @brief Get the BufferImage containing an atlas + * + * @param[in] atlas AtlasId returned when atlas was created + * + * @return Atlas Handle + */ + Dali::Atlas GetAtlasContainer( AtlasId atlas ) const; + + /** + * @brief Get the Id of the atlas containing an image + * + * @param[in] id ImageId + * + * @return Atlas Id + */ + AtlasId GetAtlas( ImageId id ); + + /** + * @brief Get the size of the blocks used in an atlas + * + * @param[in] atlas AtlasId + * + * @return width and height of the blocks used + */ + Vector2 GetBlockSize( AtlasId atlas ); + + /** + * @brief Get the current size of an atlas + * + * @param[in] atlas AtlasId + * + * @return width and height of the atlas + */ + Vector2 GetAtlasSize( AtlasId atlas ); + + /** + * @brief Get the number of blocks available in an atlas + * + * @param[in] atlas AtlasId + * + * @return Number of blocks free in this atlas + */ + SizeType GetFreeBlocks( AtlasId atlas ); + + /** + * @brief Sets the pixel area of any new atlas and also the individual block size + * + * @param[in] size pixel area of atlas + * + * @param blockSize pixel area in atlas for a block + */ + void SetNewAtlasSize( const Vector2& size, + const Vector2& blockSize ); + + /** + * @brief Get the number of atlases created + * + * @return number of atlases + */ + SizeType GetAtlasCount() const; + + /** + * @brief Get the pixel format used by an atlas + * + * @param[in] atlas AtlasId + * + * @return Pixel format used by this atlas + */ + Pixel::Format GetPixelFormat( AtlasId atlas ); + + /** + * @brief Fill in a metrics structure showing current status of this Atlas Manager + * + * @param[in] metrics metrics structure to be filled + */ + void GetMetrics( Metrics& metrics ); + +private: + + explicit DALI_INTERNAL AtlasManager(Internal::AtlasManager *impl); + +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_ATLAS_MANAGER_H__ \ No newline at end of file diff --git a/dali-toolkit/internal/controls/buttons/button-impl.cpp b/dali-toolkit/internal/controls/buttons/button-impl.cpp index 0d3fcd5..c42531f 100644 --- a/dali-toolkit/internal/controls/buttons/button-impl.cpp +++ b/dali-toolkit/internal/controls/buttons/button-impl.cpp @@ -26,7 +26,7 @@ #include // INTERNAL INCLUDES -#include +#include /** * Button states and contents @@ -615,9 +615,8 @@ float Button::GetAnimationTime() const void Button::SetLabel( const std::string& label ) { - Toolkit::TextView textView = Toolkit::TextView::New( label ); - textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit ); // Make sure our text always fits inside the button - SetLabel( textView ); + Toolkit::TextLabel textLabel = Toolkit::TextLabel::New( label ); + SetLabel( textLabel ); } void Button::SetLabel( Actor label ) diff --git a/dali-toolkit/internal/controls/buttons/push-button-impl.cpp b/dali-toolkit/internal/controls/buttons/push-button-impl.cpp index 1890686..3910e43 100644 --- a/dali-toolkit/internal/controls/buttons/push-button-impl.cpp +++ b/dali-toolkit/internal/controls/buttons/push-button-impl.cpp @@ -23,7 +23,7 @@ #include // INTERNAL INCLUDES -#include +#include namespace Dali { @@ -579,13 +579,13 @@ Vector3 PushButton::GetNaturalSize() SizeOfActorIfLarger( GetBackgroundImage(), size ); // If label, test against it's size - Toolkit::TextView textView = Toolkit::TextView::DownCast( GetLabel() ); - if( textView ) + Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( GetLabel() ); + if( label ) { - Vector3 textViewSize = textView.GetNaturalSize(); + Vector3 labelSize = label.GetNaturalSize(); - size.width = std::max( size.width, textViewSize.width + TEXT_PADDING * 2.0f ); - size.height = std::max( size.height, textViewSize.height + TEXT_PADDING * 2.0f ); + size.width = std::max( size.width, labelSize.width + TEXT_PADDING * 2.0f ); + size.height = std::max( size.height, labelSize.height + TEXT_PADDING * 2.0f ); } return size; diff --git a/dali-toolkit/internal/controls/buttons/radio-button-impl.h b/dali-toolkit/internal/controls/buttons/radio-button-impl.h index eec11ab..d525a43 100644 --- a/dali-toolkit/internal/controls/buttons/radio-button-impl.h +++ b/dali-toolkit/internal/controls/buttons/radio-button-impl.h @@ -23,7 +23,6 @@ #include // INTERNAL INCLUDES -#include #include #include #include "button-impl.h" diff --git a/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.cpp b/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.cpp index 4e486ba..e8ce9e0 100644 --- a/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.cpp +++ b/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.cpp @@ -56,12 +56,8 @@ NavigationTitleBar::NavigationTitleBar(NavigationControl& naviControl, mTitleIconLayout= Toolkit::TableView::New( 3,2 ); SetFixedSizes(); - mTitle = Toolkit::TextView::New(); - mTitle.SetTextAlignment( Toolkit::Alignment::HorizontalLeft ); - mTitle.SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit); - mSubTitle = Toolkit::TextView::New(); - mSubTitle.SetTextAlignment( Toolkit::Alignment::HorizontalLeft ); - mSubTitle.SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit); + mTitle = Toolkit::TextLabel::New(); + mSubTitle = Toolkit::TextLabel::New(); } void NavigationTitleBar::Update( Toolkit::Page page ) @@ -113,8 +109,7 @@ void NavigationTitleBar::Update( Toolkit::Page page ) } // add title and subtitle(if exist) - mTitle.SetText( page.GetTitle() ); - mTitle.SetStyleToCurrentText(mCurrentStyle->titleTextStyle); + mTitle.SetProperty( Toolkit::TextLabel::Property::TEXT, page.GetTitle() ); if( page.GetSubTitle().empty() ) //display title { mTitleLayout.SetFixedHeight( 1,mCurrentStyle->titleHeightWithoutSubtitle - mCurrentStyle->subtitleHeight ); @@ -124,8 +119,7 @@ void NavigationTitleBar::Update( Toolkit::Page page ) { mTitleLayout.SetFixedHeight( 1, mCurrentStyle->titleHeightWithSubtitle ); mTitleLayout.AddChild( mTitle, Toolkit::TableView::CellPosition(1,0) ); - mSubTitle.SetText( page.GetSubTitle() ); - mSubTitle.SetStyleToCurrentText(mCurrentStyle->subtitleTextStyle); + mSubTitle.SetProperty( Toolkit::TextLabel::Property::TEXT, page.GetSubTitle() ); mTitleLayout.AddChild( mSubTitle, Toolkit::TableView::CellPosition(2,0) ); } diff --git a/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h b/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h index 0377a2e..c8200ed 100644 --- a/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h +++ b/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h @@ -21,7 +21,7 @@ // INTERNAL INCLUDES #include #include -#include +#include #include #include @@ -81,8 +81,8 @@ private: Toolkit::TableView mTitleLayout; Toolkit::TableView mTitleIconLayout; - Toolkit::TextView mTitle; - Toolkit::TextView mSubTitle; + Toolkit::TextLabel mTitle; + Toolkit::TextLabel mSubTitle; }; diff --git a/dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h b/dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h index ecb3d3b..80603d8 100644 --- a/dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h +++ b/dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h @@ -20,7 +20,6 @@ // INTERNAL INCLUDES #include -#include #include #include #include diff --git a/dali-toolkit/internal/controls/popup/popup-impl.cpp b/dali-toolkit/internal/controls/popup/popup-impl.cpp index 69df006..42981a3 100755 --- a/dali-toolkit/internal/controls/popup/popup-impl.cpp +++ b/dali-toolkit/internal/controls/popup/popup-impl.cpp @@ -262,26 +262,16 @@ void Popup::SetButtonAreaImage( Actor image ) void Popup::SetTitle( const std::string& text ) { - Toolkit::TextView titleActor = Toolkit::TextView::New(); - titleActor.SetName( "POPUP_TITLE" ); - titleActor.SetText( text ); - titleActor.SetColor( Color::BLACK ); - titleActor.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); - titleActor.SetWidthExceedPolicy( Toolkit::TextView::Split ); - titleActor.SetLineJustification( Toolkit::TextView::Center ); - - SetTitle( titleActor ); -} - -void Popup::SetTitle( Toolkit::TextView titleActor ) -{ // Replaces the current title actor. if( mPopupLayout ) { mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 0, 0 ) ); } - mTitle = titleActor; + mTitle = Toolkit::TextLabel::New( text ); + mTitle.SetName( "POPUP_TITLE" ); + mTitle.SetProperty( Toolkit::TextLabel::Property::MULTI_LINE, true ); + mTitle.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); if( mPopupLayout ) { @@ -294,9 +284,14 @@ void Popup::SetTitle( Toolkit::TextView titleActor ) RelayoutRequest(); } -Toolkit::TextView Popup::GetTitle() const +std::string Popup::GetTitle() const { - return mTitle; + if( mTitle ) + { + return mTitle.GetProperty( Toolkit::TextLabel::Property::TEXT ); + } + + return std::string(); } void Popup::CreateFooter() @@ -747,7 +742,7 @@ Vector3 Popup::GetNaturalSize() const float titleBuffer = 0.5f; titleNaturalSize.width += titleBuffer; - // As TextView GetNaturalSize does not take wrapping into account, limit the width + // As TextLabel GetNaturalSize does not take wrapping into account, limit the width // to that of the stage if( titleNaturalSize.width >= maxWidth) { diff --git a/dali-toolkit/internal/controls/popup/popup-impl.h b/dali-toolkit/internal/controls/popup/popup-impl.h index ec85966..efdac51 100755 --- a/dali-toolkit/internal/controls/popup/popup-impl.h +++ b/dali-toolkit/internal/controls/popup/popup-impl.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace Dali { @@ -84,14 +85,9 @@ public: void SetTitle( const std::string& text ); /** - * @copydoc Toolkit::Popup::SetTitle( TextView titleActor ) - */ - void SetTitle( Toolkit::TextView titleActor ); - - /** * @copydoc Toolkit::Popup::GetTitle */ - Toolkit::TextView GetTitle() const; + std::string GetTitle() const; /** * @copydoc Toolkit::Popup::AddButton @@ -325,7 +321,7 @@ private: Actor mBackgroundImage; ///< Stores the background image. Actor mButtonAreaImage; ///< Stores the button background image. - Toolkit::TextView mTitle; ///< Stores the text title. + Toolkit::TextLabel mTitle; ///< Stores the text title. Actor mContent; ///< Stores popup's content. Actor mBottomBg; ///< bottom button bar background. ImageActor is replaced with Actor due to hidden image. Actor mTailImage; ///< Stores the tail image diff --git a/dali-toolkit/internal/controls/slider/slider-impl.cpp b/dali-toolkit/internal/controls/slider/slider-impl.cpp index 0cd8783..7ab8438 100755 --- a/dali-toolkit/internal/controls/slider/slider-impl.cpp +++ b/dali-toolkit/internal/controls/slider/slider-impl.cpp @@ -348,13 +348,13 @@ void Slider::DisplayValue( float value, bool raiseSignals ) } } - if( mHandleValueTextView ) + if( mHandleValueTextLabel ) { std::stringstream ss; ss.precision( GetValuePrecision() ); ss << std::fixed << clampledValue; - mHandleValueTextView.SetText( ss.str() ); + mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, ss.str() ); } } @@ -523,13 +523,15 @@ ImageActor Slider::CreatePopupArrow() return arrow; } -Toolkit::TextView Slider::CreatePopupText() +Toolkit::TextLabel Slider::CreatePopupText() { - Toolkit::TextView textView = Toolkit::TextView::New(); - textView.SetParentOrigin( ParentOrigin::CENTER ); - textView.SetAnchorPoint( AnchorPoint::CENTER ); - textView.SetZ( VALUE_DISPLAY_TEXT_Z ); - return textView; + Toolkit::TextLabel textLabel = Toolkit::TextLabel::New(); + textLabel.SetParentOrigin( ParentOrigin::CENTER ); + textLabel.SetAnchorPoint( AnchorPoint::CENTER ); + textLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + textLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + textLabel.SetZ( VALUE_DISPLAY_TEXT_Z ); + return textLabel; } ImageActor Slider::CreatePopup() @@ -539,8 +541,8 @@ ImageActor Slider::CreatePopup() popup.SetParentOrigin( ParentOrigin::TOP_CENTER ); popup.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); - mValueTextView = CreatePopupText(); - popup.Add( mValueTextView ); + mValueTextLabel = CreatePopupText(); + popup.Add( mValueTextLabel ); return popup; } @@ -574,24 +576,21 @@ void Slider::ResizeHandleRegion( const Vector2& region ) void Slider::CreateHandleValueDisplay() { - if( mHandle && !mHandleValueTextView ) + if( mHandle && !mHandleValueTextLabel ) { - mHandleValueTextView = Toolkit::TextView::New(); - mHandleValueTextView.SetParentOrigin( ParentOrigin::CENTER ); - mHandleValueTextView.SetAnchorPoint( AnchorPoint::CENTER ); - mHandleValueTextView.SetSize( GetHandleRegion() ); - mHandleValueTextView.SetZ( HANDLE_VALUE_DISPLAY_TEXT_Z ); - mHandle.Add( mHandleValueTextView ); + mHandleValueTextLabel = Toolkit::TextLabel::New(); + mHandleValueTextLabel.SetParentOrigin( ParentOrigin::CENTER ); + mHandleValueTextLabel.SetAnchorPoint( AnchorPoint::CENTER ); + mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mHandleValueTextLabel.SetDrawMode( DrawMode::OVERLAY ); + mHandle.Add( mHandleValueTextLabel ); } } void Slider::DestroyHandleValueDisplay() { - if(mHandleValueTextView) - { - mHandleValueTextView.Unparent(); - mHandleValueTextView.Reset(); - } + UnparentAndReset(mHandleValueTextLabel); } void Slider::SetPopupTextColor( const Vector4& color ) @@ -1018,26 +1017,15 @@ bool Slider::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tr void Slider::DisplayPopup( float value ) { // Value displayDoConnectSignal - if( mValueTextView ) + if( mValueTextLabel ) { std::stringstream ss; ss.precision( GetValuePrecision() ); ss << std::fixed << value; - mValueTextView.SetText( ss.str() ); - TextStyle style; - style.SetTextColor( GetPopupTextColor() ); - mValueTextView.SetStyleToCurrentText( style, TextStyle::COLOR); + mValueTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, ss.str() ); if( mValueDisplay ) { - Font font = Font::New(); - float popupWidth = font.MeasureText( ss.str() ).x + VALUE_POPUP_MARGIN * 2.0f; - if( popupWidth < VALUE_POPUP_MIN_WIDTH ) - { - popupWidth = VALUE_POPUP_MIN_WIDTH; - } - - mPopup.SetSize( popupWidth, VALUE_POPUP_HEIGHT ); mValueDisplay.SetVisible( true ); mValueTimer.SetInterval( VALUE_VIEW_SHOW_DURATION ); diff --git a/dali-toolkit/internal/controls/slider/slider-impl.h b/dali-toolkit/internal/controls/slider/slider-impl.h index 8fee62e..a8003c7 100755 --- a/dali-toolkit/internal/controls/slider/slider-impl.h +++ b/dali-toolkit/internal/controls/slider/slider-impl.h @@ -25,7 +25,7 @@ // INTERNAL INCLUDES #include #include -#include +#include namespace Dali { @@ -434,7 +434,7 @@ private: * * @return The textview created for the popup */ - Toolkit::TextView CreatePopupText(); + Toolkit::TextLabel CreatePopupText(); /** * Create the value display for the slider @@ -687,8 +687,8 @@ private: ImageActor mPopup; ///< Popup backing ImageActor mPopupArrow; ///< Popup arrow backing - Toolkit::TextView mValueTextView; //< The text value in popup - Toolkit::TextView mHandleValueTextView; ///< The text value on handle + Toolkit::TextLabel mValueTextLabel; //< The text value in popup + Toolkit::TextLabel mHandleValueTextLabel; ///< The text value on handle Vector2 mHandleLastTouchPoint; ///< The last touch point for the handle Timer mValueTimer; ///< Timer used to hide value view diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp new file mode 100644 index 0000000..f189207 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2015 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 +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +using namespace Dali::Toolkit::Text; + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND; +} + +namespace +{ + +const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] = +{ + { "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN }, + { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER }, + { "END", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END }, +}; +const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); + +const Scripting::StringEnum< Toolkit::Text::LayoutEngine::VerticalAlignment > VERTICAL_ALIGNMENT_STRING_TABLE[] = +{ + { "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP }, + { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER }, + { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM }, +}; +const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); + +// Type registration +BaseHandle Create() +{ + return Toolkit::TextField::New(); +} + +// Setup properties, signals and actions using the type-registry. +DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextField, Toolkit::Control, Create ); + +DALI_PROPERTY_REGISTRATION( TextField, "rendering-backend", INTEGER, RENDERING_BACKEND ) +DALI_PROPERTY_REGISTRATION( TextField, "placeholder-text", STRING, PLACEHOLDER_TEXT ) +DALI_PROPERTY_REGISTRATION( TextField, "text", STRING, TEXT ) +DALI_PROPERTY_REGISTRATION( TextField, "font-family", STRING, FONT_FAMILY ) +DALI_PROPERTY_REGISTRATION( TextField, "font-style", STRING, FONT_STYLE ) +DALI_PROPERTY_REGISTRATION( TextField, "point-size", FLOAT, POINT_SIZE ) +DALI_PROPERTY_REGISTRATION( TextField, "exceed-policy", INTEGER, EXCEED_POLICY ) +DALI_PROPERTY_REGISTRATION( TextField, "primary-cursor-color", VECTOR4, PRIMARY_CURSOR_COLOR ) +DALI_PROPERTY_REGISTRATION( TextField, "secondary-cursor-color", VECTOR4, SECONDARY_CURSOR_COLOR ) +DALI_PROPERTY_REGISTRATION( TextField, "enable-cursor-blink", BOOLEAN, ENABLE_CURSOR_BLINK ) +DALI_PROPERTY_REGISTRATION( TextField, "cursor-blink-interval", FLOAT, CURSOR_BLINK_INTERVAL ) +DALI_PROPERTY_REGISTRATION( TextField, "cursor-blink-duration", FLOAT, CURSOR_BLINK_DURATION ) +DALI_PROPERTY_REGISTRATION( TextField, "grab-handle-image", STRING, GRAB_HANDLE_IMAGE ) +DALI_PROPERTY_REGISTRATION( TextField, "decoration-bounding-box", RECTANGLE, DECORATION_BOUNDING_BOX ) +DALI_PROPERTY_REGISTRATION( TextField, "horizontal-alignment", STRING, HORIZONTAL_ALIGNMENT ) +DALI_PROPERTY_REGISTRATION( TextField, "vertical-alignment", STRING, VERTICAL_ALIGNMENT ) +DALI_TYPE_REGISTRATION_END() + +} // namespace + +Toolkit::TextField TextField::New() +{ + // Create the implementation, temporarily owned by this handle on stack + IntrusivePtr< TextField > impl = new TextField(); + + // Pass ownership to CustomActor handle + Toolkit::TextField handle( *impl ); + + // Second-phase init of the implementation + // This can only be done after the CustomActor connection has been made... + impl->Initialize(); + + return handle; +} + +void TextField::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +{ + Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) ); + + if( textField ) + { + TextField& impl( GetImpl( textField ) ); + + switch( index ) + { + case Toolkit::TextField::Property::RENDERING_BACKEND: + { + int backend = value.Get< int >(); + + if( impl.mRenderingBackend != backend ) + { + impl.mRenderingBackend = backend; + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT: + { + if( impl.mController ) + { + //impl.mController->SetPlaceholderText( value.Get< std::string >() ); TODO + } + break; + } + case Toolkit::TextField::Property::TEXT: + { + if( impl.mController ) + { + impl.mController->SetText( value.Get< std::string >() ); + } + break; + } + case Toolkit::TextField::Property::FONT_FAMILY: + { + if( impl.mController ) + { + std::string fontFamily = value.Get< std::string >(); + + if( impl.mController->GetDefaultFontFamily() != fontFamily ) + { + impl.mController->SetDefaultFontFamily( fontFamily ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextField::Property::FONT_STYLE: + { + if( impl.mController ) + { + std::string fontStyle = value.Get< std::string >(); + + if( impl.mController->GetDefaultFontStyle() != fontStyle ) + { + impl.mController->SetDefaultFontStyle( fontStyle ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextField::Property::POINT_SIZE: + { + if( impl.mController ) + { + float pointSize = value.Get< float >(); + + if( impl.mController->GetDefaultPointSize() != pointSize /*TODO - epsilon*/ ) + { + impl.mController->SetDefaultPointSize( pointSize ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextField::Property::EXCEED_POLICY: + { + impl.mExceedPolicy = value.Get< int >(); + break; + } + case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetColor( PRIMARY_CURSOR, value.Get< Vector4 >() ); + } + break; + } + case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetColor( SECONDARY_CURSOR, value.Get< Vector4 >() ); + } + break; + } + case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK: + { + if( impl.mController ) + { + impl.mController->SetEnableCursorBlink( value.Get< bool >() ); + } + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetCursorBlinkInterval( value.Get< float >() ); + } + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_DURATION: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetCursorBlinkDuration( value.Get< float >() ); + } + break; + } + case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + + if( impl.mDecorator ) + { + impl.mDecorator->SetGrabHandleImage( image ); + } + break; + } + case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetBoundingBox( value.Get< Rect >() ); + } + break; + } + case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT: + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); + + if( engine.GetHorizontalAlignment() != alignment ) + { + engine.SetHorizontalAlignment( alignment ); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::VERTICAL_ALIGNMENT: + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + const LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); + + if( engine.GetVerticalAlignment() != alignment ) + { + engine.SetVerticalAlignment( alignment ); + impl.RequestTextRelayout(); + } + break; + } + } // switch + } // textfield +} + +Property::Value TextField::GetProperty( BaseObject* object, Property::Index index ) +{ + Property::Value value; + + Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) ); + + if( textField ) + { + TextField& impl( GetImpl( textField ) ); + + switch( index ) + { + case Toolkit::TextField::Property::RENDERING_BACKEND: + { + value = impl.mRenderingBackend; + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT: + { + if( impl.mController ) + { + std::string text; + impl.mController->GetPlaceholderText( text ); + value = text; + } + break; + } + case Toolkit::TextField::Property::TEXT: + { + if( impl.mController ) + { + std::string text; + impl.mController->GetText( text ); + value = text; + } + break; + } + case Toolkit::TextField::Property::EXCEED_POLICY: + { + value = impl.mExceedPolicy; + break; + } + case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetColor( PRIMARY_CURSOR ); + } + break; + } + case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetColor( SECONDARY_CURSOR ); + } + break; + } + case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK: + { + value = impl.mController->GetEnableCursorBlink(); + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetCursorBlinkInterval(); + } + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_DURATION: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetCursorBlinkDuration(); + } + break; + } + case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetBoundingBox(); + } + break; + } + case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT: + { + if( impl.mController ) + { + value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) ); + } + break; + } + case Toolkit::TextField::Property::VERTICAL_ALIGNMENT: + { + if( impl.mController ) + { + value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) ); + } + break; + } + } //switch + } + + return value; +} + +void TextField::OnInitialize() +{ + Actor self = Self(); + + mController = Text::Controller::New( *this ); + + mDecorator = Text::Decorator::New( *this, *mController ); + + mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX ); + + mController->EnableTextInput( mDecorator ); + + // Forward input events to controller + EnableGestureDetection(Gesture::Tap); + GetTapGestureDetector().SetMaximumTapsRequired( 2 ); + EnableGestureDetection(Gesture::Pan); + + // Set BoundingBox to stage size if not already set. + if ( mDecorator->GetBoundingBox().IsEmpty() ) + { + Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); + mDecorator->SetBoundingBox( Rect( 0.0f, 0.0f, stageSize.width, stageSize.height ) ); + } + + // Fill-parent area by default + self.SetResizePolicy( FILL_TO_PARENT, WIDTH ); + self.SetResizePolicy( FILL_TO_PARENT, HEIGHT ); +} + +void TextField::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) +{ + GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); +} + +Vector3 TextField::GetNaturalSize() +{ + return mController->GetNaturalSize(); +} + +float TextField::GetHeightForWidth( float width ) +{ + return mController->GetHeightForWidth( width ); +} + +void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container ) +{ + if( mController->Relayout( size ) || + !mRenderer ) + { + const Vector2& scrollPosition = mController->GetScrollPosition(); + const Vector2& alignmentOffset = mController->GetAlignmentOffset(); + + Vector2 offset = scrollPosition + alignmentOffset; + + if( mDecorator ) + { + mDecorator->Relayout( size, offset ); + } + + if( !mRenderer ) + { + mRenderer = Backend::Get().NewRenderer( mRenderingBackend ); + } + + RenderableActor renderableActor; + if( mRenderer ) + { + renderableActor = mRenderer->Render( mController->GetView() ); + } + + EnableClipping( (Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy), size ); + + if( renderableActor != mRenderableActor ) + { + UnparentAndReset( mRenderableActor ); + mRenderableActor = renderableActor; + } + + if( mRenderableActor ) + { + mRenderableActor.SetPosition( offset.x, offset.y ); + + // Make sure the actor is parented correctly with/without clipping + if( mClipper ) + { + mClipper->GetRootActor().Add( mRenderableActor ); + } + else + { + Self().Add( mRenderableActor ); + } + } + } +} + +void TextField::OnKeyInputFocusGained() +{ + VirtualKeyboard::StatusChangedSignal().Connect( this, &TextField::KeyboardStatusChanged ); + + ImfManager imfManager = ImfManager::Get(); + + if ( imfManager ) + { + imfManager.EventReceivedSignal().Connect( this, &TextField::OnImfEvent ); + + // Notify that the text editing start. + imfManager.Activate(); + + // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated. + imfManager.SetRestoreAfterFocusLost( true ); + } + + mController->KeyboardFocusGainEvent(); +} + +void TextField::OnKeyInputFocusLost() +{ + VirtualKeyboard::StatusChangedSignal().Disconnect( this, &TextField::KeyboardStatusChanged ); + + ImfManager imfManager = ImfManager::Get(); + if ( imfManager ) + { + // The text editing is finished. Therefore the imf manager don't have restore activation. + imfManager.SetRestoreAfterFocusLost( false ); + + // Notify that the text editing finish. + imfManager.Deactivate(); + + imfManager.EventReceivedSignal().Disconnect( this, &TextField::OnImfEvent ); + } + + mController->KeyboardFocusLostEvent(); +} + +void TextField::OnTap( const TapGesture& gesture ) +{ + // Show the keyboard if it was hidden. + if (!VirtualKeyboard::IsVisible()) + { + VirtualKeyboard::Show(); + } + + SetKeyInputFocus(); + + mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y ); +} + +void TextField::OnPan( const PanGesture& gesture ) +{ + mController->PanEvent( gesture.state, gesture.displacement ); +} + +bool TextField::OnKeyEvent( const KeyEvent& event ) +{ + if( Dali::DALI_KEY_ESCAPE == event.keyCode ) + { + ClearKeyInputFocus(); + } + + return mController->KeyEvent( event ); +} + +ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent ) +{ + switch ( imfEvent.eventName ) + { + case ImfManager::COMMIT: + { + KeyEvent event( "", imfEvent.predictiveString, 0, 0, 0, KeyEvent::Down ); + mController->KeyEvent( event ); + break; + } + case ImfManager::PREEDIT: // fall through + case ImfManager::DELETESURROUNDING: + case ImfManager::GETSURROUNDING: + case ImfManager::VOID: + { + // do nothing + } + } // end switch + + return ImfManager::ImfCallbackData(); +} + +void TextField::RequestTextRelayout() +{ + RelayoutRequest(); +} + +void TextField::EnableClipping( bool clipping, const Vector2& size ) +{ + if( clipping ) + { + // Not worth to created clip actor if width or height is equal to zero. + if( size.width > Math::MACHINE_EPSILON_1000 && size.height > Math::MACHINE_EPSILON_1000 ) + { + if( !mClipper ) + { + Actor self = Self(); + + mClipper = Clipper::New( size ); + self.Add( mClipper->GetRootActor() ); + self.Add( mClipper->GetImageActor() ); + } + else if ( mClipper ) + { + mClipper->Refresh( size ); + } + } + } + else + { + // Note - this will automatically remove the root & image actors + mClipper.Reset(); + } +} + +void TextField::KeyboardStatusChanged(bool keyboardShown) +{ + // Just hide the grab handle when keyboard is hidden. + if (!keyboardShown ) + { + mController->KeyboardFocusLostEvent(); + } +} + +TextField::TextField() +: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ), + mRenderingBackend( DEFAULT_RENDERING_BACKEND ), + mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP ) +{ +} + +TextField::~TextField() +{ + mClipper.Reset(); +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h new file mode 100644 index 0000000..5428275 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -0,0 +1,212 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__ + +/* + * Copyright (c) 2015 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 +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * @brief A control which renders a short text string. + */ +class TextField : public Control, public Text::ControlInterface +{ +public: + + /** + * @copydoc Dali::Toollkit::TextField::New() + */ + static Toolkit::TextField New(); + + // Properties + + /** + * @brief Called when a property of an object of this type is set. + * + * @param[in] object The object whose property is set. + * @param[in] index The property index. + * @param[in] value The new property value. + */ + static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); + + /** + * @brief Called to retrieve a property of an object of this type. + * + * @param[in] object The object whose property is to be retrieved. + * @param[in] index The property index. + * @return The current value of the property. + */ + static Property::Value GetProperty( BaseObject* object, Property::Index index ); + +private: // From Control + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnInitialize(); + + /** + * @copydoc Control::OnStyleChange() + */ + virtual void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); + + /** + * @copydoc Control::GetNaturalSize() + */ + virtual Vector3 GetNaturalSize(); + + /** + * @copydoc Control::GetHeightForWidth() + */ + virtual float GetHeightForWidth( float width ); + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); + + /** + * @copydoc Control::OnKeyInputFocusGained() + */ + virtual void OnKeyInputFocusGained(); + + /** + * @copydoc Control::OnKeyInputFocusLost() + */ + virtual void OnKeyInputFocusLost(); + + /** + * @copydoc Control::OnTap() + */ + virtual void OnTap( const TapGesture& tap ); + + /** + * @copydoc Control::OnPan() + */ + virtual void OnPan( const PanGesture& gesture ); + + /** + * @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&) + */ + virtual bool OnKeyEvent(const KeyEvent& event); + + /** + * @brief Event received from IMF manager + * + * @param[in] imfManager The IMF manager. + * @param[in] imfEvent The event received. + * @return A data struture indicating if update is needed, cursor position and current text. + */ + ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent ); + + /** + * @copydoc Text::ControlInterface::RequestTextRelayout() + */ + virtual void RequestTextRelayout(); + +private: // Implementation + + /** + * @brief Enable or disable clipping. + * + * @param[in] clipping True if clipping should be enabled. + * @param[in] size The area to clip within. + */ + void EnableClipping( bool clipping, const Vector2& size ); + + /** + * @brief Callback when keyboard is shown/hidden. + * + * @param[in] keyboardShown True if keyboard is shown. + */ + void KeyboardStatusChanged( bool keyboardShown ); + + /** + * Construct a new TextField. + */ + TextField(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~TextField(); + +private: + + // Undefined copy constructor and assignment operators + TextField(const TextField&); + TextField& operator=(const TextField& rhs); + +private: // Data + + Text::ControllerPtr mController; + Text::RendererPtr mRenderer; + Text::DecoratorPtr mDecorator; + Text::ClipperPtr mClipper; ///< For EXCEED_POLICY_CLIP + + RenderableActor mRenderableActor; + + int mRenderingBackend; + int mExceedPolicy; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Toolkit::Internal::TextField& GetImpl( Toolkit::TextField& textField ) +{ + DALI_ASSERT_ALWAYS(textField); + + Dali::RefObject& handle = textField.GetImplementation(); + + return static_cast(handle); +} + +inline const Toolkit::Internal::TextField& GetImpl( const Toolkit::TextField& textField ) +{ + DALI_ASSERT_ALWAYS(textField); + + const Dali::RefObject& handle = textField.GetImplementation(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__ diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp new file mode 100644 index 0000000..73f40e9 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2015 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 + +// INTERNAL INCLUDES +#include +#include +#include +#include + +using Dali::Toolkit::Text::LayoutEngine; +using Dali::Toolkit::Text::Backend; + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND; +} + +namespace +{ + +const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] = +{ + { "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN }, + { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER }, + { "END", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END }, +}; +const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); + +const Scripting::StringEnum< Toolkit::Text::LayoutEngine::VerticalAlignment > VERTICAL_ALIGNMENT_STRING_TABLE[] = +{ + { "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP }, + { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER }, + { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM }, +}; +const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); + +// Type registration +BaseHandle Create() +{ + return Toolkit::TextLabel::New(); +} + +// Setup properties, signals and actions using the type-registry. +DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextLabel, Toolkit::Control, Create ); + +DALI_PROPERTY_REGISTRATION( TextLabel, "rendering-backend", INTEGER, RENDERING_BACKEND ) +DALI_PROPERTY_REGISTRATION( TextLabel, "text", STRING, TEXT ) +DALI_PROPERTY_REGISTRATION( TextLabel, "font-family", STRING, FONT_FAMILY ) +DALI_PROPERTY_REGISTRATION( TextLabel, "font-style", STRING, FONT_STYLE ) +DALI_PROPERTY_REGISTRATION( TextLabel, "point-size", FLOAT, POINT_SIZE ) +DALI_PROPERTY_REGISTRATION( TextLabel, "multi-line", BOOLEAN, MULTI_LINE ) +DALI_PROPERTY_REGISTRATION( TextLabel, "horizontal-alignment", STRING, HORIZONTAL_ALIGNMENT ) +DALI_PROPERTY_REGISTRATION( TextLabel, "vertical-alignment", STRING, VERTICAL_ALIGNMENT ) +DALI_PROPERTY_REGISTRATION( TextLabel, "text-color", VECTOR4, TEXT_COLOR ) +DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-offset", VECTOR2, SHADOW_OFFSET ) +DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-color", VECTOR4, SHADOW_COLOR ) +DALI_PROPERTY_REGISTRATION( TextLabel, "underline-enabled", BOOLEAN, UNDERLINE_ENABLED ) +DALI_PROPERTY_REGISTRATION( TextLabel, "underline-color", VECTOR4, UNDERLINE_COLOR ) +DALI_TYPE_REGISTRATION_END() + +} // namespace + +Toolkit::TextLabel TextLabel::New() +{ + // Create the implementation, temporarily owned by this handle on stack + IntrusivePtr< TextLabel > impl = new TextLabel(); + + // Pass ownership to CustomActor handle + Toolkit::TextLabel handle( *impl ); + + // Second-phase init of the implementation + // This can only be done after the CustomActor connection has been made... + impl->Initialize(); + + return handle; +} + +void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +{ + Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) ); + + if( label ) + { + TextLabel& impl( GetImpl( label ) ); + switch( index ) + { + case Toolkit::TextLabel::Property::RENDERING_BACKEND: + { + int backend = value.Get< int >(); + + if( impl.mRenderingBackend != backend ) + { + impl.mRenderingBackend = backend; + impl.mRenderer.Reset(); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextLabel::Property::TEXT: + { + if( impl.mController ) + { + impl.mController->SetText( value.Get< std::string >() ); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextLabel::Property::FONT_FAMILY: + { + if( impl.mController ) + { + std::string fontFamily = value.Get< std::string >(); + + if( impl.mController->GetDefaultFontFamily() != fontFamily ) + { + impl.mController->SetDefaultFontFamily( fontFamily ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::FONT_STYLE: + { + if( impl.mController ) + { + std::string fontStyle = value.Get< std::string >(); + + if( impl.mController->GetDefaultFontStyle() != fontStyle ) + { + impl.mController->SetDefaultFontStyle( fontStyle ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::POINT_SIZE: + { + if( impl.mController ) + { + float pointSize = value.Get< float >(); + + if( impl.mController->GetDefaultPointSize() != pointSize /*TODO - epsilon*/ ) + { + impl.mController->SetDefaultPointSize( pointSize ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::MULTI_LINE: + { + if( impl.mController ) + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + LayoutEngine::Layout layout = value.Get< bool >() ? LayoutEngine::MULTI_LINE_BOX : LayoutEngine::SINGLE_LINE_BOX; + + if( engine.GetLayout() != layout ) + { + engine.SetLayout( layout ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT: + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); + + if( engine.GetHorizontalAlignment() != alignment ) + { + engine.SetHorizontalAlignment( alignment ); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT: + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + const LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); + + if( engine.GetVerticalAlignment() != alignment ) + { + engine.SetVerticalAlignment( alignment ); + impl.RequestTextRelayout(); + } + break; + } + + case Toolkit::TextLabel::Property::TEXT_COLOR: + { + if ( impl.mController ) + { + Vector4 textColor = value.Get< Vector4 >(); + if ( impl.mController->GetTextColor() != textColor ) + { + impl.mController->SetTextColor( textColor ); + impl.RequestTextRelayout(); + } + } + break; + } + + case Toolkit::TextLabel::Property::SHADOW_OFFSET: + { + if( impl.mController ) + { + Vector2 shadowOffset = value.Get< Vector2 >(); + if ( impl.mController->GetShadowOffset() != shadowOffset ) + { + impl.mController->SetShadowOffset( shadowOffset ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::SHADOW_COLOR: + { + if( impl.mController ) + { + Vector4 shadowColor = value.Get< Vector4 >(); + if ( impl.mController->GetShadowColor() != shadowColor ) + { + impl.mController->SetShadowColor( shadowColor ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_COLOR: + { + if( impl.mController ) + { + Vector4 color = value.Get< Vector4 >(); + if ( impl.mController->GetUnderlineColor() != color ) + { + impl.mController->SetUnderlineColor( color ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: + { + if( impl.mController ) + { + bool enabled = value.Get< bool >(); + if ( impl.mController->IsUnderlineEnabled() != enabled ) + { + impl.mController->SetUnderlineEnabled( enabled ); + impl.RequestTextRelayout(); + } + } + break; + } + } + } +} + +Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index index ) +{ + Property::Value value; + + Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) ); + + if( label ) + { + TextLabel& impl( GetImpl( label ) ); + switch( index ) + { + case Toolkit::TextLabel::Property::RENDERING_BACKEND: + { + value = impl.mRenderingBackend; + break; + } + case Toolkit::TextLabel::Property::TEXT: + { + if( impl.mController ) + { + std::string text; + impl.mController->GetText( text ); + value = text; + } + break; + } + case Toolkit::TextLabel::Property::MULTI_LINE: + { + if( impl.mController ) + { + value = static_cast( LayoutEngine::MULTI_LINE_BOX == impl.mController->GetLayoutEngine().GetLayout() ); + } + break; + } + case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT: + { + if( impl.mController ) + { + value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) ); + } + break; + } + case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT: + { + if( impl.mController ) + { + value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) ); + } + break; + } + case Toolkit::TextLabel::Property::TEXT_COLOR: + { + if ( impl.mController ) + { + value = impl.mController->GetTextColor(); + } + break; + } + case Toolkit::TextLabel::Property::SHADOW_OFFSET: + { + if ( impl.mController ) + { + value = impl.mController->GetShadowOffset(); + } + break; + } + case Toolkit::TextLabel::Property::SHADOW_COLOR: + { + if ( impl.mController ) + { + value = impl.mController->GetShadowColor(); + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_COLOR: + { + if ( impl.mController ) + { + value = impl.mController->GetUnderlineColor(); + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: + { + if ( impl.mController ) + { + value = impl.mController->IsUnderlineEnabled(); + } + break; + } + } + } + + return value; +} + +void TextLabel::OnInitialize() +{ + Actor self = Self(); + + mController = Text::Controller::New( *this ); + + // Use height-for-width negotiation by default + self.SetResizePolicy( FILL_TO_PARENT, WIDTH ); + self.SetResizePolicy( DIMENSION_DEPENDENCY, HEIGHT ); +} + +void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) +{ + GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); +} + +Vector3 TextLabel::GetNaturalSize() +{ + return mController->GetNaturalSize(); +} + +float TextLabel::GetHeightForWidth( float width ) +{ + return mController->GetHeightForWidth( width ); +} + +void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container ) +{ + if( mController->Relayout( size ) || + !mRenderer ) + { + if( !mRenderer ) + { + mRenderer = Backend::Get().NewRenderer( mRenderingBackend ); + } + + RenderableActor renderableActor; + if( mRenderer ) + { + renderableActor = mRenderer->Render( mController->GetView() ); + } + + if( renderableActor != mRenderableActor ) + { + UnparentAndReset( mRenderableActor ); + + if( renderableActor ) + { + const Vector2& alignmentOffset = mController->GetAlignmentOffset(); + renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y ); + + Self().Add( renderableActor ); + } + + mRenderableActor = renderableActor; + } + } +} + +void TextLabel::RequestTextRelayout() +{ + RelayoutRequest(); +} + +TextLabel::TextLabel() +: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ), + mRenderingBackend( DEFAULT_RENDERING_BACKEND ) +{ +} + +TextLabel::~TextLabel() +{ +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.h b/dali-toolkit/internal/controls/text-controls/text-label-impl.h new file mode 100644 index 0000000..c69bd7c --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -0,0 +1,153 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__ + +/* + * Copyright (c) 2015 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 +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * @brief A control which renders a short text string. + */ +class TextLabel : public Control, public Text::ControlInterface +{ +public: + + /** + * @copydoc Dali::Toollkit::TextLabel::New() + */ + static Toolkit::TextLabel New(); + + // Properties + + /** + * @brief Called when a property of an object of this type is set. + * + * @param[in] object The object whose property is set. + * @param[in] index The property index. + * @param[in] value The new property value. + */ + static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); + + /** + * @brief Called to retrieve a property of an object of this type. + * + * @param[in] object The object whose property is to be retrieved. + * @param[in] index The property index. + * @return The current value of the property. + */ + static Property::Value GetProperty( BaseObject* object, Property::Index index ); + +private: // From Control + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnInitialize(); + + /** + * @copydoc Control::OnStyleChange() + */ + virtual void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); + + /** + * @copydoc Control::OnRelayout() + */ + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); + + /** + * @copydoc Control::GetNaturalSize() + */ + virtual Vector3 GetNaturalSize(); + + /** + * @copydoc Control::GetHeightForWidth() + */ + virtual float GetHeightForWidth( float width ); + + /** + * @copydoc Text::ControlInterface::RequestTextRelayout() + */ + virtual void RequestTextRelayout(); + +private: // Implementation + + /** + * Construct a new TextLabel. + */ + TextLabel(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~TextLabel(); + +private: + + // Undefined copy constructor and assignment operators + TextLabel(const TextLabel&); + TextLabel& operator=(const TextLabel& rhs); + +private: // Data + + Text::ControllerPtr mController; + Text::RendererPtr mRenderer; + RenderableActor mRenderableActor; + + int mRenderingBackend; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Toolkit::Internal::TextLabel& GetImpl( Toolkit::TextLabel& textLabel ) +{ + DALI_ASSERT_ALWAYS(textLabel); + + Dali::RefObject& handle = textLabel.GetImplementation(); + + return static_cast(handle); +} + +inline const Toolkit::Internal::TextLabel& GetImpl( const Toolkit::TextLabel& textLabel ) +{ + DALI_ASSERT_ALWAYS(textLabel); + + const Dali::RefObject& handle = textLabel.GetImplementation(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__ diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp new file mode 100644 index 0000000..6db6845 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp @@ -0,0 +1,675 @@ +/* + * Copyright (c) 2015 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 +#include +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +// todo Move this to adaptor?? +#define GET_LOCALE_TEXT(string) dgettext("elementary", string) + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ +const Dali::Vector4 DEFAULT_POPUP_BACKGROUND( Dali::Vector4( .20f, 0.29f, 0.44f, 1.0f ) ); +const Dali::Vector4 DEFAULT_POPUP_BACKGROUND_PRESSED( Dali::Vector4( 0.07f, 0.10f, 0.17f, 1.0f ) ); +const Dali::Vector4 DEFAULT_POPUP_LINE_COLOR( Dali::Vector4( 0.36f, 0.45f, 0.59f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_ICON( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_ICON_PRESSED( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_TEXT( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_TEXT_PRESSED( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); + +const std::string DEFAULT_POPUP_BACKGROUND_IMAGE( DALI_IMAGE_DIR "popup_bubble_bg.#.png" ); +const std::string OPTION_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" ); +const std::string OPTION_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" ); +const std::string OPTION_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.png" ); +const std::string OPTION_ICON_PASTE( DALI_IMAGE_DIR "copy_paste_icon_paste.png" ); +const std::string OPTION_ICON_SELECT( DALI_IMAGE_DIR "copy_paste_icon_select.png" ); +const std::string OPTION_ICON_SELECT_ALL( DALI_IMAGE_DIR "copy_paste_icon_select_all.png" ); + +const Dali::Vector2 DEFAULT_POPUP_MAX_SIZE( 470.0f, 120.0f ); ///< The maximum size of the popup. + +const float OPTION_TEXT_LINE_HEIGHT( 32.0f ); ///< The line height of the text. +const Dali::Vector2 OPTION_ICON_SIZE( 0.f, 0.f ); ///< The size of the icon. +const float OPTION_GAP_ICON_TEXT( 6.f ); ///< The gap between the icon and the text +const float OPTION_MARGIN_WIDTH( 10.f ); ///< The margin between the right or lefts edge and the text or icon. +const float OPTION_MAX_WIDTH( DEFAULT_POPUP_MAX_SIZE.width / 6 ); ///< The maximum width of the option (currently set to the max) +const float OPTION_MIN_WIDTH( 86.0f ); ///< The minimum width of the option. + +const float POPUP_DIVIDER_WIDTH( 1.f ); ///< The size of the divider. + +const Dali::Vector2 POPUP_TAIL_SIZE( 20.0f, 16.0f ); ///< The size of the tail. +const float POPUP_TAIL_Y_OFFSET( 5.f ); ///< The y offset of the tail (when its position is on the bottom). +const float POPUP_TAIL_TOP_Y_OFFSET( 3.f ); ///< The y offset of the tail (when its position is on the top). + +const float HIDE_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup hide animation in seconds. +const float SHOW_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup show animation in seconds. + +const char* const OPTION_SELECT_WORD = "option-select_word"; // "Select Word" popup option. +const char* const OPTION_SELECT_ALL("option-select_all"); // "Select All" popup option. +const char* const OPTION_CUT("option-cut"); // "Cut" popup option. +const char* const OPTION_COPY("option-copy"); // "Copy" popup option. +const char* const OPTION_PASTE("option-paste"); // "Paste" popup option. +const char* const OPTION_CLIPBOARD("option-clipboard"); // "Clipboard" popup option. + +} // namespace + +//// Comparison function for ButtonRequirement Priority +//bool TextSelectionPopup::PriorityCompare( ButtonRequirement const& a, ButtonRequirement const& b ) +//{ +// return a.priority < b.priority; +//} + + +Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New() +{ + // Create the implementation, temporarily owned by this handle on stack + IntrusivePtr< TextSelectionPopup > impl = new TextSelectionPopup(); + + // Pass ownership to CustomActor handle + Dali::Toolkit::TextSelectionPopup handle( *impl ); + + // Second-phase init of the implementation + // This can only be done after the CustomActor connection has been made... + impl->Initialize(); + + return handle; +} + +void TextSelectionPopup::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +{ + Toolkit::TextSelectionPopup selectionPopup = Toolkit::TextSelectionPopup::DownCast( Dali::BaseHandle( object ) ); + + if( selectionPopup ) + { + TextSelectionPopup& impl( GetImpl( selectionPopup ) ); + + switch( index ) + { + case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE: + { + impl.SetPopupMaxSize( value.Get< Vector2 >() ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_BACKGROUND_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_BACKGROUND, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_CLIPBOARD_BUTTON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_CUT_BUTTON_ICON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_COPY_BUTTON_ICON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_PASTE_BUTTON_ICON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_SELECT_BUTTON_ICON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_SELECT_ALL_BUTTON_ICON, image ); + break; + } + } // switch + } // TextSelectionPopup +} + +Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::Index index ) +{ + Property::Value value; + + Toolkit::TextSelectionPopup selectionPopup = Toolkit::TextSelectionPopup::DownCast( Dali::BaseHandle( object ) ); + + if( selectionPopup ) + { + TextSelectionPopup& impl( GetImpl( selectionPopup ) ); + + switch( index ) + { + case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE: + { + value = impl.GetPopupMaxSize(); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_BACKGROUND_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_BACKGROUND ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_CLIPBOARD_BUTTON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_CUT_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_COPY_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_PASTE_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_SELECT_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_SELECT_ALL_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + } // switch + } + return value; +} + +void TextSelectionPopup::OnInitialize() +{ + CreatePopup(); +} + +void TextSelectionPopup::OnRelayout( const Vector2& size, RelayoutContainer& container ) +{ + +} + +void TextSelectionPopup::SetPopupMaxSize( const Size& maxSize ) +{ + mMaxSize = maxSize; +} + +const Dali::Vector2& TextSelectionPopup::GetPopupMaxSize() const +{ + return mMaxSize; +} + +void TextSelectionPopup::SetPopupImage( PopupParts part, Dali::Image image ) +{ + switch ( part ) + { + case POPUP_BACKGROUND : + { + mBackgroundImage = image; + } + break; + case POPUP_CLIPBOARD_BUTTON : + { + mClipboardIconImage = image; + } + break; + case POPUP_CUT_BUTTON_ICON : + { + mCutIconImage = image; + } + break; + case POPUP_COPY_BUTTON_ICON : + { + mCopyIconImage = image; + } + break; + case POPUP_PASTE_BUTTON_ICON : + { + mPasteIconImage = image; + } + break; + case POPUP_SELECT_BUTTON_ICON : + { + mSelectIconImage = image; + } + break; + case POPUP_SELECT_ALL_BUTTON_ICON : + { + mSelectAllIconImage = image; + } + break; + + } // switch +} + +Dali::Image TextSelectionPopup::GetPopupImage( PopupParts part ) +{ + switch ( part ) + { + case POPUP_BACKGROUND : + { + return mBackgroundImage; + } + break; + case POPUP_CLIPBOARD_BUTTON : + { + return mClipboardIconImage; + } + break; + case POPUP_CUT_BUTTON_ICON : + { + return mCutIconImage; + } + break; + case POPUP_COPY_BUTTON_ICON : + { + return mCopyIconImage; + } + break; + case POPUP_PASTE_BUTTON_ICON : + { + return mPasteIconImage; + } + break; + case POPUP_SELECT_BUTTON_ICON : + { + return mSelectIconImage; + } + break; + case POPUP_SELECT_ALL_BUTTON_ICON : + { + return mSelectAllIconImage; + } + break; + default : + { + DALI_ASSERT_DEBUG( "Unknown Popup Part" ); + } + } // switch + + return Dali::Image(); +} + + void TextSelectionPopup::CreateOrderedListOfPopupOptions() + { + mOrderListOfButtons.clear(); + + // Create button for each possible option using Option priority + if ( !mCutIconImage ) + { + mCutIconImage = ResourceImage::New( OPTION_ICON_CUT ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), mCutIconImage, true ) ); + + if ( !mCopyIconImage ) + { + mCopyIconImage = ResourceImage::New( OPTION_ICON_COPY ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), mCopyIconImage, true ) ); + + if ( !mPasteIconImage ) + { + mPasteIconImage = ResourceImage::New( OPTION_ICON_PASTE ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), mPasteIconImage, true ) ); + + if ( !mSelectIconImage ) + mSelectIconImage = ResourceImage::New( OPTION_ICON_SELECT ); + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), mSelectIconImage, true ) ); + + if ( !mSelectAllIconImage ) + { + mSelectAllIconImage = ResourceImage::New( OPTION_ICON_SELECT_ALL ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), mSelectAllIconImage, true ) ); + + if ( !mClipboardIconImage ) + { + mClipboardIconImage = ResourceImage::New( OPTION_ICON_CLIPBOARD ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), mClipboardIconImage, true ) ); + + // Sort the buttons according their priorities. + std::sort( mOrderListOfButtons.begin(), mOrderListOfButtons.end(), TextSelectionPopup::ButtonPriorityCompare() ); + } + + void TextSelectionPopup::CreateBackground() + { + if ( !mBackgroundImage ) + { + mBackgroundImage = ResourceImage::New( DEFAULT_POPUP_BACKGROUND_IMAGE ); + } + + NinePatchImage backgroundImageNinePatch = NinePatchImage::DownCast( mBackgroundImage ); + if( backgroundImageNinePatch ) + { + const Size ninePatchImageSize = Size( static_cast( mBackgroundImage.GetWidth() ), static_cast( mBackgroundImage.GetHeight() ) ); + Rect childRect = backgroundImageNinePatch.GetChildRectangle(); + + // -1u because of the cropping. + mNinePatchMargins.x = childRect.x - 1u; + mNinePatchMargins.y = ninePatchImageSize.width - ( childRect.x + childRect.width ) - 1u; + mNinePatchMargins.z = childRect.y - 1u; + mNinePatchMargins.w = ninePatchImageSize.height - ( childRect.y + childRect.height ) - 1u; + } + + SetBackgroundImage( mBackgroundImage ); + SetBackgroundColor( mBackgroundColor ); + } + + void TextSelectionPopup::AddOption( Actor& parent, const std::string& name, const std::string& caption, const Image iconImage, bool finalOption, bool showIcons ) + { + // 1. Create the backgrounds for the popup option both normal and pressed. + // Both containers will be added to a button. + Actor optionContainer = Actor::New(); + optionContainer.SetRelayoutEnabled( true ); + optionContainer.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + optionContainer.SetDrawMode( DrawMode::OVERLAY ); + optionContainer.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + + ImageActor optionPressedContainer = Toolkit::CreateSolidColorActor( mBackgroundPressedColor ); + optionPressedContainer.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + optionPressedContainer.SetDrawMode( DrawMode::OVERLAY ); + optionPressedContainer.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + + // 2. Add text. + Toolkit::TextLabel captionTextLabel = Toolkit::TextLabel::New(); + captionTextLabel.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + captionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption ); + // optionContainer.Add( captionTextLabel ); Temporary removed. + + Toolkit::TextLabel pressedCaptionTextLabel = Toolkit::TextLabel::New(); + pressedCaptionTextLabel.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + pressedCaptionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption ); + // optionPressedContainer.Add( pressedCaptionTextLabel ); Temporary removed. + + // Calculates the icon/text position. + float iconTextOffsetY = 0.0f; + + if ( showIcons ) + { + // 3. Create the icons + ImageActor pressedIcon = ImageActor::New( iconImage ); + ImageActor icon = ImageActor::New( iconImage ); + + optionContainer.Add( icon ); + optionPressedContainer.Add( pressedIcon ); + + iconTextOffsetY = 0.5f * ( ( DEFAULT_POPUP_MAX_SIZE.height - mNinePatchMargins.z - mNinePatchMargins.w ) - ( OPTION_ICON_SIZE.height + OPTION_GAP_ICON_TEXT + OPTION_TEXT_LINE_HEIGHT ) ); + + icon.SetParentOrigin( ParentOrigin::TOP_CENTER ); + icon.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + icon.SetY( iconTextOffsetY ); + + pressedIcon.SetParentOrigin( ParentOrigin::TOP_CENTER ); + pressedIcon.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + pressedIcon.SetY( iconTextOffsetY ); + + // Layout icon + gap + text + captionTextLabel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); + pressedCaptionTextLabel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); + pressedCaptionTextLabel.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); + captionTextLabel.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); + pressedCaptionTextLabel.SetY( -iconTextOffsetY ); + captionTextLabel.SetY( -iconTextOffsetY ); + } + else + { + // Centre option text + captionTextLabel.SetAnchorPoint( AnchorPoint::CENTER ); + captionTextLabel.SetParentOrigin( ParentOrigin::CENTER ); + pressedCaptionTextLabel.SetAnchorPoint( AnchorPoint::CENTER ); + pressedCaptionTextLabel.SetParentOrigin( ParentOrigin::CENTER ); + } + + // Calculate the size of the text. + Vector3 textSize = captionTextLabel.GetNaturalSize(); + textSize.width = std::min( textSize.width, OPTION_MAX_WIDTH - 2.f * OPTION_MARGIN_WIDTH ); + + // Set the size to the text. Text will be ellipsized if exceeds the max width. + captionTextLabel.SetSize( textSize.GetVectorXY() ); + pressedCaptionTextLabel.SetSize( textSize.GetVectorXY() ); + + // 4. Calculate the size of option. + + // The width is the max size of the text or the icon plus the margins clamped between the option min and max size. + // The height is the whole popup height minus the ninepatch margins. + const Vector2 optionSize( std::min( OPTION_MAX_WIDTH, std::max( OPTION_MIN_WIDTH, std::max( textSize.width, OPTION_ICON_SIZE.width ) + 2.f * OPTION_MARGIN_WIDTH ) ), + DEFAULT_POPUP_MAX_SIZE.height - mNinePatchMargins.z - mNinePatchMargins.w ); + + optionContainer.SetSize( optionSize ); + optionPressedContainer.SetSize( optionSize ); + + // 5. Create a option. + Toolkit::PushButton option = Toolkit::PushButton::New(); + option.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + option.SetSize( optionSize ); + option.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + option.SetX( mContentSize.width ); + option.SetName( name ); + option.SetAnimationTime( 0.0f ); + //option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed ); + + parent.Add( option ); + + // 6. Set the normal option image. + option.SetButtonImage( optionContainer ); + + // 7. Set the pressed option image + option.SetSelectedImage( optionPressedContainer ); + + // 8. Update the content size. + mContentSize.width += optionSize.width; + mContentSize.height = std::max ( optionSize.height, mContentSize.height ); + + // 9. Add the divider + if( !finalOption ) + { + const Size size( POPUP_DIVIDER_WIDTH, mContentSize.height ); + + ImageActor divider = Toolkit::CreateSolidColorActor( Color::WHITE ); + divider.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + divider.SetSize( size ); + divider.SetParentOrigin( ParentOrigin::TOP_LEFT ); + divider.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + divider.SetPosition( mContentSize.width - POPUP_DIVIDER_WIDTH, 0.0f ); + parent.Add( divider ); + } + } + + void TextSelectionPopup::SetUpPopup( Size& size ) + { + Actor self = Self(); + + // Create Layer and Stencil. + mStencilLayer = Layer::New(); + ImageActor stencil = CreateSolidColorActor( Color::RED ); + stencil.SetDrawMode( DrawMode::STENCIL ); + stencil.SetVisible( true ); + Actor scrollview = Actor::New(); //todo make a scrollview + stencil.SetRelayoutEnabled( true ); + + self.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + self.SetSize( mRequiredPopUpSize ); // control matches stencil size + + mStencilLayer.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + mStencilLayer.SetSize( size ); // matches stencil size + + stencil.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + scrollview.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mButtons.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + + mStencilLayer.SetAnchorPoint(AnchorPoint::TOP_LEFT); + scrollview.SetAnchorPoint(AnchorPoint::TOP_LEFT); + mButtons.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + + mStencilLayer.SetPosition( mNinePatchMargins.x, mNinePatchMargins.y ); + + self.Add( mStencilLayer ); + mStencilLayer.Add( stencil ); + mStencilLayer.Add( scrollview ); + scrollview.Add( mButtons ); + } + + void TextSelectionPopup::AddPopupOptions( bool createTail, bool showIcons ) + { + mShowIcons = showIcons; + + mContentSize = Vector2::ZERO; + + mButtons = Actor::New(); + mButtons.SetRelayoutEnabled( true ); + + // Add the options into the buttons container. + + // 1. Determine how many buttons are active and should be added to container. + std::size_t numberOfOptions = 0u; + for( std::vector::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it ) + { + const ButtonRequirement& button( *it ); + if( button.enabled ) + { + ++numberOfOptions; + } + } + + // 2. Iterate list of buttons and add active ones. + std::size_t optionsAdded = 0u; + for( std::vector::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it ) + { + const ButtonRequirement& button( *it ); + if ( button.enabled ) + { + ++optionsAdded; + AddOption( mButtons, button.name, button.caption, button.icon, optionsAdded == numberOfOptions, mShowIcons ); + } + } + + // Calculate the size of the whole popup which may not be all visible. + mRequiredPopUpSize = Size( std::min( mMaxSize.width, mContentSize.width + mNinePatchMargins.x + mNinePatchMargins.y ), DEFAULT_POPUP_MAX_SIZE.height ); + + // Size of the contents within the popup + mVisiblePopUpSize = Size( mRequiredPopUpSize.width - mNinePatchMargins.x - mNinePatchMargins.y, mRequiredPopUpSize.height - mNinePatchMargins.z - mNinePatchMargins.w ); + } + + void TextSelectionPopup::CreatePopup() + { + if ( !mStencilLayer ) + { + CreateOrderedListOfPopupOptions(); //todo Currently causes all options to be shown + CreateBackground(); + AddPopupOptions( true, true ); + SetUpPopup( mVisiblePopUpSize ); + } + + mStencilLayer.RaiseToTop(); + } + +TextSelectionPopup::TextSelectionPopup() +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_NONE ) ), + mMaxSize ( DEFAULT_POPUP_MAX_SIZE ), + mVisiblePopUpSize( DEFAULT_POPUP_MAX_SIZE ), + mRequiredPopUpSize( DEFAULT_POPUP_MAX_SIZE ), + mBackgroundColor( DEFAULT_POPUP_BACKGROUND ), + mBackgroundPressedColor( DEFAULT_POPUP_BACKGROUND_PRESSED ), + mLineColor( DEFAULT_POPUP_LINE_COLOR ), + mIconColor( DEFAULT_OPTION_ICON ), + mIconPressedColor( DEFAULT_OPTION_ICON_PRESSED ), + mTextColor( DEFAULT_OPTION_TEXT ), + mTextPressedColor( DEFAULT_OPTION_TEXT_PRESSED ), + mSelectOptionPriority( 1 ), + mSelectAllOptionPriority ( 2 ), + mCutOptionPriority ( 3 ), + mCopyOptionPriority ( 4 ), + mPasteOptionPriority ( 5 ), + mClipboardOptionPriority( 6 ), + mShowIcons( true ) +{ +} + +TextSelectionPopup::~TextSelectionPopup() +{ +} + + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h new file mode 100644 index 0000000..ffca9dd --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h @@ -0,0 +1,306 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_POPUP_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_POPUP_H__ + +/* + * Copyright (c) 2015 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 + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ +enum PopupParts +{ + POPUP_BACKGROUND, + POPUP_CLIPBOARD_BUTTON, + POPUP_CUT_BUTTON_ICON, + POPUP_COPY_BUTTON_ICON, + POPUP_PASTE_BUTTON_ICON, + POPUP_SELECT_BUTTON_ICON, + POPUP_SELECT_ALL_BUTTON_ICON, +}; + +} // namespace + +class TextSelectionPopup : public Control +{ +public: + + enum Buttons + { + ButtonsCut, + ButtonsCopy, + ButtonsPaste, + ButtonsSelect, + ButtonsSelectAll, + ButtonsClipboard, + ButtonsEnumEnd + }; + + struct ButtonRequirement + { + ButtonRequirement() + : id( ButtonsEnumEnd ), + priority( 0u ), + name(), + caption(), + icon(), + enabled( false ) + {} + + ButtonRequirement( Buttons buttonId, + std::size_t buttonPriority, + const std::string& buttonName, + const std::string& buttonCaption, + Dali::Image& buttonIcon, + bool buttonEnabled ) + : id( buttonId ), + priority( buttonPriority ), + name( buttonName ), + caption( buttonCaption ), + icon( buttonIcon ), + enabled( buttonEnabled ) + {} + + Buttons id; + std::size_t priority; + std::string name; + std::string caption; + Dali::Image icon; + bool enabled; + }; + + struct ButtonPriorityCompare + { + bool operator()( const ButtonRequirement& lhs, const ButtonRequirement& rhs ) const { + return lhs.priority < rhs.priority; + } + }; + +// static inline bool ButtonPriorityCompare( ButtonRequirement a, ButtonRequirement b ) +// { +// return a.priority < b.priority ? true : false; +// } + + /** + * @copydoc Dali::Toollkit::TextSelectionPopup::New() + */ + static Toolkit::TextSelectionPopup New(); + + // Properties + + /** + * @brief Called when a property of an object of this type is set. + * + * @param[in] object The object whose property is set. + * @param[in] index The property index. + * @param[in] value The new property value. + */ + static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); + + /** + * @brief Called to retrieve a property of an object of this type. + * + * @param[in] object The object whose property is to be retrieved. + * @param[in] index The property index. + * @return The current value of the property. + */ + static Property::Value GetProperty( BaseObject* object, Property::Index index ); + + void CreatePopup(); + + void DestroyPopup(); + +private: // From Control + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnInitialize(); + +// /** +// * @copydoc Control::GetNaturalSize() +// */ +// virtual Vector3 GetNaturalSize(); +// +// /** +// * @copydoc Control::GetHeightForWidth() +// */ +// virtual float GetHeightForWidth( float width ); + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); +// +// /** +// * Received for single & double taps +// */ +// virtual void OnTap( const TapGesture& tap ); +// +// /** +// * @copydoc Text::ControlInterface::RequestTextRelayout() +// */ +// virtual void RequestTextRelayout(); + + /** + * Set max size of Popup + * @param[in] maxSize Size (Vector2) + */ + void SetPopupMaxSize( const Size& maxSize ); + + /** + * Get Max size of Popup + * @return Vector2 the max size of the Popup + */ + const Dali::Vector2& GetPopupMaxSize() const; + + /** + * @brief Sets the image for the given part of the Popup. + * + * @param[in] part The part of the pop from the Enum PopupParts + * @param[in] image The image to use. + */ + void SetPopupImage( PopupParts part, Dali::Image image ); + + /** + * @brief Retrieves the image of the given part used by the popup + * + * @param[in] part The part of the popup + * @return The image used for that part. + */ + Dali::Image GetPopupImage( PopupParts part ); + + void CreateOrderedListOfPopupOptions(); + + void CreateBackground(); + + void AddOption( Actor& parent, const std::string& name, const std::string& caption, const Image iconImage, bool finalOption, bool showIcons ); + + void SetUpPopup( Size& size ); + + void AddPopupOptions( bool createTail, bool showIcons ); + +private: // Implementation + + /** + * Construct a new TextField. + */ + TextSelectionPopup(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~TextSelectionPopup(); + +private: + + // Undefined copy constructor and assignment operators + TextSelectionPopup(const TextSelectionPopup&); + TextSelectionPopup& operator=(const TextSelectionPopup& rhs); + +private: // Data + + Actor mButtons; // Actor which holds all the buttons, sensitivity can be set oActor buttons via this actor + Layer mStencilLayer; // Layer to enable clipping when buttons exceed popup + + // Images to be used by the Popup + Image mBackgroundImage; + Image mCutIconImage; + Image mCopyIconImage; + Image mPasteIconImage; + Image mClipboardIconImage; + Image mSelectIconImage; + Image mSelectAllIconImage; + + ImageActor mBackground; // The background popup panel + ImageActor mTail; // The tail for the popup + ImageActor mTailEffect; //todo remove // the tail effect + ImageActor mTailLine; //todo remove // The border/outline around the tail + + Size mMaxSize; // Max size of the Popup + Size mVisiblePopUpSize; // Visible Size of popup excluding content that needs scrolling. + Size mRequiredPopUpSize; // Total size of popup including any invisible margin + + Vector4 mNinePatchMargins; // Margins between the edge of the cropped image and the nine patch rect (left, right, top, bottom). + + Size mContentSize; // Size of Content (i.e. Buttons) + //Animation mAnimation; // Popup Hide/Show animation. + + std::vector mOrderListOfButtons; // List of buttons in the order to be displayed and a flag to indicate if needed. + + Vector4 mBackgroundColor; // Color of the background of the text input popup + Vector4 mBackgroundPressedColor; // Color of the option background. + Vector4 mLineColor; // Color of the line around the text input popup + Vector4 mIconColor; // Color of the popup icon. + Vector4 mIconPressedColor; // Color of the popup icon when pressed. + Vector4 mTextColor; // Color of the popup text. + Vector4 mTextPressedColor; // Color of the popup text when pressed. + + // Priority of Options/Buttons in the Cut and Paste pop-up, higher priority buttons are displayed first, left to right. + std::size_t mSelectOptionPriority; // Position of Select Button + std::size_t mSelectAllOptionPriority; // Position of Select All button + std::size_t mCutOptionPriority; // Position of Cut button + std::size_t mCopyOptionPriority; // Position of Copy button + std::size_t mPasteOptionPriority; // Position of Paste button + std::size_t mClipboardOptionPriority; // Position of Clipboard button + + bool mShowIcons; // Flag to show icons + +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Toolkit::Internal::TextSelectionPopup& GetImpl( Toolkit::TextSelectionPopup& textSelectionPopup ) +{ + DALI_ASSERT_ALWAYS( textSelectionPopup ); + + Dali::RefObject& handle = textSelectionPopup.GetImplementation(); + + return static_cast(handle); +} + +inline const Toolkit::Internal::TextSelectionPopup& GetImpl( const Toolkit::TextSelectionPopup& textSelectionPopup ) +{ + DALI_ASSERT_ALWAYS( textSelectionPopup ); + + const Dali::RefObject& handle = textSelectionPopup.GetImplementation(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_POPUP_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp deleted file mode 100644 index 25d30d1..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp +++ /dev/null @@ -1,1082 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include - -using namespace Dali; - -namespace -{ -#if defined(DEBUG_ENABLED) - Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXT_INPUT_DECORATOR"); -#endif - -const Vector3 DEFAULT_SELECTION_HANDLE_SIZE( 51.0f, 79.0f, 0.0f ); -const float TOP_HANDLE_TOP_OFFSET(-1.5f); // Offset between top handle and cutCopyPaste pop-up -const float BOTTOM_HANDLE_BOTTOM_OFFSET(1.5f); // Offset between bottom handle and cutCopyPaste pop-up -const float UI_Z_OFFSET( 0.2f ); // Text Selection Handles/Cursor z-offset. -const Vector3 UI_OFFSET(0.0f, 0.0f, UI_Z_OFFSET); // Text Selection Handles/Cursor offset. -const char* DEFAULT_CURSOR( DALI_IMAGE_DIR "cursor.png" ); -const Vector4 DEFAULT_CURSOR_IMAGE_9_BORDER( 2.0f, 2.0f, 2.0f, 2.0f ); -const std::size_t CURSOR_BLINK_INTERVAL = 500; // Cursor blink interval -const float CURSOR_THICKNESS(6.0f); -const Degree CURSOR_ANGLE_OFFSET(2.0f); // Offset from the angle - -const unsigned int SCROLL_TICK_INTERVAL = 50u; -const float SCROLL_THRESHOLD = 10.f; -const float SCROLL_SPEED = 15.f; - -/** - * Whether the given position plus the cursor size offset is inside the given boundary. - * - * @param[in] position The given position. - * @param[in] cursorSize The cursor size. - * @param[in] controlSize The given boundary. - * @param[in] threshold imaginary indent around boundary that will trigger the position to be outside of control. - * - * @return whether the given position is inside the given boundary. - */ -bool IsPositionWithinControl( const Vector3& position, const Size& cursorSize, const Vector3& controlSize, const Vector2 threshold = Vector2::ZERO ) -{ - return ( position.x >= -Math::MACHINE_EPSILON_1000 + threshold.x ) && - ( position.x <= controlSize.width - threshold.x + Math::MACHINE_EPSILON_1000 ) && - ( position.y - cursorSize.height >= -Math::MACHINE_EPSILON_1000 + threshold.y ) && - ( position.y <= controlSize.height + Math::MACHINE_EPSILON_1000 - threshold.y); -} - -} - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -Decorator::Decorator( TextViewCharacterPositioning& textViewManager, TextInputTextStyle& textStyle ): - mTextViewCharacterPositioning( textViewManager ), - mTextStyle( textStyle ), - mSelectionHandleOnePosition(0), - mSelectionHandleTwoPosition(0), - mGrabHandlePosition(0), - mCursorPosition( 0 ), - mTextHighlight( textViewManager ), - mCursorBlinkStatus( true ), - mCursorVisibility( true ), - mCursorRTLEnabled( false ), - mIsGrabHandleInScrollArea( false ), - mIsCursorInScrollArea( false ), - mGrabHandleVisibility( false ), - mGrabHandleEnabled( true ) -{ -} - -Decorator::~Decorator() -{ -} - -/** - * Bounding Box - */ -void Decorator::SetBoundingBox( const Rect& boundingRectangle ) -{ - // Convert to world coordinates and store as a Vector4 to be compatible with Property Notifications. - Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); - - const float originX = boundingRectangle.x - 0.5f * stageSize.width; - const float originY = boundingRectangle.y - 0.5f * stageSize.height; - - const Vector4 boundary( originX, - originY, - originX + boundingRectangle.width, - originY + boundingRectangle.height ); - - mBoundingRectangleWorldCoordinates = boundary; -} - -Vector4 Decorator::GetBoundingBox() const -{ - return mBoundingRectangleWorldCoordinates; -} - -/** - * Selection Handles - */ -void Decorator::OnHandlePan(Actor actor, const PanGesture& gesture) -{ - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - - switch (gesture.state) - { - case Gesture::Started: - // fall through so code not duplicated - case Gesture::Continuing: - { - if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleOne() ) - { - MoveSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition, gesture.displacement ); - HidePopUp(); - } - else if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleTwo() ) - { - MoveSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition, gesture.displacement ); - HidePopUp(); - } - else if ( actor.GetParent() == mTextInputHandles.GetGrabHandle() ) - { - SetCursorVisibility( true ); - ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea ); - MoveGrabHandle( gesture.displacement ); - HidePopUp(); // Do not show popup while handle is moving - } - } - break; - - case Gesture::Finished: - { - // Revert back to non-pressed selection handle images - if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleOne() ) - { - mSelectionHandleOneActualPosition = MoveSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition, gesture.displacement ); - ShowPopupCutCopyPaste(); - } - else if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleTwo() ) - { - mSelectionHandleTwoActualPosition = MoveSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition, gesture.displacement ); - ShowPopupCutCopyPaste(); - } - else if ( actor.GetParent() == mTextInputHandles.GetGrabHandle() ) - { - MoveGrabHandle( gesture.displacement ); - SetCursorVisibility( true ); - ShowPopupCutCopyPaste(); - } - } - break; - default: - break; - } -} - -void Decorator::CreateSelectionHandles( Actor targetParent ) -{ - if ( !mPanGestureDetector ) - { - mPanGestureDetector = PanGestureDetector::New(); - mPanGestureDetector.DetectedSignal().Connect(this, &Decorator::OnHandlePan); - } - - if ( !mTextInputHandles.GetSelectionHandleOne() ) - { - mTextInputHandles.CreateSelectionHandles(); - - mTextInputHandles.AttachSelectionHandlesToGivenPanGesture( mPanGestureDetector ); - - targetParent.Add( mTextInputHandles.GetSelectionHandleOne() ); - targetParent.Add( mTextInputHandles.GetSelectionHandleTwo() ); - - SetUpHandlePropertyNotifications(); - } -} - -void Decorator::RemoveSelectionHandles() -{ - mTextInputHandles.DestorySelectionHandles(); -} - -Vector3 Decorator::GetSelectionHandleSize() -{ - return DEFAULT_SELECTION_HANDLE_SIZE; -} - -std::size_t Decorator::GetHandleOnePosition() const -{ - return mSelectionHandleOnePosition; -} - -std::size_t Decorator::GetHandleTwoPosition() const -{ - return mSelectionHandleTwoPosition; -} - -Vector3 Decorator::PositionSelectionHandle( Actor selectionHandle, std::size_t position ) -{ - bool direction(false); - Vector3 alternatePosition; - bool alternatePositionValid(false); - - Vector3 actualPositionOfSelectionHandle = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( position, direction, alternatePosition,alternatePositionValid ); - - return PositionSelectionHandle( selectionHandle, actualPositionOfSelectionHandle, position ); - -} - -Vector3 Decorator::PositionSelectionHandle( Actor selectionHandle, Vector3& actualPosition, std::size_t position ) -{ - const Vector3 DEFAULT_HANDLE_OFFSET(0.0f, -5.0f, 0.0f); - - selectionHandle.SetPosition( actualPosition += DEFAULT_HANDLE_OFFSET ); - - return actualPosition; -} - -void Decorator::SetSelectionHandlesVisibility(bool visible ) -{ - mTextInputHandles.SetSelectionHandleOneVisibility( visible ); - mTextInputHandles.SetSelectionHandleTwoVisibility( visible ); -} - -void Decorator::PositionSelectionHandles( std::size_t start, std::size_t end ) -{ - mSelectionHandleOnePosition = start; - mSelectionHandleTwoPosition = end; - - mTextViewCharacterPositioning.UpdateTextLayoutInfo(); - - mSelectionHandleOneActualPosition = PositionSelectionHandle( mTextInputHandles.GetSelectionHandleOne(), mSelectionHandleOnePosition ); - mSelectionHandleTwoActualPosition = PositionSelectionHandle( mTextInputHandles.GetSelectionHandleTwo(), mSelectionHandleTwoPosition ); -} - -Vector3 Decorator::MoveSelectionHandle( Actor selectionHandle, - Vector3& actualSelectionHandlePosition, - std::size_t& currentSelectionHandlePosition, - const Vector2& displacement ) -{ - Vector3 actualHandlePosition; - actualSelectionHandlePosition.x += displacement.x * selectionHandle.GetCurrentScale().x; - actualSelectionHandlePosition.y += displacement.y * selectionHandle.GetCurrentScale().y; - - // Selection handles should jump to the nearest character - std::size_t newHandlePosition = 0; - newHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( actualSelectionHandlePosition.GetVectorXY() ); - - bool direction(false); - Vector3 alternatePosition; - bool alternatePositionValid(false); - actualHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandlePosition,direction, alternatePosition, alternatePositionValid ); - - bool handleVisible = true; - - if ( handleVisible && // Ensure the handle is visible. - ( newHandlePosition != currentSelectionHandlePosition ) && // Ensure the handle has moved. - ( newHandlePosition != mSelectionHandleTwoPosition ) && // Ensure new handle position not the same position as an existing handle. - ( newHandlePosition != mSelectionHandleOnePosition ) ) - { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::MoveSelectionHandle Handle visible and moved]\n"); - - currentSelectionHandlePosition = newHandlePosition; - - PositionSelectionHandle( selectionHandle, actualHandlePosition, newHandlePosition ); - - ShowUpdatedHighlight(); - - // Set Active Style to that of first character in selection - std::size_t firstHandleInSelection = std::min( mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - - const TextStyle inputStyle = mTextViewCharacterPositioning.GetStyleAt( firstHandleInSelection ); - mTextStyle.SetInputStyle( inputStyle ); - } - return actualHandlePosition; // Returns Handle position passed in if new value not assigned. -} - -/** - * GrabHandle - */ -void Decorator::PositionGrabHandle( std::size_t positionInText ) -{ - bool direction(false); - Vector3 alternatePosition; - bool alternatePositionValid(false); - - mGrabHandlePosition = positionInText; - - mTextViewCharacterPositioning.UpdateTextLayoutInfo(); - mActualGrabHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( positionInText, direction, alternatePosition,alternatePositionValid ); - - mTextInputHandles.GetGrabHandle().SetPosition( mActualGrabHandlePosition ); -} - -void Decorator::MoveGrabHandle( const Vector2& displacement /*, std::size_t currentHandlePosition */) -{ - mActualGrabHandlePosition.x += displacement.x; - mActualGrabHandlePosition.y += displacement.y; - - // Grab handle should jump to the nearest character and take cursor with it - std::size_t newHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY() ); - - Vector3 actualHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandlePosition ); - - bool handleVisible = true; - - if( ( newHandlePosition != mGrabHandlePosition ) && // Only redraw cursor and do updates if position changed - ( handleVisible ) )// and the new position is visible (if scroll is not enabled, it's always true). - { - mActualGrabHandlePosition = actualHandlePosition; - mTextInputHandles.GetGrabHandle().SetPosition( mActualGrabHandlePosition ); - - //PositionGrabHandle( newHandlePosition ); - mGrabHandlePosition = newHandlePosition; - SetCurrentCursorPosition( mGrabHandlePosition ); - DrawCursor( mGrabHandlePosition ); - - const std::size_t cursorPosition = GetCurrentCursorPosition(); - - // Let keyboard know the new cursor position so can 're-capture' for prediction. - mCursorRePositionedSignal.Emit(); - - // Set Input Style to that of cursor position - if ( !mTextViewCharacterPositioning.IsStyledTextEmpty() && ( cursorPosition > 0 ) ) - { - DALI_ASSERT_DEBUG( ( 0 <= cursorPosition-1 ) && ( cursorPosition-1 < mTextViewCharacterPositioning.StyledTextSize() ) ); - } - } -} - -void Decorator::ShowGrabHandle( bool visible ) -{ - mGrabHandleVisibility = visible; - mTextInputHandles.SetGrabHandleVisibility( visible ); -} - -void Decorator::CreateGrabHandle( Actor targetParent ) -{ - if ( !mPanGestureDetector ) - { - mPanGestureDetector = PanGestureDetector::New(); - mPanGestureDetector.DetectedSignal().Connect(this, &Decorator::OnHandlePan); - } - - if ( !mTextInputHandles.GetGrabHandle() ) - { - mTextInputHandles.CreateGrabHandle(); - mTextInputHandles.AttachGrabHandleToGivenPanGesture( mPanGestureDetector ); - targetParent.Add( mTextInputHandles.GetGrabHandle() ); - } -} - -void Decorator::SetGrabHandleImage( Image image ) -{ - mTextInputHandles.SetGrabHandleImage( image ); -} - -void Decorator::EnableGrabHandle( bool toggle) -{ - // enables grab handle with will in turn de-activate magnifier - mGrabHandleEnabled = toggle; -} - -bool Decorator::IsGrabHandleEnabled() -{ - // if false then magnifier will be shown instead. - return mGrabHandleEnabled; -} - -/** - * Cursor - */ -std::size_t Decorator::GetCurrentCursorPosition() const -{ - return mCursorPosition; -} - -void Decorator::SetCurrentCursorPosition( std::size_t newCursorPosition ) -{ - mCursorPosition = newCursorPosition; -} - -void Decorator::SetCursorVisibility( bool visible ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::SetCursorVisibility[%s]\n", ( visible )?"true":"false"); - - mCursorVisibility = visible; - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea ); - mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled ); -} - -void Decorator::DrawCursor(const std::size_t nthChar) -{ - std::size_t cursorPosition = GetCurrentCursorPosition(); - - // Get height of cursor and set its size - Size size( CURSOR_THICKNESS, 0.0f ); - - Vector2 min, max; // out parameters for GetRowRectFromCharacterPosition - size.height = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mTextViewCharacterPositioning.GetVisualPosition( cursorPosition ), min, max ).height; - - mCursor.SetSize(size); - - // If the character is italic then the cursor also tilts. - if ( !mTextViewCharacterPositioning.IsStyledTextEmpty() && ( cursorPosition > 0 ) ) - { - DALI_ASSERT_DEBUG( ( 0 <= cursorPosition-1 ) && ( cursorPosition-1 < mTextViewCharacterPositioning.StyledTextSize() ) ); - const TextStyle styleAtCursor = mTextViewCharacterPositioning.GetStyleAt( cursorPosition-1 ); - mCursor.SetOrientation( styleAtCursor.IsItalicsEnabled() ? Degree( styleAtCursor.GetItalicsAngle() - CURSOR_ANGLE_OFFSET ) : Degree( 0.f ), Vector3::ZAXIS ); - } - - DALI_ASSERT_DEBUG( cursorPosition <= mTextViewCharacterPositioning.GetNumberOfCharactersInText() ); - if ( ( cursorPosition <= mTextViewCharacterPositioning.GetNumberOfCharactersInText() ) ) - { - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid( false ); // Alternate cursor validity flag. - bool directionRTL( false ); // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 position = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition, directionRTL, altPosition, altPositionValid ); - - SetAltCursorEnabled( altPositionValid ); - - mCursor.SetPosition( position + UI_OFFSET ); - } -} - -void Decorator::SetAltCursorEnabled( bool enabled ) -{ - mCursorRTLEnabled = enabled; - mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled ); -} - -void Decorator::SetCursorImage(Dali::Image image, const Vector4& border ) -{ - DALI_ASSERT_DEBUG ( image && "Create cursor image invalid") - - if ( image ) - { - mCursor.SetImage( image ); - mCursor.SetNinePatchBorder( border ); - } -} - -void Decorator::SetRTLCursorImage( Image image, const Vector4& border ) -{ - DALI_ASSERT_DEBUG ( image && "Create cursor image invalid") - - if ( image ) - { - mCursorRTL.SetImage( image ); - mCursorRTL.SetNinePatchBorder( border ); - } -} - -ImageActor Decorator::CreateCursor( Image cursorImage, const Vector4& border, const std::string& cursorName ) -{ - ImageActor cursor; - - if ( cursorImage ) - { - cursor = ImageActor::New( cursorImage ); - } - else - { - cursor = ImageActor::New( ResourceImage::New( DEFAULT_CURSOR ) ); - } - - cursor.SetStyle(ImageActor::STYLE_NINE_PATCH); - cursor.SetNinePatchBorder( border ); - cursor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER); - cursor.SetVisible(false); - cursor.SetName( cursorName ); - return cursor; -} - -void Decorator::CreateCursors( Actor targetParent ) -{ - Image mCursorImage = ResourceImage::New( DEFAULT_CURSOR ); - mCursor = CreateCursor (mCursorImage, DEFAULT_CURSOR_IMAGE_9_BORDER , "mainCursor"); - mCursorRTL = CreateCursor ( mCursorImage, DEFAULT_CURSOR_IMAGE_9_BORDER, "rtlCursor"); - targetParent.Add( mCursor ); - targetParent.Add( mCursorRTL ); -} - -Size Decorator::GetCursorSizeAt( std::size_t positionWithinTextToGetCursorSize ) -{ - std::size_t visualPosition = mTextViewCharacterPositioning.GetVisualPosition( positionWithinTextToGetCursorSize ); - - Vector2 min, max; - - const Size cursorSize( CURSOR_THICKNESS, - mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( visualPosition, min, max ).height ); - - return cursorSize; -} - -void Decorator::StartCursorBlinkTimer() -{ - if ( !mCursorBlinkTimer ) - { - mCursorBlinkTimer = Timer::New( CURSOR_BLINK_INTERVAL ); - mCursorBlinkTimer.TickSignal().Connect( this, &Decorator::OnCursorBlinkTimerTick ); - } - - if ( !mCursorBlinkTimer.IsRunning() ) - { - mCursorBlinkTimer.Start(); - } -} - -void Decorator::StopCursorBlinkTimer() -{ - if ( mCursorBlinkTimer ) - { - mCursorBlinkTimer.Stop(); - } -} - -bool Decorator::OnCursorBlinkTimerTick() -{ - // Cursor blinking - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus ); - if ( mCursorRTLEnabled ) - { - mCursorRTL.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus ); - } - mCursorBlinkStatus = !mCursorBlinkStatus; - - return true; -} - -/** - * Highlight - */ -void Decorator::ShowUpdatedHighlight() -{ - Toolkit::TextView::TextLayoutInfo textLayoutInfo = mTextViewCharacterPositioning.GetLayoutInfo(); - TextHighlight::HighlightInfo highlightInfo = mTextHighlight.CalculateHighlightInfo( mSelectionHandleOnePosition, mSelectionHandleTwoPosition, textLayoutInfo ); - - // Clamp highlightInfo so they don't exceed the boundary of the control. - const Vector3& controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize(); - highlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) ); - - mTextHighlight.UpdateHighlight( highlightInfo ); -} - -void Decorator::CreateHighlight( Actor parent ) -{ - DALI_ASSERT_DEBUG( parent && "Highlight target parent does not exist" ); - - if ( !mHighlightMeshActor ) - { - mHighlightMeshActor = MeshActor::New( mTextHighlight.CreateHighLightMesh() ); - mHighlightMeshActor.SetName( "HighlightMeshActor" ); - parent.Add( mHighlightMeshActor ); - } -} - -void Decorator::RemoveHighlight() -{ - if ( mHighlightMeshActor ) - { - mHighlightMeshActor.Unparent(); - mHighlightMeshActor.Reset(); - // NOTE: We cannot dereference mHighlightMesh, due to a how the scene-graph MeshRenderer uses the Mesh data. - } -} - -void Decorator::HighlightVisibility( bool visiblility ) -{ - if ( mHighlightMeshActor ) - { - mHighlightMeshActor.SetVisible( visiblility ); - } -} - -/** - * Callbacks connected to be Property notifications for Boundary checking. - */ -// Note If PropertyNotification signal definition included Actor we would not need to duplicate functions. -void Decorator::OnHandleOneLeavesBoundary( PropertyNotification& source) -{ - mTextInputHandles.GetSelectionHandleOne().SetOpacity(0.0f); -} - -void Decorator::OnHandleOneWithinBoundary(PropertyNotification& source) -{ - mTextInputHandles.GetSelectionHandleOne().SetOpacity(1.0f); -} - -void Decorator::OnHandleTwoLeavesBoundary( PropertyNotification& source) -{ - mTextInputHandles.GetSelectionHandleTwo().SetOpacity(0.0f); -} - -void Decorator::OnHandleTwoWithinBoundary(PropertyNotification& source) -{ - mTextInputHandles.GetSelectionHandleTwo().SetOpacity(1.0f); -} - -void Decorator::OnLeftBoundaryExceeded(PropertyNotification& source) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "TextInputDecorationLayouter::OnLeftBoundaryExceeded\n"); - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - selectionHandleOne.SetScale( -1.0f, 1.0f, 1.0f ); - selectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_LEFT); -} - -void Decorator::OnReturnToLeftBoundary(PropertyNotification& source) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "TextInputDecorationLayouter::OnReturnToLeftBoundary\n"); - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - selectionHandleOne.SetScale( 1.0f, 1.0f, 1.0f ); - selectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_RIGHT); -} - -void Decorator::OnRightBoundaryExceeded(PropertyNotification& source) -{ - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - selectionHandleTwo.SetScale( -1.0f, 1.0f, 1.0f ); - selectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_RIGHT); -} - -void Decorator::OnReturnToRightBoundary(PropertyNotification& source) -{ - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - selectionHandleTwo.SetScale( 1.0f, 1.0f, 1.0f ); - selectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_LEFT); -} - -void Decorator::SetUpHandlePropertyNotifications() -{ - /* Property notifications for handles exceeding the boundary and returning back within boundary */ - - Vector3 handlesize = GetSelectionHandleSize(); - - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - - // Exceeding horizontal boundary - PropertyNotification leftNotification = selectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.x + handlesize.x) ); - leftNotification.NotifySignal().Connect( this, &Decorator::OnLeftBoundaryExceeded ); - - PropertyNotification rightNotification = selectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.z - handlesize.x ) ); - rightNotification.NotifySignal().Connect( this, &Decorator::OnRightBoundaryExceeded ); - - // Within horizontal boundary - PropertyNotification leftLeaveNotification = selectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.x + 2*handlesize.x ) ); - leftLeaveNotification.NotifySignal().Connect( this, &Decorator::OnReturnToLeftBoundary ); - - PropertyNotification rightLeaveNotification = selectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.z - 2*handlesize.x ) ); - rightLeaveNotification.NotifySignal().Connect( this, &Decorator::OnReturnToRightBoundary ); - - // Exceeding vertical boundary - PropertyNotification verticalExceedNotificationOne = selectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalExceedNotificationOne.NotifySignal().Connect( this, &Decorator::OnHandleOneLeavesBoundary ); - - PropertyNotification verticalExceedNotificationTwo = selectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalExceedNotificationTwo.NotifySignal().Connect( this, &Decorator::OnHandleTwoLeavesBoundary ); - - // Within vertical boundary - PropertyNotification verticalWithinNotificationOne = selectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalWithinNotificationOne.NotifySignal().Connect( this, &Decorator::OnHandleOneWithinBoundary ); - - PropertyNotification verticalWithinNotificationTwo = selectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalWithinNotificationTwo.NotifySignal().Connect( this, &Decorator::OnHandleTwoWithinBoundary ); -} - -/** - * PopUp - */ -Vector3 Decorator::PositionOfPopUpRelativeToSelectionHandles() -{ - Vector3 position; - Vector2 min, max; - Vector3 topHandle; - Size rowSize; - - // When text is selected, show popup above top handle (and text), or below bottom handle. - - // topHandle: referring to the top most point of the handle or the top line of selection. - if ( mSelectionHandleTwoActualPosition.y > mSelectionHandleOneActualPosition.y ) // Handle may switch positions so calculate which is top. - { - topHandle = mSelectionHandleOneActualPosition; - rowSize= mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mSelectionHandleOnePosition, min, max ); - } - else - { - topHandle = mSelectionHandleTwoActualPosition; - rowSize = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mSelectionHandleTwoPosition, min, max ); - } - topHandle.y += TOP_HANDLE_TOP_OFFSET - rowSize.height; - position = Vector3(topHandle.x, topHandle.y, 0.0f); - - return position; -} - -Vector3 Decorator::AlternatePopUpPositionRelativeToSelectionHandles() -{ - // alternativePosition: referring to the bottom most point of the handle or the bottom line of selection. - Vector3 alternativePosition; - alternativePosition.y = std::max ( mSelectionHandleTwoActualPosition.y , mSelectionHandleOneActualPosition.y ); - alternativePosition.y += GetSelectionHandleSize().y + mPopUpPanel.GetSize().y + BOTTOM_HANDLE_BOTTOM_OFFSET; - - return alternativePosition; -} - -Vector3 Decorator::PositionOfPopUpRelativeToCursor() -{ - // When no text is selected, show PopUp at position of cursor - Vector3 position; - Vector2 min, max; - std::size_t cursorPosition = GetCurrentCursorPosition(); - position = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition ); - const Size rowSize = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( cursorPosition, min, max ); - position.y -= rowSize.height; - - return position; -} - -Vector3 Decorator::AlternatePopUpPositionRelativeToCursor() -{ - std::size_t cursorPosition = GetCurrentCursorPosition(); - Vector3 alternativePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition ); - - if ( mTextInputHandles.GetGrabHandle() ) - { - // If grab handle enabled then position pop-up below the grab handle. - alternativePosition.y += mTextInputHandles.GetGrabHandle().GetCurrentSize().height + mPopUpPanel.GetSize().y + BOTTOM_HANDLE_BOTTOM_OFFSET ; - } - else - { - alternativePosition.y += mPopUpPanel.GetSize().y; - } - - return alternativePosition; - -} - -Vector3 Decorator::PositionOfPopUpRelativeToGrabHandle() -{ - return Vector3::ZERO; -} - -void Decorator::ShowPopUp() -{ - Vector3 position; - Vector3 alternativePosition; - Size rowSize; - - DALI_ASSERT_DEBUG( mPopUpTarget && "PopUp Target Actor does not exist" ); - - if( mHighlightMeshActor ) // Text Selection mode - { - position = PositionOfPopUpRelativeToSelectionHandles(); - } - else // Not in Text Selection mode so position relative to cursor. - { - position = PositionOfPopUpRelativeToCursor(); - } - - // reposition popup above the desired cursor position. - mPopUpPanel.Show( mPopUpTarget, true ); - mPopUpPanel.Self().SetPosition( position ); - mPopUpPanel.PressedSignal().Connect( this, &Decorator::OnPopupButtonPressed ); - - SetUpPopUpPositionNotifications(); - mPopUpPanel.ApplyConfinementConstraint( mBoundingRectangleWorldCoordinates ); -} - -void Decorator::ShowPopUp( Actor target ) -{ - mPopUpTarget = target; - ShowPopupCutCopyPaste(); -} - -void Decorator::ShowPopupCutCopyPaste() -{ - bool isAllTextSelectedAlready = ( mTextViewCharacterPositioning.StyledTextSize() == GetSelectedText().size() ); - bool isTextEmpty = mTextViewCharacterPositioning.IsStyledTextEmpty() ; - bool isSubsetOfTextAlreadySelected = ( !isAllTextSelectedAlready ) && mHighlightMeshActor; - - Clipboard clipboard = Clipboard::Get(); - bool hasClipboardGotContent = clipboard.NumberOfItems(); - - mPopUpPanel.CreateCutCopyPastePopUp( isAllTextSelectedAlready, isTextEmpty, hasClipboardGotContent, isSubsetOfTextAlreadySelected ); - ShowPopUp(); -} - -void Decorator::HidePopUp( bool animate, bool signalFinished ) -{ -} - -void Decorator::AddPopupOption(const std::string& name, const std::string& caption, const Image icon, bool finalOption) -{ - mPopUpPanel.AddButton(name, caption, icon, finalOption); -} - -void Decorator::ClearPopup() -{ - mPopUpPanel.Clear(); -} - -void Decorator::PopUpLeavesVerticalBoundary( PropertyNotification& source) -{ - Vector3 position, alternativePosition; - - if( mHighlightMeshActor ) // Text Selection mode - { - alternativePosition = AlternatePopUpPositionRelativeToSelectionHandles(); - } - else // Not in Text Selection mode - { - alternativePosition = AlternatePopUpPositionRelativeToCursor(); - // if can't be positioned above, then position below row. - } - // reposition popup above the desired cursor position. - mPopUpPanel.Self().SetPosition( alternativePosition ); -} - -void Decorator::SetUpPopUpPositionNotifications( ) -{ - // Note Property notifications ignore any set anchor point so conditions must allow for this. Default is Top Left. - - // Exceeding vertical boundary - PropertyNotification verticalExceedNotificationOne = mPopUpPanel.Self().AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + mPopUpPanel.GetSize().y/2, - mBoundingRectangleWorldCoordinates.w - mPopUpPanel.GetSize().y/2 ) ); - verticalExceedNotificationOne.NotifySignal().Connect( this, &Decorator::PopUpLeavesVerticalBoundary ); -} - -bool Decorator::OnPopupButtonPressed( Toolkit::Button button ) -{ - mPopUpButtonPressedSignal.Emit( button ); - return false; -} - -Decorator::PressedSignal& Decorator::PopUpButtonPressedSignal() -{ - return mPopUpButtonPressedSignal; -} - -Decorator::CursorPositionedSignal& Decorator::CursorRePositionedSignal() -{ - return mCursorRePositionedSignal; -} - -/** - * Decoration Positioning during Scrolling - */ -void Decorator::TextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::TextViewScrolled\n"); - - const Vector3& controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize(); // todo Could store size and only update in Control Size change. - Size cursorSize( CURSOR_THICKNESS, 0.f ); - - // Updates the cursor and grab handle position and visibility. - if( mTextInputHandles.GetGrabHandle() || mCursor ) - { - Vector2 min, max; - size_t cursorTextPosition = GetCurrentCursorPosition(); - cursorSize.height = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( cursorTextPosition, min, max ).height; - - const Vector3 cursorPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorTextPosition ); - - bool mIsCursorInScrollArea = IsPositionWithinControl( cursorPosition, cursorSize, controlSize ); - bool mIsGrabHandleInScrollArea = mIsCursorInScrollArea; - - Vector2 actualGrabHandlePosition = cursorPosition.GetVectorXY(); - - if( mTextInputHandles.GetGrabHandle() ) - { - ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea ); - PositionGrabHandle( cursorTextPosition ); - } - - if( mCursor ) - { - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea ); - DrawCursor( cursorTextPosition ); - mCursor.SetPosition( Vector3(actualGrabHandlePosition) + UI_OFFSET ); - } - } - - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - - // Updates the selection handles and highlighted text position and visibility. - if( mTextInputHandles.GetSelectionHandleOne() && mTextInputHandles.GetSelectionHandleTwo() ) - { - const Vector3 cursorPositionOne = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition ); - const Vector3 cursorPositionTwo = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition ); - - Size cursorSize( GetCursorSizeAt( mSelectionHandleOnePosition ) ); - const bool isSelectionHandleOneVisible = IsPositionWithinControl( cursorPositionOne, cursorSize, controlSize ); - - cursorSize = GetCursorSizeAt( mSelectionHandleTwoPosition ); - const bool isSelectionHandleTwoVisible = IsPositionWithinControl( cursorPositionTwo, cursorSize, controlSize ); - - mSelectionHandleOneActualPosition = cursorPositionOne.GetVectorXY(); - mSelectionHandleTwoActualPosition = cursorPositionTwo.GetVectorXY(); - - selectionHandleOne.SetVisible( isSelectionHandleOneVisible ); - selectionHandleTwo.SetVisible( isSelectionHandleTwoVisible ); - - PositionSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition ); - PositionSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition ); - - if( mHighlightMeshActor ) - { - mHighlightMeshActor.SetVisible( true ); - ShowUpdatedHighlight(); - } - } -} - -void Decorator::StartScrollTimer() -{ - if( !mScrollTimer ) - { - mScrollTimer = Timer::New( SCROLL_TICK_INTERVAL ); - mScrollTimer.TickSignal().Connect( this, &Decorator::OnScrollTimerTick ); - } - - if( !mScrollTimer.IsRunning() ) - { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::StartScrollTimer\n"); - mScrollTimer.Start(); - } -} - -void Decorator::StopScrollTimer() -{ - if( mScrollTimer ) - { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::StopScrollTimer\n"); - - mScrollTimer.Stop(); - mScrollTimer.Reset(); - } -} - -bool Decorator::OnScrollTimerTick() -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::OnScrollTimerTick\n"); - - if ( mGrabHandleVisibility && mTextInputHandles.GetGrabHandle() ) - { - std::size_t newGrabHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY() ); - if ( mGrabHandlePosition != newGrabHandlePosition ) - { - Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition(); - Vector2 scrollDelta = ( mActualGrabHandlePosition - mCurrentHandlePosition ).GetVectorXY(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::OnScrollTimerTick scrollPosition(%f) scrollDelta(%f)\n", scrollPosition.x, scrollDelta.x); - scrollPosition += scrollDelta; - mTextViewCharacterPositioning.SetScrollPosition( scrollPosition ); - - mActualGrabHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newGrabHandlePosition ).GetVectorXY(); - } - } - - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - - if ( selectionHandleOne && selectionHandleTwo ) - { - std::size_t newHandleOnePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mSelectionHandleOneActualPosition.GetVectorXY() ); - - // todo duplicated code should be a function - - if ( mSelectionHandleOnePosition != newHandleOnePosition ) - { - const Vector3 actualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandleOnePosition ); - - Vector2 scrollDelta = ( actualPosition - mSelectionHandleOneActualPosition ).GetVectorXY(); - - Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition(); - scrollPosition += scrollDelta; - mTextViewCharacterPositioning.SetScrollPosition( scrollPosition ); - - mSelectionHandleOnePosition = newHandleOnePosition; - mSelectionHandleOneActualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition ).GetVectorXY(); - } - else - { - mSelectionHandleOneActualPosition.x += mScrollDisplacement.x; - mSelectionHandleOneActualPosition.y += mScrollDisplacement.y; - } - - std::size_t newHandleTwoPosition = mTextViewCharacterPositioning.ReturnClosestIndex( mSelectionHandleTwoActualPosition.GetVectorXY() ); - - if ( mSelectionHandleTwoPosition != newHandleTwoPosition ) - { - const Vector3 actualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandleTwoPosition ); - - Vector2 scrollDelta = ( actualPosition - mSelectionHandleTwoActualPosition ).GetVectorXY(); - - Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition(); - scrollPosition += scrollDelta; - mTextViewCharacterPositioning.SetScrollPosition( scrollPosition ); - - mSelectionHandleTwoPosition = newHandleTwoPosition; - mCurrentHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition ).GetVectorXY(); - - } - else - { - mSelectionHandleTwoActualPosition.x += mScrollDisplacement.x; - mSelectionHandleTwoActualPosition.y += mScrollDisplacement.y; - } - } - - return true; -} - -/** - * Text Selection - */ -MarkupProcessor::StyledTextArray Decorator::GetSelectedText() -{ - MarkupProcessor::StyledTextArray currentSelectedText; - - if ( mHighlightMeshActor ) // Text Selected - { - MarkupProcessor::StyledTextArray::iterator it = mTextViewCharacterPositioning.GetStyledTextArray().begin() + std::min(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - MarkupProcessor::StyledTextArray::iterator end = mTextViewCharacterPositioning.GetStyledTextArray().begin() + std::max(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - - for(; it != end; ++it) - { - MarkupProcessor::StyledText& styledText( *it ); - currentSelectedText.push_back( styledText ); - } - } - return currentSelectedText; -} - -} // Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h b/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h deleted file mode 100644 index 7de78bf..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h +++ /dev/null @@ -1,634 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class Decorator; - -typedef IntrusivePtr DecoratorPtr; - -/** - * @brief Decorator Class - * - * Decorations are Selection Handles, cursor, grab handle, magnifier the "cut copy paste" PopUp and Selection highlight. - * The Decorator triggers creation of these decorations and positions them. - * Decoration positions can be dependent on other decorations like the PopUp on the Selection handles. - * The decorator maintains a Bounding Box which the decorations have to be positioned within, decorations can be flipped or hidden to obey this Bounding Box. - * Scrolling of Text can effect positioning of decorations, the decorator repositions decorations in this case. - */ - -class Decorator : public ConnectionTracker -{ - -public: - - /** - * @brief Constructor - * - * @param[in] textviewManager TextViewManager to be used - */ - Decorator( TextViewCharacterPositioning& textviewManager, TextInputTextStyle& textStyle); - - /** - * @brief Default destructor - */ - ~Decorator(); - - /** - * @brief Set the dimensions of the bounding rectangle for decorations to obey. - * - * @param[in] boundingRectangle - */ - void SetBoundingBox( const Rect& boundingRectangle ); - - /** - * @brief Get the bounding dimensions of the bounding box - * - * @return dimensions of the bounding box from world origin. (x, y, w, z ) - * - * ----------------- - * | ^ | - * | | | - * | y | - * | | | - * | v | - * |<--x--> o <--z-->| - * | ^ | - * | | | - * | w | - * | | | - * | v | - * ----------------- - */ - Vector4 GetBoundingBox() const; - - /** - * @brief Callback when a handle is panned/moved, either selection handles or grab handle - * - * @param actor Handle of the selection or grab handle. - * @param gesture Data structure with the parameters of the gesture. - */ - void OnHandlePan(Actor actor, const PanGesture& gesture); - - // Selection Handles - - /** - * @brief Create a left and right selection handle and parent both to the provided actor - * @param[in] parent actor in which the handles should be added to. - */ - void CreateSelectionHandles( Actor parent ); - - /** - * @brief Remove selection handles from their parent - */ - void RemoveSelectionHandles(); - - /** - * @brief Get size of Selection handles - * - * @return size of a selection handle - */ - Vector3 GetSelectionHandleSize(); - - /** - * @brief Get position of Selection handle within text - * - * @return character position of a selection handle one - */ - std::size_t GetHandleOnePosition() const; - - /** - * @brief Get position of Selection handle within text - * - * @return character position of a selection handle two - */ - std::size_t GetHandleTwoPosition() const; - - /** - * @brief Position Selection a single handle at given positions within the text string. - * - * @param[in] selectionHandle handle to be positioned - * @param[in] position where to place handle - * @return Vector3 Position of handle as a coordinate. - */ - Vector3 PositionSelectionHandle( Actor selectionHandle, std::size_t position ); - - /** - * @brief Position Selection a single handle at given coordinates - * - * @param[in] selectionHandle handle to be positioned - * @param[in] actualPosition coordinates to position handle - * @param[in] position where to place handle - * @return Vector3 Position of handle as a coordinate. - */ - Vector3 PositionSelectionHandle( Actor selectionHandle, Vector3& actualPosition, std::size_t position ); - - /** - * @brief Make both selection handle visible or invisible - * @param[in] visible true to make visible, false to fine - */ - void SetSelectionHandlesVisibility( bool visible ); - - /** - * @brief Position Selection handles at given positions within the text string. - * - * @param[in] start where to place first handle - * @param[in] end where to place second handle - */ - void PositionSelectionHandles( std::size_t start, std::size_t end ); - - /** - * @brief Move selection handle by the given displacement. - * - * @param[in] selectionHandle Actor to move - * @param[in] actualSelectionHandlePosition actual current position of the handle in x y z - * @param[in] currentSelectionHandlePosition current position along the string - * @param[in] displacement the x y displacement - */ - Vector3 MoveSelectionHandle( Actor selectionHandle, - Vector3& actualSelectionHandlePosition, - std::size_t& currentSelectionHandlePosition, - const Vector2& displacement ); - - /* Grab Handle */ - - /** - * @brief Position GrabHandlewith depending on the the character in the text it should be placed at - * @param[in] positonInText the character position within the text the handle should be at - */ - void PositionGrabHandle( std::size_t positionInText ); - - /** - * @brief Move grab handle to the required position within the text - * - * @param[in] displacement Displacement of the grab handle in actor coordinates. - */ - void MoveGrabHandle( const Vector2& displacement ); - - /** - * @brief Show or hide the GrabHandle is visibility is true - * - * @param[in] visible flag to show or not show the grab handle - */ - void ShowGrabHandle( bool visible ); - - /** - * @brief Create the GrabHandle used to position cursor - * @param[in] targetParent the Actor to parent the GrabHandle - */ - void CreateGrabHandle( Actor targetParent ); - - /** - * @brief Set the image to be used as the cursor grab hander - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - */ - void SetGrabHandleImage( Image image ); - - /** - * @brief Toggle to enable the grab handle, used to position cursor when magnifier not being used. - * Default behaviour is to use the magnifier to position the cursor, enabling this prevents the magnifier from being shown. - * @param[in] toggle true to enable, false to disable grab handle - */ - void EnableGrabHandle(bool toggle); - - /** - * @brief Method to check if grab handle is enabled, if false then the magnifier will be used to position cursor. - * @return bool returns true is grab handle enabled. - */ - bool IsGrabHandleEnabled(); - - /* Cursor */ - - /** - * @brief Get the current Cursor position - * @return current cursor position - */ - std::size_t GetCurrentCursorPosition() const; - - /** - * @brief Set the Cursor position - * @param[in] the position the cursor should be set to - */ - void SetCurrentCursorPosition( std::size_t newCursorPosition ); - - /** - * @brief Set if the cursors are visible or not. - * @param[in] visible flag true for visible - */ - void SetCursorVisibility( bool visible ); - - /** - * @brief Display cursor - * @param[in] nthChar position in text string to display cursor - */ - void DrawCursor( const std::size_t nthChar = 0 ); - - /** - * Sets alternate cursor enable state - * @see SetCursorVisibility - * alternate cursor will only be visible if both SetCursorVisiblity - * and cursor enabled have been set to true. - */ - void SetAltCursorEnabled( bool enabled ); - - /** - * @brief Set the image to be used for the regular left to right cursor - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - * @param[in] border The nine patch border for the image. - */ - void SetCursorImage( Image image, const Vector4& border ); - - /** - * @brief Set the image to be used for the Right to Left cursor - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - * @param[in] border The nine patch border for the image. - */ - void SetRTLCursorImage( Image image, const Vector4& border ); - - /** - * @brief Creates a cursor from the supplied image and nine patch border. - * @param[in] cursorImage the image to be used for the cursor. - * @param[in] border the nine patch border corresponding to the supplied image. - * @paran[in] cursorName actor name for cursor - * @return the image actor to be used as the cursor. - */ - ImageActor CreateCursor( Image cursorImage, const Vector4& border, const std::string& cursorName ); - - /** - * @brief Creates a regular and Right-To-Left cursor and parents them to give target Actor - * @param[in] targetParent target Actor - */ - void CreateCursors( Actor targetParent ); - - /** - * @Brief Returns the cursor size at a given position in the text. - * @return Size the size of the cursor - */ - Size GetCursorSizeAt( std::size_t positionWithinTextToGetCursorSize ); - - /** - * @brief Start a timer to signal cursor to blink. - */ - void StartCursorBlinkTimer(); - - /** - * @brief Stop the timer signalling the cursor to blink. - */ - void StopCursorBlinkTimer(); - - /** - * @brief Callback when handle timer ticks. - * - * Cursor should become visible/invisible to simulate blinking. - * - * @return True if the timer should be keep running. - */ - bool OnCursorBlinkTimerTick(); - - /* Selection Highlight */ - - /** - * @brief Updates mesh data for selection highlight depending on handle positions and displays it. - */ - void ShowUpdatedHighlight(); - - /** - * @brief Creates the Highlight used for selection - * - * @param[in] parent target actor in which the handles should be added to. - */ - void CreateHighlight( Actor parent ); - - /** - * @brief Remove Highlight actor from it's parent - */ - void RemoveHighlight(); - - /** - * @brief Set the visibility of the Highlight - * - * @param[in] visibility True to show and False to hide. - */ - void HighlightVisibility( bool visiblility ); - - /* Boundary Property Notifications when handle exceed bounding box*/ - - /** - * @brief PropertyNotification Callback when left boundary exceeded so handle can be flipped. - * - * @param[in] source PropertyNotification - */ - void OnLeftBoundaryExceeded( PropertyNotification& source ); - /** - * @brief PropertyNotification Callback when within left boundary so handle can be flipped back. - * - * @param[in] source PropertyNotification - */ - void OnReturnToLeftBoundary( PropertyNotification& source ); - /** - * @brief PropertyNotification Callback when right boundary exceeded so handle can be flipped. - * - * @param[in] source PropertyNotification - */ - void OnRightBoundaryExceeded( PropertyNotification& source ); - /** - * @brief PropertyNotification Callback when within right boundary so handle can be flipped back. - * - * @param[in] source PropertyNotification - */ - void OnReturnToRightBoundary( PropertyNotification& source ); - - /** - * @brief PropertyNotification Callbacks for hiding handle one when it exceeds boundary. - * - * @param[in] source PropertyNotification - */ - void OnHandleOneLeavesBoundary( PropertyNotification& source ); - /** - * @brief PropertyNotification Callbacks for showing hidden handle one when returns within boundary - * - * @param[in] source PropertyNotification - */ - void OnHandleOneWithinBoundary( PropertyNotification& source ); - /** - * @brief PropertyNotification Callbacks for hiding handle two it when exceeds boundary. - * - * @param[in] source PropertyNotification - */ - void OnHandleTwoLeavesBoundary( PropertyNotification& source ); - /** - * @brief PropertyNotification Callbacks for showing hidden handle two when returns within boundary - * - * @param[in] source PropertyNotification - */ - void OnHandleTwoWithinBoundary( PropertyNotification& source ); - - /** - * @brief Set up property notifications on the position of the handles to facilitate flipping and hiding when at screen boundary. - */ - void SetUpHandlePropertyNotifications(); - - // Cut & Paste Pop-up - - /** - * @brief Calculate positioning of PopUp relative to handles - * @return Actual position of PopUp - */ - Vector3 PositionOfPopUpRelativeToSelectionHandles( ); - - /** - * @brief Calculate alternative position of PopUp relative to handles when can it not be displayed in the default upper position. - * @return Actual position of PopUp - */ - Vector3 AlternatePopUpPositionRelativeToSelectionHandles(); - - /** - * @brief Calculate positioning of PopUp relative to cursor - * @return Actual position of PopUp - */ - Vector3 PositionOfPopUpRelativeToCursor(); - - /** - * @brief Calculate alternative position of PopUp relative to cursor when can not be displayed in normal upper position. - * @return Actual position of PopUp - */ - Vector3 AlternatePopUpPositionRelativeToCursor(); - - /** - * @brief Calculate positioning of PopUp relative to GrabHandle - * @return Actual position of PopUp - */ - Vector3 PositionOfPopUpRelativeToGrabHandle(); - - /** - * @brief Show the PopUp in the provided target - * @param[in] target target actor in which the PopUp should be added to. - */ - void ShowPopUp( Actor target ); - - /** - * @brief Show PopUp in previously set Target. - * @pre Must have previously called ShopPopUp( Actor target ) otherwise PopUp will not be shown. - */ - void ShowPopUp(); - - /** - * @brief Create and Show Cut Copy Paste PopUp - */ - void ShowPopupCutCopyPaste(); - - /** - * @brief Hide PopUp - * @param[in] animate Animate or just hide instantly, default is true - * @param[in] signalFinished Signal when finished, default is true - */ - void HidePopUp( bool animate=true, bool signalFinished=true ); - - /** - * @brief Adds a popup option. - * @brief Creates popup frame if not already created. - * @param[in] name The unique name for this option. - * @param[in] caption The caption (label) for this option - * @param[in] icon the image icon to be displayed for this option - * @param[in] finalOption Flag to indicate that this is the final option. - * (set to true on the last option you add) - */ - void AddPopupOption(const std::string& name, const std::string& caption, const Image icon, bool finalOption = false); - - /** - * @brief Removes popup, and its options. - */ - void ClearPopup(); - - /** - * @brief PropertyNotification Callbacks for flipping PopUp when exceeds boundary. - * @param[in] source PropertyNotification - */ - void PopUpLeavesVerticalBoundary( PropertyNotification& source ); - - /** - * @brief Setup position notifications when PopUp exceeds boundary - */ - void SetUpPopUpPositionNotifications( ); - - /** - * @brief Callback for when a button is pressed in popup panel - * @param[in] button handle to the button pressed. - * @return bool consummation - */ - bool OnPopupButtonPressed( Toolkit::Button button ); - - // Decoration positioning during scrolling - - /** - * @brief Updates the position of the decorations when Text is scrolled. - * - * @param[in] textView Handle of the text-view. - * @param[in] scrollPosition The difference with the previous scroll position. - */ - void TextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ); - - /** - * @brief Creates and starts a timer to scroll the text when handles are close to the edges of the text-input. - * - * It only starts the timer if it's already created. - */ - void StartScrollTimer(); - - /** - * @brief Stops the timer used to scroll the text. - */ - void StopScrollTimer(); - - /** - * @brief Scroll Text according to handle position - * @param[in out] handlePosition handle position within character string - * @param[in] actual vector position of handle - * @return updated actual vector position of handle - */ - Vector3 ScrollRelativeToHandle( std::size_t& handlePosition, Vector3& actualHandlePosition ); - - /** - * @brief Callback called by the timer used to scroll the text. - * - * It calculates and sets a new scroll position. - */ - bool OnScrollTimerTick(); - - // Text Selection - - /** - * @brief Function to get Text selected between the 2 selection handles. - * @return StyledTextArray an array of - */ - MarkupProcessor::StyledTextArray GetSelectedText(); - -private: - - /** - * @brief Copy Constructor - * @param[in] decorator - * Undefined/Hidden. - */ - Decorator(const Decorator& decorator); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - Decorator& operator=(const Decorator& rhs); - -public: - - typedef Signal< bool( Toolkit::Button ) > PressedSignal; - typedef Signal< void () > CursorPositionedSignal; - /** - * @brief Signal emitted when the button is touched. - * This is relayed from the PopUp class. It enables the owner of the Decorator to act on the PopUp button press. - */ - PressedSignal& PopUpButtonPressedSignal(); - - /** - * @brief Signal emitted when the cursor is repositioned - * @param[in] cursor the new cursor position - */ - CursorPositionedSignal& CursorRePositionedSignal(); - -private: - - Vector4 mBoundingRectangleWorldCoordinates; - - TextViewCharacterPositioning& mTextViewCharacterPositioning; - - TextInputHandles mTextInputHandles; - - TextInputTextStyle& mTextStyle; - - Vector3 mSelectionHandleOneActualPosition; // Actual x y position of handle - Vector3 mSelectionHandleTwoActualPosition; // Actual x y position of handle - std::size_t mSelectionHandleOnePosition; // Position of handle along the string of text - std::size_t mSelectionHandleTwoPosition; // Position of handle along the string of text - - TextInputPopupNew mPopUpPanel; // PopUp used for Cut Cpoy and Paste - Actor mPopUpTarget; // Target Actor to parent PopUp - - Vector3 mActualGrabHandlePosition; // Actual position of grab handle, this might not be snapped to a character - std::size_t mGrabHandlePosition; // Position of grab handle along the string of text - Vector3 mCurrentHandlePosition; - - std::size_t mCursorPosition; // Current cursor position within the text string - ImageActor mCursor; // Cursor overlayed on Text to show where new text will be inserted - ImageActor mCursorRTL; // Right To Left Cursor overlayed on Text (where new RTL text would be inserted) - Animation mCursorAnimation; // Animation for cursor blinking. - Timer mCursorBlinkTimer; // Timer to signal cursor to blink - - Vector2 mScrollDisplacement; // How much to scroll by - Timer mScrollTimer; // Timer to scroll text over a period of time not all in one update. - - TextHighlight mTextHighlight; // Holds data required to construct the highlight - MeshActor mHighlightMeshActor; // Mesh Actor to display highlight - - PanGestureDetector mPanGestureDetector; - - PressedSignal mPopUpButtonPressedSignal; // Signal emitted when a button within the popup is pressed. - CursorPositionedSignal mCursorRePositionedSignal; // Signal emitted when a button when cursor position is changed. - - bool mCursorBlinkStatus:1; // \e true shows the cursor, \e false hides it. - bool mCursorVisibility:1; // Should cursor be visible - bool mCursorRTLEnabled:1; // Enable state of Alternate RTL Cursor (need to keep track of this as it's not always enabled) - bool mIsGrabHandleInScrollArea:1; // Whether the grab handle is inside the boundaries of the text-input. - bool mIsCursorInScrollArea:1; // Whether the cursor is inside the boundaries of the text-input. - bool mGrabHandleVisibility:1; // Should grab handle be visible - bool mGrabHandleEnabled:1; // Flag to enable the grab handle instead of the default magnifier. -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-handles-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-handles-impl.cpp deleted file mode 100644 index 8249889..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-handles-impl.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -using namespace Dali; - -namespace -{ -const char* const DEFAULT_SELECTION_HANDLE_ONE( DALI_IMAGE_DIR "text-input-selection-handle-left.png" ); -const char* const DEFAULT_SELECTION_HANDLE_TWO( DALI_IMAGE_DIR "text-input-selection-handle-right.png" ); -const char* const DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" ); -const char* const DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" ); - -const char* const DEFAULT_GRAB_HANDLE( DALI_IMAGE_DIR "insertpoint-icon.png" ); - -const Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SCALE( 1.5f, 1.5f, 1.0f ); -const Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SCALE( 1.5f, 2.0f, 1.0f ); - -const char* const SELECTION_GRAB_AREA_ONE( "SelectionHandleOneGrabArea"); -const char* const SELECTION_GRAB_AREA_TWO( "SelectionHandleTwoGrabArea"); -const char* const GRABHANDLE_GRAB_AREA( "GrabHandleGrabArea"); - -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "TEXT_INPUT_HANDLES" ); -#endif - -Actor CreateGrabArea( const std::string& name, const Vector3& relativeScale ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: CreateGrabArea\n" ); - - Actor handleGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move - handleGrabArea.SetName( name ); - handleGrabArea.SetResizePolicy( SIZE_RELATIVE_TO_PARENT, ALL_DIMENSIONS ); - handleGrabArea.SetSizeModeFactor( relativeScale ); - handleGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - - return handleGrabArea; -} - -ImageActor CreateHandle( const Vector3& anchorPoint, const Image& handleImage, const std::string& name ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: CreateSelectionHandle\n" ); - - ImageActor selectionHandle = ImageActor::New( handleImage ); - selectionHandle.SetName( name ); - selectionHandle.SetAnchorPoint( anchorPoint ); - selectionHandle.SetDrawMode( DrawMode::OVERLAY ); // ensure handle above text - - return selectionHandle; -} -} - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -// Default constructor -TextInputHandles::TextInputHandles(): - mSelectionHandleOne(), - mSelectionHandleTwo(), - mSelectionHandleOneOffset( Vector3::ZERO ), - mSelectionHandleTwoOffset( Vector3::ZERO ), - mSelectionHandleOneCoordinatePosition( Vector3::ZERO ), - mSelectionHandleTwoCoordinatePosition( Vector3::ZERO ), - mSelectionHandleOneStringPosition( 0 ), - mSelectionHandleTwoStringPosition( 0 ), - mIsSelectionHandleOneFlipped( false ), - mIsSelectionHandleTwoFlipped( false ) -{ -} - -TextInputHandles::~TextInputHandles() -{ -} - -void TextInputHandles::CreateSelectionHandles() -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: CreateSelectionHandles\n" ); - - mSelectionHandleOneImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE ); - mSelectionHandleOneImagePressed = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE_PRESSED ); - mSelectionHandleOne = CreateHandle( AnchorPoint::TOP_RIGHT, mSelectionHandleOneImage, "SelectionHandleOne" ); - mIsSelectionHandleOneFlipped = false; - - mHandleOneGrabArea = CreateGrabArea( SELECTION_GRAB_AREA_ONE, DEFAULT_SELECTION_HANDLE_RELATIVE_SCALE ); - mSelectionHandleOne.Add( mHandleOneGrabArea ); - mHandleOneGrabArea.TouchedSignal().Connect(this, &TextInputHandles::OnSelectionHandleTouched); - -// mTapDetector.Attach( mHandleOneGrabArea ); - - mSelectionHandleTwoImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO ); - mSelectionHandleTwoImagePressed = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO_PRESSED ); - mSelectionHandleTwo = CreateHandle( AnchorPoint::TOP_LEFT, mSelectionHandleTwoImage, "SelectionHandleTwo" ); - mIsSelectionHandleTwoFlipped = false; - - mHandleTwoGrabArea = CreateGrabArea( SELECTION_GRAB_AREA_TWO, DEFAULT_SELECTION_HANDLE_RELATIVE_SCALE ); - mSelectionHandleTwo.Add( mHandleTwoGrabArea ); - mHandleTwoGrabArea.TouchedSignal().Connect(this, &TextInputHandles::OnSelectionHandleTouched); - - // mTapDetector.Attach( mHandleTwoGrabArea ); -} - -void TextInputHandles::DestorySelectionHandles() -{ - if ( mSelectionHandleOne && mSelectionHandleTwo) - { - mSelectionHandleOne.Unparent(); - mSelectionHandleTwo.Unparent(); - mSelectionHandleOneImagePressed.Reset(); - mSelectionHandleOneImage.Reset(); - mSelectionHandleTwoImagePressed.Reset(); - mSelectionHandleTwoImage.Reset(); - mSelectionHandleOne.Reset(); - mSelectionHandleTwo.Reset(); - } -} - -void TextInputHandles::SetSelectionHandleOneVisibility( bool visibility ) -{ - if ( mSelectionHandleOne ) - { - mSelectionHandleOne.SetVisible( visibility ); - } -} - -void TextInputHandles::SetSelectionHandleTwoVisibility( bool visibility ) -{ - if ( mSelectionHandleTwo ) - { - mSelectionHandleTwo.SetVisible( visibility ); - } -} - -void TextInputHandles::AttachSelectionHandlesToGivenPanGesture( PanGestureDetector& panGestureDetector ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: AttachSelectionHandlesToGivenPanGesture\n" ); - - panGestureDetector.Attach( mHandleOneGrabArea ); - panGestureDetector.Attach( mHandleTwoGrabArea ); -} - -void TextInputHandles::AttachSelectionHandlesToGivenTapDetector(TapGestureDetector& tapGestureDetector ) -{ - tapGestureDetector.Attach( mHandleOneGrabArea ); - tapGestureDetector.Attach( mHandleTwoGrabArea ); -} - -void TextInputHandles::AttachGrabHandleToGivenPanGesture( PanGestureDetector& panGestureDetector ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: AttachGrabHandleToGivenPanGesture\n" ); - - panGestureDetector.Attach( mGrabHandleGrabArea ); -} - -Actor TextInputHandles::GetSelectionHandleOne() -{ - return mSelectionHandleOne; -} - -Actor TextInputHandles::GetSelectionHandleTwo() -{ - return mSelectionHandleTwo; -} - -bool TextInputHandles::OnSelectionHandleTouched(Dali::Actor actor, const TouchEvent& touch) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: OnSelectionHandleTouched\n" ); - - Image pressedImage; - Image normalImage; - - ImageActor handleTouched = ImageActor::DownCast( actor.GetParent() ); // Hit actor would be the GrabArea hence get parent. - - if ( handleTouched == mSelectionHandleOne ) - { - pressedImage = mSelectionHandleOneImagePressed; - normalImage = mSelectionHandleOneImage; - } - else - { - pressedImage = mSelectionHandleTwoImagePressed; - normalImage = mSelectionHandleTwoImage; - } - - if (touch.GetPoint(0).state == TouchPoint::Down) - { - handleTouched.SetImage( pressedImage ); - } - else if (touch.GetPoint(0).state == TouchPoint::Up ) - { - handleTouched.SetImage( normalImage ); - } - return false; -} - -// Grab handle - -Actor TextInputHandles::GetGrabHandle() -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: GetGrabHandle\n" ); - - return mGrabHandle; -} - -void TextInputHandles::CreateGrabHandle() -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: CreateGrabHandle\n" ); - - if ( !mGrabHandle ) - { - if ( !mGrabHandleImage ) - { - mGrabHandleImage = ResourceImage::New( DEFAULT_GRAB_HANDLE ); - } - - mGrabHandle = CreateHandle( AnchorPoint::TOP_CENTER, mGrabHandleImage, "GrabHandle" ); - mGrabHandleGrabArea = CreateGrabArea( GRABHANDLE_GRAB_AREA, DEFAULT_GRAB_HANDLE_RELATIVE_SCALE ); - mGrabHandle.Add( mGrabHandleGrabArea ); - } -} - -void TextInputHandles::DestoryGrabHandle() -{ - if ( mGrabHandle ) - { - mGrabHandle.Unparent(); - mGrabHandleImage.Reset(); - mGrabHandle.Reset(); - } -} - -void TextInputHandles::SetGrabHandleImage( Dali::Image image ) -{ - if ( mGrabHandle ) - { - mGrabHandleImage = image; - mGrabHandle.SetImage( mGrabHandleImage ); - } -} - -void TextInputHandles::SetGrabHandleVisibility( bool visibility ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: SetGrabHandleVisibility (%s) \n", ( visibility )?"true":"false" ); - - if ( mGrabHandle ) - { - mGrabHandle.SetVisible( visibility ); - } -} - -} // Internal - -} // namespace Toolkit - -} // namespace Dali - diff --git a/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h b/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h deleted file mode 100644 index c5f9013..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ -/** - * Class to create handles and alter their visualisation. - * Not responsible for positioning. - */ - -class TextInputHandles : public ConnectionTracker -{ - -public: - - /** - * Default constructor - */ - TextInputHandles(); - - /** - * Destructor - */ - ~TextInputHandles(); - - /** - * Create the selection handles - */ - void CreateSelectionHandles(); - - /** - * Un-parents the Selection Handles and resets their Image Actors - */ - void DestorySelectionHandles(); - - /** - * Set the Actor visibility on Selection Handle One - * @param[in] visibility visibility flag - */ - void SetSelectionHandleOneVisibility( bool visibility ); - - /** - * Set the Actor visibility on Selection Handle Two - * @param[in] visibility visibility flag - */ - void SetSelectionHandleTwoVisibility( bool visibility ); - - /** - * Attach the two selection handles to the pan gesture detector - * @param[in] panGestureDetector the PanGestureDetector to attach to - */ - void AttachSelectionHandlesToGivenPanGesture(PanGestureDetector& panGestureDetector ); - - /** - * Attach the two selection handles to the tap gesture detector - * @param[in] tapGestureDetector the TapGestureDetector to attach to - */ - void AttachSelectionHandlesToGivenTapDetector(TapGestureDetector& tapGestureDetector ); - - /** - * Attach the grab handle to the pan gesture detector - * @param[in] panGestureDetector the PanGestureDetector to attach to - */ - void AttachGrabHandleToGivenPanGesture( PanGestureDetector& panGestureDetector ); - - /** - * Get Selection handle one - * @return selection handle actor - */ - Actor GetSelectionHandleOne(); - - /** - * Get Selection handle two - * @return selection handle actor - */ - Actor GetSelectionHandleTwo(); - - /** - * Get the grab handle - * @return grab handle Actor - */ - Actor GetGrabHandle(); - - /** - * Create the grab handle that positions the cursor - * @param[in] image the image to be used. - */ - void CreateGrabHandle(); - - /** - * Removes and Resets GrabHandle - */ - void DestoryGrabHandle(); - - /** - * Set the image to be used as the cursor grab hander - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - */ - void SetGrabHandleImage( Dali::Image image ); - - /** - * Set the Actor visibility on the GrabHandle - * @param[in] visibility visibility flag - */ - void SetGrabHandleVisibility( bool visibility ); - - /* Touch Event Callbacks */ - - /** - * Callback on selection handle touched. - * Sets the image depending if handle in pressed or normal state - * @param[in] actor touched - * @param[in] touch touch event, used to determine if down or up event - */ - bool OnSelectionHandleTouched(Dali::Actor actor, const TouchEvent& touch); - -private: - - /** - * @brief Copy Constructor - * @param[in] handles - * Undefined/Hidden. - */ - TextInputHandles(const TextInputHandles& handles); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - TextInputHandles& operator=(const TextInputHandles& rhs); - -private: - - ImageActor mSelectionHandleOne; // First selection handle used for selecting text to cut&paste - ImageActor mSelectionHandleTwo; // Second selection handle used for selecting text to cut&paste - Actor mHandleOneGrabArea; // Invisible actor that receives pans events for the selection handle. - Actor mHandleTwoGrabArea; // Invisible actor that receives pans events for the selection handle. - - Image mSelectionHandleOneImage; // image used for selection handle one - Image mSelectionHandleOneImagePressed; // image used for selection handle one pressed state - Image mSelectionHandleTwoImage; // image used for selection handle two - Image mSelectionHandleTwoImagePressed; // image used for selection handle two pressed state - - Vector3 mSelectionHandleOneOffset; // Handle One's Offset - Vector3 mSelectionHandleTwoOffset; // Handle Two's Offset - Vector3 mSelectionHandleOneCoordinatePosition; // Actual x y z position of handle - Vector3 mSelectionHandleTwoCoordinatePosition; // Actual x y z position of handle - std::size_t mSelectionHandleOneStringPosition; // Position of handle along the string of text - std::size_t mSelectionHandleTwoStringPosition; // Position of handle along the string of text - - Image mGrabHandleImage; // Image to be used for grab handle - ImageActor mGrabHandle; // Handle used to move cursor for editing - Actor mGrabHandleGrabArea; // invisible actor that receives pans events for the grab handle. - - bool mIsSelectionHandleOneFlipped:1; // Flag to know whether the handle one is flipped or not. - bool mIsSelectionHandleTwoFlipped:1; // Flag to know whether the handle two is flipped or not. -}; - - -} // namespace Internal - - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-impl.cpp deleted file mode 100644 index fc289f8..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-impl.cpp +++ /dev/null @@ -1,5534 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - -using namespace Dali; - -// Local Data -namespace -{ - -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXT_INPUT"); -#endif - -const std::size_t DEFAULT_MAX_SIZE( std::numeric_limits::max() ); // Max possible number -const std::size_t DEFAULT_NUMBER_OF_LINES_LIMIT( std::numeric_limits::max() ); // Max possible number -const Vector3 DEFAULT_SELECTION_HANDLE_SIZE( 51.0f, 79.0f, 0.0f ); // Selection cursor image size -const Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.5f, 2.0f, 1.0f ); -const Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f ); -const Vector4 LIGHTBLUE( 0.07f, 0.41f, 0.59f, 1.0f ); // Used for Selection highlight - -const char* DEFAULT_GRAB_HANDLE( DALI_IMAGE_DIR "insertpoint-icon.png" ); -const char* DEFAULT_SELECTION_HANDLE_ONE( DALI_IMAGE_DIR "text-input-selection-handle-left.png" ); -const char* DEFAULT_SELECTION_HANDLE_TWO( DALI_IMAGE_DIR "text-input-selection-handle-right.png" ); -const char* DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" ); -const char* DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" ); - -const std::size_t CURSOR_BLINK_INTERVAL = 500; ///< Cursor blink interval -const float CHARACTER_THRESHOLD( 2.5f ); ///< the threshold of a line. -const float DISPLAYED_HIGHLIGHT_Z_OFFSET( 0.1f ); ///< 1. Highlight rendered (z-offset). -const float DISPLAYED_TEXT_VIEW_Z_OFFSET( 0.2f ); ///< 2. Text rendered (z-offset). -const float UI_Z_OFFSET( 0.2f ); ///< 3. Text Selection Handles/Cursor z-offset. - -const Vector3 UI_OFFSET(0.0f, 0.0f, UI_Z_OFFSET); ///< Text Selection Handles/Cursor offset. -const Vector3 DEFAULT_HANDLE_ONE_OFFSET(0.0f, -5.0f, 0.0f); ///< Handle One's Offset -const Vector3 DEFAULT_HANDLE_TWO_OFFSET(0.0f, -5.0f, 0.0f); ///< Handle Two's Offset -const float TOP_HANDLE_TOP_OFFSET( 34.0f); ///< Offset between top handle and cutCopyPaste pop-up -const float BOTTOM_HANDLE_BOTTOM_OFFSET(34.0f); ///< Offset between bottom handle and cutCopyPaste pop-up -const float CURSOR_THICKNESS(4.0f); -const Degree CURSOR_ANGLE_OFFSET(2.0f); ///< Offset from the angle of italic angle. -const Vector4 DEFAULT_CURSOR_COLOR(1.0f, 1.0f, 1.0f, 1.0f); - -const char* const NEWLINE = "\n"; - -const TextStyle DEFAULT_TEXT_STYLE; - -const unsigned int SCROLL_TICK_INTERVAL = 50u; -const float SCROLL_THRESHOLD = 10.f; -const float SCROLL_SPEED = 15.f; - -/** - * Selection state enumeration (FSM) - */ -enum SelectionState -{ - SelectionNone, ///< Currently not encountered selected section. - SelectionStarted, ///< Encountered selected section - SelectionFinished ///< Finished selected section -}; - -std::size_t FindVisibleCharacterLeft( std::size_t cursorPosition, const Toolkit::TextView::CharacterLayoutInfoContainer& characterLayoutInfoTable ) -{ - for( Toolkit::TextView::CharacterLayoutInfoContainer::const_reverse_iterator it = characterLayoutInfoTable.rbegin() + characterLayoutInfoTable.size() - cursorPosition, endIt = characterLayoutInfoTable.rend(); - it != endIt; - ++it ) - { - if( ( *it ).mIsVisible ) - { - return --cursorPosition; - } - - --cursorPosition; - } - - return 0u; -} - -std::size_t FindVisibleCharacterRight( std::size_t cursorPosition, const Toolkit::TextView::CharacterLayoutInfoContainer& characterLayoutInfoTable ) -{ - for( Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator it = characterLayoutInfoTable.begin() + cursorPosition, endIt = characterLayoutInfoTable.end(); it < endIt; ++it ) - { - if( ( *it ).mIsVisible ) - { - return cursorPosition; - } - - ++cursorPosition; - } - - return cursorPosition; -} - -/** - * Whether the given position plus the cursor size offset is inside the given boundary. - * - * @param[in] position The given position. - * @param[in] cursorSize The cursor size. - * @param[in] controlSize The given boundary. - * - * @return whether the given position is inside the given boundary. - */ -bool IsPositionInsideBoundaries( const Vector3& position, const Size& cursorSize, const Vector3& controlSize ) -{ - return ( position.x >= -Math::MACHINE_EPSILON_1000 ) && - ( position.x <= controlSize.width + Math::MACHINE_EPSILON_1000 ) && - ( position.y - cursorSize.height >= -Math::MACHINE_EPSILON_1000 ) && - ( position.y <= controlSize.height + Math::MACHINE_EPSILON_1000 ); -} - -/** - * Splits a text in two halves. - * - * If the text's number of characters is odd, firstHalf has one more character. - * - * @param[in] text The text to be split. - * @param[out] firstHalf The first half of the text. - * @param[out] secondHalf The second half of the text. - */ -void SplitText( const Toolkit::MarkupProcessor::StyledTextArray& text, - Toolkit::MarkupProcessor::StyledTextArray& firstHalf, - Toolkit::MarkupProcessor::StyledTextArray& secondHalf ) -{ - firstHalf.clear(); - secondHalf.clear(); - - const std::size_t textLength = text.size(); - const std::size_t half = ( textLength / 2 ) + ( textLength % 2 ); - - firstHalf.insert( firstHalf.end(), text.begin(), text.begin() + half ); - secondHalf.insert( secondHalf.end(), text.begin() + half, text.end() ); -} - -} // end of namespace - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace // Unnamed namespace -{ - -BaseHandle Create() -{ - return Toolkit::TextInput::New(); -} - -// Setup properties, signals and actions using the type-registry. -DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextInput, Toolkit::Control, Create ) - -DALI_PROPERTY_REGISTRATION( TextInput, "highlight-color", VECTOR4, HIGHLIGHT_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-bg-color", VECTOR4, CUT_AND_PASTE_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-pressed-color", VECTOR4, CUT_AND_PASTE_PRESSED_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-border-color", VECTOR4, CUT_AND_PASTE_BORDER_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-icon-color", VECTOR4, CUT_AND_PASTE_ICON_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-icon-pressed-color", VECTOR4, CUT_AND_PASTE_ICON_PRESSED_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-text-color", VECTOR4, CUT_AND_PASTE_TEXT_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-text-pressed-color", VECTOR4, CUT_AND_PASTE_TEXT_PRESSED_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-button-position-priority", UNSIGNED_INTEGER, CUT_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "copy-button-position-priority", UNSIGNED_INTEGER, COPY_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "paste-button-position-priority", UNSIGNED_INTEGER, PASTE_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "select-button-position-priority", UNSIGNED_INTEGER, SELECT_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "select-all-button-position-priority", UNSIGNED_INTEGER, SELECT_ALL_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "clipboard-button-position-priority", UNSIGNED_INTEGER, CLIPBOARD_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "popup-offset-from-text", VECTOR4, POP_UP_OFFSET_FROM_TEXT ) -DALI_PROPERTY_REGISTRATION( TextInput, "cursor-color", VECTOR4, CURSOR_COLOR ) - -DALI_SIGNAL_REGISTRATION( TextInput, "start-input", SIGNAL_START_INPUT ) -DALI_SIGNAL_REGISTRATION( TextInput, "end-input", SIGNAL_END_INPUT ) -DALI_SIGNAL_REGISTRATION( TextInput, "style-changed", SIGNAL_STYLE_CHANGED ) -DALI_SIGNAL_REGISTRATION( TextInput, "max-input-characters-reached", SIGNAL_MAX_INPUT_CHARACTERS_REACHED ) -DALI_SIGNAL_REGISTRATION( TextInput, "toolbar-displayed", SIGNAL_TOOLBAR_DISPLAYED ) -DALI_SIGNAL_REGISTRATION( TextInput, "text-exceed-boundaries", SIGNAL_TEXT_EXCEED_BOUNDARIES ) - -DALI_TYPE_REGISTRATION_END() - -} - -// [TextInput::HighlightInfo] ///////////////////////////////////////////////// - -void TextInput::HighlightInfo::AddQuad( float x1, float y1, float x2, float y2 ) -{ - QuadCoordinates quad(x1, y1, x2, y2); - mQuadList.push_back( quad ); -} - -void TextInput::HighlightInfo::Clamp2D(const Vector2& min, const Vector2& max) -{ - for(std::size_t i = 0;i < mQuadList.size(); i++) - { - QuadCoordinates& quad = mQuadList[i]; - - quad.min.Clamp(min, max); - quad.max.Clamp(min, max); - } // end for -} - -// [TextInput] //////////////////////////////////////////////////////////////// - -Dali::Toolkit::TextInput TextInput::New() -{ - // Create the implementation - TextInputPtr textInput(new TextInput()); - // Pass ownership to CustomActor via derived handle - Dali::Toolkit::TextInput handle(*textInput); - handle.SetName( "TextInput"); - - textInput->Initialize(); - return handle; -} - -TextInput::TextInput() -:Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ), - mState( StateEdit ), - mStyledText(), - mInputStyle(), - mLineHeight( 0.f ), - mDisplayedTextView(), - mStyledPlaceHolderText(), - mMaxStringLength( DEFAULT_MAX_SIZE ), - mNumberOflinesLimit( DEFAULT_NUMBER_OF_LINES_LIMIT ), - mCursorPosition( 0 ), - mActualGrabHandlePosition( 0.0f, 0.0f, 0.0f ), - mIsSelectionHandleOneFlipped( false ), - mIsSelectionHandleTwoFlipped( false ), - mSelectionHandleOneOffset( DEFAULT_HANDLE_ONE_OFFSET ), - mSelectionHandleTwoOffset( DEFAULT_HANDLE_TWO_OFFSET ), - mSelectionHandleOneActualPosition( 0.0f, 0.0f , 0.0f ), - mSelectionHandleTwoActualPosition( 0.0f, 0.0f , 0.0f ), - mSelectionHandleOnePosition( 0 ), - mSelectionHandleTwoPosition( 0 ), - mPreEditString(), - mPreEditStartPosition( 0 ), - mPreEditLength ( 0 ), - mNumberOfSurroundingCharactersDeleted( 0 ), - mTouchStartTime( 0 ), - mTextLayoutInfo(), - mCurrentCopySelecton(), - mPopupPanel(), - mScrollTimer(), - mScrollDisplacement(), - mCurrentHandlePosition(), - mCurrentSelectionId(), - mCurrentSelectionHandlePosition(), - mRequestedSelection( 0, 0 ), - mSelectionHandleFlipMargin( 0.0f, 0.0f, 0.0f, 0.0f ), - mBoundingRectangleWorldCoordinates( 0.0f, 0.0f, 0.0f, 0.0f ), - mClipboard(), - mMaterialColor( LIGHTBLUE ), - mPopupOffsetFromText ( Vector4( 0.0f, TOP_HANDLE_TOP_OFFSET, 0.0f, BOTTOM_HANDLE_BOTTOM_OFFSET ) ), - mOverrideAutomaticAlignment( false ), - mCursorRTLEnabled( false ), - mClosestCursorPositionEOL ( false ), - mCursorBlinkStatus( true ), - mCursorVisibility( false ), - mGrabHandleVisibility( false ), - mIsCursorInScrollArea( true ), - mIsGrabHandleInScrollArea( true ), - mEditModeActive( false ), - mEditOnTouch( true ), - mTextSelection( true ), - mExceedEnabled( true ), - mGrabHandleEnabled( true ), - mIsSelectionHandleFlipEnabled( true ), - mPreEditFlag( false ), - mIgnoreCommitFlag( false ), - mIgnoreFirstCommitFlag( false ), - mSelectingText( false ), - mPreserveCursorPosition( false ), - mSelectTextOnCommit( false ), - mUnderlinedPriorToPreEdit ( false ), - mCommitByKeyInput( false ), - mPlaceHolderSet( false ), - mMarkUpEnabled( false ) -{ - // Updates the line height accordingly with the input style. - UpdateLineHeight(); -} - -TextInput::~TextInput() -{ - StopCursorBlinkTimer(); -} - -// Public - -std::string TextInput::GetText() const -{ - std::string text; - - // Return text-view's text only if the text-input's text is not empty - // in order to not to return the placeholder text. - if( !mStyledText.empty() ) - { - text = mDisplayedTextView.GetText(); - } - - return text; -} - -std::string TextInput::GetMarkupText() const -{ - std::string markupString; - MarkupProcessor::GetMarkupString( mStyledText, markupString ); - - return markupString; -} - -void TextInput::ShowPlaceholderText( const MarkupProcessor::StyledTextArray& stylePlaceHolderText ) -{ - mDisplayedTextView.SetText( stylePlaceHolderText ); - mPlaceHolderSet = true; - mDisplayedTextView.SetScrollPosition( Vector2( 0.0f,0.0f ) ); -} - -void TextInput::SetPlaceholderText( const std::string& placeHolderText ) -{ - // Get the placeholder styled text array from the markup string. - MarkupProcessor::GetStyledTextArray( placeHolderText, mStyledPlaceHolderText, IsMarkupProcessingEnabled() ); - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } -} - -std::string TextInput::GetPlaceholderText() -{ - // Traverses the styled placeholder array getting only the text. - // Note that for some languages a 'character' could be represented by more than one 'char' - - std::string placeholderText; - for( MarkupProcessor::StyledTextArray::const_iterator it = mStyledPlaceHolderText.begin(), endIt = mStyledPlaceHolderText.end(); it != endIt; ++it ) - { - placeholderText.append( (*it).mText.GetText() ); - } - - return placeholderText ; -} - -void TextInput::SetInitialText(const std::string& initialText) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "SetInitialText string[%s]\n", initialText.c_str() ); - - if ( mPreEditFlag ) // If in the pre-edit state and text is being set then discard text being inserted. - { - mPreEditFlag = false; - mIgnoreCommitFlag = true; - } - - SetText( initialText ); - PreEditReset( false ); // Reset keyboard as text changed -} - -void TextInput::SetText(const std::string& initialText) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "SetText string[%s]\n", initialText.c_str() ); - - GetStyledTextArray( initialText, mStyledText, IsMarkupProcessingEnabled() ); - - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - mDisplayedTextView.SetText( mStyledText ); - mPlaceHolderSet = false; - } - - GetTextLayoutInfo(); - - mCursorPosition = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition( mCursorPosition ); - imfManager.SetSurroundingText( initialText ); - imfManager.NotifyCursorPosition(); - } - - if( IsScrollEnabled() ) - { - ScrollTextViewToMakeCursorVisible( Vector3( mTextLayoutInfo.mScrollOffset.x, mTextLayoutInfo.mScrollOffset.y, 0.f ) ); - } - - ShowGrabHandleAndSetVisibility( false ); - - RemoveHighlight(); - - DrawCursor(); - - EmitTextModified(); -} - -void TextInput::SetText( const MarkupProcessor::StyledTextArray& styleText ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "SetText markup text\n" ); - - mDisplayedTextView.SetText( styleText ); - mPlaceHolderSet = false; - - // If text alignment hasn't been manually set by application developer, then we - // automatically determine the alignment based on the content of the text i.e. what - // language the text begins with. - // TODO: This should determine different alignments for each line (broken by '\n') of text. - if(!mOverrideAutomaticAlignment) - { - // Determine bidi direction of first character (skipping past whitespace, numbers, and symbols) - bool leftToRight(true); - - if( !styleText.empty() ) - { - bool breakOut(false); - - for( MarkupProcessor::StyledTextArray::const_iterator textIter = styleText.begin(), textEndIter = styleText.end(); ( textIter != textEndIter ) && ( !breakOut ); ++textIter ) - { - const Text& text = textIter->mText; - - for( std::size_t i = 0; i < text.GetLength(); ++i ) - { - Character character( text[i] ); - if( character.GetCharacterDirection() != Character::Neutral ) - { - leftToRight = ( character.GetCharacterDirection() == Character::LeftToRight ); - breakOut = true; - break; - } - } - } - } - - // Based on this direction, either left or right align text if not manually set by application developer. - mDisplayedTextView.SetTextAlignment( static_cast( - ( leftToRight ? Toolkit::Alignment::HorizontalLeft : Toolkit::Alignment::HorizontalRight) | - Toolkit::Alignment::VerticalTop ) ); - mDisplayedTextView.SetLineJustification( leftToRight ? Toolkit::TextView::Left : Toolkit::TextView::Right); - } - - EmitTextModified(); -} - -void TextInput::SetMaxCharacterLength(std::size_t maxChars) -{ - mMaxStringLength = maxChars; -} - -void TextInput::SetNumberOfLinesLimit(std::size_t maxLines) -{ - DALI_ASSERT_DEBUG( maxLines > 0 ) - - if ( maxLines > 0) - { - mNumberOflinesLimit = maxLines; - } -} - -std::size_t TextInput::GetNumberOfLinesLimit() const -{ - return mNumberOflinesLimit; -} - -std::size_t TextInput::GetNumberOfCharacters() const -{ - return mStyledText.size(); -} - -// Styling -void TextInput::SetMaterialDiffuseColor( const Vector4& color ) -{ - mMaterialColor = color; - if ( mCustomMaterial ) - { - mCustomMaterial.SetDiffuseColor( mMaterialColor ); - mMeshData.SetMaterial( mCustomMaterial ); - } -} - -const Vector4& TextInput::GetMaterialDiffuseColor() const -{ - return mMaterialColor; -} - -// Signals - -Toolkit::TextInput::InputSignalType& TextInput::InputStartedSignal() -{ - return mInputStartedSignal; -} - -Toolkit::TextInput::InputSignalType& TextInput::InputFinishedSignal() -{ - return mInputFinishedSignal; -} - -Toolkit::TextInput::InputSignalType& TextInput::CutAndPasteToolBarDisplayedSignal() -{ - return mCutAndPasteToolBarDisplayed; -} - -Toolkit::TextInput::StyleChangedSignalType& TextInput::StyleChangedSignal() -{ - return mStyleChangedSignal; -} - -Toolkit::TextInput::TextModifiedSignalType& TextInput::TextModifiedSignal() -{ - return mTextModifiedSignal; -} - -Toolkit::TextInput::MaxInputCharactersReachedSignalType& TextInput::MaxInputCharactersReachedSignal() -{ - return mMaxInputCharactersReachedSignal; -} - -Toolkit::TextInput::InputTextExceedBoundariesSignalType& TextInput::InputTextExceedBoundariesSignal() -{ - return mInputTextExceedBoundariesSignal; -} - -bool TextInput::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) -{ - Dali::BaseHandle handle( object ); - - bool connected( true ); - Toolkit::TextInput textInput = Toolkit::TextInput::DownCast( handle ); - - if( 0 == strcmp( signalName.c_str(), SIGNAL_START_INPUT ) ) - { - textInput.InputStartedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_END_INPUT ) ) - { - textInput.InputFinishedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_STYLE_CHANGED ) ) - { - textInput.StyleChangedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_INPUT_CHARACTERS_REACHED ) ) - { - textInput.MaxInputCharactersReachedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_TOOLBAR_DISPLAYED ) ) - { - textInput.CutAndPasteToolBarDisplayedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_EXCEED_BOUNDARIES ) ) - { - textInput.InputTextExceedBoundariesSignal().Connect( tracker, functor ); - } - else - { - // signalName does not match any signal - connected = false; - } - - return connected; -} - -void TextInput::SetEditable(bool editMode, bool setCursorOnTouchPoint, const Vector2& touchPoint) -{ - if(editMode) - { - // update line height before calculate the actual position. - UpdateLineHeight(); - - if(!mEditModeActive) - { - if( setCursorOnTouchPoint ) - { - // Sets the cursor position for the given touch point. - ReturnClosestIndex( touchPoint, mCursorPosition ); - - // Creates the grab handle. - if( IsGrabHandleEnabled() ) - { - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition); - - CreateGrabHandle(); - - mActualGrabHandlePosition.x = cursorPosition.x; // Set grab handle to be at the cursor position - mActualGrabHandlePosition.y = cursorPosition.y; // Set grab handle to be at the cursor position - mGrabHandle.SetPosition( mActualGrabHandlePosition + UI_OFFSET ); - ShowGrabHandleAndSetVisibility( true ); - - // Scrolls the text-view if needed. - if( IsScrollEnabled() ) - { - ScrollTextViewToMakeCursorVisible( cursorPosition ); - } - } - } - else - { - mCursorPosition = mStyledText.size(); // Initially set cursor position to end of string. - } - } - - StartEditMode(); - } - else - { - EndEditMode(); - } -} - -bool TextInput::IsEditable() const -{ - return mEditModeActive; -} - -void TextInput::SetEditOnTouch( bool editOnTouch ) -{ - mEditOnTouch = editOnTouch; -} - -bool TextInput::IsEditOnTouch() const -{ - return mEditOnTouch; -} - -void TextInput::SetTextSelectable( bool textSelectable ) -{ - mTextSelection = textSelectable; -} - -bool TextInput::IsTextSelectable() const -{ - return mTextSelection; -} - -bool TextInput::IsTextSelected() const -{ - return mHighlightMeshActor; -} - -void TextInput::DeSelectText() -{ - RemoveHighlight(); - HidePopup(); - CursorUpdate(); -} - -void TextInput::SetGrabHandleImage(Dali::Image image ) -{ - if (image) - { - CreateGrabHandle(image); - } -} - -void TextInput::SetCursorImage(Dali::Image image, const Vector4& border ) -{ - DALI_ASSERT_DEBUG ( image && "Create cursor image invalid") - - if ( image ) - { - mCursor.SetImage( image ); - mCursor.SetNinePatchBorder( border ); - } -} - -Vector3 TextInput::GetSelectionHandleSize() -{ - return DEFAULT_SELECTION_HANDLE_SIZE; -} - -void TextInput::SetRTLCursorImage(Dali::Image image, const Vector4& border ) -{ - DALI_ASSERT_DEBUG ( image && "Create cursor image invalid") - - if ( image ) - { - mCursorRTL.SetImage( image); - mCursorRTL.SetNinePatchBorder( border ); - } -} - -void TextInput::EnableGrabHandle(bool toggle) -{ - // enables grab handle with will in turn de-activate magnifier - mGrabHandleEnabled = toggle; -} - -bool TextInput::IsGrabHandleEnabled() -{ - // if false then magnifier will be shown instead. - return mGrabHandleEnabled; -} - -void TextInput::EnableSelectionHandleFlip( bool toggle ) -{ - // Deprecated function. To be removed. - mIsSelectionHandleFlipEnabled = toggle; -} - -bool TextInput::IsSelectionHandleFlipEnabled() -{ - // Deprecated function, To be removed. Returns true as handle flipping always enabled by default so handles do not exceed screen. - return true; -} - -void TextInput::SetSelectionHandleFlipMargin( const Vector4& margin ) -{ - // Deprecated function, now just stores margin for retreival, remove completely once depricated Public API removed. - Vector3 textInputSize = mDisplayedTextView.GetCurrentSize(); - const Vector4 flipBoundary( -margin.x, -margin.y, textInputSize.width + margin.z, textInputSize.height + margin.w ); - - mSelectionHandleFlipMargin = margin; -} - -void TextInput::SetBoundingRectangle( const Rect& boundingRectangle ) -{ - // Convert to world coordinates and store as a Vector4 to be compatiable with Property Notifications. - Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); - - const float originX = boundingRectangle.x - 0.5f * stageSize.width; - const float originY = boundingRectangle.y - 0.5f * stageSize.height; - - const Vector4 boundary( originX, - originY, - originX + boundingRectangle.width, - originY + boundingRectangle.height ); - - mBoundingRectangleWorldCoordinates = boundary; -} - -const Rect TextInput::GetBoundingRectangle() const -{ - Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); - - const float originX = mBoundingRectangleWorldCoordinates.x + 0.5f * stageSize.width; - const float originY = mBoundingRectangleWorldCoordinates.y + 0.5f * stageSize.height; - - RectboundingRect( originX, originY, mBoundingRectangleWorldCoordinates.z - mBoundingRectangleWorldCoordinates.x, mBoundingRectangleWorldCoordinates.w - mBoundingRectangleWorldCoordinates.y); - - return boundingRect; -} - -const Vector4& TextInput::GetSelectionHandleFlipMargin() -{ - return mSelectionHandleFlipMargin; -} - -void TextInput::SetTextColor( const Vector4& color ) -{ - mDisplayedTextView.SetColor( color ); -} - -void TextInput::SetActiveStyle( const TextStyle& style, const TextStyle::Mask mask ) -{ - if( style != mInputStyle ) - { - // different style. - bool emitSignal = false; - - // mask: modify style according to mask, if different emit signal. - const TextStyle oldInputStyle( mInputStyle ); - - // Copy the new style. - mInputStyle.Copy( style, mask ); - - // if style has changed, emit signal. - if( oldInputStyle != mInputStyle ) - { - emitSignal = true; - } - - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - // Changing font point size will require the cursor to be re-sized - DrawCursor(); - - if( emitSignal ) - { - EmitStyleChangedSignal(); - } - } -} - -void TextInput::ApplyStyle( const TextStyle& style, const TextStyle::Mask mask ) -{ - if ( IsTextSelected() ) - { - const std::size_t begin = std::min(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - const std::size_t end = std::max(mSelectionHandleOnePosition, mSelectionHandleTwoPosition) - 1; - - if( !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() ) - { - ApplyStyleToRange(style, mask, mTextLayoutInfo.mCharacterLogicalToVisualMap[begin], mTextLayoutInfo.mCharacterLogicalToVisualMap[end]); - } - - // Keeps the old style to be compared with the new one. - const TextStyle oldInputStyle( mInputStyle ); - - // Copy only those parameters from the style which are set in the mask. - mInputStyle.Copy( style, mask ); - - if( mInputStyle != oldInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } -} - -void TextInput::ApplyStyleToAll( const TextStyle& style, const TextStyle::Mask mask ) -{ - if( !mStyledText.empty() ) - { - ApplyStyleToRange( style, mask, 0, mStyledText.size() - 1 ); - } -} - -TextStyle TextInput::GetStyleAtCursor() const -{ - TextStyle style; - - if ( !mStyledText.empty() && ( mCursorPosition > 0 ) ) - { - DALI_ASSERT_DEBUG( ( 0 <= mCursorPosition-1 ) && ( mCursorPosition-1 < mStyledText.size() ) ); - style = mStyledText.at( mCursorPosition-1 ).mStyle; - } - else // No text. - { - style = mInputStyle; - - if ( mInputStyle.GetFontPointSize() < Math::MACHINE_EPSILON_1000 ) - { - Dali::Font defaultFont = Dali::Font::New(); - style.SetFontPointSize( PointSize( defaultFont.GetPointSize()) ); - } - } - - return style; -} - -TextStyle TextInput::GetStyleAt( std::size_t position ) const -{ - DALI_ASSERT_DEBUG( ( 0 <= position ) && ( position <= mStyledText.size() ) ); - - if( position >= mStyledText.size() ) - { - position = mStyledText.size() - 1; - } - - return mStyledText.at( position ).mStyle; -} - -void TextInput::SetTextAlignment( Toolkit::Alignment::Type align ) -{ - mDisplayedTextView.SetTextAlignment( align ); - mOverrideAutomaticAlignment = true; -} - -void TextInput::SetTextLineJustification( Toolkit::TextView::LineJustification justification ) -{ - mDisplayedTextView.SetLineJustification( justification ); - mOverrideAutomaticAlignment = true; -} - -void TextInput::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ) -{ - mDisplayedTextView.SetFadeBoundary( fadeBoundary ); -} - -const Toolkit::TextView::FadeBoundary& TextInput::GetFadeBoundary() const -{ - return mDisplayedTextView.GetFadeBoundary(); -} - -Toolkit::Alignment::Type TextInput::GetTextAlignment() const -{ - return mDisplayedTextView.GetTextAlignment(); -} - -void TextInput::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ) -{ - mDisplayedTextView.SetMultilinePolicy( policy ); -} - -Toolkit::TextView::MultilinePolicy TextInput::GetMultilinePolicy() const -{ - return mDisplayedTextView.GetMultilinePolicy(); -} - -void TextInput::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ) -{ - mDisplayedTextView.SetWidthExceedPolicy( policy ); -} - -Toolkit::TextView::ExceedPolicy TextInput::GetWidthExceedPolicy() const -{ - return mDisplayedTextView.GetWidthExceedPolicy(); -} - -void TextInput::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ) -{ - mDisplayedTextView.SetHeightExceedPolicy( policy ); -} - -Toolkit::TextView::ExceedPolicy TextInput::GetHeightExceedPolicy() const -{ - return mDisplayedTextView.GetHeightExceedPolicy(); -} - -void TextInput::SetExceedEnabled( bool enable ) -{ - mExceedEnabled = enable; -} - -bool TextInput::GetExceedEnabled() const -{ - return mExceedEnabled; -} - -void TextInput::SetBackground(Dali::Image image ) -{ - // TODO Should add this function and add public api to match. -} - -bool TextInput::OnTouchEvent(const TouchEvent& event) -{ - return false; -} - -bool TextInput::OnKeyEvent(const KeyEvent& event) -{ - switch( event.state ) - { - case KeyEvent::Down: - { - return OnKeyDownEvent(event); - } - break; - - case KeyEvent::Up: - { - return OnKeyUpEvent(event); - } - break; - - default: - { - return false; - } - break; - } -} - -void TextInput::OnKeyInputFocusGained() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, ">>OnKeyInputFocusGained\n" ); - - mEditModeActive = true; - - mActiveLayer.RaiseToTop(); // Ensure layer holding handles is on top - - mInputStyle = GetStyleAtCursor(); // Inherit style from cursor position - - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - // Connect the signals to use in text input. - VirtualKeyboard::StatusChangedSignal().Connect( this, &TextInput::KeyboardStatusChanged ); - VirtualKeyboard::LanguageChangedSignal().Connect( this, &TextInput::SetTextDirection ); - - // Set the text direction if empty and connect to the signal to ensure we change direction when the language changes. - SetTextDirection(); - - GetTextLayoutInfo(); - - DrawCursor(); - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - Toolkit::TextInput handle( GetOwner() ); - mInputStartedSignal.Emit( handle ); - - ImfManager imfManager = ImfManager::Get(); - - if ( imfManager ) - { - imfManager.EventReceivedSignal().Connect(this, &TextInput::ImfEventReceived); - - // Notify that the text editing start. - imfManager.Activate(); - - // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated. - imfManager.SetRestoreAfterFocusLost( true ); - - imfManager.SetCursorPosition( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - - mClipboard = Clipboard::Get(); // Store handle to clipboard - - // Now in edit mode we can accept string to paste from clipboard - ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() ); - if ( notifier ) - { - notifier.ContentSelectedSignal().Connect( this, &TextInput::OnClipboardTextSelected ); - } -} - -void TextInput::OnKeyInputFocusLost() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, ">>OnKeyInputFocusLost\n" ); - - if( mPreEditFlag ) - { - // If key input focus is lost, it removes the - // underline from the last pre-edit text. - RemovePreEditStyle(); - const std::size_t numberOfCharactersDeleted = DeletePreEdit(); - InsertAt( mPreEditString, mPreEditStartPosition, numberOfCharactersDeleted ); - EmitTextModified(); - } - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - // The text editing is finished. Therefore the imf manager don't have restore activation. - imfManager.SetRestoreAfterFocusLost( false ); - - // Notify that the text editing finish. - imfManager.Deactivate(); - - imfManager.EventReceivedSignal().Disconnect(this, &TextInput::ImfEventReceived); - } - // Disconnect signal used the text input. - VirtualKeyboard::LanguageChangedSignal().Disconnect( this, &TextInput::SetTextDirection ); - - Toolkit::TextInput handle( GetOwner() ); - mInputFinishedSignal.Emit( handle ); - mEditModeActive = false; - mPreEditFlag = false; - RemoveHighlight(); - SetCursorVisibility( false ); - StopCursorBlinkTimer(); - - ShowGrabHandleAndSetVisibility( false ); - - mClipboard.Reset(); - // No longer in edit mode so do not want to receive string from clipboard - ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() ); - if ( notifier ) - { - notifier.ContentSelectedSignal().Disconnect( this, &TextInput::OnClipboardTextSelected ); - } - - Clipboard clipboard = Clipboard::Get(); - if ( clipboard ) - { - clipboard.HideClipboard(); - } -} - -void TextInput::OnControlStageConnection() -{ - Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); - - if ( mBoundingRectangleWorldCoordinates == Vector4::ZERO ) - { - SetBoundingRectangle( Rect( 0.0f, 0.0f, stageSize.width, stageSize.height )); - } -} - -void TextInput::CreateActiveLayer() -{ - Actor self = Self(); - mActiveLayer = Layer::New(); - mActiveLayer.SetName ( "ActiveLayerActor" ); - - mActiveLayer.SetAnchorPoint( AnchorPoint::CENTER); - mActiveLayer.SetParentOrigin( ParentOrigin::CENTER); - mActiveLayer.SetPositionInheritanceMode( USE_PARENT_POSITION ); - - self.Add( mActiveLayer ); - mActiveLayer.RaiseToTop(); -} - -void TextInput::OnInitialize() -{ - CreateTextViewActor(); - - SetUpTouchEvents(); - - // Create 2 cursors (standard LTR and RTL cursor for when text can be added at - // different positions depending on language) - mCursor = CreateCursor(DEFAULT_CURSOR_COLOR); - mCursorRTL = CreateCursor(DEFAULT_CURSOR_COLOR); - - Actor self = Self(); - self.Add( mCursor ); - self.Add( mCursorRTL ); - - mCursorVisibility = false; - - CreateActiveLayer(); // todo move this so layer only created when needed. - - // Assign names to image actors - mCursor.SetName("mainCursor"); - mCursorRTL.SetName("rtlCursor"); -} - -void TextInput::OnControlSizeSet(const Vector3& targetSize) -{ - mDisplayedTextView.SetSize( targetSize ); - GetTextLayoutInfo(); - mActiveLayer.SetSize(targetSize); -} - -void TextInput::OnRelayout( const Vector2& size, RelayoutContainer& container ) -{ - container.Add( mDisplayedTextView, size ); - container.Add( mPopupPanel.GetRootActor(), size ); - - GetTextLayoutInfo(); - - DrawCursor(); -} - -Vector3 TextInput::GetNaturalSize() -{ - Vector3 naturalSize = mDisplayedTextView.GetNaturalSize(); - - if( mEditModeActive && ( Vector3::ZERO == naturalSize ) ) - { - // If the natural is zero, it means there is no text. Let's return the cursor height as the natural height. - naturalSize.height = mLineHeight; - } - - return naturalSize; -} - -float TextInput::GetHeightForWidth( float width ) -{ - float height = mDisplayedTextView.GetHeightForWidth( width ); - - if( mEditModeActive && ( fabsf( height ) < Math::MACHINE_EPSILON_1000 ) ) - { - // If the height is zero, it means there is no text. Let's return the cursor height. - height = mLineHeight; - } - - return height; -} - -/*end of Virtual methods from parent*/ - -// Private Internal methods - -void TextInput::OnHandlePan(Actor actor, const PanGesture& gesture) -{ - switch (gesture.state) - { - case Gesture::Started: - // fall through so code not duplicated - case Gesture::Continuing: - { - if (actor == mGrabArea) - { - SetCursorVisibility( true ); - ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea ); - MoveGrabHandle( gesture.displacement ); - HidePopup(); // Do not show popup whilst handle is moving - } - else if (actor == mHandleOneGrabArea) - { - // the displacement in PanGesture is affected by the actor's rotation. - mSelectionHandleOneActualPosition.x += gesture.displacement.x * mSelectionHandleOne.GetCurrentScale().x; - mSelectionHandleOneActualPosition.y += gesture.displacement.y * mSelectionHandleOne.GetCurrentScale().y; - - MoveSelectionHandle( HandleOne, gesture.displacement ); - - mState = StateDraggingHandle; - HidePopup(); - } - else if (actor == mHandleTwoGrabArea) - { - // the displacement in PanGesture is affected by the actor's rotation. - mSelectionHandleTwoActualPosition.x += gesture.displacement.x * mSelectionHandleTwo.GetCurrentScale().x; - mSelectionHandleTwoActualPosition.y += gesture.displacement.y * mSelectionHandleTwo.GetCurrentScale().y; - - MoveSelectionHandle( HandleTwo, gesture.displacement ); - - mState = StateDraggingHandle; - HidePopup(); - } - } - break; - - case Gesture::Finished: - { - // Revert back to non-pressed selection handle images - if (actor == mGrabArea) - { - mActualGrabHandlePosition = MoveGrabHandle( gesture.displacement ); - SetCursorVisibility( true ); - SetUpPopupSelection(); - ShowPopup(); - } - if (actor == mHandleOneGrabArea) - { - // the displacement in PanGesture is affected by the actor's rotation. - mSelectionHandleOneActualPosition.x += gesture.displacement.x * mSelectionHandleOne.GetCurrentScale().x; - mSelectionHandleOneActualPosition.y += gesture.displacement.y * mSelectionHandleOne.GetCurrentScale().y; - - mSelectionHandleOneActualPosition = MoveSelectionHandle( HandleOne, gesture.displacement ); - - mSelectionHandleOne.SetImage( mSelectionHandleOneImage ); - mState = StateEdit; - ShowPopupCutCopyPaste(); - } - if (actor == mHandleTwoGrabArea) - { - // the displacement in PanGesture is affected by the actor's rotation. - mSelectionHandleTwoActualPosition.x += gesture.displacement.x * mSelectionHandleTwo.GetCurrentScale().x; - mSelectionHandleTwoActualPosition.y += gesture.displacement.y * mSelectionHandleTwo.GetCurrentScale().y; - - mSelectionHandleTwoActualPosition = MoveSelectionHandle( HandleTwo, gesture.displacement ); - - mSelectionHandleTwo.SetImage( mSelectionHandleTwoImage ); - mState = StateEdit; - ShowPopupCutCopyPaste(); - } - } - break; - default: - break; - } -} - -// Stop the flashing animation so easy to see when moved. -bool TextInput::OnPressDown(Dali::Actor actor, const TouchEvent& touch) -{ - if (touch.GetPoint(0).state == TouchPoint::Down) - { - SetCursorVisibility( true ); - StopCursorBlinkTimer(); - } - else if (touch.GetPoint(0).state == TouchPoint::Up) - { - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - } - return false; -} - -// selection handle one -bool TextInput::OnHandleOneTouched(Dali::Actor actor, const TouchEvent& touch) -{ - if (touch.GetPoint(0).state == TouchPoint::Down) - { - mSelectionHandleOne.SetImage( mSelectionHandleOneImagePressed ); - } - else if (touch.GetPoint(0).state == TouchPoint::Up) - { - mSelectionHandleOne.SetImage( mSelectionHandleOneImage ); - } - return false; -} - -// selection handle two -bool TextInput::OnHandleTwoTouched(Dali::Actor actor, const TouchEvent& touch) -{ - if (touch.GetPoint(0).state == TouchPoint::Down) - { - mSelectionHandleTwo.SetImage( mSelectionHandleTwoImagePressed ); - } - else if (touch.GetPoint(0).state == TouchPoint::Up) - { - mSelectionHandleTwo.SetImage( mSelectionHandleTwoImage ); - } - return false; -} - -void TextInput::OnDoubleTap(Dali::Actor actor, const Dali::TapGesture& tap) -{ - // If text exists then select nearest word. - if ( !mStyledText.empty()) - { - HidePopup(); - - ShowGrabHandleAndSetVisibility( false ); - - - if ( mPreEditFlag ) - { - // PreEdit will be committed here without needing a commit from IMF. Remove pre-edit underline and reset flags which - // converts the pre-edit word being displayed to a committed word. - if ( !mUnderlinedPriorToPreEdit ) - { - TextStyle style; - style.SetUnderline( false ); - ApplyStyleToRange( style, TextStyle::UNDERLINE , mPreEditStartPosition, mPreEditStartPosition + mPreEditLength -1 ); - } - mPreEditFlag = false; - mIgnoreCommitFlag = true; // Predictive word interrupted, text displayed will not change, no need to actually commit. - // Reset keyboard and set true so cursor position is preserved. Otherwise cursor position will that of the committed text not new tap location. - PreEditReset( false ); - } - mCursorPosition = 0; - - mTextLayoutInfo.mScrollOffset = mDisplayedTextView.GetScrollPosition(); - ReturnClosestIndex( tap.localPoint, mCursorPosition ); - - std::size_t start = 0; - std::size_t end = 0; - Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end ); - - mCursorPosition = end; // Ensure cursor is positioned at end of selected word - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - - if ( !mStyledText.at(end-1).mText[0].IsWhiteSpace() ) - { - SelectText( start, end ); - ShowPopupCutCopyPaste(); - } - else - { - RemoveHighlight( false ); // Remove highlight but do not auto hide popup - HidePopup( false ); // Hide popup with setting to do auto show. - SetUpPopupSelection( false ); // Set to false so if nearest word is whitespace it will not show cut button. - ShowPopup(); - } - } - else if ( mClipboard && mClipboard.NumberOfItems() ) - { - ShowPopupCutCopyPaste(); - } - - // If no text and clipboard empty then do nothing -} - -// TODO: Change the function name to be more general. -void TextInput::OnTextTap(Dali::Actor actor, const Dali::TapGesture& tap) -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "OnTap mPreEditFlag[%s] mEditOnTouch[%s] mEditModeActive[%s] ", (mPreEditFlag)?"true":"false" - , (mEditOnTouch)?"true":"false" - , (mEditModeActive)?"true":"false"); - - if( mHandleOneGrabArea == actor || mHandleTwoGrabArea == actor ) - { - return; - } - - if( mGrabArea == actor ) - { - if( mPopupPanel.GetState() == TextInputPopup::StateHidden || mPopupPanel.GetState() == TextInputPopup::StateHiding ) - { - SetUpPopupSelection(); - ShowPopup(); - } - - return; - } - - HidePopup(); - RemoveHighlight(); - - mTextLayoutInfo.mScrollOffset = mDisplayedTextView.GetScrollPosition(); - - // Initially don't create the grab handle. - bool createGrabHandle = false; - - if ( !mEditModeActive ) - { - // update line height before calculate the actual position. - UpdateLineHeight(); - - // Only start edit mode if TextInput configured to edit on touch - if ( mEditOnTouch ) - { - // Set the initial cursor position in the tap point. - ReturnClosestIndex(tap.localPoint, mCursorPosition ); - StartEditMode(); - } - } - else - { - // Show the keyboard if it was hidden. - if (!VirtualKeyboard::IsVisible()) - { - VirtualKeyboard::Show(); - } - - // Reset keyboard as tap event has occurred. - // Set true so cursor position is preserved. Otherwise cursor position will that of the committed text not new tap location. - PreEditReset( true ); - - GetTextLayoutInfo(); - - if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) // If string empty we do not need a grab handle. - { - // As already in edit mode, reposition cursor near tap and show grab handle for cursor, if grab handle not enabled then magnifier will be used instead. - - ReturnClosestIndex(tap.localPoint, mCursorPosition ); - - DALI_LOG_INFO( gLogFilter, Debug::General, "mCursorPosition[%u]", mCursorPosition ); - - // Notify keyboard so it can 're-capture' word for predictive text. - // As we have done a reset, is this required, expect IMF keyboard to request this information. - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - const TextStyle oldInputStyle( mInputStyle ); - - mInputStyle = GetStyleAtCursor(); // Inherit style from cursor position - - DrawCursor(); - - // Create the grab handle. - // Grab handle is created later. - createGrabHandle = true; - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } - } - - // Edit mode started after grab handle created to ensure the signal InputStarted is sent last. - // This is used to ensure if selecting text hides the grab handle then this code is run after grab handle is created, - // otherwise the Grab handle will be shown when selecting. - if ( createGrabHandle && IsGrabHandleEnabled() ) - { - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid ); - - if( altPositionValid ) - { - // Check which of the positions is the closest. - if( fabsf( altPosition.x - tap.localPoint.x ) < fabsf( cursorPosition.x - tap.localPoint.x ) ) - { - cursorPosition = altPosition; - } - } - - CreateGrabHandle(); - - mActualGrabHandlePosition.x = cursorPosition.x; // Set grab handle to be at the cursor position - mActualGrabHandlePosition.y = cursorPosition.y; // Set grab handle to be at the cursor position - mGrabHandle.SetPosition( mActualGrabHandlePosition + UI_OFFSET ); - ShowGrabHandleAndSetVisibility( mIsGrabHandleInScrollArea ); - - } -} - -void TextInput::OnLongPress(Dali::Actor actor, const Dali::LongPressGesture& longPress) -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "OnLongPress\n" ); - - // Ignore longpress if in selection mode already - if( mHighlightMeshActor ) - { - return; - } - - if(longPress.state == Dali::Gesture::Started) - { - // Start edit mode on long press - if ( !mEditModeActive ) - { - StartEditMode(); - } - - // If text exists then select nearest word. - if ( !mStyledText.empty()) - { - HidePopup(); - - ShowGrabHandleAndSetVisibility( false ); - - - if ( mPreEditFlag ) - { - // PreEdit will be committed here without needing a commit from IMF. Remove pre-edit underline and reset flags which - // converts the pre-edit word being displayed to a committed word. - if ( !mUnderlinedPriorToPreEdit ) - { - TextStyle style; - style.SetUnderline( false ); - ApplyStyleToRange( style, TextStyle::UNDERLINE , mPreEditStartPosition, mPreEditStartPosition + mPreEditLength -1 ); - } - mPreEditFlag = false; - mIgnoreCommitFlag = true; // Predictive word interrupted, text displayed will not change, no need to actually commit. - // Reset keyboard and set true so cursor position is preserved. Otherwise cursor position will that of the committed text not new tap location. - PreEditReset( false ); - } - mCursorPosition = 0; - - mTextLayoutInfo.mScrollOffset = mDisplayedTextView.GetScrollPosition(); - ReturnClosestIndex( longPress.localPoint, mCursorPosition ); - - std::size_t start = 0; - std::size_t end = 0; - Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end ); - - mCursorPosition = end; // Ensure cursor is positioned at end of selected word - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - - SelectText( start, end ); - } - - // if no text but clipboard has content then show paste option, if no text and clipboard empty then do nothing - if ( ( mClipboard && mClipboard.NumberOfItems() ) || !mStyledText.empty() ) - { - ShowPopupCutCopyPaste(); - } - } -} - -void TextInput::OnClipboardTextSelected( ClipboardEventNotifier& notifier ) -{ - const Text clipboardText( notifier.GetContent() ); - PasteText( clipboardText ); - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - ShowGrabHandleAndSetVisibility( false ); - - - HidePopup(); -} - -bool TextInput::OnPopupButtonPressed( Toolkit::Button button ) -{ - mPopupPanel.PressedSignal().Disconnect( this, &TextInput::OnPopupButtonPressed ); - - const std::string& name = button.GetName(); - - if(name == TextInputPopup::OPTION_SELECT_WORD) - { - std::size_t start = 0; - std::size_t end = 0; - Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end ); - - SelectText( start, end ); - } - else if(name == TextInputPopup::OPTION_SELECT_ALL) - { - SetCursorVisibility(false); - StopCursorBlinkTimer(); - - std::size_t end = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); - std::size_t start = 0; - - SelectText( start, end ); - } - else if(name == TextInputPopup::OPTION_CUT) - { - bool ret = CopySelectedTextToClipboard(); - - if ( ret ) - { - DeleteHighlightedText( true ); - CursorUpdate(); - } - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - HidePopup(); - } - else if(name == TextInputPopup::OPTION_COPY) - { - CopySelectedTextToClipboard(); - - RemoveHighlight(); - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - HidePopup(); - } - else if(name == TextInputPopup::OPTION_PASTE) - { - const Text retrievedString( mClipboard.GetItem( 0 ) ); // currently can only get first item in clip board, index 0; - - PasteText(retrievedString); - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - ShowGrabHandleAndSetVisibility( false ); - - HidePopup(); - } - else if(name == TextInputPopup::OPTION_CLIPBOARD) - { - // In the case of clipboard being shown we do not want to show updated pop-up after hide animation completes - // Hence pass the false parameter for signalFinished. - HidePopup( true, false ); - mClipboard.ShowClipboard(); - } - - return false; -} - -bool TextInput::OnCursorBlinkTimerTick() -{ - // Cursor blinking - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus ); - if ( mCursorRTLEnabled ) - { - mCursorRTL.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus ); - } - mCursorBlinkStatus = !mCursorBlinkStatus; - - return true; -} - -void TextInput::OnPopupHideFinished(TextInputPopup& popup) -{ - popup.HideFinishedSignal().Disconnect( this, &TextInput::OnPopupHideFinished ); - - // Change Popup menu to Cut/Copy/Paste if text has been selected. - if(mHighlightMeshActor && mState == StateEdit) - { - ShowPopupCutCopyPaste(); - } -} - -//FIXME this routine needs to be re-written as it contains too many branches. -bool TextInput::OnKeyDownEvent(const KeyEvent& event) -{ - std::string keyName = event.keyPressedName; - std::string keyString = event.keyPressed; - - DALI_LOG_INFO(gLogFilter, Debug::General, "OnKeyDownEvent keyName[%s] KeyString[%s]\n", keyName.c_str(), keyString.c_str() ); - - // Do not consume "Tab" and "Escape" keys. - if(keyName == "Tab" || keyName == "Escape") - { - // Escape key to end the edit mode - EndEditMode(); - - return false; - } - - HidePopup(); // If Pop-up shown then hides it as editing text. - - // Update Flag, indicates whether to update the text-input contents or not. - // Any key stroke that results in a visual change of the text-input should - // set this flag to true. - bool update(false); - - // Whether to scroll text to cursor position. - // Scroll is needed always the cursor is updated and after the pre-edit is received. - bool scroll = false; - - if (keyName == "Return") - { - if ( mNumberOflinesLimit > 1) // Prevents New line character / Return adding an extra line if limit set to 1 - { - bool preEditFlagPreviouslySet( mPreEditFlag ); - - // replaces highlighted text with new line - DeleteHighlightedText( false ); - - mCursorPosition = mCursorPosition + InsertAt( Text( NEWLINE ), mCursorPosition, 0 ); - - // If we are in pre-edit mode then pressing enter will cause a commit. But the commit string does not include the - // '\n' character so we need to ensure that the immediately following commit knows how it occurred. - if ( mPreEditFlag ) - { - mCommitByKeyInput = true; - } - - // If attempting to insert a new-line brings us out of PreEdit mode, then we should not ignore the next commit. - if ( preEditFlagPreviouslySet && !mPreEditFlag ) - { - mPreEditFlag = true; - mIgnoreCommitFlag = false; - } - EmitTextModified(); - update = true; - } - else - { - RemoveHighlight(); - } - } // Return - else if ( keyName == "space" ) - { - if ( mHighlightMeshActor ) - { - // Some text is selected so erase it before adding space. - DeleteHighlightedText( true ); - } - - mCursorPosition = mCursorPosition + InsertAt(Text(keyString), mCursorPosition, 0); - - // If we are in pre-edit mode then pressing the space-bar will cause a commit. But the commit string does not include the - // ' ' character so we need to ensure that the immediately following commit knows how it occurred. - if ( mPreEditFlag ) - { - mCommitByKeyInput = true; - } - EmitTextModified(); - update = true; - } // space - else if (keyName == "BackSpace") - { - if ( mHighlightMeshActor ) - { - // Some text is selected so erase it - DeleteHighlightedText( true ); - update = true; - } - else - { - if ( mCursorPosition > 0 ) - { - DeleteCharacter( mCursorPosition ); - update = true; - } - } - EmitTextModified(); - } // BackSpace - else if (keyName == "Right") - { - AdvanceCursor(); - RemoveHighlight(); - } - else if (keyName == "Left") - { - AdvanceCursor(true); - RemoveHighlight(); - } - else // event is a character - { - // Some text may be selected, hiding keyboard causes an empty keystring to be sent, we don't want to delete highlight in this case - if ( !keyString.empty() ) - { - // replaces highlighted text with new character - DeleteHighlightedText( false ); - - // Received key String - mCursorPosition += InsertAt( Text( keyString ), mCursorPosition, 0 ); - update = true; - EmitTextModified(); - } - } - - // If key event has resulted in a change in the text/cursor, then trigger a relayout of text - // as this is a costly operation. - if(update) - { - CursorUpdate(); - } - - if(update || scroll) - { - if( IsScrollEnabled() ) - { - // Calculates the new cursor position (in actor coordinates) - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition ); - - ScrollTextViewToMakeCursorVisible( cursorPosition ); - } - } - - return true; -} - -bool TextInput::OnKeyUpEvent(const KeyEvent& event) -{ - std::string keyName = event.keyPressedName; - std::string keyString = event.keyPressed; - - DALI_LOG_INFO(gLogFilter, Debug::General, "OnKeyUpEvent keyName[%s] KeyString[%s]\n", keyName.c_str(), keyString.c_str() ); - - // The selected text become deselected when the key code is DALI_KEY_BACK. - if( IsTextSelected() && ( keyName == "XF86Stop" || keyName == "XF86Send") ) - { - DeSelectText(); - return true; - } - - return false; -} - -void TextInput::ChooseRtlSelectionHandlePosition( const Vector3& cursorPositionOne, - const Vector3& cursorPositionTwo, - bool altPositionValidOne, - bool altPositionValidTwo, - const Vector3& altPositionOne, - const Vector3& altPositionTwo ) -{ - // TODO VCC Valid for one line. - // Try to place the selection handles. TODO think in something better. Probably need to know the direction of the paragraph. - if( cursorPositionOne != cursorPositionTwo ) - { - if( cursorPositionOne.x < cursorPositionTwo.x ) - { - mSelectionHandleOneActualPosition = cursorPositionOne; - mSelectionHandleTwoActualPosition = cursorPositionTwo; - } - else - { - mSelectionHandleOneActualPosition = cursorPositionTwo; - mSelectionHandleTwoActualPosition = cursorPositionOne; - } - } - else - { - mSelectionHandleOneActualPosition = cursorPositionOne; - if( altPositionValidOne ) - { - if( altPositionOne.x < mSelectionHandleOneActualPosition.x ) - { - mSelectionHandleOneActualPosition = altPositionOne; - } - } - if( altPositionValidTwo ) - { - if( altPositionTwo.x < mSelectionHandleOneActualPosition.x ) - { - mSelectionHandleOneActualPosition = altPositionTwo; - } - } - - mSelectionHandleTwoActualPosition = cursorPositionTwo; - if( altPositionValidTwo ) - { - if( altPositionTwo.x > mSelectionHandleTwoActualPosition.x ) - { - mSelectionHandleTwoActualPosition = altPositionTwo; - } - } - if( altPositionValidOne ) - { - if( altPositionOne.x > mSelectionHandleTwoActualPosition.x ) - { - mSelectionHandleTwoActualPosition = altPositionOne; - } - } - } -} - -void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ) -{ - // Updates the stored scroll position. - mTextLayoutInfo.mScrollOffset = textView.GetScrollPosition(); - - const Vector3& controlSize = GetControlSize(); - Size cursorSize( CURSOR_THICKNESS, 0.f ); - - // Updates the cursor and grab handle position and visibility. - if( mGrabHandle || mCursor ) - { - cursorSize.height = GetRowRectFromCharacterPosition( mCursorPosition ).height; - - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid ); - - if( altPositionValid ) - { - // Check which of the positions is the closest. - if( fabsf( altPosition.x - mActualGrabHandlePosition.x ) < fabsf( cursorPosition.x - mActualGrabHandlePosition.x ) ) - { - cursorPosition = altPosition; - } - } - - mIsCursorInScrollArea = mIsGrabHandleInScrollArea = IsPositionInsideBoundaries( cursorPosition, cursorSize, controlSize ); - - mActualGrabHandlePosition = cursorPosition.GetVectorXY(); - - if( mGrabHandle ) - { - ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea ); - mGrabHandle.SetPosition( mActualGrabHandlePosition + UI_OFFSET ); - } - - if( mCursor ) - { - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea ); - mCursor.SetPosition( mActualGrabHandlePosition + UI_OFFSET ); - } - } - - // Updates the selection handles and highlighted text position and visibility. - if( mSelectionHandleOne && mSelectionHandleTwo ) - { - Vector3 altPositionOne; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValidOne; // Alternate cursor validity flag. - bool directionRTLOne; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition, directionRTLOne, altPositionOne, altPositionValidOne ); - - Vector3 altPositionTwo; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValidTwo; // Alternate cursor validity flag. - bool directionRTLTwo; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition, directionRTLTwo, altPositionTwo, altPositionValidTwo ); - - // VCC TODO: This method is a hack for one line. - ChooseRtlSelectionHandlePosition( cursorPositionOne, - cursorPositionTwo, - altPositionValidOne, - altPositionValidTwo, - altPositionOne, - altPositionTwo ); - - cursorSize.height = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + mSelectionHandleOnePosition ) ).mSize.height; - const bool isSelectionHandleOneVisible = IsPositionInsideBoundaries( cursorPositionOne, cursorSize, controlSize ); - cursorSize.height = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + mSelectionHandleTwoPosition ) ).mSize.height; - const bool isSelectionHandleTwoVisible = IsPositionInsideBoundaries( cursorPositionTwo, cursorSize, controlSize ); - - mSelectionHandleOne.SetVisible( isSelectionHandleOneVisible ); - mSelectionHandleTwo.SetVisible( isSelectionHandleTwoVisible ); - mSelectionHandleOne.SetPosition( mSelectionHandleOneActualPosition + UI_OFFSET + mSelectionHandleOneOffset ); - mSelectionHandleTwo.SetPosition( mSelectionHandleTwoActualPosition + UI_OFFSET + mSelectionHandleTwoOffset ); - - if( mHighlightMeshActor ) - { - mHighlightMeshActor.SetVisible( true ); - UpdateHighlight(); - } - } -} - -void TextInput::ScrollTextViewToMakeCursorVisible( const Vector3& cursorPosition ) -{ - // Scroll the text to make the cursor visible. - const Size cursorSize( CURSOR_THICKNESS, - GetRowRectFromCharacterPosition( mCursorPosition ).height ); - - // Need to scroll the text to make the cursor visible and to cover the whole text-input area. - - const Vector3& controlSize = GetControlSize(); - - // Calculates the new scroll position. - Vector2 scrollOffset = mTextLayoutInfo.mScrollOffset; - if( ( cursorPosition.x < 0.f ) || ( cursorPosition.x > controlSize.width ) ) - { - scrollOffset.x += cursorPosition.x; - } - - if( cursorPosition.y - cursorSize.height < 0.f || cursorPosition.y > controlSize.height ) - { - scrollOffset.y += cursorPosition.y; - } - - // Sets the new scroll position. - SetScrollPosition( Vector2::ZERO ); // TODO: need to reset to the zero position in order to make the scroll trim to work. - SetScrollPosition( scrollOffset ); -} - -void TextInput::StartScrollTimer() -{ - if( !mScrollTimer ) - { - mScrollTimer = Timer::New( SCROLL_TICK_INTERVAL ); - mScrollTimer.TickSignal().Connect( this, &TextInput::OnScrollTimerTick ); - } - - if( !mScrollTimer.IsRunning() ) - { - mScrollTimer.Start(); - } -} - -void TextInput::StopScrollTimer() -{ - if( mScrollTimer ) - { - mScrollTimer.Stop(); - } -} - -bool TextInput::OnScrollTimerTick() -{ - // TODO: need to set the new style accordingly the new handle position. - - if( !( mGrabHandleVisibility && mGrabHandle ) && !( mSelectionHandleOne && mSelectionHandleTwo ) ) - { - // nothing to do if all handles are invisible or doesn't exist. - return true; - } - - // Text scrolling - - // Choose between the grab handle or the selection handles. - Vector3& actualHandlePosition = ( mGrabHandleVisibility && mGrabHandle ) ? mActualGrabHandlePosition : ( mCurrentSelectionId == HandleOne ) ? mSelectionHandleOneActualPosition : mSelectionHandleTwoActualPosition; - std::size_t& handlePosition = ( mGrabHandleVisibility && mGrabHandle ) ? mCursorPosition : ( mCurrentSelectionId == HandleOne ) ? mSelectionHandleOnePosition : mSelectionHandleTwoPosition; - Vector3& currentHandlePosition = ( mGrabHandleVisibility && mGrabHandle ) ? mCurrentHandlePosition : mCurrentSelectionHandlePosition; - - std::size_t newCursorPosition = 0; - ReturnClosestIndex( actualHandlePosition.GetVectorXY(), newCursorPosition ); - - // Whether the handle's position is different of the previous one and in the case of the selection handle, - // the new selection handle's position needs to be different of the other one. - const bool differentSelectionHandles = ( mGrabHandleVisibility && mGrabHandle ) ? newCursorPosition != handlePosition : - ( mCurrentSelectionId == HandleOne ) ? ( newCursorPosition != handlePosition ) && ( newCursorPosition != mSelectionHandleTwoPosition ) : - ( newCursorPosition != handlePosition ) && ( newCursorPosition != mSelectionHandleOnePosition ); - - if( differentSelectionHandles ) - { - handlePosition = newCursorPosition; - - const Vector3 actualPosition = GetActualPositionFromCharacterPosition( newCursorPosition ); - - Vector2 scrollDelta = ( actualPosition - currentHandlePosition ).GetVectorXY(); - - Vector2 scrollPosition = mDisplayedTextView.GetScrollPosition(); - scrollPosition += scrollDelta; - SetScrollPosition( scrollPosition ); - - if( mDisplayedTextView.IsScrollPositionTrimmed() ) - { - StopScrollTimer(); - } - - currentHandlePosition = GetActualPositionFromCharacterPosition( newCursorPosition ).GetVectorXY(); - } - - actualHandlePosition.x += mScrollDisplacement.x; - actualHandlePosition.y += mScrollDisplacement.y; - - return true; -} - -// Public Internal Methods (public for testing purpose) - -void TextInput::SetUpTouchEvents() -{ - if ( !mTapDetector ) - { - mTapDetector = TapGestureDetector::New(); - // Attach the actors and connect the signal - mTapDetector.Attach(Self()); - - // As contains children which may register for tap the default control detector is not used. - mTapDetector.DetectedSignal().Connect(this, &TextInput::OnTextTap); - } - - if ( !mDoubleTapDetector ) - { - mDoubleTapDetector = TapGestureDetector::New( 2 ); - mDoubleTapDetector.DetectedSignal().Connect(this, &TextInput::OnDoubleTap); - - // Only attach and detach the actor to the double tap detector when we enter/leave edit mode - // so that we do not, unnecessarily, have a double tap request all the time - } - - if ( !mPanGestureDetector ) - { - mPanGestureDetector = PanGestureDetector::New(); - mPanGestureDetector.DetectedSignal().Connect(this, &TextInput::OnHandlePan); - } - - if ( !mLongPressDetector ) - { - mLongPressDetector = LongPressGestureDetector::New(); - mLongPressDetector.DetectedSignal().Connect(this, &TextInput::OnLongPress); - mLongPressDetector.Attach(Self()); - } -} - -void TextInput::CreateTextViewActor() -{ - mDisplayedTextView = Toolkit::TextView::New(); - mDisplayedTextView.SetName( "DisplayedTextView "); - mDisplayedTextView.SetMarkupProcessingEnabled( mMarkUpEnabled ); - mDisplayedTextView.SetParentOrigin(ParentOrigin::TOP_LEFT); - mDisplayedTextView.SetAnchorPoint(AnchorPoint::TOP_LEFT); - mDisplayedTextView.SetMultilinePolicy(Toolkit::TextView::SplitByWord); - mDisplayedTextView.SetWidthExceedPolicy( Toolkit::TextView::Original ); - mDisplayedTextView.SetHeightExceedPolicy( Toolkit::TextView::Original ); - mDisplayedTextView.SetLineJustification( Toolkit::TextView::Left ); - mDisplayedTextView.SetTextAlignment( static_cast( Toolkit::Alignment::HorizontalLeft | Toolkit::Alignment::VerticalTop ) ); - mDisplayedTextView.SetPosition( Vector3( 0.0f, 0.0f, DISPLAYED_TEXT_VIEW_Z_OFFSET ) ); - - mDisplayedTextView.ScrolledSignal().Connect( this, &TextInput::OnTextViewScrolled ); - - Self().Add( mDisplayedTextView ); -} - -// Start a timer to initiate, used by the cursor to blink. -void TextInput::StartCursorBlinkTimer() -{ - if ( !mCursorBlinkTimer ) - { - mCursorBlinkTimer = Timer::New( CURSOR_BLINK_INTERVAL ); - mCursorBlinkTimer.TickSignal().Connect( this, &TextInput::OnCursorBlinkTimerTick ); - } - - if ( !mCursorBlinkTimer.IsRunning() ) - { - mCursorBlinkTimer.Start(); - } -} - -// Start a timer to initiate, used by the cursor to blink. -void TextInput::StopCursorBlinkTimer() -{ - if ( mCursorBlinkTimer ) - { - mCursorBlinkTimer.Stop(); - } -} - -void TextInput::StartEditMode() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "TextInput StartEditMode mEditModeActive[%s]\n", (mEditModeActive)?"true":"false" ); - - if(!mEditModeActive) - { - SetKeyInputFocus(); - } - - if ( mDoubleTapDetector ) - { - mDoubleTapDetector.Attach( Self() ); - } -} - -void TextInput::EndEditMode() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "TextInput EndEditMode mEditModeActive[%s]\n", (mEditModeActive)?"true":"false" ); - - ClearKeyInputFocus(); - - if ( mDoubleTapDetector ) - { - mDoubleTapDetector.Detach( Self() ); - } -} - -void TextInput::ApplyPreEditStyle( std::size_t preEditStartPosition, std::size_t preEditStringLength ) -{ - if ( mPreEditFlag && ( preEditStringLength > 0 ) ) - { - mUnderlinedPriorToPreEdit = mInputStyle.IsUnderlineEnabled(); - TextStyle style; - style.SetUnderline( true ); - ApplyStyleToRange( style, TextStyle::UNDERLINE , preEditStartPosition, preEditStartPosition + preEditStringLength -1 ); - } -} - -void TextInput::RemovePreEditStyle() -{ - if ( !mUnderlinedPriorToPreEdit ) - { - TextStyle style; - style.SetUnderline( false ); - SetActiveStyle( style, TextStyle::UNDERLINE ); - } -} - -// IMF related methods - - -ImfManager::ImfCallbackData TextInput::ImfEventReceived( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent ) -{ - bool update( false ); - bool preeditResetRequired ( false ); - - if (imfEvent.eventName != ImfManager::GETSURROUNDING ) - { - HidePopup(); // If Pop-up shown then hides it as editing text. - } - - switch ( imfEvent.eventName ) - { - case ImfManager::PREEDIT: - { - mIgnoreFirstCommitFlag = false; - - // Some text may be selected, hiding keyboard causes an empty predictive string to be sent, we don't want to delete highlight in this case - if ( mHighlightMeshActor && (!imfEvent.predictiveString.empty()) ) - { - // replaces highlighted text with new character - DeleteHighlightedText( false ); - } - - preeditResetRequired = PreEditReceived( imfEvent.predictiveString, imfEvent.cursorOffset ); - - if( IsScrollEnabled() ) - { - // Calculates the new cursor position (in actor coordinates) - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition ); - ScrollTextViewToMakeCursorVisible( cursorPosition ); - } - - update = true; - - break; - } - case ImfManager::COMMIT: - { - if( mIgnoreFirstCommitFlag ) - { - // Do not commit in this case when keyboard sends a commit when shows for the first time (work-around for imf keyboard). - mIgnoreFirstCommitFlag = false; - } - else - { - // A Commit message is a word that has been accepted, it may have been a pre-edit word previously but now commited. - - // Some text may be selected, hiding keyboard causes an empty predictive string to be sent, we don't want to delete highlight in this case - if ( mHighlightMeshActor && (!imfEvent.predictiveString.empty()) ) - { - // replaces highlighted text with new character - DeleteHighlightedText( false ); - } - - // A PreEditReset can cause a commit message to be sent, the Ignore Commit flag is used in scenarios where the word is - // not needed, one such scenario is when the pre-edit word is too long to fit. - if ( !mIgnoreCommitFlag ) - { - update = CommitReceived( imfEvent.predictiveString ); - } - else - { - mIgnoreCommitFlag = false; // reset ignore flag so next commit is acted upon. - } - } - - if( update ) - { - if( IsScrollEnabled() ) - { - // Calculates the new cursor position (in actor coordinates) - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition ); - - ScrollTextViewToMakeCursorVisible( cursorPosition ); - } - } - break; - } - case ImfManager::DELETESURROUNDING: - { - DALI_LOG_INFO( gLogFilter, Debug::General, "ImfEventReceived - delete surrounding mPreEditFlag[%s] cursor offset[%d] characters to delete[%d] position to delete[%u] \n", - (mPreEditFlag)?"true":"false", imfEvent.cursorOffset, imfEvent.numberOfChars, static_cast( mCursorPosition+imfEvent.cursorOffset) ); - - mPreEditFlag = false; - - std::size_t toDelete = 0; - std::size_t numberOfCharacters = 0; - - if( mHighlightMeshActor ) - { - // delete highlighted text. - toDelete = std::min( mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - numberOfCharacters = std::max( mSelectionHandleOnePosition, mSelectionHandleTwoPosition ) - toDelete; - } - else - { - if( static_cast(std::abs( imfEvent.cursorOffset )) < mCursorPosition ) - { - toDelete = mCursorPosition + imfEvent.cursorOffset; - } - if( toDelete + imfEvent.numberOfChars > mStyledText.size() ) - { - numberOfCharacters = mStyledText.size() - toDelete; - } - else - { - numberOfCharacters = imfEvent.numberOfChars; - } - } - DALI_LOG_INFO( gLogFilter, Debug::General, "ImfEventReceived - deleteSurrounding pre-delete range mCursorPosition[%u] \n", mCursorPosition); - DeleteRange( toDelete, numberOfCharacters ); - - mCursorPosition = toDelete; - mNumberOfSurroundingCharactersDeleted = numberOfCharacters; - - EmitTextModified(); - - DALI_LOG_INFO( gLogFilter, Debug::General, "ImfEventReceived - deleteSurrounding post-delete range mCursorPosition[%u] \n", mCursorPosition); - break; - } - case ImfManager::GETSURROUNDING: - { - // If text is selected/highlighted and surrounding text received we do not want the keyboard to store the word at cursor and return it as a predictive word along with - // the next key pressed. Instead the Select function sets the cursor position and surrounding text. - if (! ( mHighlightMeshActor || mSelectingText ) ) - { - std::string text( GetText() ); - DALI_LOG_INFO( gLogFilter, Debug::General, "OnKey - surrounding text - set text [%s] and cursor[%u] \n", text.c_str(), mCursorPosition ); - - imfManager.SetCursorPosition( mCursorPosition ); - imfManager.SetSurroundingText( text ); - } - - if( 0 != mNumberOfSurroundingCharactersDeleted ) - { - mDisplayedTextView.RemoveTextFrom( mCursorPosition, mNumberOfSurroundingCharactersDeleted ); - mNumberOfSurroundingCharactersDeleted = 0; - - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - } - break; - } - case ImfManager::VOID: - { - DALI_ASSERT_DEBUG( false ); - } - } // end switch - - ImfManager::ImfCallbackData callbackData( update, mCursorPosition, GetText(), preeditResetRequired ); - - return callbackData; -} - -bool TextInput::PreEditReceived(const std::string& keyString, std::size_t cursorOffset ) -{ - mPreserveCursorPosition = false; // As in pre-edit state we should have the cursor at the end of the word displayed not last touch position. - - DALI_LOG_INFO(gLogFilter, Debug::General, ">>PreEditReceived preserveCursorPos[%d] mCursorPos[%d] mPreEditFlag[%d]\n", - mPreserveCursorPosition, mCursorPosition, mPreEditFlag ); - - bool preeditResetRequest ( false ); - - if( mPreEditFlag ) // Already in pre-edit state. - { - if( mStyledText.size() >= mMaxStringLength ) - { - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived styledTextSize >= mMaxStringLength \n"); - // Cannot fit these characters into field, clear pre-edit. - if ( !mUnderlinedPriorToPreEdit ) - { - TextStyle style; - style.SetUnderline( false ); - ApplyStyleToRange( style, TextStyle::UNDERLINE , mPreEditStartPosition, mPreEditStartPosition + mPreEditLength -1 ); - } - mIgnoreCommitFlag = true; - preeditResetRequest = false; // this will reset the keyboard's predictive suggestions. - mPreEditFlag = false; - EmitMaxInputCharactersReachedSignal(); - } - else - { - // delete existing pre-edit string - const std::size_t numberOfCharactersToReplace = DeletePreEdit(); - - // Store new pre-edit string - mPreEditString.SetText( keyString ); - - if ( keyString.empty() ) - { - mPreEditFlag = false; - mCursorPosition = mPreEditStartPosition; - - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - mDisplayedTextView.RemoveTextFrom( mPreEditStartPosition, numberOfCharactersToReplace ); - } - - GetTextLayoutInfo(); - EmitTextModified(); - } - else - { - // Insert new pre-edit string. InsertAt updates the size and position table. - mPreEditLength = InsertAt( mPreEditString, mPreEditStartPosition, numberOfCharactersToReplace ); - // If word was too long to be inserted then cursorOffset would be out of range as keyboard assumes there is not limit. Hence use of std::min. - mCursorPosition = mPreEditStartPosition + std::min( cursorOffset, mPreEditLength ); - ApplyPreEditStyle( mPreEditStartPosition, mPreEditLength ); - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived mCursorPosition[%u] \n", mCursorPosition); - EmitTextModified(); - } - // cursor update to keyboard is not done here as the keyboard knows the cursor position and provides the 'cursorOffset'. - DrawCursor(); - } - } - else // mPreEditFlag not set - { - if ( !keyString.empty() ) // Imf can send an empty pre-edit followed by Backspace instead of a commit. - { - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived Initial Pre-Edit string \n"); - // new pre-edit so move into pre-edit state by setting flag - mPreEditFlag = true; - mPreEditString.SetText( keyString ); // store new pre-edit string - mPreEditStartPosition = mCursorPosition; // store starting cursor position of pre-edit so know where to re-start from - mPreEditLength = InsertAt( mPreEditString, mPreEditStartPosition, 0 ); - // If word was too long to be inserted then cursorOffset would be out of range as keyboard assumes there is not limit. Hence use of std::min. - mCursorPosition = mPreEditStartPosition + std::min( cursorOffset, mPreEditLength ); - ApplyPreEditStyle( mPreEditStartPosition, mPreEditLength ); - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived mCursorPosition[%u] mPreEditStartPosition[%u]\n", mCursorPosition, mPreEditStartPosition); - // cursor update to keyboard is not done here as the keyboard knows the cursor position and provides the 'cursorOffset'. - DrawCursor(); - EmitTextModified(); - } - else - { - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived with empty keyString\n"); - } - } - - return preeditResetRequest; -} - -bool TextInput::CommitReceived(const std::string& keyString ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, ">>CommitReceived preserveCursorPos[%d] mPreEditStartPosition [%d] mCursorPos[%d] mPreEditFlag[%d] mIgnoreCommitFlag[%s]\n", - mPreserveCursorPosition, mPreEditStartPosition, mCursorPosition, mPreEditFlag, (mIgnoreCommitFlag)?"true":"false" ); - - bool update( false ); - - RemovePreEditStyle(); - - const std::size_t styledTextSize( mStyledText.size() ); - if( styledTextSize >= mMaxStringLength ) - { - // Cannot fit these characters into field, clear pre-edit. - if ( mPreEditFlag ) - { - mIgnoreCommitFlag = true; - mPreEditFlag = false; - } - EmitMaxInputCharactersReachedSignal(); - } - else - { - if( mPreEditFlag ) - { - // delete existing pre-edit string - const std::size_t numberOfCharactersToReplace = DeletePreEdit(); - mPreEditFlag = false; - - DALI_LOG_INFO(gLogFilter, Debug::General, "CommitReceived mPreserveCursorPosition[%s] mPreEditStartPosition[%u]\n", - (mPreserveCursorPosition)?"true":"false", mPreEditStartPosition ); - - if ( mPreserveCursorPosition ) // PreEditReset has been called triggering this commit. - { - // No need to update cursor position as Cursor location given by touch. - InsertAt( Text( keyString ), mPreEditStartPosition, numberOfCharactersToReplace ); - mPreserveCursorPosition = false; - } - else - { - // Cursor not set by touch so needs to be re-positioned to input more text - mCursorPosition = mPreEditStartPosition + InsertAt( Text(keyString), mPreEditStartPosition, numberOfCharactersToReplace ); // update cursor position as InsertAt, re-draw cursor with this - - // If a space or enter caused the commit then our string is one longer than the string given to us by the commit key. - if ( mCommitByKeyInput ) - { - mCursorPosition = std::min ( mCursorPosition + 1, mStyledText.size() ); - mCommitByKeyInput = false; - } - } - - EmitTextModified(); - - if ( mSelectTextOnCommit ) - { - SelectText(mRequestedSelection.mStartOfSelection, mRequestedSelection.mEndOfSelection ); - } - - update = true; - } - else // mPreEditFlag not set - { - if ( !mIgnoreCommitFlag ) // Check if this commit should be ignored. - { - if( mStyledText.empty() && mPlaceHolderSet ) - { - // If the styled text is empty and the placeholder text is set, it needs to be cleared. - mDisplayedTextView.SetText( "" ); - mNumberOfSurroundingCharactersDeleted = 0; - mPlaceHolderSet = false; - } - mCursorPosition = mCursorPosition + InsertAt( Text( keyString ), mCursorPosition, mNumberOfSurroundingCharactersDeleted ); - update = true; - mNumberOfSurroundingCharactersDeleted = 0; - EmitTextModified(); - } - else - { - mIgnoreCommitFlag = false; // Reset flag so future commits will not be ignored. - } - } - } - - mSelectTextOnCommit = false; - - DALI_LOG_INFO(gLogFilter, Debug::General, "CommitReceived << mCursorPos[%d] mPreEditFlag[%d] update[%s] \n", - mCursorPosition, mPreEditFlag, (update)?"true":"false" ); - - return update; -} - -// End of IMF related methods - -std::size_t TextInput::DeletePreEdit() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, ">>DeletePreEdit mPreEditFlag[%s] \n", (mPreEditFlag)?"true":"false"); - - DALI_ASSERT_DEBUG( mPreEditFlag ); - - const std::size_t preEditStringLength = mPreEditString.GetLength(); - const std::size_t styledTextSize = mStyledText.size(); - - std::size_t endPosition = mPreEditStartPosition + preEditStringLength; - - // Prevents erase items outside mStyledText bounds. - if( mPreEditStartPosition > styledTextSize ) - { - DALI_ASSERT_DEBUG( !"TextInput::DeletePreEdit. mPreEditStartPosition > mStyledText.size()" ); - mPreEditStartPosition = styledTextSize; - } - - if( ( endPosition > styledTextSize ) || ( endPosition < mPreEditStartPosition ) ) - { - DALI_ASSERT_DEBUG( !"TextInput::DeletePreEdit. ( endPosition > mStyledText.size() ) || ( endPosition < mPreEditStartPosition )" ); - endPosition = styledTextSize; - } - - mStyledText.erase( mStyledText.begin() + mPreEditStartPosition, mStyledText.begin() + endPosition ); - - // DeletePreEdit() doesn't remove characters from the text-view because may be followed by an InsertAt() which inserts characters, - // in that case, the Insert should use the returned number of deleted characters and replace the text which helps the text-view to - // reuse glyphs. - // In case DeletePreEdit() is not followed by an InsertAt() characters must be deleted after this call. - - return preEditStringLength; -} - -void TextInput::PreEditReset( bool preserveCursorPosition ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReset preserveCursorPos[%d] mCursorPos[%d] \n", - preserveCursorPosition, mCursorPosition); - - // Store flag to indicate that we do not want to lose the cursor position as the reset may have occurred due to touch event moving the cursor. - mPreserveCursorPosition = preserveCursorPosition; - - // Reset incase we are in a pre-edit state. - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.Reset(); // Will trigger a commit message - } -} - -void TextInput::CursorUpdate() -{ - DrawCursor(); - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - std::string text( GetText() ); - imfManager.SetSurroundingText( text ); // Notifying IMF of a cursor change triggers a surrounding text request so updating it now. - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } -} - -/* Delete highlighted characters redisplay*/ -void TextInput::DeleteHighlightedText( bool inheritStyle ) -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "DeleteHighlightedText handlePosOne[%u] handlePosTwo[%u]\n", mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - - if( mHighlightMeshActor ) - { - mCursorPosition = std::min( mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - - MarkupProcessor::StyledTextArray::iterator start = mStyledText.begin() + mCursorPosition; - MarkupProcessor::StyledTextArray::iterator end = mStyledText.begin() + std::max( mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - - // Get the styled text of the characters to be deleted as it may be needed if - // the "exceed the text-input's boundaries" option is disabled. - MarkupProcessor::StyledTextArray styledCharactersToDelete; - - styledCharactersToDelete.insert( styledCharactersToDelete.begin(), start, end ); - - mStyledText.erase( start, end ); // erase range of characters - - // Remove text from TextView and update place holder text if required - - // Set the placeholder text only if the styled text is empty. - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - const std::size_t numberOfCharacters = std::max( mSelectionHandleOnePosition, mSelectionHandleTwoPosition ) - mCursorPosition; - - mDisplayedTextView.RemoveTextFrom( mCursorPosition, numberOfCharacters ); - - // It may happen than after removing a white space or a new line character, - // two words merge, this new word could be big enough to not fit in its - // current line, so moved to the next one, and make some part of the text to - // exceed the text-input's boundary. - if( !mExceedEnabled ) - { - // Get the new text layout after removing some characters. - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - - // Get text-input's size. - const Vector3& size = GetControlSize(); - - if( ( mTextLayoutInfo.mTextSize.width > size.width ) || - ( mTextLayoutInfo.mTextSize.height > size.height ) ) - { - mDisplayedTextView.InsertTextAt( mCursorPosition, styledCharactersToDelete ); - - mStyledText.insert( mStyledText.begin() + mCursorPosition, - styledCharactersToDelete.begin(), - styledCharactersToDelete.end() ); - } - } - } - GetTextLayoutInfo(); - - RemoveHighlight(); - - EmitTextModified(); - - if( inheritStyle ) - { - const TextStyle oldInputStyle( mInputStyle ); - - mInputStyle = GetStyleAtCursor(); // Inherit style from cursor position - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } - } -} - -void TextInput::DeleteRange( const std::size_t start, const std::size_t ncharacters ) -{ - DALI_ASSERT_DEBUG( start <= mStyledText.size() ); - DALI_ASSERT_DEBUG( !mStyledText.empty() ); - - DALI_LOG_INFO(gLogFilter, Debug::General, ">>DeleteRange pre mStyledText[%s] mPreEditFlag[%s] \n", GetText().c_str(), (mPreEditFlag)?"true":"false"); - - - if ( ( !mStyledText.empty()) && ( ( start + ncharacters ) <= mStyledText.size() ) ) - { - MarkupProcessor::StyledTextArray::iterator itStart = mStyledText.begin() + start; - MarkupProcessor::StyledTextArray::iterator itEnd = mStyledText.begin() + start + ncharacters; - - mStyledText.erase(itStart, itEnd); - - // update the selection handles if they are visible. - if( mHighlightMeshActor ) - { - std::size_t& minHandle = ( mSelectionHandleOnePosition <= mSelectionHandleTwoPosition ? mSelectionHandleOnePosition : mSelectionHandleTwoPosition ); - std::size_t& maxHandle = ( mSelectionHandleTwoPosition > mSelectionHandleOnePosition ? mSelectionHandleTwoPosition : mSelectionHandleOnePosition ); - - if( minHandle >= start + ncharacters ) - { - minHandle -= ncharacters; - } - else if( ( minHandle > start ) && ( minHandle < start + ncharacters ) ) - { - minHandle = start; - } - - if( maxHandle >= start + ncharacters ) - { - maxHandle -= ncharacters; - } - else if( ( maxHandle > start ) && ( maxHandle < start + ncharacters ) ) - { - maxHandle = start; - } - } - - // Set text is not called here as currently it can not process the set text from deletion and then the set text from the in-coming pre-edit. - } - - DALI_LOG_INFO(gLogFilter, Debug::General, "DeleteRange<< post mStyledText[%s] mPreEditFlag[%s] \n", GetText().c_str(), (mPreEditFlag)?"true":"false"); - - // Although mStyledText has been set to a new text string we no longer re-draw the text or notify the cursor change. - // This is a performance decision as the use of this function often means the text is being replaced or just deleted. - // Mean we do not re-draw the text more than we have too. -} - -/* Delete character at current cursor position and redisplay*/ -void TextInput::DeleteCharacter( std::size_t positionToDelete ) -{ - // Ensure positionToDelete is not out of bounds. - DALI_ASSERT_DEBUG( positionToDelete <= mStyledText.size() ); - DALI_ASSERT_DEBUG( !mStyledText.empty() ); - DALI_ASSERT_DEBUG( positionToDelete > 0 ); - - DALI_LOG_INFO(gLogFilter, Debug::General, "DeleteCharacter positionToDelete[%u]", positionToDelete ); - - - if ( ( !mStyledText.empty()) && ( positionToDelete > 0 ) && positionToDelete <= mStyledText.size() ) // don't try to delete if no characters left of cursor - { - MarkupProcessor::StyledTextArray::iterator it = mStyledText.begin() + positionToDelete - 1; - - // Get the styled text of the character to be deleted as it may be needed if - // the "exceed the text-input's boundaries" option is disabled. - const MarkupProcessor::StyledText styledCharacterToDelete( *it ); - - mStyledText.erase(it); // erase the character left of positionToDelete - - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - mDisplayedTextView.RemoveTextFrom( positionToDelete - 1, 1 ); - - const Character characterToDelete = styledCharacterToDelete.mText[0]; - - // It may happen than after removing a white space or a new line character, - // two words merge, this new word could be big enough to not fit in its - // current line, so moved to the next one, and make some part of the text to - // exceed the text-input's boundary. - if( !mExceedEnabled ) - { - if( characterToDelete.IsWhiteSpace() || characterToDelete.IsNewLine() ) - { - // Get the new text layout after removing one character. - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - - // Get text-input's size. - const Vector3& size = GetControlSize(); - - if( ( mTextLayoutInfo.mTextSize.width > size.width ) || - ( mTextLayoutInfo.mTextSize.height > size.height ) ) - { - MarkupProcessor::StyledTextArray array; - array.push_back( styledCharacterToDelete ); - mDisplayedTextView.InsertTextAt( positionToDelete - 1, array ); - - mStyledText.insert( mStyledText.begin() + ( positionToDelete - 1 ), styledCharacterToDelete ); - } - } - } - } - GetTextLayoutInfo(); - - ShowGrabHandleAndSetVisibility( false ); - - mCursorPosition = positionToDelete -1; - - const TextStyle oldInputStyle( mInputStyle ); - - mInputStyle = GetStyleAtCursor(); // Inherit style from cursor position - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } -} - -/*Insert new character into the string and (optionally) redisplay text-input*/ -std::size_t TextInput::InsertAt( const Text& newText, const std::size_t insertionPosition, const std::size_t numberOfCharactersToReplace ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "InsertAt insertionPosition[%u]\n", insertionPosition ); - - // Ensure insertionPosition is not out of bounds. - DALI_ASSERT_ALWAYS( insertionPosition <= mStyledText.size() ); - - bool textExceedsMaximunNumberOfCharacters = false; - bool textExceedsBoundary = false; - std::size_t insertedStringLength = DoInsertAt( newText, insertionPosition, numberOfCharactersToReplace, textExceedsMaximunNumberOfCharacters, textExceedsBoundary ); - - ShowGrabHandleAndSetVisibility( false ); - - if( textExceedsMaximunNumberOfCharacters || textExceedsBoundary ) - { - if( mPreEditFlag ) - { - mIgnoreCommitFlag = true; - mPreEditFlag = false; - // A PreEditReset( false ) should be triggered from here if the keyboards predictive suggestions must be cleared. - // Although can not directly call PreEditReset() as it will cause a recursive emit loop. - } - - if( textExceedsMaximunNumberOfCharacters ) - { - EmitMaxInputCharactersReachedSignal(); - } - - if( textExceedsBoundary ) - { - EmitInputTextExceedsBoundariesSignal(); - PreEditReset( false ); - } - } - - return insertedStringLength; -} - -ImageActor TextInput::CreateCursor( const Vector4& color) -{ - ImageActor cursor; - cursor = CreateSolidColorActor(color); - cursor.SetName( "Cursor" ); - - cursor.SetParentOrigin(ParentOrigin::TOP_LEFT); - cursor.SetAnchorPoint(AnchorPoint::BOTTOM_LEFT); - cursor.SetVisible(false); - - return cursor; -} - -void TextInput::AdvanceCursor(bool reverse, std::size_t places) -{ - // As cursor is not moving due to grab handle, handle should be hidden. - ShowGrabHandleAndSetVisibility( false ); - - bool cursorPositionChanged = false; - if (reverse) - { - if ( mCursorPosition >= places ) - { - mCursorPosition = mCursorPosition - places; - cursorPositionChanged = true; - } - } - else - { - if ((mCursorPosition + places) <= mStyledText.size()) - { - mCursorPosition = mCursorPosition + places; - cursorPositionChanged = true; - } - } - - if( cursorPositionChanged ) - { - const std::size_t cursorPositionForStyle = ( 0 == mCursorPosition ? 0 : mCursorPosition - 1 ); - - const TextStyle oldInputStyle( mInputStyle ); - mInputStyle = GetStyleAt( cursorPositionForStyle ); // Inherit style from selected position. - - DrawCursor(); - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - } -} - -void TextInput::DrawCursor() -{ - const Size rowRect = GetRowRectFromCharacterPosition( mCursorPosition ); - - // Get height of cursor and set its size - Size size( CURSOR_THICKNESS, 0.0f ); - if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) - { - size.height = rowRect.height; - } - else - { - // Measure Font so know how big text will be if no initial text to measure. - size.height = mLineHeight; - } - - mCursor.SetSize(size); - - // If the character is italic then the cursor also tilts. - mCursor.SetOrientation( mInputStyle.IsItalicsEnabled() ? Degree( mInputStyle.GetItalicsAngle() - CURSOR_ANGLE_OFFSET ) : Degree( 0.f ), Vector3::ZAXIS ); - - DALI_ASSERT_DEBUG( mCursorPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ); - - if( ( mCursorPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) ) - { - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 position = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid ); - - SetAltCursorEnabled( altPositionValid ); - - if( !altPositionValid ) - { - mCursor.SetPosition( position + UI_OFFSET ); - } - else - { - size.height *= 0.5f; - mCursor.SetSize(size); - mCursor.SetPosition( position + UI_OFFSET - Vector3( 0.0f, directionRTL ? 0.0f : size.height, 0.0f ) ); - - // TODO: change this cursor pos, to be the one where the cursor is sourced from. - size.height = rowRect.height * 0.5f; - mCursorRTL.SetSize(size); - mCursorRTL.SetPosition( altPosition + UI_OFFSET - Vector3( 0.0f, directionRTL ? size.height : 0.0f, 0.0f ) ); - } - - if( IsScrollEnabled() ) - { - // Whether cursor and grab handle are inside the boundaries of the text-input when text scroll is enabled. - mIsCursorInScrollArea = mIsGrabHandleInScrollArea = IsPositionInsideBoundaries( position, size, GetControlSize() ); - } - } // EditMode -} - -void TextInput::SetAltCursorEnabled( bool enabled ) -{ - mCursorRTLEnabled = enabled; - mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled ); -} - -void TextInput::SetCursorVisibility( bool visible ) -{ - mCursorVisibility = visible; - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea ); - mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled ); -} - -void TextInput::CreateGrabHandle( Dali::Image image ) -{ - if ( !mGrabHandle ) - { - if ( !image ) - { - mGrabHandleImage = ResourceImage::New(DEFAULT_GRAB_HANDLE); - } - else - { - mGrabHandleImage = image; - } - - mGrabHandle = ImageActor::New(mGrabHandleImage); - mGrabHandle.SetParentOrigin(ParentOrigin::TOP_LEFT); - mGrabHandle.SetAnchorPoint(AnchorPoint::TOP_CENTER); - - mGrabHandle.SetDrawMode(DrawMode::OVERLAY); - - ShowGrabHandleAndSetVisibility( false ); - - CreateGrabArea( mGrabHandle ); - - mActiveLayer.Add(mGrabHandle); - } -} - -void TextInput::CreateGrabArea( Actor& parent ) -{ - mGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move - mGrabArea.SetName( "GrabArea" ); - mGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - mGrabArea.SetResizePolicy( SIZE_RELATIVE_TO_PARENT, ALL_DIMENSIONS ); - mGrabArea.SetSizeModeFactor( DEFAULT_GRAB_HANDLE_RELATIVE_SIZE ); - mGrabArea.TouchedSignal().Connect(this,&TextInput::OnPressDown); - mTapDetector.Attach( mGrabArea ); - mPanGestureDetector.Attach( mGrabArea ); - mLongPressDetector.Attach( mGrabArea ); - - parent.Add(mGrabArea); -} - -Vector3 TextInput::MoveGrabHandle( const Vector2& displacement ) -{ - Vector3 actualHandlePosition; - - if (mGrabHandle) - { - mActualGrabHandlePosition.x += displacement.x; - mActualGrabHandlePosition.y += displacement.y; - - // Grab handle should jump to the nearest character and take cursor with it - std::size_t newCursorPosition = 0; - ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY(), newCursorPosition ); - - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - actualHandlePosition = GetActualPositionFromCharacterPosition( newCursorPosition, directionRTL, altPosition, altPositionValid ); - - if( altPositionValid ) - { - // Check which of the positions is the closest. - if( fabsf( altPosition.x - mActualGrabHandlePosition.x ) < fabsf( actualHandlePosition.x - mActualGrabHandlePosition.x ) ) - { - actualHandlePosition = altPosition; - } - } - - bool handleVisible = true; - - if( IsScrollEnabled() ) - { - const Vector3 controlSize = GetControlSize(); - const Size cursorSize = GetRowRectFromCharacterPosition( newCursorPosition ); - // Scrolls the text if the handle is not in a visible position - handleVisible = IsPositionInsideBoundaries( actualHandlePosition, - cursorSize, - controlSize ); - - if( handleVisible ) - { - StopScrollTimer(); - mCurrentHandlePosition = actualHandlePosition; - mScrollDisplacement = Vector2::ZERO; - } - else - { - if( ( actualHandlePosition.x < SCROLL_THRESHOLD ) && ( displacement.x <= 0.f ) ) - { - mScrollDisplacement.x = -SCROLL_SPEED; - } - else if( ( actualHandlePosition.x > controlSize.width - SCROLL_THRESHOLD ) && ( displacement.x >= 0.f ) ) - { - mScrollDisplacement.x = SCROLL_SPEED; - } - if( ( actualHandlePosition.y < SCROLL_THRESHOLD ) && ( displacement.y <= 0.f ) ) - { - mScrollDisplacement.y = -SCROLL_SPEED; - } - else if( ( actualHandlePosition.y > controlSize.height - SCROLL_THRESHOLD ) && ( displacement.y >= 0.f ) ) - { - mScrollDisplacement.y = SCROLL_SPEED; - } - StartScrollTimer(); - } - } - - if( handleVisible && // Only redraw cursor and do updates if position changed - ( newCursorPosition != mCursorPosition ) ) // and the new position is visible (if scroll is not enabled, it's always true). - { - mCursorPosition = newCursorPosition; - - mGrabHandle.SetPosition( actualHandlePosition + UI_OFFSET ); - - const TextStyle oldInputStyle( mInputStyle ); - - mInputStyle = GetStyleAtCursor(); //Inherit style from cursor position - - CursorUpdate(); // Let keyboard know the new cursor position so can 're-capture' for prediction. - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } - } - - return actualHandlePosition; -} - -void TextInput::ShowGrabHandle( bool visible ) -{ - if ( IsGrabHandleEnabled() ) - { - if( mGrabHandle ) - { - mGrabHandle.SetVisible( mGrabHandleVisibility ); - } - StartMonitoringStageForTouch(); - } -} - -void TextInput::ShowGrabHandleAndSetVisibility( bool visible ) -{ - mGrabHandleVisibility = visible; - ShowGrabHandle( visible ); -} - -// Callbacks connected to be Property notifications for Boundary checking. - -void TextInput::OnLeftBoundaryExceeded(PropertyNotification& source) -{ - mIsSelectionHandleOneFlipped = true; - mSelectionHandleOne.SetScale( -1.0f, 1.0f, 1.0f ); - mSelectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_LEFT); -} - -void TextInput::OnReturnToLeftBoundary(PropertyNotification& source) -{ - mIsSelectionHandleOneFlipped = false; - mSelectionHandleOne.SetScale( 1.0f, 1.0f, 1.0f ); - mSelectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_RIGHT); -} - -void TextInput::OnRightBoundaryExceeded(PropertyNotification& source) -{ - mIsSelectionHandleTwoFlipped = true; - mSelectionHandleTwo.SetScale( -1.0f, 1.0f, 1.0f ); - mSelectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_RIGHT); -} - -void TextInput::OnReturnToRightBoundary(PropertyNotification& source) -{ - mIsSelectionHandleTwoFlipped = false; - mSelectionHandleTwo.SetScale( 1.0f, 1.0f, 1.0f ); - mSelectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_LEFT); -} - -// todo change PropertyNotification signal definition to include Actor. Hence won't need duplicate functions. -void TextInput::OnHandleOneLeavesBoundary( PropertyNotification& source) -{ - mSelectionHandleOne.SetOpacity(0.0f); -} - -void TextInput::OnHandleOneWithinBoundary(PropertyNotification& source) -{ - mSelectionHandleOne.SetOpacity(1.0f); -} - -void TextInput::OnHandleTwoLeavesBoundary( PropertyNotification& source) -{ - mSelectionHandleTwo.SetOpacity(0.0f); -} - -void TextInput::OnHandleTwoWithinBoundary(PropertyNotification& source) -{ - mSelectionHandleTwo.SetOpacity(1.0f); -} - -// End of Callbacks connected to be Property notifications for Boundary checking. - -void TextInput::SetUpHandlePropertyNotifications() -{ - /* Property notifications for handles exceeding the boundary and returning back within boundary */ - - Vector3 handlesize = GetSelectionHandleSize(); - - // Exceeding horizontal boundary - PropertyNotification leftNotification = mSelectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.x + handlesize.x) ); - leftNotification.NotifySignal().Connect( this, &TextInput::OnLeftBoundaryExceeded ); - - PropertyNotification rightNotification = mSelectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.z - handlesize.x ) ); - rightNotification.NotifySignal().Connect( this, &TextInput::OnRightBoundaryExceeded ); - - // Within horizontal boundary - PropertyNotification leftLeaveNotification = mSelectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.x + 2*handlesize.x ) ); - leftLeaveNotification.NotifySignal().Connect( this, &TextInput::OnReturnToLeftBoundary ); - - PropertyNotification rightLeaveNotification = mSelectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.z - 2*handlesize.x ) ); - rightLeaveNotification.NotifySignal().Connect( this, &TextInput::OnReturnToRightBoundary ); - - // Exceeding vertical boundary - PropertyNotification verticalExceedNotificationOne = mSelectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalExceedNotificationOne.NotifySignal().Connect( this, &TextInput::OnHandleOneLeavesBoundary ); - - PropertyNotification verticalExceedNotificationTwo = mSelectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalExceedNotificationTwo.NotifySignal().Connect( this, &TextInput::OnHandleTwoLeavesBoundary ); - - // Within vertical boundary - PropertyNotification verticalWithinNotificationOne = mSelectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalWithinNotificationOne.NotifySignal().Connect( this, &TextInput::OnHandleOneWithinBoundary ); - - PropertyNotification verticalWithinNotificationTwo = mSelectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalWithinNotificationTwo.NotifySignal().Connect( this, &TextInput::OnHandleTwoWithinBoundary ); -} - -void TextInput::CreateSelectionHandles( std::size_t start, std::size_t end, Dali::Image handleOneImage, Dali::Image handleTwoImage ) -{ - mSelectionHandleOnePosition = start; - mSelectionHandleTwoPosition = end; - - if ( !mSelectionHandleOne ) - { - // create normal and pressed images - mSelectionHandleOneImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE ); - mSelectionHandleOneImagePressed = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE_PRESSED ); - - mSelectionHandleOne = ImageActor::New( mSelectionHandleOneImage ); - mSelectionHandleOne.SetName("SelectionHandleOne"); - mSelectionHandleOne.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mSelectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_RIGHT ); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text. - mIsSelectionHandleOneFlipped = false; - mSelectionHandleOne.SetDrawMode( DrawMode::OVERLAY ); // ensure grab handle above text - - mHandleOneGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move - mHandleOneGrabArea.SetName("SelectionHandleOneGrabArea"); - - mHandleOneGrabArea.SetResizePolicy( SIZE_RELATIVE_TO_PARENT, ALL_DIMENSIONS ); - mHandleOneGrabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); - mHandleOneGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - - mTapDetector.Attach( mHandleOneGrabArea ); - mPanGestureDetector.Attach( mHandleOneGrabArea ); - - mHandleOneGrabArea.TouchedSignal().Connect(this,&TextInput::OnHandleOneTouched); - - mSelectionHandleOne.Add( mHandleOneGrabArea ); - mActiveLayer.Add( mSelectionHandleOne ); - } - - if ( !mSelectionHandleTwo ) - { - // create normal and pressed images - mSelectionHandleTwoImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO ); - mSelectionHandleTwoImagePressed = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO_PRESSED ); - - mSelectionHandleTwo = ImageActor::New( mSelectionHandleTwoImage ); - mSelectionHandleTwo.SetName("SelectionHandleTwo"); - mSelectionHandleTwo.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mSelectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - mIsSelectionHandleTwoFlipped = false; - mSelectionHandleTwo.SetDrawMode(DrawMode::OVERLAY); // ensure grab handle above text - - mHandleTwoGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move - mHandleTwoGrabArea.SetName("SelectionHandleTwoGrabArea"); - mHandleTwoGrabArea.SetResizePolicy( SIZE_RELATIVE_TO_PARENT, ALL_DIMENSIONS ); - mHandleTwoGrabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); - mHandleTwoGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - - mTapDetector.Attach( mHandleTwoGrabArea ); - mPanGestureDetector.Attach( mHandleTwoGrabArea ); - - mHandleTwoGrabArea.TouchedSignal().Connect(this, &TextInput::OnHandleTwoTouched); - - mSelectionHandleTwo.Add( mHandleTwoGrabArea ); - - mActiveLayer.Add( mSelectionHandleTwo ); - } - - SetUpHandlePropertyNotifications(); - - // update table as text may have changed. - GetTextLayoutInfo(); - - Vector3 altPositionOne; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValidOne; // Alternate cursor validity flag. - bool directionRTLOne; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition, directionRTLOne, altPositionOne, altPositionValidOne ); - - Vector3 altPositionTwo; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValidTwo; // Alternate cursor validity flag. - bool directionRTLTwo; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition, directionRTLTwo, altPositionTwo, altPositionValidTwo ); - - // VCC TODO: This method is a hack for one line. - ChooseRtlSelectionHandlePosition( cursorPositionOne, - cursorPositionTwo, - altPositionValidOne, - altPositionValidTwo, - altPositionOne, - altPositionTwo ); - - mSelectionHandleOne.SetPosition( mSelectionHandleOneActualPosition + UI_OFFSET + mSelectionHandleOneOffset ); - mSelectionHandleTwo.SetPosition( mSelectionHandleTwoActualPosition + UI_OFFSET + mSelectionHandleTwoOffset ); - - // Calculates and set the visibility if the scroll mode is enabled. - bool isSelectionHandleOneVisible = true; - bool isSelectionHandleTwoVisible = true; - if( IsScrollEnabled() ) - { - const Vector3& controlSize( GetControlSize() ); - isSelectionHandleOneVisible = IsPositionInsideBoundaries( mSelectionHandleOneActualPosition, Size::ZERO, controlSize ); - isSelectionHandleTwoVisible = IsPositionInsideBoundaries( mSelectionHandleTwoActualPosition, Size::ZERO, controlSize ); - mSelectionHandleOne.SetVisible( isSelectionHandleOneVisible ); - mSelectionHandleTwo.SetVisible( isSelectionHandleTwoVisible ); - } - - CreateHighlight(); // function will only create highlight if not already created. -} - -Vector3 TextInput::MoveSelectionHandle( SelectionHandleId handleId, const Vector2& displacement ) -{ - Vector3 actualHandlePosition; - - if ( mSelectionHandleOne && mSelectionHandleTwo ) - { - const Vector3& controlSize = GetControlSize(); - - Size cursorSize( CURSOR_THICKNESS, 0.f ); - - // Get a reference of the wanted selection handle (handle one or two). - Vector3& actualSelectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleOneActualPosition : mSelectionHandleTwoActualPosition; - - // Get a reference for the current position of the handle and a copy of its pair - std::size_t& currentSelectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleOnePosition : mSelectionHandleTwoPosition; - const std::size_t pairSelectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleTwoPosition : mSelectionHandleOnePosition; - - // Get a handle of the selection handle actor - ImageActor selectionHandleActor = ( handleId == HandleOne ) ? mSelectionHandleOne : mSelectionHandleTwo; - - // Selection handles should jump to the nearest character - std::size_t newHandlePosition = 0; - ReturnClosestIndex( actualSelectionHandlePosition.GetVectorXY(), newHandlePosition ); - - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - actualHandlePosition = GetActualPositionFromCharacterPosition( newHandlePosition, directionRTL, altPosition, altPositionValid ); - if( altPositionValid ) - { - // Check which of the positions is the closest. - if( fabsf( altPosition.x - actualSelectionHandlePosition.x ) < fabsf( actualHandlePosition.x - actualSelectionHandlePosition.x ) ) - { - actualHandlePosition = altPosition; - } - } - - bool handleVisible = true; - - if( IsScrollEnabled() ) - { - mCurrentSelectionId = handleId; - - cursorSize.height = GetRowRectFromCharacterPosition( newHandlePosition ).height; - // Restricts the movement of the grab handle inside the boundaries of the text-input. - handleVisible = IsPositionInsideBoundaries( actualHandlePosition, - cursorSize, - controlSize ); - - if( handleVisible ) - { - StopScrollTimer(); - mCurrentSelectionHandlePosition = actualHandlePosition; - mScrollDisplacement = Vector2::ZERO; - } - else - { - if( ( actualHandlePosition.x < SCROLL_THRESHOLD ) && ( displacement.x <= 0.f ) ) - { - mScrollDisplacement.x = -SCROLL_SPEED; - } - else if( ( actualHandlePosition.x > controlSize.width - SCROLL_THRESHOLD ) && ( displacement.x >= 0.f ) ) - { - mScrollDisplacement.x = SCROLL_SPEED; - } - if( ( actualHandlePosition.y < SCROLL_THRESHOLD ) && ( displacement.y <= 0.f ) ) - { - mScrollDisplacement.y = -SCROLL_SPEED; - } - else if( ( actualHandlePosition.y > controlSize.height - SCROLL_THRESHOLD ) && ( displacement.y >= 0.f ) ) - { - mScrollDisplacement.y = SCROLL_SPEED; - } - StartScrollTimer(); - } - } - - if ( handleVisible && // Ensure the handle is visible. - ( newHandlePosition != pairSelectionHandlePosition ) && // Ensure handle one is not the same position as handle two. - ( newHandlePosition != currentSelectionHandlePosition ) ) // Ensure the handle has moved. - { - currentSelectionHandlePosition = newHandlePosition; - - Vector3 selectionHandleOffset = ( handleId == HandleOne ) ? mSelectionHandleOneOffset : mSelectionHandleTwoOffset; - selectionHandleActor.SetPosition( actualHandlePosition + UI_OFFSET + selectionHandleOffset ); - - UpdateHighlight(); - - if ( handleId == HandleOne ) - { - const TextStyle oldInputStyle( mInputStyle ); - - // Set Active Style to that of first character in selection - if( mSelectionHandleOnePosition < mStyledText.size() ) - { - mInputStyle = ( mStyledText.at( mSelectionHandleOnePosition ) ).mStyle; - } - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } - } - } - - return actualHandlePosition; // Returns Handle position passed in if new value not assigned. -} - -void TextInput::SetSelectionHandlePosition(SelectionHandleId handleId) -{ - const std::size_t selectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleOnePosition : mSelectionHandleTwoPosition; - ImageActor selectionHandleActor = ( handleId == HandleOne ) ? mSelectionHandleOne : mSelectionHandleTwo; - - if ( selectionHandleActor ) - { - const Vector3 actualHandlePosition = GetActualPositionFromCharacterPosition( selectionHandlePosition ); - Vector3 selectionHandleOffset = ( handleId == HandleOne ) ? mSelectionHandleOneOffset : mSelectionHandleTwoOffset; - selectionHandleActor.SetPosition( actualHandlePosition + UI_OFFSET + selectionHandleOffset ); - - if( IsScrollEnabled() ) - { - const Size cursorSize( CURSOR_THICKNESS, - GetRowRectFromCharacterPosition( selectionHandlePosition ).height ); - selectionHandleActor.SetVisible( IsPositionInsideBoundaries( actualHandlePosition, - cursorSize, - GetControlSize() ) ); - } - } -} - -void TextInput::GetVisualTextSelection( std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection ) -{ - selectedVisualText.resize( mTextLayoutInfo.mCharacterLogicalToVisualMap.size(), false ); - - // VCC Set true/false in logical order. TODO : It needs to be checked. - - if( startSelection > endSelection ) - { - std::swap( startSelection, endSelection ); - } - std::size_t index = 0u; - for( std::vector::iterator it = selectedVisualText.begin(), endIt = selectedVisualText.end(); it != endIt; ++it, ++index ) - { - if( ( index < startSelection ) || ( endSelection <= index ) ) - { - *it = false; - } - else - { - *it = true; - } - } -} - -// Calculate the dimensions of the quads they will make the highlight mesh -TextInput::HighlightInfo TextInput::CalculateHighlightInfo() -{ - // At the moment there is no public API to modify the block alignment option. - - mNewHighlightInfo.mQuadList.clear(); // clear last quad information. - - if ( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() && !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() ) - { - Toolkit::TextView::CharacterLayoutInfoContainer::iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin(); - Toolkit::TextView::CharacterLayoutInfoContainer::iterator end = mTextLayoutInfo.mCharacterLayoutInfoTable.end(); - - // Get vector of flags representing characters that are selected (true) vs unselected (false). - std::vector selectedVisualText; - GetVisualTextSelection( selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - std::vector::iterator selectedIt = selectedVisualText.begin(); - std::vector::iterator selectedEndIt = selectedVisualText.end(); - - SelectionState selectionState = SelectionNone; ///< Current selection status of cursor over entire text. - float rowLeft = 0.0f; - float rowRight = 0.0f; - // Keep track of the TextView's min/max extents. Should be able to query this from TextView. - float maxRowLeft = std::numeric_limits::max(); - float maxRowRight = 0.0f; - - Toolkit::TextView::CharacterLayoutInfoContainer::iterator lastIt = it; - - // Scan through entire text. - while(it != end) - { - // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection. - - Toolkit::TextView::CharacterLayoutInfo& charInfo(*it); - bool charSelected = false; - if( selectedIt != selectedEndIt ) - { - charSelected = *selectedIt++; - } - - if( selectionState == SelectionNone ) - { - if( charSelected ) - { - selectionState = SelectionStarted; - rowLeft = charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x; - rowRight = rowLeft + charInfo.mSize.width; - } - } - else if( selectionState == SelectionStarted ) - { - // break selection on: - // 1. new line causing selection break. (\n or wordwrap) - // 2. character not selected. - if( !charSelected || - ( charInfo.mPosition.y - lastIt->mPosition.y > CHARACTER_THRESHOLD ) ) - { - // finished selection. - // TODO: TextView should have a table of visual rows, and each character a reference to the row - // that it resides on. That way this enumeration is not necessary. - Vector2 min, max; - if(lastIt->mIsNewParagraphChar) - { - // If the last character is a new line, then to get the row rect, we need to scan from the character before the new line. - lastIt = std::max( mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), lastIt - 1 ); - } - const Size rowSize( GetRowRectFromCharacterPosition( lastIt - mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), min, max ) ); - maxRowLeft = std::min(maxRowLeft, min.x); - maxRowRight = std::max(maxRowRight, max.x); - float rowBottom = lastIt->mPosition.y - mTextLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - - // Still selected, and block-align mode then set rowRight to max, so it can be clamped afterwards - if(charSelected) - { - rowRight = std::numeric_limits::max(); - } - mNewHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - - selectionState = SelectionNone; - - // Still selected? start a new selection - if( charSelected ) - { - // if block-align mode then set rowLeft to min, so it can be clamped afterwards - rowLeft = 0.0f; - rowRight = ( charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width; - selectionState = SelectionStarted; - } - } - else - { - // build up highlight(s) with this selection data. - rowLeft = std::min( charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x, rowLeft ); - rowRight = std::max( ( charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width, rowRight ); - } - } - - lastIt = it++; - } - - // If reached end, and still on selection, then close selection. - if(it == end) - { - if(selectionState == SelectionStarted) - { - // finished selection. - Vector2 min, max; - if(lastIt->mIsNewParagraphChar) - { - lastIt = std::max( mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), lastIt - 1 ); - } - const Size rowSize( GetRowRectFromCharacterPosition( lastIt - mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), min, max ) ); - maxRowLeft = std::min(maxRowLeft, min.x); - maxRowRight = std::max(maxRowRight, max.x); - float rowBottom = lastIt->mPosition.y - mTextLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - mNewHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - } - } - - // Get the top left and bottom right corners. - const Toolkit::TextView::CharacterLayoutInfo& firstCharacter( *mTextLayoutInfo.mCharacterLayoutInfoTable.begin() ); - const Vector2 topLeft( maxRowLeft, firstCharacter.mPosition.y - firstCharacter.mSize.height ); - const Vector2 bottomRight( topLeft.x + mTextLayoutInfo.mTextSize.width, topLeft.y + mTextLayoutInfo.mTextSize.height ); - - // Clamp quads so they appear to clip to borders of the whole text. - mNewHighlightInfo.Clamp2D( topLeft, bottomRight ); - - // For block-align align Further Clamp quads to max left and right extents - // BlockAlign: Will adjust highlight to block: - // i.e. - // H[ello] (top row right = max of all rows right) - // [--this-] (middle rows' left = min of all rows left, middle rows' right = max of all rows right) - // [is some] (middle rows' left = min of all rows left, middle rows' right = max of all rows right) - // [text] (bottom row left = min of all rows left) - // (common in SMS messaging selection) - // - // As opposed to the default which is tight text highlighting. - // H[ello] - // [this] - // [is some] - // [text] - // (common in regular text editors/web browser selection) - mNewHighlightInfo.Clamp2D( Vector2(maxRowLeft, topLeft.y), Vector2(maxRowRight, bottomRight.y ) ); - - // Finally clamp quads again so they don't exceed the boundry of the control. - const Vector3& controlSize = GetControlSize(); - mNewHighlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) ); - } // end if - - return mNewHighlightInfo; -} - -// VCC TODO: two methods are not needed. this one is a quick hack to fix PLMs. Should implement one which support both directions. -// This method creates one quad per character so different selection boxes for a mix of LTR and RTL languages are created. -TextInput::HighlightInfo TextInput::CalculateHighlightInfoRtl() -{ - // At the moment there is no public API to modify the block alignment option. - - mNewHighlightInfo.mQuadList.clear(); // clear last quad information. - - if ( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() && !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() ) - { - Toolkit::TextView::CharacterLayoutInfoContainer::iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin(); - Toolkit::TextView::CharacterLayoutInfoContainer::iterator end = mTextLayoutInfo.mCharacterLayoutInfoTable.end(); - - // Get vector of flags representing characters that are selected (true) vs unselected (false). - std::vector selectedVisualText; - GetVisualTextSelection( selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - std::vector::iterator selectedIt = selectedVisualText.begin(); - std::vector::iterator selectedEndIt = selectedVisualText.end(); - - // SelectionState selectionState = SelectionNone; ///< Current selection status of cursor over entire text. - float rowLeft = 0.0f; - float rowRight = 0.0f; - - // VCC TODO this is valid for one line. - Vector2 min, max; - const Size rowSize = GetRowRectFromCharacterPosition( 0, min, max ); - - // Scan through entire text. - while(it != end) - { - // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection. - - Toolkit::TextView::CharacterLayoutInfo& charInfo(*it); - bool charSelected = false; - if( selectedIt != selectedEndIt ) - { - charSelected = *selectedIt++; - } - - if( charSelected ) - { - rowLeft = charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x; - rowRight = rowLeft + charInfo.mSize.width; - - float rowBottom = charInfo.mPosition.y - mTextLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - mNewHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - } - - ++it; - } - - // Finally clamp quads again so they don't exceed the boundry of the control. - const Vector3& controlSize = GetControlSize(); - mNewHighlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) ); - } // end if - - return mNewHighlightInfo; -} - -void TextInput::UpdateHighlight() -{ -// Construct a Mesh with a texture to be used as the highlight 'box' for selected text -// -// Example scenarios where mesh is made from 3, 1, 2, 2 ,3 or 3 quads. -// -// [ TOP ] [ TOP ] [TOP ] [ TOP ] [ TOP ] [ TOP ] -// [ MIDDLE ] [BOTTOM] [BOTTOM] [ MIDDLE ] [ MIDDLE ] -// [ BOTTOM] [ MIDDLE ] [ MIDDLE ] -// [BOTTOM] [ MIDDLE ] -// [BOTTOM] -// -// Each quad is created as 2 triangles. -// Middle is just 1 quad regardless of its size. -// -// (0,0) (0,0) -// 0* *2 0* *2 -// TOP TOP -// 3* *1 3* *1 -// 4* *1 4* *6 -// MIDDLE BOTTOM -// 6* *5 7* *5 -// 6* *8 -// BOTTOM -// 9* *7 -// - - if ( mHighlightMeshActor ) - { - // vertex and triangle buffers should always be present if MeshActor is alive. - HighlightInfo newHighlightInfo = CalculateHighlightInfoRtl(); - MeshData::VertexContainer vertices; - Dali::MeshData::FaceIndices faceIndices; - - if( !newHighlightInfo.mQuadList.empty() ) - { - std::vector::iterator iter = newHighlightInfo.mQuadList.begin(); - std::vector::iterator endIter = newHighlightInfo.mQuadList.end(); - - // vertex position defaults to (0 0 0) - MeshData::Vertex vertex; - // set normal for all vertices as (0 0 1) pointing outward from TextInput Actor. - vertex.nZ = 1.0f; - - for(std::size_t v = 0; iter != endIter; ++iter,v+=4 ) - { - // Add each quad geometry (a sub-selection) to the mesh data. - - // 0-----1 - // |\ | - // | \ A | - // | \ | - // | B \ | - // | \| - // 2-----3 - - QuadCoordinates& quad = *iter; - // top-left (v+0) - vertex.x = quad.min.x; - vertex.y = quad.min.y; - vertices.push_back( vertex ); - - // top-right (v+1) - vertex.x = quad.max.x; - vertex.y = quad.min.y; - vertices.push_back( vertex ); - - // bottom-left (v+2) - vertex.x = quad.min.x; - vertex.y = quad.max.y; - vertices.push_back( vertex ); - - // bottom-right (v+3) - vertex.x = quad.max.x; - vertex.y = quad.max.y; - vertices.push_back( vertex ); - - // triangle A (3, 1, 0) - faceIndices.push_back( v + 3 ); - faceIndices.push_back( v + 1 ); - faceIndices.push_back( v ); - - // triangle B (0, 2, 3) - faceIndices.push_back( v ); - faceIndices.push_back( v + 2 ); - faceIndices.push_back( v + 3 ); - - mMeshData.SetFaceIndices( faceIndices ); - } - - BoneContainer bones(0); // passed empty as bones not required - mMeshData.SetData( vertices, faceIndices, bones, mCustomMaterial ); - mHighlightMesh.UpdateMeshData(mMeshData); - } - } -} - -void TextInput::ClearPopup() -{ - mPopupPanel.Clear(); -} - -void TextInput::AddPopupOptions() -{ - mPopupPanel.AddPopupOptions(); -} - -void TextInput::SetPopupPosition( const Vector3& position, const Vector2& alternativePosition ) -{ - const Vector3& visiblePopUpSize = mPopupPanel.GetVisibileSize(); - - Vector3 clampedPosition ( position ); - Vector3 tailOffsetPosition ( position ); - - float xOffSet( 0.0f ); - - Actor self = Self(); - const Vector3 textViewTopLeftWorldPosition = self.GetCurrentWorldPosition() - self.GetCurrentSize()*0.5f; - - const float popUpLeft = textViewTopLeftWorldPosition.x + position.x - visiblePopUpSize.width*0.5f; - const float popUpTop = textViewTopLeftWorldPosition.y + position.y - visiblePopUpSize.height; - - // Clamp to left or right or of boundary - if( popUpLeft < mBoundingRectangleWorldCoordinates.x ) - { - xOffSet = mBoundingRectangleWorldCoordinates.x - popUpLeft ; - } - else if ( popUpLeft + visiblePopUpSize.width > mBoundingRectangleWorldCoordinates.z ) - { - xOffSet = mBoundingRectangleWorldCoordinates.z - ( popUpLeft + visiblePopUpSize.width ); - } - - clampedPosition.x = position.x + xOffSet; - tailOffsetPosition.x = -xOffSet; - - // Check if top left of PopUp outside of top bounding rectangle, if so then flip to lower position. - bool flipTail( false ); - - if ( popUpTop < mBoundingRectangleWorldCoordinates.y ) - { - clampedPosition.y = alternativePosition.y + visiblePopUpSize.height; - flipTail = true; - } - - mPopupPanel.GetRootActor().SetPosition( clampedPosition ); - mPopupPanel.SetTailPosition( tailOffsetPosition, flipTail ); -} - -void TextInput::HidePopup(bool animate, bool signalFinished ) -{ - if ( ( mPopupPanel.GetState() == TextInputPopup::StateShowing ) || ( mPopupPanel.GetState() == TextInputPopup::StateShown ) ) - { - mPopupPanel.Hide( animate ); - - if( animate && signalFinished ) - { - mPopupPanel.HideFinishedSignal().Connect( this, &TextInput::OnPopupHideFinished ); - } - } -} - -void TextInput::ShowPopup( bool animate ) -{ - Vector3 position; - Vector2 alternativePopupPosition; - - if(mHighlightMeshActor && mState == StateEdit) - { - Vector3 topHandle; - Vector3 bottomHandle; // referring to the bottom most point of the handle or the bottom line of selection. - Size rowSize; - // When text is selected, show popup above top handle (and text), or below bottom handle. - // topHandle: referring to the top most point of the handle or the top line of selection. - if ( mSelectionHandleTwoActualPosition.y > mSelectionHandleOneActualPosition.y ) - { - topHandle = mSelectionHandleOneActualPosition; - bottomHandle = mSelectionHandleTwoActualPosition; - rowSize= GetRowRectFromCharacterPosition( mSelectionHandleOnePosition ); - } - else - { - topHandle = mSelectionHandleTwoActualPosition; - bottomHandle = mSelectionHandleOneActualPosition; - rowSize = GetRowRectFromCharacterPosition( mSelectionHandleTwoPosition ); - } - topHandle.y += -mPopupOffsetFromText.y - rowSize.height; - position = Vector3(topHandle.x, topHandle.y, 0.0f); - - float xPosition = ( fabsf( topHandle.x - bottomHandle.x ) )*0.5f + std::min( mSelectionHandleOneActualPosition.x , mSelectionHandleTwoActualPosition.x ); - - position.x = xPosition; - - // Alternative position if no upper space - bottomHandle.y += GetSelectionHandleSize().y + mPopupOffsetFromText.w; - alternativePopupPosition = Vector2 ( position.x, bottomHandle.y ); - } - else - { - // When no text is selected, show popup at world position of grab handle or cursor - position = GetActualPositionFromCharacterPosition( mCursorPosition ); - const Size rowSize = GetRowRectFromCharacterPosition( mCursorPosition ); - position.y -= ( mPopupOffsetFromText.y + rowSize.height ); - // if can't be positioned above, then position below row. - alternativePopupPosition = Vector2( position.x, position.y ); // default if no grab handle - if ( mGrabHandle ) - { - // If grab handle enabled then position pop-up below the grab handle. - alternativePopupPosition.y = rowSize.height + mGrabHandle.GetCurrentSize().height + mPopupOffsetFromText.w +50.0f; - } - } - - SetPopupPosition( position, alternativePopupPosition ); - - // Show popup - mPopupPanel.Show( Self(), animate ); - StartMonitoringStageForTouch(); - - mPopupPanel.PressedSignal().Connect( this, &TextInput::OnPopupButtonPressed ); -} - -void TextInput::ShowPopupCutCopyPaste() -{ - ClearPopup(); - - mPopupPanel.CreateOrderedListOfOptions(); // todo Move this so only run when order has changed - // Check the selected text is whole text or not. - if( IsTextSelected() && ( mStyledText.size() != GetSelectedText().size() ) ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelectAll, true ); - } - - if ( !mStyledText.empty() && IsTextSelected() ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCopy, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, true ); - } - - if( mClipboard && mClipboard.NumberOfItems() ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsPaste, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsClipboard, true ); - } - - AddPopupOptions(); - - mPopupPanel.Hide(false); - ShowPopup(); -} - -void TextInput::SetUpPopupSelection( bool showCutButton ) -{ - ClearPopup(); - mPopupPanel.CreateOrderedListOfOptions(); // todo Move this so only run when order has changed - // If no text exists then don't offer to select - if ( !mStyledText.empty() ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelectAll, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelect, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, ( showCutButton && IsTextSelected() ) ); - } - // if clipboard has valid contents then offer paste option - if( mClipboard && mClipboard.NumberOfItems() ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsPaste, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsClipboard, true ); - } - - AddPopupOptions(); - - mPopupPanel.Hide(false); -} - -bool TextInput::ReturnClosestIndex(const Vector2& source, std::size_t& closestIndex ) -{ - bool found = false; - closestIndex = 0; - - std::vector matchedCharacters; - bool lastRightToLeftChar(false); /// RTL state of previous character encountered (character on the left of touch point) - bool rightToLeftChar(false); /// RTL state of current character encountered (character on the right of touch point) - float glyphIntersection(0.0f); /// Glyph intersection, the point between the two nearest characters touched. - - const Vector2 sourceScrollOffset( source + mTextLayoutInfo.mScrollOffset ); - - if ( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) - { - float closestYdifference = std::numeric_limits::max(); - std::size_t lineOffset = 0; /// Keep track of position of the first character on the matched line of interest. - std::size_t numberOfMatchedCharacters = 0; - - // 1. Find closest character line to y part of source, create vector of all entries in that Y position - // TODO: There should be an easy call to enumerate through each visual line, instead of each character on all visual lines. - - for( std::vector::const_iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), endIt = mTextLayoutInfo.mCharacterLayoutInfoTable.end(); it != endIt; ++it ) - { - const Toolkit::TextView::CharacterLayoutInfo& info( *it ); - float baselinePosition = info.mPosition.y - info.mDescender; - - if( info.mIsVisible ) - { - // store difference between source y point and the y position of the current character - float currentYdifference = fabsf( sourceScrollOffset.y - ( baselinePosition ) ); - - if( currentYdifference < closestYdifference ) - { - // closest so far; store this difference and clear previous matchedCharacters as no longer closest - lineOffset = it - mTextLayoutInfo.mCharacterLayoutInfoTable.begin(); - closestYdifference = currentYdifference; - matchedCharacters.clear(); - numberOfMatchedCharacters = 0; // reset count - } - - // add all characters that are on the same Y axis (within the CHARACTER_THRESHOLD) to the matched array. - if( fabsf( closestYdifference - currentYdifference ) < CHARACTER_THRESHOLD ) - { - // ignore new line character. - if( !info.mIsNewParagraphChar ) - { - matchedCharacters.push_back( info ); - numberOfMatchedCharacters++; - } - } - } - } // End of loop checking each character's y position in the character layout table - - // Check if last character is a newline, if it is - // then need pretend there is an imaginary line afterwards, - // and check if user is touching below previous line. - const Toolkit::TextView::CharacterLayoutInfo& lastInfo( mTextLayoutInfo.mCharacterLayoutInfoTable[mTextLayoutInfo.mCharacterLayoutInfoTable.size() - 1] ); - - if( ( lastInfo.mIsVisible ) && ( lastInfo.mIsNewParagraphChar ) && ( sourceScrollOffset.y > lastInfo.mPosition.y ) ) - { - closestIndex = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); - } - else - { - // 2 Iterate through matching list of y positions and find closest matching X position. - - bool matched( false ); - - // Traverse the characters in the visual order. VCC TODO: check for more than one line. - std::size_t visualIndex = 0u; - const std::size_t matchedCharactersSize = matchedCharacters.size(); - for( ; visualIndex < matchedCharactersSize; ++visualIndex ) - { - const Toolkit::TextView::CharacterLayoutInfo& info( *( matchedCharacters.begin() + mTextLayoutInfo.mCharacterVisualToLogicalMap[visualIndex] ) ); - - if( info.mIsVisible ) - { - // stop when on left side of character's center. - const float characterMidPointPosition = info.mPosition.x + ( info.mSize.width * 0.5f ) ; - if( sourceScrollOffset.x < characterMidPointPosition ) - { - if(info.mIsRightToLeftCharacter) - { - rightToLeftChar = true; - } - glyphIntersection = info.mPosition.x; - matched = true; - break; - } - - lastRightToLeftChar = info.mIsRightToLeftCharacter; - } - } - - if( visualIndex == matchedCharactersSize ) - { - rightToLeftChar = lastRightToLeftChar; - } - - closestIndex = lineOffset + visualIndex; - - mClosestCursorPositionEOL = false; // reset - if( ( visualIndex == matchedCharactersSize ) && !matched ) - { - mClosestCursorPositionEOL = true; // Reached end of matched characters in closest line but no match so cursor should be after last character. - } - - // For RTL characters, need to adjust closestIndex by 1 (as the inequality above would be reverse) - if( rightToLeftChar && lastRightToLeftChar ) - { - --closestIndex; // (-1 = numeric_limits::max()) - } - } - } - - // closestIndex is the visual index, need to convert it to the logical index - if( !mTextLayoutInfo.mCharacterVisualToLogicalMap.empty() ) - { - if( closestIndex < mTextLayoutInfo.mCharacterVisualToLogicalMap.size() ) - { - // Checks for situations where user is touching between LTR and RTL - // characters. To identify if the user means the end of a LTR string - // or the beginning of an RTL string, and vice versa. - if( closestIndex > 0 ) - { - if( rightToLeftChar && !lastRightToLeftChar ) - { - // [LTR] [RTL] - // |..|..| - // AAA BBB - // A: In this touch range, the user is indicating that they wish to place - // the cursor at the end of the LTR text. - // B: In this touch range, the user is indicating that they wish to place - // the cursor at the end of the RTL text. - - // Result of touching A area: - // [.....LTR]|[RTL......]+ - // - // |: primary cursor (for typing LTR chars) - // +: secondary cursor (for typing RTL chars) - - // Result of touching B area: - // [.....LTR]+[RTL......]| - // - // |: primary cursor (for typing RTL chars) - // +: secondary cursor (for typing LTR chars) - - if( sourceScrollOffset.x < glyphIntersection ) - { - --closestIndex; - } - } - else if( !rightToLeftChar && lastRightToLeftChar ) - { - if( sourceScrollOffset.x < glyphIntersection ) - { - --closestIndex; - } - } - } - - closestIndex = mTextLayoutInfo.mCharacterVisualToLogicalMap[closestIndex]; - // If user touched a left-side of RTL char, and the character on the left was an LTR then position logical cursor - // one further ahead - if( rightToLeftChar && !lastRightToLeftChar ) - { - ++closestIndex; - } - } - else if( closestIndex == std::numeric_limits::max() ) // -1 RTL (after last arabic character on line) - { - closestIndex = mTextLayoutInfo.mCharacterVisualToLogicalMap.size(); - } - else if( mTextLayoutInfo.mCharacterLayoutInfoTable[ mTextLayoutInfo.mCharacterVisualToLogicalMap[ closestIndex - 1 ] ].mIsRightToLeftCharacter ) // size() LTR (after last european character on line) - { - closestIndex = 0; - } - } - - return found; -} - -float TextInput::GetLineJustificationPosition() const -{ - const Vector3& size = mDisplayedTextView.GetCurrentSize(); - Toolkit::Alignment::Type alignment = mDisplayedTextView.GetTextAlignment(); - float alignmentOffset = 0.f; - - // Work out cursor 'x' position when there are any character accordingly with the text view alignment settings. - if( alignment & Toolkit::Alignment::HorizontalLeft ) - { - alignmentOffset = 0.f; - } - else if( alignment & Toolkit::Alignment::HorizontalCenter ) - { - alignmentOffset = 0.5f * ( size.width - mTextLayoutInfo.mTextSize.width ); - } - else if( alignment & Toolkit::Alignment::HorizontalRight ) - { - alignmentOffset = size.width - mTextLayoutInfo.mTextSize.width; - } - - Toolkit::TextView::LineJustification justification = mDisplayedTextView.GetLineJustification(); - float justificationOffset = 0.f; - - switch( justification ) - { - case Toolkit::TextView::Left: - { - justificationOffset = 0.f; - break; - } - case Toolkit::TextView::Center: - { - justificationOffset = 0.5f * mTextLayoutInfo.mTextSize.width; - break; - } - case Toolkit::TextView::Right: - { - justificationOffset = mTextLayoutInfo.mTextSize.width; - break; - } - case Toolkit::TextView::Justified: - { - justificationOffset = 0.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( false ); - } - } // end switch - - return alignmentOffset + justificationOffset; -} - -Vector3 TextInput::PositionCursorAfterWordWrap( std::size_t characterPosition ) const -{ - /* Word wrap occurs automatically in TextView when the exceed policy moves a word to the next line when not enough space on current. - A newline character is not inserted in this case */ - - Vector3 cursorPosition; - - Toolkit::TextView::CharacterLayoutInfo currentCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - - bool noWrap = true; - - if( characterPosition > 0u ) - { - Toolkit::TextView::CharacterLayoutInfo previousCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition - 1u ]; - - // If previous character on a different line then use current characters position - if( fabsf( (currentCharInfo.mPosition.y - currentCharInfo.mDescender ) - ( previousCharInfo.mPosition.y - previousCharInfo.mDescender) ) > Math::MACHINE_EPSILON_1000 ) - { - // VCC TODO: PositionCursorAfterWordWrap currently doesn't work for multiline. Need to check this branch. - if ( mClosestCursorPositionEOL ) - { - cursorPosition = Vector3( previousCharInfo.mPosition.x + previousCharInfo.mSize.width, previousCharInfo.mPosition.y, previousCharInfo.mPosition.z ) ; - } - else - { - cursorPosition = Vector3( currentCharInfo.mPosition ); - } - - noWrap = false; - } - } - - if( noWrap ) - { - // If the character is left to right, the position is the character's position plus its width. - const float ltrOffset = !currentCharInfo.mIsRightToLeftCharacter ? currentCharInfo.mSize.width : 0.f; - - cursorPosition.x = currentCharInfo.mPosition.x + ltrOffset; - cursorPosition.y = currentCharInfo.mPosition.y; - } - - return cursorPosition; -} - -Vector3 TextInput::GetActualPositionFromCharacterPosition( std::size_t characterPosition ) const -{ - bool direction = false; - Vector3 alternatePosition; - bool alternatePositionValid = false; - - return GetActualPositionFromCharacterPosition( characterPosition, direction, alternatePosition, alternatePositionValid ); -} - -Vector3 TextInput::GetActualPositionFromCharacterPosition( std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const -{ - DALI_ASSERT_DEBUG( ( mTextLayoutInfo.mCharacterLayoutInfoTable.size() == mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ) && - ( mTextLayoutInfo.mCharacterLayoutInfoTable.size() == mTextLayoutInfo.mCharacterVisualToLogicalMap.size() ) && - "TextInput::GetActualPositionFromCharacterPosition. All layout tables must have the same size." ); - - Vector3 cursorPosition( 0.f, 0.f, 0.f ); - - alternatePositionValid = false; - directionRTL = false; - - if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) - { - if( characterPosition == 0u ) - { - // When the cursor position is at the beginning, it should be at the start of the current character. - // If the current character is LTR, then the start is on the right side of the glyph. - // If the current character is RTL, then the start is on the left side of the glyph. - - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() ) ).mIsVisible ) - { - characterPosition = FindVisibleCharacter( Right, 0u ); - } - - const Toolkit::TextView::CharacterLayoutInfo& info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - const float rtlOffset = info.mIsRightToLeftCharacter ? info.mSize.width : 0.0f; - - cursorPosition.x = info.mPosition.x + rtlOffset; - cursorPosition.y = info.mPosition.y; - directionRTL = info.mIsRightToLeftCharacter; - } - else if( characterPosition > 0u ) - { - // Get the direction of the paragraph. - const std::size_t startCharacterPosition = GetRowStartFromCharacterPosition( characterPosition ); - const bool isParagraphRightToLeft = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + startCharacterPosition ) ).mIsRightToLeftCharacter; - - // When cursor is not at beginning, consider possibility of - // showing 2 cursors. (whereas at beginning we only ever show one cursor) - - // Cursor position should be the end of the last character. - // If the last character is LTR, then the end is on the right side of the glyph. - // If the last character is RTL, then the end is on the left side of the glyph. - - --characterPosition; - - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + characterPosition ) ).mIsVisible ) - { - characterPosition = FindVisibleCharacter( Left, characterPosition ); - } - - Toolkit::TextView::CharacterLayoutInfo info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - if( ( characterPosition > 0u ) && info.mIsNewParagraphChar && !IsScrollEnabled() ) - { - // VCC TODO : check for a new paragraph character. - - // Prevents the cursor to exceed the boundary if the last visible character is a 'new line character' and the scroll is not enabled. - const Vector3& size = GetControlSize(); - - if( info.mPosition.y + info.mSize.height - mDisplayedTextView.GetLineHeightOffset() > size.height ) - { - --characterPosition; - } - info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - } - - if( !info.mIsNewParagraphChar ) - { - cursorPosition = PositionCursorAfterWordWrap( characterPosition ); // Get position of cursor/handles taking in account auto word wrap. - } - else - { - // VCC TODO : check for a new paragraph character. - - // When cursor points to first character on new line, position cursor at the start of this glyph. - if( characterPosition < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) - { - const Toolkit::TextView::CharacterLayoutInfo& infoNext = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - const float start( infoNext.mIsRightToLeftCharacter ? infoNext.mSize.width : 0.0f ); - - cursorPosition.x = infoNext.mPosition.x + start; - cursorPosition.y = infoNext.mPosition.y; - } - else - { - // If cursor points to the end of text, then can only position - // cursor where the new line starts based on the line-justification position. - cursorPosition.x = GetLineJustificationPosition(); - - if( characterPosition == mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ) - { - // If this is after the last character, then we can assume that the new cursor - // should be exactly one row below the current row. - - const Size rowRect = GetRowRectFromCharacterPosition( characterPosition - 1u ); - cursorPosition.y = info.mPosition.y + rowRect.height; - } - else - { - // If this is not after last character, then we can use this row's height. - // should be exactly one row below the current row. - - const Size rowRect = GetRowRectFromCharacterPosition( characterPosition ); - cursorPosition.y = info.mPosition.y + rowRect.height; - } - } - } - - directionRTL = info.mIsRightToLeftCharacter; - - if( 1u < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) - { - // 1. When the cursor is neither at the beginning or the end, - // we can show multiple cursors under situations when the cursor is - // between RTL and LTR text... - if( characterPosition + 1u < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) - { - std::size_t characterAltPosition = characterPosition + 1u; - - const Toolkit::TextView::CharacterLayoutInfo& infoAlt = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterAltPosition ]; - - if(!info.mIsRightToLeftCharacter && infoAlt.mIsRightToLeftCharacter) - { - // Stuation occurs when cursor is at the end of English text (LTR) and beginning of Arabic (RTL) - // Text: [...LTR...]|[...RTL...] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - alternatePosition.x = infoAlt.mPosition.x + infoAlt.mSize.width; - alternatePosition.y = infoAlt.mPosition.y; - alternatePositionValid = true; - } - else if(info.mIsRightToLeftCharacter && !infoAlt.mIsRightToLeftCharacter) - { - // Situation occurs when cursor is at end of the Arabic text (LTR) and beginning of English (RTL) - // Text: |[...RTL...] [...LTR....] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - alternatePosition.x = infoAlt.mPosition.x; - alternatePosition.y = infoAlt.mPosition.y; - alternatePositionValid = true; - } - } - else - { - // 2. When the cursor is at the end of the text, - // and we have multi-directional text, - // we can also consider showing mulitple cursors. - // The rule here is: - // If first and last characters on row are different - // Directions, then two cursors need to be displayed. - - if( info.mIsRightToLeftCharacter != isParagraphRightToLeft ) - { - // The last character's direction is differernt than the first one of current paragraph. - - // Get first - const Toolkit::TextView::CharacterLayoutInfo& infoStart= mTextLayoutInfo.mCharacterLayoutInfoTable[ GetFirstCharacterWithSameDirection( characterPosition ) ]; - - if(info.mIsRightToLeftCharacter) - { - // For text Starting as LTR and ending as RTL. End cursor position is as follows: - // Text: [...LTR...]|[...RTL...] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text, this cursor - // should be at the end of the given line. - - alternatePosition.x = infoStart.mPosition.x + infoStart.mSize.width; - alternatePosition.y = infoStart.mPosition.y; - alternatePositionValid = true; - } - else if(!info.mIsRightToLeftCharacter) // starting RTL - { - // For text Starting as RTL and ending as LTR. End cursor position is as follows: - // Text: |[...RTL...] [...LTR....] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - alternatePosition.x = infoStart.mPosition.x; - alternatePosition.y = infoStart.mPosition.y; - alternatePositionValid = true; - } - } - } - } - } // characterPosition > 0 - } - else - { - // If the character table is void, place the cursor accordingly the text alignment. - const Vector3& size = GetControlSize(); - - Toolkit::Alignment::Type alignment = mDisplayedTextView.GetTextAlignment(); - float alignmentOffset = 0.f; - - // Work out cursor 'x' position when there are any character accordingly with the text view alignment settings. - if( alignment & Toolkit::Alignment::HorizontalLeft ) - { - alignmentOffset = 0.f; - } - else if( alignment & Toolkit::Alignment::HorizontalCenter ) - { - alignmentOffset = 0.5f * ( size.width ); - } - else if( alignment & Toolkit::Alignment::HorizontalRight ) - { - alignmentOffset = size.width; - } - - // Work out cursor 'x' position when there are any character accordingly with the text view alignment settings. - cursorPosition.x = alignmentOffset; - - // Work out cursor 'y' position when there are any character accordingly with the text view alignment settings. - if( alignment & Toolkit::Alignment::VerticalTop ) - { - cursorPosition.y = mLineHeight; - } - else if( alignment & Toolkit::Alignment::VerticalCenter ) - { - cursorPosition.y = 0.5f * ( size.height + mLineHeight ); - } - else if( alignment & Toolkit::Alignment::VerticalBottom ) - { - cursorPosition.y = size.height; - } - } - - cursorPosition.x -= mTextLayoutInfo.mScrollOffset.x; - cursorPosition.y -= mTextLayoutInfo.mScrollOffset.y; - - if( alternatePositionValid ) - { - alternatePosition.x -= mTextLayoutInfo.mScrollOffset.x; - alternatePosition.y -= mTextLayoutInfo.mScrollOffset.y; - } - - return cursorPosition; -} - -std::size_t TextInput::GetRowStartFromCharacterPosition( std::size_t logicalPosition ) const -{ - // scan string from current position to beginning of current line to note direction of line - while( logicalPosition ) - { - logicalPosition--; - if( mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsNewParagraphChar ) - { - logicalPosition++; - break; - } - } - - return logicalPosition; -} - -std::size_t TextInput::GetFirstCharacterWithSameDirection( std::size_t logicalPosition ) const -{ - const bool isRightToLeft = mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsRightToLeftCharacter; - - while( logicalPosition ) - { - logicalPosition--; - if( isRightToLeft != mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsRightToLeftCharacter ) - { - logicalPosition++; - break; - } - } - - return logicalPosition; -} - -Size TextInput::GetRowRectFromCharacterPosition(std::size_t characterPosition) const -{ - Vector2 min, max; - - return GetRowRectFromCharacterPosition( characterPosition, min, max ); -} - -Size TextInput::GetRowRectFromCharacterPosition( std::size_t characterPosition, Vector2& min, Vector2& max ) const -{ - // if we have no text content, then return position 0,0 with width 0, and height the same as cursor height. - if( mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) - { - min = Vector2::ZERO; - max = Vector2(0.0f, mLineHeight); - return max; - } - - DALI_ASSERT_DEBUG( characterPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ); - - // Initializes the min and max position. - const std::size_t initialPosition = ( characterPosition == mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) ? characterPosition - 1u : characterPosition; - min = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + initialPosition ) ).mPosition.GetVectorXY(); - max = min; - - bool found = false; - // 1) Find the line where the character is laid-out. - for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineIt = mTextLayoutInfo.mLines.begin(), lineEndIt = mTextLayoutInfo.mLines.end(); - !found && ( lineIt != mTextLayoutInfo.mLines.end() ); - ++lineIt ) - { - const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineIt ); - - // Index within the whole text to the last character of the current line. - std::size_t lastCharacterOfLine = 0u; - - Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineNextIt = lineIt + 1u; - if( lineNextIt != lineEndIt ) - { - lastCharacterOfLine = (*lineNextIt).mCharacterGlobalIndex - 1u; - } - else - { - lastCharacterOfLine = mTextLayoutInfo.mCharacterLayoutInfoTable.size() - 1u; - } - - // Check if the given chracter position is within the line. - if( ( lineInfo.mCharacterGlobalIndex <= initialPosition ) && ( initialPosition <= lastCharacterOfLine ) ) - { - // 2) Get the row rect of all laid-out characters on the line. - - // Need to scan all characters of the line because they are in the logical position. - for( Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + lineInfo.mCharacterGlobalIndex, - endIt = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + lastCharacterOfLine + 1u; - it != endIt; - ++it ) - { - const Toolkit::TextView::CharacterLayoutInfo& characterInfo( *it ); - - min.x = std::min( min.x, characterInfo.mPosition.x ); - min.y = std::min( min.y, characterInfo.mPosition.y ); - max.x = std::max( max.x, characterInfo.mPosition.x + characterInfo.mSize.width ); - max.y = std::max( max.y, characterInfo.mPosition.y + characterInfo.mSize.height ); - } - - found = true; - } - } - - return Size( max.x - min.x, max.y - min.y ); -} - -bool TextInput::WasTouchedCheck( const Actor& touchedActor ) const -{ - Actor popUpPanel = mPopupPanel.GetRootActor(); - - if ( ( touchedActor == Self() ) || ( touchedActor == popUpPanel ) ) - { - return true; - } - else - { - Dali::Actor parent( touchedActor.GetParent() ); - - if ( parent ) - { - return WasTouchedCheck( parent ); - } - } - - return false; -} - -void TextInput::StartMonitoringStageForTouch() -{ - Stage stage = Stage::GetCurrent(); - stage.TouchedSignal().Connect( this, &TextInput::OnStageTouched ); -} - -void TextInput::EndMonitoringStageForTouch() -{ - Stage stage = Stage::GetCurrent(); - stage.TouchedSignal().Disconnect( this, &TextInput::OnStageTouched ); -} - -void TextInput::OnStageTouched(const TouchEvent& event) -{ - if( event.GetPointCount() > 0 ) - { - if ( TouchPoint::Down == event.GetPoint(0).state ) - { - const Actor touchedActor(event.GetPoint(0).hitActor); - - bool popUpShown( false ); - - if ( ( mPopupPanel.GetState() == TextInputPopup::StateShowing ) || ( mPopupPanel.GetState() == TextInputPopup::StateShown ) ) - { - popUpShown = true; - } - - bool textInputTouched = (touchedActor && WasTouchedCheck( touchedActor )); - - if ( ( mHighlightMeshActor || popUpShown ) && !textInputTouched ) - { - EndMonitoringStageForTouch(); - HidePopup( true, false ); - } - - if ( ( IsGrabHandleEnabled() && mGrabHandle ) && !textInputTouched ) - { - EndMonitoringStageForTouch(); - ShowGrabHandleAndSetVisibility( false ); - } - } - } -} - -void TextInput::SelectText(std::size_t start, std::size_t end) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "SelectText mEditModeActive[%s] grabHandle[%s] start[%u] end[%u] size[%u]\n", mEditModeActive?"true":"false", - IsGrabHandleEnabled()?"true":"false", - start, end, mTextLayoutInfo.mCharacterLayoutInfoTable.size() ); - DALI_ASSERT_ALWAYS( start <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() && "TextInput::SelectText start out of max range" ); - DALI_ASSERT_ALWAYS( end <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() && "TextInput::SelectText end out of max range" ); - - StartMonitoringStageForTouch(); - - if ( mEditModeActive ) // Only allow text selection when in edit mode - { - // When replacing highlighted text keyboard should ignore current word at cursor hence notify keyboard that the cursor is at the start of the highlight. - mSelectingText = true; - - std::size_t selectionStartPosition = std::min( start, end ); - - // Hide grab handle when selecting. - ShowGrabHandleAndSetVisibility( false ); - - if( start != end ) // something to select - { - SetCursorVisibility( false ); - StopCursorBlinkTimer(); - - CreateSelectionHandles(start, end); - UpdateHighlight(); - - const TextStyle oldInputStyle( mInputStyle ); - mInputStyle = GetStyleAt( selectionStartPosition ); // Inherit style from selected position. - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - - HidePopup(); - } - - mSelectingText = false; - } -} - -MarkupProcessor::StyledTextArray TextInput::GetSelectedText() -{ - MarkupProcessor::StyledTextArray currentSelectedText; - - if ( IsTextSelected() ) - { - MarkupProcessor::StyledTextArray::iterator it = mStyledText.begin() + std::min(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - MarkupProcessor::StyledTextArray::iterator end = mStyledText.begin() + std::max(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - - for(; it != end; ++it) - { - MarkupProcessor::StyledText& styledText( *it ); - currentSelectedText.push_back( styledText ); - } - } - return currentSelectedText; -} - -void TextInput::ApplyStyleToRange(const TextStyle& style, const TextStyle::Mask mask, const std::size_t begin, const std::size_t end) -{ - const std::size_t beginIndex = std::min( begin, end ); - const std::size_t endIndex = std::max( begin, end ); - - // Apply the style - MarkupProcessor::SetTextStyleToRange( mStyledText, style, mask, beginIndex, endIndex ); - - // Create a styled text array used to replace the text into the text-view. - MarkupProcessor::StyledTextArray text; - text.insert( text.begin(), mStyledText.begin() + beginIndex, mStyledText.begin() + endIndex + 1 ); - - mDisplayedTextView.ReplaceTextFromTo( beginIndex, ( endIndex - beginIndex ) + 1, text ); - GetTextLayoutInfo(); - - if( IsScrollEnabled() ) - { - // Need to set the scroll position as the text's size may have changed. - ScrollTextViewToMakeCursorVisible( Vector3( mTextLayoutInfo.mScrollOffset.x, mTextLayoutInfo.mScrollOffset.y, 0.f ) ); - } - - ShowGrabHandleAndSetVisibility( false ); - - DrawCursor(); - - UpdateHighlight(); - - // Set Handle positioning as the new style may have repositioned the characters. - SetSelectionHandlePosition(HandleOne); - SetSelectionHandlePosition(HandleTwo); -} - -void TextInput::KeyboardStatusChanged(bool keyboardShown) -{ - // Just hide the grab handle when keyboard is hidden. - if (!keyboardShown ) - { - ShowGrabHandleAndSetVisibility( false ); - - // If the keyboard is not now being shown, then hide the popup panel - mPopupPanel.Hide( true ); - } -} - -// Removes highlight and resumes edit mode state -void TextInput::RemoveHighlight( bool hidePopup ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "RemoveHighlight\n"); - - if ( mHighlightMeshActor ) - { - if ( mSelectionHandleOne ) - { - mActiveLayer.Remove( mSelectionHandleOne ); - mSelectionHandleOne.Reset(); - mSelectionHandleOneOffset.x = 0.0f; - } - if ( mSelectionHandleTwo ) - { - mActiveLayer.Remove( mSelectionHandleTwo ); - mSelectionHandleTwo.Reset(); - mSelectionHandleTwoOffset.x = 0.0f; - } - - mNewHighlightInfo.mQuadList.clear(); - - Self().Remove( mHighlightMeshActor ); - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - mHighlightMeshActor.Reset(); - // NOTE: We cannot dereference mHighlightMesh, due - // to a bug in how the scene-graph MeshRenderer uses the Mesh data incorrectly. - - if ( hidePopup ) - { - HidePopup(); - } - } - - mSelectionHandleOnePosition = 0; - mSelectionHandleTwoPosition = 0; -} - -void TextInput::CreateHighlight() -{ - if ( !mHighlightMeshActor ) - { - mMeshData = MeshData( ); - mMeshData.SetHasNormals( true ); - - mCustomMaterial = Material::New("CustomMaterial"); - mCustomMaterial.SetDiffuseColor( mMaterialColor ); - - mMeshData.SetMaterial( mCustomMaterial ); - - mHighlightMesh = Mesh::New( mMeshData ); - - mHighlightMeshActor = MeshActor::New( mHighlightMesh ); - mHighlightMeshActor.SetName( "HighlightMeshActor" ); - mHighlightMeshActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mHighlightMeshActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - mHighlightMeshActor.SetPosition( 0.0f, 0.0f, DISPLAYED_HIGHLIGHT_Z_OFFSET ); - - Self().Add(mHighlightMeshActor); - } -} - - -bool TextInput::CopySelectedTextToClipboard() -{ - mCurrentCopySelecton.clear(); - - mCurrentCopySelecton = GetSelectedText(); - - std::string stringToStore; - - /* Create a StyledTextArray from the selected region so can use the MarkUpProcessor to produce - * a marked up string. - */ - MarkupProcessor::StyledTextArray selectedText(mCurrentCopySelecton.begin(),mCurrentCopySelecton.end()); - MarkupProcessor::GetPlainString( selectedText, stringToStore ); - - bool success = mClipboard.SetItem( stringToStore ); - return success; -} - -void TextInput::PasteText( const Text& text ) -{ - // Update Flag, indicates whether to update the text-input contents or not. - // Any key stroke that results in a visual change of the text-input should - // set this flag to true. - bool update = false; - if( mHighlightMeshActor ) - { - /* if highlighted, delete entire text, and position cursor at start of deleted text. */ - mCursorPosition = std::min(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - DeleteHighlightedText( true ); - update = true; - } - - bool textExceedsMaximunNumberOfCharacters = false; - bool textExceedsBoundary = false; - - std::size_t insertedStringLength = DoInsertAt( text, mCursorPosition, 0, textExceedsMaximunNumberOfCharacters, textExceedsBoundary ); - - mCursorPosition += insertedStringLength; - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - - update = update || ( insertedStringLength > 0 ); - if( update ) - { - CursorUpdate(); - EmitTextModified(); - } - - if( insertedStringLength < text.GetLength() ) - { - EmitMaxInputCharactersReachedSignal(); - } - - if( textExceedsBoundary ) - { - EmitInputTextExceedsBoundariesSignal(); - } -} - -void TextInput::SetTextDirection() -{ - // Put the cursor to the right if we are empty and an RTL language is being used. - if ( mStyledText.empty() ) - { - VirtualKeyboard::TextDirection direction( VirtualKeyboard::GetTextDirection() ); - - // Get the current text alignment preserving the vertical alignment. Also preserve the horizontal center - // alignment as we do not want to set the text direction if we've been asked to be in the center. - // - // TODO: Should split SetTextAlignment into two APIs to better handle this (sometimes apps just want to - // set vertical alignment but are being forced to set the horizontal alignment as well with the - // current API. - int alignment( mDisplayedTextView.GetTextAlignment() & - ( Toolkit::Alignment::VerticalTop | - Toolkit::Alignment::VerticalCenter | - Toolkit::Alignment::VerticalBottom | - Toolkit::Alignment::HorizontalCenter ) ); - Toolkit::TextView::LineJustification justification( mDisplayedTextView.GetLineJustification() ); - - // If our alignment is in the center, then do not change. - if ( !( alignment & Toolkit::Alignment::HorizontalCenter ) ) - { - alignment |= ( direction == VirtualKeyboard::LeftToRight ) ? Toolkit::Alignment::HorizontalLeft : Toolkit::Alignment::HorizontalRight; - } - - // If our justification is in the center, then do not change. - if ( justification != Toolkit::TextView::Center ) - { - justification = ( direction == VirtualKeyboard::LeftToRight ) ? Toolkit::TextView::Left : Toolkit::TextView::Right; - } - - mDisplayedTextView.SetTextAlignment( static_cast(alignment) ); - mDisplayedTextView.SetLineJustification( justification ); - } -} - -void TextInput::UpdateLineHeight() -{ - Dali::Font font = Dali::Font::New( FontParameters( mInputStyle.GetFontName(), mInputStyle.GetFontStyle(), mInputStyle.GetFontPointSize() ) ); - mLineHeight = font.GetLineHeight(); - - // If the height exceed policy is shrink or exceed the boundaries of the text-input is not allowed, then modify the line height is needed. - - const bool shrink = mDisplayedTextView && ( Toolkit::TextView::ShrinkToFit == mDisplayedTextView.GetHeightExceedPolicy() ) && mStyledText.empty(); - - if( !mExceedEnabled || shrink ) - { - mLineHeight = std::min( mLineHeight, GetControlSize().height ); - } -} - -std::size_t TextInput::FindVisibleCharacter( FindVisibleCharacterDirection direction , std::size_t cursorPosition ) const -{ - // VCC check if we need do this in the visual order ... - std::size_t position = 0u; - - const std::size_t tableSize = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); - - switch( direction ) - { - case Left: - { - position = FindVisibleCharacterLeft( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + ( tableSize == position ? position - 1u : position ) ) ).mIsVisible ) - { - position = FindVisibleCharacterRight( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - } - break; - } - case Right: - { - position = FindVisibleCharacterRight( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + ( tableSize == position ? position - 1u : position ) ) ).mIsVisible ) - { - position = FindVisibleCharacterLeft( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - } - break; - } - case ByEnd: - { - position = FindVisibleCharacterLeft( 0u, mTextLayoutInfo.mCharacterLayoutInfoTable ); - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextInput::FindVisibleCharacter() Unknown direction." ); - } - } - - return position; -} - -void TextInput::SetSortModifier( float depthOffset ) -{ - if(mDisplayedTextView) - { - mDisplayedTextView.SetSortModifier(depthOffset); - } -} - -void TextInput::SetSnapshotModeEnabled( bool enable ) -{ - if(mDisplayedTextView) - { - mDisplayedTextView.SetSnapshotModeEnabled( enable ); - } -} - -bool TextInput::IsSnapshotModeEnabled() const -{ - bool snapshotEnabled = false; - - if(mDisplayedTextView) - { - snapshotEnabled = mDisplayedTextView.IsSnapshotModeEnabled(); - } - - return snapshotEnabled; -} - -void TextInput::SetMarkupProcessingEnabled( bool enable ) -{ - mMarkUpEnabled = enable; -} - -bool TextInput::IsMarkupProcessingEnabled() const -{ - return mMarkUpEnabled; -} - -void TextInput::SetScrollEnabled( bool enable ) -{ - if( mDisplayedTextView ) - { - mDisplayedTextView.SetScrollEnabled( enable ); - } - - if( !enable ) - { - // Don't set cursor's and handle's visibility to false if they are outside the - // boundaries of the text-input. - mIsCursorInScrollArea = true; - mIsGrabHandleInScrollArea = true; - if( mSelectionHandleOne && mSelectionHandleTwo ) - { - mSelectionHandleOne.SetVisible( true ); - mSelectionHandleTwo.SetVisible( true ); - - if( mHighlightMeshActor ) - { - mHighlightMeshActor.SetVisible( true ); - } - } - } -} - -bool TextInput::IsScrollEnabled() const -{ - bool scrollEnabled = false; - - if( mDisplayedTextView ) - { - scrollEnabled = mDisplayedTextView.IsScrollEnabled(); - } - - return scrollEnabled; -} - -void TextInput::SetScrollPosition( const Vector2& position ) -{ - if( mDisplayedTextView ) - { - mDisplayedTextView.SetScrollPosition( position ); - } -} - -Vector2 TextInput::GetScrollPosition() const -{ - Vector2 scrollPosition; - - if( mDisplayedTextView ) - { - scrollPosition = mDisplayedTextView.GetScrollPosition(); - } - - return scrollPosition; -} - -std::size_t TextInput::DoInsertAt( const Text& text, const std::size_t position, const std::size_t numberOfCharactersToReplace, bool& textExceedsMaximunNumberOfCharacters, bool& textExceedsBoundary ) -{ - // determine number of characters that we can write to style text buffer, this is the insertStringLength - std::size_t insertedStringLength = std::min( text.GetLength(), mMaxStringLength - mStyledText.size() ); - textExceedsMaximunNumberOfCharacters = insertedStringLength < text.GetLength(); - - // Add style to the new input text. - MarkupProcessor::StyledTextArray textToInsert; - for( std::size_t i = 0; i < insertedStringLength; ++i ) - { - const MarkupProcessor::StyledText newStyledCharacter( text[i], mInputStyle ); - textToInsert.push_back( newStyledCharacter ); - } - - //Insert text to the TextView. - const bool emptyTextView = mStyledText.empty(); - if( emptyTextView && mPlaceHolderSet ) - { - // There is no text set so call to TextView::SetText() is needed in order to clear the placeholder text. - mDisplayedTextView.SetText( textToInsert ); - } - else - { - if( 0 == numberOfCharactersToReplace ) - { - mDisplayedTextView.InsertTextAt( position, textToInsert ); - } - else - { - mDisplayedTextView.ReplaceTextFromTo( position, numberOfCharactersToReplace, textToInsert ); - } - } - mPlaceHolderSet = false; - - if( textToInsert.empty() ) - { - // If no text has been inserted, GetTextLayoutInfo() need to be called to check whether mStyledText has some text. - GetTextLayoutInfo(); - } - else - { - // GetTextLayoutInfo() can't be used here as mStyledText is not updated yet. - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - } - - textExceedsBoundary = false; - - if( !mExceedEnabled ) - { - const Vector3& size = GetControlSize(); - - if( ( mTextLayoutInfo.mTextSize.width > size.width ) || ( mTextLayoutInfo.mTextSize.height > size.height ) ) - { - // If new text does not fit within TextView - mDisplayedTextView.RemoveTextFrom( position, insertedStringLength ); - // previously inserted text has been removed. Call GetTextLayoutInfo() to check whether mStyledText has some text. - GetTextLayoutInfo(); - textExceedsBoundary = true; - insertedStringLength = 0; - } - - if( textExceedsBoundary ) - { - // Add the part of the text which fits on the text-input. - - // Split the text which doesn't fit in two halves. - MarkupProcessor::StyledTextArray firstHalf; - MarkupProcessor::StyledTextArray secondHalf; - SplitText( textToInsert, firstHalf, secondHalf ); - - // Clear text. This text will be filled with the text inserted. - textToInsert.clear(); - - // Where to insert the text. - std::size_t positionToInsert = position; - - bool end = text.GetLength() <= 1; - while( !end ) - { - // Insert text and check ... - const std::size_t textLength = firstHalf.size(); - mDisplayedTextView.InsertTextAt( positionToInsert, firstHalf ); - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - - if( ( mTextLayoutInfo.mTextSize.width > size.width ) || ( mTextLayoutInfo.mTextSize.height > size.height ) ) - { - // Inserted text doesn't fit. - - // Remove inserted text - mDisplayedTextView.RemoveTextFrom( positionToInsert, textLength ); - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - - // The iteration finishes when only one character doesn't fit. - end = textLength <= 1; - - if( !end ) - { - // Prepare next two halves for next iteration. - MarkupProcessor::StyledTextArray copyText = firstHalf; - SplitText( copyText, firstHalf, secondHalf ); - } - } - else - { - // Text fits. - - // store text to be inserted in mStyledText. - textToInsert.insert( textToInsert.end(), firstHalf.begin(), firstHalf.end() ); - - // Increase the inserted characters counter. - insertedStringLength += textLength; - - // Prepare next two halves for next iteration. - MarkupProcessor::StyledTextArray copyText = secondHalf; - SplitText( copyText, firstHalf, secondHalf ); - - // Update where next text has to be inserted - positionToInsert += textLength; - } - } - } - } - - if( textToInsert.empty() && emptyTextView ) - { - // No character has been added and the text-view was empty. - // Show the placeholder text. - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - MarkupProcessor::StyledTextArray::iterator it = mStyledText.begin() + position; - mStyledText.insert( it, textToInsert.begin(), textToInsert.end() ); - mPlaceHolderSet = false; - } - - return insertedStringLength; -} - -void TextInput::GetTextLayoutInfo() -{ - if( mStyledText.empty() ) - { - // The text-input has no text, clear the text-view's layout info. - mTextLayoutInfo = Toolkit::TextView::TextLayoutInfo(); - } - else - { - if( mDisplayedTextView ) - { - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - } - else - { - // There is no text-view. - mTextLayoutInfo = Toolkit::TextView::TextLayoutInfo(); - } - } -} - -void TextInput::SetOffsetFromText( const Vector4& offset ) -{ - mPopupOffsetFromText = offset; -} - -const Vector4& TextInput::GetOffsetFromText() const -{ - return mPopupOffsetFromText; -} - -void TextInput::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value ) -{ - Toolkit::TextInput textInput = Toolkit::TextInput::DownCast( Dali::BaseHandle( object ) ); - - if ( textInput ) - { - TextInput& textInputImpl( GetImpl( textInput ) ); - - switch ( propertyIndex ) - { - case Toolkit::TextInput::Property::HIGHLIGHT_COLOR: - { - textInputImpl.SetMaterialDiffuseColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_PRESSED_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupPressedColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_BORDER_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupBorderColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_ICON_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupIconColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_ICON_PRESSED_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupIconPressedColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_TEXT_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupTextColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_TEXT_PRESSED_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupTextPressedColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsCut, value.Get() ); - break; - } - case Toolkit::TextInput::Property::COPY_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsCopy, value.Get() ); - break; - } - case Toolkit::TextInput::Property::PASTE_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsPaste, value.Get() ); - break; - } - case Toolkit::TextInput::Property::SELECT_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsSelect, value.Get() ); - break; - } - case Toolkit::TextInput::Property::SELECT_ALL_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsSelectAll, value.Get() ); - break; - } - case Toolkit::TextInput::Property::CLIPBOARD_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsClipboard, value.Get() ); - break; - } - case Toolkit::TextInput::Property::POP_UP_OFFSET_FROM_TEXT: - { - textInputImpl.SetOffsetFromText( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CURSOR_COLOR: - { - textInputImpl.mCursor.SetColor( value.Get< Vector4 >() ); - break; - } - } - } -} - -Property::Value TextInput::GetProperty( BaseObject* object, Property::Index propertyIndex ) -{ - Property::Value value; - - Toolkit::TextInput textInput = Toolkit::TextInput::DownCast( Dali::BaseHandle( object ) ); - - if ( textInput ) - { - TextInput& textInputImpl( GetImpl( textInput ) ); - - switch ( propertyIndex ) - { - case Toolkit::TextInput::Property::HIGHLIGHT_COLOR: - { - value = textInputImpl.GetMaterialDiffuseColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_PRESSED_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupPressedColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_BORDER_COLOR : - { - value = textInputImpl.mPopupPanel.GetCutPastePopupBorderColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_ICON_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupIconColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_ICON_PRESSED_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupIconPressedColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_TEXT_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupTextColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_TEXT_PRESSED_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupTextPressedColor(); - break; - } - case Toolkit::TextInput::Property::CUT_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsCut ); - break; - } - case Toolkit::TextInput::Property::COPY_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsCopy ); - break; - } - case Toolkit::TextInput::Property::PASTE_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsPaste ); - break; - } - case Toolkit::TextInput::Property::SELECT_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsSelect ); - break; - } - case Toolkit::TextInput::Property::SELECT_ALL_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsSelectAll ); - break; - } - case Toolkit::TextInput::Property::CLIPBOARD_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsClipboard ); - break; - } - case Toolkit::TextInput::Property::POP_UP_OFFSET_FROM_TEXT: - { - value = textInputImpl.GetOffsetFromText(); - break; - } - case Toolkit::TextInput::Property::CURSOR_COLOR: - { - value = textInputImpl.mCursor.GetCurrentColor(); - } - } - } - return value; -} - -void TextInput::EmitStyleChangedSignal() -{ - // emit signal if input style changes. - Toolkit::TextInput handle( GetOwner() ); - mStyleChangedSignal.Emit( handle, mInputStyle ); -} - -void TextInput::EmitTextModified() -{ - // emit signal when text changes. - Toolkit::TextInput handle( GetOwner() ); - mTextModifiedSignal.Emit( handle ); -} - - -void TextInput::EmitMaxInputCharactersReachedSignal() -{ - // emit signal if max characters is reached during text input. - DALI_LOG_INFO(gLogFilter, Debug::General, "EmitMaxInputCharactersReachedSignal \n"); - - Toolkit::TextInput handle( GetOwner() ); - mMaxInputCharactersReachedSignal.Emit( handle ); -} - -void TextInput::EmitInputTextExceedsBoundariesSignal() -{ - // Emit a signal when the input text exceeds the boundaries of the text input. - - Toolkit::TextInput handle( GetOwner() ); - mInputTextExceedBoundariesSignal.Emit( handle ); -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-input/text-input-impl.h b/dali-toolkit/internal/controls/text-input/text-input-impl.h deleted file mode 100644 index 66bf9ad..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-impl.h +++ /dev/null @@ -1,1569 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class TextInput; -class TextView; - -typedef IntrusivePtr TextInputPtr; - -class TextInput : public Control -{ -public: - - /** - * Create a new TextInput - * @return instrusive ptr to a TextInput - */ - static Dali::Toolkit::TextInput New(); - - /** - * @copydoc Toolkit::TextInput::GetText - */ - std::string GetText() const; - - /** - * @copydoc Toolkit::TextInput::GetMarkupText() - */ - std::string GetMarkupText() const; - - /** - * @copydoc Toolkit::TextInput::SetPlaceholderText - */ - void SetPlaceholderText( const std::string& placeHolderText ); - - /** - * @copydoc Toolkit::TextInput::SetPlaceholderText - */ - std::string GetPlaceholderText(); - - /** - * @copydoc Toolkit::TextInput::SetInitialText - */ - void SetInitialText(const std::string& initialText); - - /** - * set the text to be displayed in text-input, will overwrite any existing text. - * can be used to clear the text-input by passing an empty string. - * @param [in] initialText text to be initially displayed - */ - void SetText(const std::string& initialText); - - /** - * @copydoc Toolkit::TextInput::SetMaxCharacterLength - */ - void SetMaxCharacterLength(std::size_t maxChars); - - /** - * @copydoc Toolkit::TextInput::SetNumberOfLinesLimit - */ - void SetNumberOfLinesLimit(std::size_t maxLines); - - /** - * @copydoc Toolkit::TextInput::GetNumberOfLinesLimit - */ - std::size_t GetNumberOfLinesLimit() const; - - /** - * @copydoc Toolkit::TextInput::GetFont - */ - Font GetFont() const; - - /** - * @copydoc Toolkit::TextInput::SetFont - */ - void SetFont(Font font); - - /** - * @copydoc Toolkit::TextInput::InputStartedSignal() - */ - Toolkit::TextInput::InputSignalType& InputStartedSignal(); - - /** - * @copydoc Toolkit::TextInput::InputFinishedSignal() - */ - Toolkit::TextInput::InputSignalType& InputFinishedSignal(); - - /** - * @copydoc Toolkit::TextInput::CutAndPasteToolBarDisplayedSignal() - */ - Toolkit::TextInput::InputSignalType& CutAndPasteToolBarDisplayedSignal(); - - /** - * @copydoc Toolkit::TextInput::StyleChangedSignal() - */ - Toolkit::TextInput::StyleChangedSignalType& StyleChangedSignal(); - - /** - * @copydoc Toolkit::TextInput::TextModifiedSignal() - */ - Toolkit::TextInput::TextModifiedSignalType& TextModifiedSignal(); - - /** - * @copydoc Toolkit::TextInput::MaxInputCharactersReachedSignal() - */ - Toolkit::TextInput::MaxInputCharactersReachedSignalType& MaxInputCharactersReachedSignal(); - - /** - * @copydoc Toolkit::TextInput::InputTextExceedBoundariesSignal() - */ - Toolkit::TextInput::InputTextExceedBoundariesSignalType& InputTextExceedBoundariesSignal(); - - /** - * Connects a callback function with the object's signals. - * @param[in] object The object providing the signal. - * @param[in] tracker Used to disconnect the signal. - * @param[in] signalName The signal to connect to. - * @param[in] functor A newly allocated FunctorDelegate. - * @return True if the signal was connected. - * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor. - */ - static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ); - - /** - * @see Toolkit::TextInput::SetEditMode(bool editMode) - * @see Toolkit::TextInput::SetEditMode(bool editMode, const Vector2& touchPoint) - * - * @param[in] editMode true or false to indicate editMode on or off. - * @param[in] setCursorOnTouchPoint Whether to use the touch point to set the cursor position. - * @param[in] touchPoint A position in actor coordinates within the text-input. - */ - void SetEditable(bool editMode, bool setCursorOnTouchPoint, const Vector2& touchPoint = Vector2::ZERO); - - /** - * @copydoc Toolkit::TextInput::GetEditMode - */ - bool IsEditable() const; - - /** - * @copydoc Toolkit::TextInput::SetTextSelectable - */ - void SetTextSelectable(bool textSelectable = true); - - /** - * @copydoc Toolkit::TextInput::IsTextSelectable - */ - bool IsTextSelectable() const; - - /** - * @copydoc Toolkit::TextInput::IsTextSelected - */ - bool IsTextSelected() const; - - /** - * @copydoc Toolkit::TextInput::DeSelectText - */ - void DeSelectText(); - - /** - * @copydoc Toolkit::TextInput::SetEditOnTouch - */ - void SetEditOnTouch(bool editOnTouch); - - /** - * @copydoc Toolkit::TextInput::IsEditOnTouch - */ - bool IsEditOnTouch() const; - - /** - * @copydoc Toolkit::TextInput::SetGrabHandleImage - */ - void SetGrabHandleImage(Dali::Image image); - - /** - * @copydoc Toolkit::TextInput::SetCursorImage - */ - void SetCursorImage(Dali::Image image, const Vector4& border ); - - /** - * @copydoc Toolkit::TextInput::GetSelectionHandleSize - */ - Vector3 GetSelectionHandleSize(); - - /** - * @copydoc Toolkit::TextInput::SetRTLCursorImage - */ - void SetRTLCursorImage(Dali::Image image, const Vector4& border ); - - /** - * @copydoc Toolkit::TextInput::EnableGrabHandle - */ - void EnableGrabHandle(bool toggle); - - /** - * @copydoc Toolkit::TextInput::IsGrabHandleEnabled - */ - bool IsGrabHandleEnabled(); - - /** - * @copydoc Toolkit::TextInput::EnableSelectionHandleFlip - */ - void EnableSelectionHandleFlip( bool toggle ); - - /** - * @copydoc Toolkit::TextInput::IsSelectionHandleFlipEnabled - */ - bool IsSelectionHandleFlipEnabled(); - - /** - * @copydoc Toolkit::TextInput::SetSelectionHandleFlipMargin - */ - void SetSelectionHandleFlipMargin( const Vector4& margin ); - - /** - * @copydoc Toolkit::TextInput::SetBoundingRectangle - */ - void SetBoundingRectangle( const Rect& boundingRectangle ); - - /** - * @copydoc Toolkit::TextInput::GetBoundingRectangle - */ - const Rect GetBoundingRectangle() const; - - /** - * @copydoc Toolkit::TextInput::GetSelectionHandleFlipMargin - */ - const Vector4& GetSelectionHandleFlipMargin(); - - /** - * @copydoc Toolkit::TextInput::SetTextColor - */ - void SetTextColor( const Vector4& color ); - - /** - * @copydoc Toolkit::TextInput::SetActiveStyle - */ - void SetActiveStyle( const TextStyle& style, const TextStyle::Mask mask ); - - /** - * @copydoc Toolkit::TextInput::ApplyStyle - */ - void ApplyStyle( const TextStyle& style, const TextStyle::Mask mask ); - - /** - * @copydoc Toolkit::TextInput::ApplyStyleToAll - */ - void ApplyStyleToAll( const TextStyle& style, const TextStyle::Mask mask ); - - /** - * @copydoc Toolkit::TextInput::GetStyleAtCursor - */ - TextStyle GetStyleAtCursor() const; - - /** - * Retrieves the character style for the given position. - * @param[in] position The character position which style is required. - * @return The style for the given position. - */ - TextStyle GetStyleAt( std::size_t position ) const; - - /** - * @copydoc Toolkit::TextInput::SetTextAlignment() - */ - void SetTextAlignment( Toolkit::Alignment::Type align ); - - /** - * @copydoc Toolkit::TextInput::SetTextLineJustification() - */ - void SetTextLineJustification( Toolkit::TextView::LineJustification justification ); - - /** - * @copydoc Toolkit::TextInput::SetFadeBoundary() - */ - void SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ); - - /** - * @copydoc Toolkit::TextInput::GetFadeBoundary() - */ - const Toolkit::TextView::FadeBoundary& GetFadeBoundary() const; - - /** - * @copydoc Toolkit::TextInput::GetTextAlignment() - */ - Toolkit::Alignment::Type GetTextAlignment() const; - - /** - * @copydoc Toolkit::TextInput::SetMultilinePolicy() - */ - void SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ); - - /** - * @copydoc Toolkit::TextInput::GetMultilinePolicy() - */ - Toolkit::TextView::MultilinePolicy GetMultilinePolicy() const; - - /** - * @copydoc Toolkit::TextInput::SetWidthExceedPolicy() - */ - void SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @copydoc Toolkit::TextInput::GetWidthExceedPolicy() - */ - Toolkit::TextView::ExceedPolicy GetWidthExceedPolicy() const; - - /** - * @copydoc Toolkit::TextInput::SetHeightExceedPolicy() - */ - void SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @copydoc Toolkit::TextInput::GetHeightExceedPolicy() - */ - Toolkit::TextView::ExceedPolicy GetHeightExceedPolicy() const; - - /** - * @copydoc Toolkit::TextInput::SetExceedEnabled() - */ - void SetExceedEnabled( bool enable ); - - /** - * @copydoc Toolkit::TextInput::GetExceedEnabled() - */ - bool GetExceedEnabled() const; - - /** - * @copydoc Toolkit::TextInput::SetBackground - */ - void SetBackground(Dali::Image image ); - - /** - * @copydoc Toolkit::TextInput::SetNumberOfLines - */ - void SetNumberOfLines(std::size_t lines); - - /** - * @copydoc Toolkit::TextInput::GetNumberOfLines - */ - std::size_t GetNumberOfLines(); - - /** - * @copydoc Toolkit::TextInput::GetNumberOfCharacters - */ - std::size_t GetNumberOfCharacters() const; - - /** - * Styling - */ - - /** - * Set the diffuse color for the highlight - * @param[in] color color to use - */ - void SetMaterialDiffuseColor( const Vector4& color ); - - /** - * Get the diffuse color used by the highlight - * @return color - */ - const Vector4& GetMaterialDiffuseColor() const; - -private: - - /** - * structure to hold each highlight box needed for text selection - */ - struct HighlightBox - { - Vector3 size; ///< size of the highlight box - Vector3 position; ///< position of highlight box - ImageActor highlightBoxActor; ///< as actor that is the highlight box - }; - - /** - * structure to hold each character in displayed string and its position from the left - */ - struct CharPositions - { - char character; ///< todo change to UTF to aid multi-language support - Vector3 position; - Vector2 size; - }; - - /** - * structure to hold coordinates of each quad, which will make up the mesh. - */ - struct QuadCoordinates - { - /** - * Default constructor - */ - QuadCoordinates() - { - } - - /** - * Constructor - * @param[in] x1 left co-ordinate - * @param[in] y1 top co-ordinate - * @param[in] x2 right co-ordinate - * @param[in] y2 bottom co-ordinate - */ - QuadCoordinates(float x1, float y1, float x2, float y2) - : min(x1, y1), - max(x2, y2) - { - } - - Vector2 min; ///< top-left (minimum) position of quad - Vector2 max; ///< bottom-right (maximum) position of quad - }; - - typedef std::vector QuadContainer; - - /** - * structure for information required to build the highlight mesh - */ - struct HighlightInfo - { - /** - * Adds a Quad (2D rectangular sub-selection) - * @param[in] x1 left co-ordinate - * @param[in] y1 top co-ordinate - * @param[in] x2 right co-ordinate - * @param[in] y2 bottom co-ordinate - */ - void AddQuad( float x1, float y1, float x2, float y2 ); - - /** - * Clamps all quads to fit within a min -> max 2D boundary. - */ - void Clamp2D(const Vector2& min, const Vector2& max); - - QuadContainer mQuadList; ///< List of quads (sub-selections that form to create complete selection) - }; - - /** - * Holds requested selection start and end points for highlighted text. - */ - struct SelectionParameters - { - SelectionParameters( size_t start, size_t end ) - : mStartOfSelection( start ), mEndOfSelection( end ) - { - - } - - size_t mStartOfSelection; - size_t mEndOfSelection; - }; - - enum State - { - StateEdit, - StateDraggingHandle - }; - - enum SelectionHandleId - { - HandleOne, ///< Selection handle one which is on the left - HandleTwo ///< Selection handle two which is on the right - }; - - /** - * Two different behaviours are needed to convert a touch point into a character index. - * When a tap is received and the touch point doesn't hit any character, the final character selected might - * be different than the one selected if the event is a pan. - * i.e. If a tap is received and the touch point doesn't hit any character the expected position of the cursor - * would be the end or the beginning of a line. However, this behaviour would be weird while panning. - */ - enum TouchToIndex - { - TapMode, ///< Touch point to character index conversion mode used for Tap events. - DragMode ///< Touch point to character index conversion mode used for Pan events. - }; - - /** - * Used to set the direction when find the next visible character. - */ - enum FindVisibleCharacterDirection - { - Left, ///< Find visible characters on the left. - Right, ///< Find visible characters on the right. - ByEnd ///< Start finding visible characters by the end. - }; - - /** - * - */ - virtual bool OnTouchEvent(const TouchEvent& event); - - /** - * From CustomActorImpl; called after the Text Input actor is touched - * @param[in] event The KeyEvent event. - * @return True if the event should be consumed. - */ - virtual bool OnKeyEvent(const KeyEvent& event); - - /** - * From CustomActorImpl; called when this actor gains keyboard focus. - */ - virtual void OnKeyInputFocusGained(); - - /** - * From CustomActorImpl; called when this actor loses keyboard focus. - */ - virtual void OnKeyInputFocusLost(); - - /** - * From Control; called whenever the control is added to the stage. - */ - virtual void OnControlStageConnection(); - -private: // From Control - - /** - * Creation of the layer that is used by top level active parts of the TextInput like handles - */ - void CreateActiveLayer(); - - /** - * @copydoc Control::OnInitialize() - */ - virtual void OnInitialize(); - - /** - * @copydoc Control::OnControlSizeSet() - */ - virtual void OnControlSizeSet(const Vector3& targetSize); - - /** - * @copydoc Control::OnRelayout() - */ - virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); - - /** - * Retrieves the text-input's natural size by calling TextView::GetNaturalSize(). - * - * @return The natural size. - */ - virtual Vector3 GetNaturalSize(); - - /** - * Retrieves the text-input's \e height for a given \e width by calling TextView::GetHeightForWidth(). - * - * @param[in] width The given \e width. - * - * @return The \e height for the given \e width. - */ - virtual float GetHeightForWidth( float width ); - -protected: - - /** - * Construct a new TextInput. - */ - TextInput(); - - /** - * A reference counted object may only be deleted by calling Unreference() - */ - virtual ~TextInput(); - -private: - - // Undefined - TextInput(const TextInput&); - - // Undefined - TextInput& operator=(const TextInput& rhs); - - /** - * Callback when a handle is panned/moved, either selection handles or grab handle - * @param actor Handle of the selection or grab handle. - * @param gesture Data structure with the parameters of the gesture. - */ - void OnHandlePan(Actor actor, const PanGesture& gesture); - - /** - * Callback for touch down on Grab handle - * @param[in] actor touched - * @param[in] touch touch event - */ - bool OnPressDown(Dali::Actor actor, const TouchEvent& touch); - - /** - * Callback for touch down on Selection handle one - * @param[in] actor touched - * @param[in] touch touch event, used to determine if down or up event - */ - bool OnHandleOneTouched(Dali::Actor actor, const TouchEvent& touch); - - /** - * Callback for touch down on Selection handle two - * @param[in] actor touched - * @param[in] touch touch event, used to determine if down or up event - */ - bool OnHandleTwoTouched(Dali::Actor actor, const TouchEvent& touch); - - /** - * Callback for tap on TextInput - * @param[in] actor - * @param[in] tap touch event - */ - void OnTextTap(Dali::Actor actor, const Dali::TapGesture& tap); - - /** - * Callback for double tap on TextInput - * @param[in] actor - * @param[in] tap touch event - */ - void OnDoubleTap(Dali::Actor actor, const Dali::TapGesture& tap); - - /** - * Callback for long press on TextInput - * @param[in] actor - * @param[in] longPress long press event - */ - void OnLongPress(Dali::Actor actor, const Dali::LongPressGesture& longPress); - - /** - * Callback for the ClipboardEventNotifier when text is selected in the clipboard window. - * @param[in] notifier The Clipboard Event Notifier. - */ - void OnClipboardTextSelected( ClipboardEventNotifier& notifier ); - - /** - * Callback for when a button is pressed in popup panel - * @param[in] button handle to the button pressed. - */ - bool OnPopupButtonPressed( Toolkit::Button button ); - - /** - * Callback when handle timer ticks. - * - * Cursor should become visible/invisible to simulate blinking. - * - * @return True if the timer should be keep running. - */ - bool OnCursorBlinkTimerTick(); - - /** - * Invoked upon popup Hide animation completing. - * @note Only called for animating hide, not called for instantaneous (animate = false) - * @param[in] popup The popup which was hidden. - */ - void OnPopupHideFinished(TextInputPopup& popup); - - /** - * Called in OnKeyEvent to handle key down events. - * @param[in] event The KeyEvent event. - * @return True if the event should be consumed. - */ - bool OnKeyDownEvent(const KeyEvent& event); - - /** - * Called in OnKeyEvent to handle key up events. - * @param[in] event The KeyEvent event. - * @return True if the event should be consumed. - */ - bool OnKeyUpEvent(const KeyEvent& event); - - /** - * Chooses from all handle position and alternative handle positions where to set the position of the two selection handles. - * - * @param[in] cursorPositionOne The initial position of the first selection handle. - * @param[in] cursorPositionTwo The initial position of the second selection handle. - * @param[in] altPositionValidOne Whether there is an alternative position for the first selection handle. - * @param[in] altPositionValidTwo Whether there is an alternative position for the second selection handle. - * @param[in] altPositionOne The alternative position of the first selection handle. - * @param[in] altPositionTwo The alternative position of the second selection handle. - */ - void ChooseRtlSelectionHandlePosition( const Vector3& cursorPositionOne, - const Vector3& cursorPositionTwo, - bool altPositionValidOne, - bool altPositionValidTwo, - const Vector3& altPositionOne, - const Vector3& altPositionTwo ); - /** - * Callback called when the text-view is scrolled. - * - * Updates the selection and grab handles, and the highlighted text. - * - * @param[in] textView Handle of the text-view. - * @param[in] scrollPosition The difference with the previous scroll position. - */ - void OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ); - - /** - * Scrolls the text-view to make the cursor visible. - * - * @param[in] cursorPosition The actual cursor position in actor coordinates. - */ - void ScrollTextViewToMakeCursorVisible( const Vector3& cursorPosition ); - - /** - * Creates and starts a timer to scroll the text when handles are close to the edges of the text-input. - * - * It only starts the timer if it's already created. - */ - void StartScrollTimer(); - - /** - * Stops the timer used to scroll the text. - */ - void StopScrollTimer(); - - /** - * Callback called by the timer used to scroll the text. - * - * It calculates and sets a new scroll position. - */ - bool OnScrollTimerTick(); - -public: // Public to allow internal testing. - - /** - * Register for touch events - */ - void SetUpTouchEvents(); - - /** - * Sets up TextView Actor - */ - void CreateTextViewActor(); - - /** - * Set Styled Text for text input. - * @param[in] styleText The new styled text for the text input. - */ - void SetText( const MarkupProcessor::StyledTextArray& styleText ); - - /** - * Start a timer to signal cursor to blink. - */ - void StartCursorBlinkTimer(); - - /** - * Stop the timer signalling the cursor to blink. - */ - void StopCursorBlinkTimer(); - - /** - * Starts input, setting focus and showing keyboard.. - */ - void StartEditMode(); - - /** - * Called when End of input and focus no longer required, keyboard is hidden. - */ - void EndEditMode(); - - /** - * Applies a style to the current pre-edit / predicted word to show it is being edited. - * @param[in] preEditStartPosition position in text array that the predicted word starts at - * @param[in] preEditStringLength used to calculate how many characters need their style changed. - */ - void ApplyPreEditStyle( std::size_t preEditStartPosition, std::size_t preEditStringLength ); - - /** - * Restores style to value before applying Pre-Edit style. - */ - void RemovePreEditStyle(); - - /** - * Event received from IMF manager - * @return ImfCallbackData data struture undicating if update is needed, cursor position and current text - */ - ImfManager::ImfCallbackData ImfEventReceived( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& test ); - - /** - * Called when the OnKey event is a Pre-edit string - * @param[in] keyString String received in Pre-edit - * @param[in] cursorOffset the cursor offset from where the pre-edit word starts - * @return bool true if preedit reset is required. - */ - bool PreEditReceived( const std::string& keyString, std::size_t cursorOffset ); - - /** - * Called when the OnKey event is a Commit string - * @param[in] keyString String received in Comment - * @return update flag to trigger cursor update of TextInput only when needed. - */ - bool CommitReceived( const std::string& keyString ); - - /** - * Deletes Pre-edit string - * By default it doesn't update the character's size and position table, which is a costly - * operation. As in many cases deletion and insertion (InsertAt) of text - * occurs in the same action i.e. preedit/commit. It makes sense to - * delete without updating, and then insert with updating. - * - * @return The number of characters to be deleted. - */ - std::size_t DeletePreEdit(); - - /** - * Reset all pre-edit flag and signal IMF keyboard that the current pre-edit word has been comitted. - * This may be due to the cursor being moved by user or reached the max character limit. - * @param[in] preserveCursorPosition Set true to keep cursor in current position, eg. touch event caused cursor to move. - */ - void PreEditReset( bool preserveCursorPosition ); - - /** - * Called after cursor position needs updating. - * Redraws cursor and notifies VirtualKeyboard - */ - void CursorUpdate(); - - /** - * Delete highlighted characters - * @param[in] inheritStyle Whether style from previous character in the string should be inherited. - */ - void DeleteHighlightedText( bool inheritStyle ); - - /* - * Delete range of characters - * @param[in] start position of characters to delete - * @param[in] ncharacters number of characters to delete - */ - void DeleteRange(std::size_t start, std::size_t ncharacters); - - /** - * Delete character at current cursor position and redisplay - * @param[in] positionToDelete position of character to delete - */ - void DeleteCharacter( std::size_t positionToDelete ); - - /** - * Add or replaces characters to currently displayed string at cursor position - * By default it doesn't update the character's size and position table, which is a costly - * operation. As in many cases deletion and insertion (InsertAt) of text - * occurs in the same action i.e. preedit/commit. It makes sense to - * delete without updating, and then insert with updating. - * @param[in] newText string to add to TextInput display string. - * @param[in] insertionPosition position to insert at. - * @param[in] numberOfCharactersToReplace The number of characters to replace. - * @return number of characters to offset the cursor by. - */ - std::size_t InsertAt( const Text& newText, const std::size_t insertionPosition, const std::size_t numberOfCharactersToReplace ); - - /** - * Creates a cursor. - * @param[in] color the cursor color. - * @return the image actor to be used as the cursor. - */ - ImageActor CreateCursor( const Vector4 &color ); - - /** - * Moves cursor to the right - * param[in] reverse if true then cursor moves in the reverse direction (to the left) - * param[in] places number of character cursor should move. - */ - void AdvanceCursor(bool reverse = false, std::size_t places = 1); - - /** - * Draw a cursor / caret at position where new text should appear - */ - void DrawCursor(); - - /** - * Sets cursor visibility - * This sets visibility of the cursor. Which is comprised of 2 - * cursors. The conventional cursor, and the alternate (RTL) cursor, - * which only appears when the cursor is at a character that can have - * a character appended to different visual positions depending on whether that - * character to be appended is RTL or LTR. - * @param[in] visible true - enable visibility for cursor, false - disable visiblity for cursor - */ - void SetCursorVisibility( bool visible ); - - /** - * Sets alternate cursor enable state - * @see SetCursorVisibility - * alternate cursor will only be visible if both SetCursorVisiblity - * and cursor enabled have been set to true. - */ - void SetAltCursorEnabled( bool enabled ); - - /** - * Create the grab handle that positions the cursor - * @param[in] image to be used for grab handle - * - */ - void CreateGrabHandle(Image image=Image()); - - /** - * Create Grab area to be used by Grab Handle - */ - void CreateGrabArea( Actor& parent); - - /** - * Move grab handle to the required character position - * - * @param[in] displacement Displacement of the grab handle in actor coordinates. - * - * @return The new actual position the handle has been set to. - */ - Vector3 MoveGrabHandle( const Vector2& displacement ); - - /** - * Show or hide the grab handle without baking the visibility flag. - * Used when the Grab handle needs to be invisible due to text-view scrolling making it out of view - * - * @param[in] visible bool flag to set as true is grab handle should be shown, else false to hide. - */ - void ShowGrabHandle( bool visible ); - - /** - * Show or hide the grab handle and bake the visibility flag. - * Used when the state of text-input changes to a state which the grabhandle is not required. E.g. Selection mode starts or edit mode ends. - * Calls ShowGrabHandle. - * - * @param[in] visible bool flag to set as true is grab handle should be shown, else false to hide. - */ - void ShowGrabHandleAndSetVisibility( bool visible ); - - /* Boundary Property Notifications when handle exceed bounding box*/ - - /** - * PropertyNotification Callback when left boundary exceeded so handle can be flipped. - * @param[in] source PropertyNotification - */ - void OnLeftBoundaryExceeded( PropertyNotification& source ); - /** - * PropertyNotification Callback when within left boundary so handle can be flipped back. - * @param[in] source PropertyNotification - */ - void OnReturnToLeftBoundary( PropertyNotification& source ); - /** - * PropertyNotification Callback when right boundary exceeded so handle can be flipped. - * @param[in] source PropertyNotification - */ - void OnRightBoundaryExceeded( PropertyNotification& source ); - /** - * * PropertyNotification Callback when within right boundary so handle can be flipped back. - * @param[in] source PropertyNotification - */ - void OnReturnToRightBoundary( PropertyNotification& source ); - - /** - * PropertyNotification Callbacks for hiding handle one when it exceeds boundary. - * @param[in] source PropertyNotification - */ - void OnHandleOneLeavesBoundary( PropertyNotification& source ); - /** - * PropertyNotification Callbacks for showing hidden handle one when returns within boundary - * @param[in] source PropertyNotification - */ - void OnHandleOneWithinBoundary( PropertyNotification& source ); - /** - * PropertyNotification Callbacks for hiding handle two it when exceeds boundary. - * @param[in] source PropertyNotification - */ - void OnHandleTwoLeavesBoundary( PropertyNotification& source ); - /** - * PropertyNotification Callbacks for showing hidden handle two when returns within boundary - * * @param[in] source PropertyNotification - */ - void OnHandleTwoWithinBoundary( PropertyNotification& source ); - - /** - * Set up property notifications on the position of the handles to facilitate flipping and hiding when at screen boundary. - */ - void SetUpHandlePropertyNotifications(); - - /** - * Create the selection handles that bound text to be selected for copy/cut. - * @param[in] start initial position of start selection handle. - * @param[in] end initial position of end selection handle. - * @param[in] handleOneImage (optional) to be used for selection handle - * @param[in] handleTwoImage (optional) to be used for selection handle - */ - void CreateSelectionHandles( std::size_t start = 0, std::size_t end = std::numeric_limits::max(), Dali::Image handleOneImage = Dali::Image(), Dali::Image handleTwoImage = Dali::Image() ); - - /** - * Move the selection handles to required positions in text. - * - * @param[in] handleId the handle to position - * @param[in] displacement Displacement of the selection handle in actor coordinates. - * - * @return The new actual position the handle has been set to. - */ - Vector3 MoveSelectionHandle(SelectionHandleId handleId, const Vector2& displacement); - - /** - * Calculate and position the specified selection handle the given index position - * - * @param[in] handleId the handle to position - */ - void SetSelectionHandlePosition(SelectionHandleId handleId); - - /** - * Gets a table of the visual text positions which has a flag - * for each Character. The flag is either true (character selected) - * or false (character deselected) - * @note startSelection can be greater or less than endSelection - * - * @param[in,out] selectedVisualText The vector to be resized and populated with the selected flags - * @param[in] startSelection The start selection point for the text - * @param[in] endSelection The end selection point for the text - */ - void GetVisualTextSelection(std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection); - - /** - * Iterates between selection handles and computes the info required to build the highlight mesh - */ - HighlightInfo CalculateHighlightInfo(); - - /** - * This method was added to fix a PLM. it creates one quad per character so the mesh can show different selection boxes when a mix of right to left and left to right text is selected. - */ - HighlightInfo CalculateHighlightInfoRtl(); - - /** - * Calculates new Mesh data so highlight moves with selection handles. - */ - void UpdateHighlight(); - - /** - * Removes popup, and its options. - */ - void ClearPopup(); - - /** - * Adds Popup options which have been enabled. - */ - void AddPopupOptions(); - - /** - * Sets popup position - * @param[in] position The actual position for this popup. - * @param[in] alternativePosition Alternative popup position if no space in upper area. - */ - void SetPopupPosition(const Vector3& position, const Vector2& alternativePosition ); - - /** - * Hides the popup - * @param[in] animate (optional) whether to animate popup to hide state over time (i.e. tween). - * @param[in] signalFinished (optional) whether to perform an animation finish operation after the hide animation completes. Requires animate to be true. - */ - void HidePopup( bool animate = true, bool signalFinished = true ); - - /** - * Shows the popup - * @param[in] animate (optional) whether to animate popup to show state over time (i.e. tween). - */ - void ShowPopup(bool animate = true); - - /** - * Shows the cut-copy-paste popup - */ - void ShowPopupCutCopyPaste(); - - /** - * Setup the selection popup and clipboard if relevant so the correct options are shown when ShowPopup is called. - * @param[in] showCutButton Flag to show or hide cut button, in some cases like whitespace we do not want to cut just select. - * default is true. - */ - void SetUpPopupSelection( bool showCutButton = true ); - - /** - * Return the logical index containing the character position closest to the source. - * Used for positioning the grab handle at characters when dragged along. - * Two different behaviours are needed in case the source point doesn't actually touch a - * character. @see TouchToIndex. - * @param[in] source float to match against - * @param[out] closestIndex index to the vector of character's size and position. - * @return \e true if the source point is actually inside the geometry provided by TextView. - */ - bool ReturnClosestIndex(const Vector2& source, std::size_t& closestIndex ); - - /** - * Returns the X-position of the current line justification - * (relative to left of text-view container) - * @return X position for line justification - */ - float GetLineJustificationPosition() const; - - /** - * Currently the cursor is positioned at the previous characters position plus it's width. - * If the previous character is on a different line then this function returns the correct position. - * @param[in] characterPosition the character position index that the cursor should be at - * @return position of cursor/handle - */ - Vector3 PositionCursorAfterWordWrap( std::size_t characterPosition ) const; - - - /** - * Return a vector which is the actual position for the given character position - * The character position is where a cursor would be position for that character. - * @param[in] characterPosition the logical (input) position in the 'string' of characters. - * - * @return Vector3 the actual x,y,z position - */ - Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition ) const; - - /** - * Return a vector which is the actual position for the given character position - * The character position is where a cursor would be positioned for that character to be inserted. - * An additional alternatePosition is also set in circumstances where the possible writing - * of characters would be in the opposite direction. - * e.g. "HelloشقشلاهؤEnglish" - * | | - * * + - * [*] - Primary actual position for cursor i.e. continuing writing LTR (English) - * [+] - Alternate actual position for cursor i.e. writing RTL (Arabic) - * - * @param[in] characterPosition the logical (input) position in the 'string' of characters. - * @param[out] directionRTL Whether the actual x,y,z position is after LTR (false) or RTL (true) text. - * @param[out] alternatePosition the actual x,y,z position of the cursor if user types - * in alternate direction to current flow of text. - * @param[out] alternatePositionValid whether this alternate position is valid. - * @return Vector3 the actual x,y,z position - */ - Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const; - - /** - * Retrieve the character position of the first character on the row of text - * that this character resides on. - * @param[in] logicalPosition the position in the 'string' of characters. - * @return logical character position of start of row. - */ - std::size_t GetRowStartFromCharacterPosition(std::size_t logicalPosition) const; - - /** - * Retrieves the first character of a group of characters with the same direction. - * - * @param[in] logicalPosition Index to a character. - * - * @return Index to the character. - */ - std::size_t GetFirstCharacterWithSameDirection( std::size_t logicalPosition ) const; - - /** - * Retrieve the dimensions of this row of text that the character resides on. - * @param[in] characterPosition the position in the 'string' of characters. - * @return The size of the rectangle representing this row - */ - Size GetRowRectFromCharacterPosition(std::size_t characterPosition) const; - - /** - * Retrieve the dimensions (and min-max) of this row of text that the character resides on. - * @param[in] characterPosition the position in the 'string' of characters. - * @param[out] min the top-left position of the rectangle representing this row - * @param[out] max the bottom-right position of the rectangle representing this row - * @return The size of the rectangle representing this row (max - min) - */ - Size GetRowRectFromCharacterPosition(std::size_t characterPosition, Vector2& min, Vector2& max) const; - - /** - * Checks if the provided touchedActor was this text-input - * @param[in] touchedActor the touched actor that will be checked against this text-input - * @return true if the touchActor was the text-input or one of its children - */ - bool WasTouchedCheck( const Actor& touchedActor ) const; - - /** - * Connect to the stage touch event - */ - void StartMonitoringStageForTouch(); - - /** - * Disconnect from the stage touch event - */ - void EndMonitoringStageForTouch(); - - /** - * Callback for when the screen is touched, this will be connected when selection starts and disconnected when it ends. - * @param[in] event The touch event - */ - void OnStageTouched(const TouchEvent& event); - - - /** - * Select the text between the given values - * @param[in] start position within array to start selection - * @param[in] end position within array to end selection - */ - void SelectText(std::size_t start, std::size_t end); - - /** - * Gets selected text and returns it as a StyleText vector - * @return StyledText vector that is selected. - */ - MarkupProcessor::StyledTextArray GetSelectedText(); - - /** - * Applies the given style to all text, selected or not selected. - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - */ - void ApplyStyleToRange(const TextStyle& style, const TextStyle::Mask mask, const std::size_t begin, const std::size_t end); - - /** - * Callback for when the keyboard status changes - * @param[in] keyboardShown Whether the keyboard has just been shown or not. - */ - void KeyboardStatusChanged(bool keyboardShown); - - /** - * Hide highlight shown between selection handles. - * @param[in] hidePopup flag to hide the popup too, default is to hide popup. - */ - void RemoveHighlight( bool hidePopup = true ); - - /** - * Highlights text that has been selected - */ - void CreateHighlight(); - - /** - * Copies selected text to clipboard - * @return bool true if copy was successful. - */ - bool CopySelectedTextToClipboard(); - - /** - * Pastes the given text to currently displayed string at the current cursor position - * @param[in] text Text to be pasted - */ - void PasteText( const Text& text ); - - /** - * Sets the direction of the text if it is empty. - */ - void SetTextDirection(); - - /** - * Updates the line height accordingly with the current text input style. - */ - void UpdateLineHeight(); - - /** - * Finds a visible character. - * - * The \e direction parameters specifies from where to start to look for a visible character. \e Left means start by characters in lower - * positions than \e cursorPosition, \e Right means start by characters in greater positions than \e cursorPosition and \e ByEnd starts - * by the last characters. - * - * If \e Left or \e Right is provided and any character is found, then looks in the other direction. - * - * @param[in] direction Direction used to find a visible character. - * @param[in] cursorPosition Starting position. - * - * @return The found visible character. - */ - std::size_t FindVisibleCharacter( const FindVisibleCharacterDirection direction , const std::size_t cursorPosition ) const; - - /** - * @copydoc SetSortModifier() - */ - void SetSortModifier( float depthOffset ); - - /** - * @copydoc SetSnapshotModeEnabled() - */ - void SetSnapshotModeEnabled( bool enable ); - - /** - * @copydoc IsSnapshotModeEnabled() - */ - bool IsSnapshotModeEnabled() const; - - /** - * @copydoc SetScrollEnabled() - */ - void SetScrollEnabled( bool enable ); - - /** - * @copydoc IsScrollEnabled() - */ - bool IsScrollEnabled() const; - - /** - * @copydoc SetScrollPosition() - */ - void SetScrollPosition( const Vector2& position ); - - /** - * @copydoc GetScrollPosition() - */ - Vector2 GetScrollPosition() const; - - /** - * @brief Sets whether markup processing should be carried out. - * - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ); - - /** - * @brief Returns whether markup processing is enabled or not - * - * @return true is markup processing is enabled - */ - bool IsMarkupProcessingEnabled() const; - - /** - * Insert or replaces the given text in the given position. It checks if the text exceeds the maximum allowed number of characters - * and if it fits in the text-input's boundaries. - * - * @param[in] text Text to be inserted. - * @param[in] position Position where the text is inserted. - * @param[in] numberOfCharactersToReplace The number of characters to replace. - * @param[out] textExceedsMaximunNumberOfCharacters The number of characters that have been inserted. - * @param[out] textExceedsBoundary Whether the inserted text has exceeded the boundaries of the text-input. - * - * @return The number of characters that have been inserted. - */ - std::size_t DoInsertAt( const Text& text, std::size_t position, std::size_t numberOfCharactersToReplace, bool& textExceedsMaximunNumberOfCharacters, bool& textExceedsBoundary ); - - /** - * Retrieve Text-view's layout info. - */ - void GetTextLayoutInfo(); - - /** - * Set the offset for positioning Popup from the TextInput - * @param[in] offset in the order, left, top, right, bottom - */ - void SetOffsetFromText( const Vector4& offset ); - - /** - * Get the offset of the Popup from the TextInput - * @return Vector4 with the offset in the order, left, top, right, bottom - */ - const Vector4& GetOffsetFromText() const; - - /** - * Show the Placeholder text with an already created StyleTextArray - * @param[in] stylePlaceHolderText Required placeholder text to be used - */ - void ShowPlaceholderText( const MarkupProcessor::StyledTextArray& stylePlaceHolderText ); - - // Properties - - /** - * Called when a property of an object of this type is set. - * @param[in] object The object whose property is set. - * @param[in] index The property index. - * @param[in] value The new property value. - */ - static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); - - /** - * Called to retrieve a property of an object of this type. - * @param[in] object The object whose property is to be retrieved. - * @param[in] index The property index. - * @return The current value of the property. - */ - static Property::Value GetProperty( BaseObject* object, Property::Index propertyIndex ); - - /** - * Emits the style changed signal. - */ - void EmitStyleChangedSignal(); - - /** - * Emit signal when text is modified. - */ - void EmitTextModified(); - - /** - * Emits max input characters reached signal. - */ - void EmitMaxInputCharactersReachedSignal(); - - /** - * Emits a signal when the input text exceeds the boundaries of the text-input. - */ - void EmitInputTextExceedsBoundariesSignal(); - -private: - - State mState; ///< Current State of Text input. - MarkupProcessor::StyledTextArray mStyledText; ///< String currently displayed by TextView with style info. - TextStyle mInputStyle; ///< Stores the current input style. - float mLineHeight; ///< Stores the current line height accordingly with the input style. - Toolkit::TextView mDisplayedTextView; ///< Actor which actually display text - - MarkupProcessor::StyledTextArray mStyledPlaceHolderText; ///< Text used as place holder with style info. - - std::size_t mMaxStringLength; ///< Max number of characters for string - std::size_t mNumberOflinesLimit; ///< Limit on the number of lines this TextInput will display. - - ImageActor mCursor; ///< Cursor overlayed on Text to show where new text will be inserted - ImageActor mCursorRTL; ///< Right To Left Cursor overlayed on Text (where new RTL text would be inserted) - Animation mCursorAnimation; ///< animator for cursor blinking. - std::size_t mCursorPosition; ///< position along string cursor is at. - Timer mCursorBlinkTimer; ///< Timer to signal cursor to blink - - Layer mActiveLayer; ///< Layer for active handles and alike that ensures they are above all else. - - Image mGrabHandleImage; ///< image to be used for grab handle - ImageActor mGrabHandle; ///< Handle used to move cursor for editing - - Actor mGrabArea; ///< invisible actor that receives pans events for the grab handle. - PanGestureDetector mPanGestureDetector; ///< Pan gesture for handles - TapGestureDetector mTapDetector; ///< used to start editing - TapGestureDetector mDoubleTapDetector; ///< double tap detector - - Vector3 mActualGrabHandlePosition; ///< actual position of grab handle, this might not be snapped to a character - - LongPressGestureDetector mLongPressDetector; ///< Gesture to start selection - - /*Selection handles*/ - Image mSelectionHandleOneImage; ///< image used for selection handle one - Image mSelectionHandleOneImagePressed; ///< image used for selection handle one pressed state - Image mSelectionHandleTwoImage; ///< image used for selection handle two - Image mSelectionHandleTwoImagePressed; ///< image used for selection handle two pressed state - - bool mIsSelectionHandleOneFlipped:1; ///< Flag to know whether the handle one is flipped or not. - bool mIsSelectionHandleTwoFlipped:1; ///< Flag to know whether the handle two is flipped or not. - Vector3 mSelectionHandleOneOffset; ///< Handle One's Offset - Vector3 mSelectionHandleTwoOffset; ///< Handle Two's Offset - Vector3 mSelectionHandleOneActualPosition; ///< Actual x y position of handle - Vector3 mSelectionHandleTwoActualPosition; ///< Actual x y position of handle - std::size_t mSelectionHandleOnePosition; ///< Position of handle along the string of text - std::size_t mSelectionHandleTwoPosition; ///< Position of handle along the string of text - ImageActor mSelectionHandleOne; ///< First selection handle used for selecting text to cut&paste - ImageActor mSelectionHandleTwo; ///< Second selection handle used for selecting text to cut&paste - Actor mHandleOneGrabArea; ///< invisible actor that receives pans events for the selection handle. - Actor mHandleTwoGrabArea; ///< invisible actor that receives pans events for the selection handle. - - Mesh mHighlightMesh; ///< Mesh Data for highlight - MeshActor mHighlightMeshActor; ///< Mesh Actor to display highlight - MeshData mMeshData; ///< Container to hold meshData for highlight - Material mCustomMaterial; ///< Custom material used for highlight - HighlightInfo mNewHighlightInfo; ///< Geometry info to create highlight. - - Text mPreEditString; ///< Holds current input string prior to it being committed. - std::size_t mPreEditStartPosition; ///< Cursor position for start of pre-edit string - std::size_t mPreEditLength; ///< Cursor position for length of current pre-edit string after purging characters that do not fit. - std::size_t mNumberOfSurroundingCharactersDeleted; ///< Stores the number of surrounding characters deleted. - unsigned long mTouchStartTime; ///< Touch Start time (time in ms when down press began) - - Toolkit::TextView::TextLayoutInfo mTextLayoutInfo; ///< It contains a table layout info per character sorted by the character's visual index (retrieved from TextView), - ///< a reorder map that stores each character's visual (output) index according to its logical (input) index, - ///< a reorder map that stores each character's logical (input) index according to its visual (output) index, - ///< the text size after layout and the scroll offset. - - MarkupProcessor::StyledTextArray mCurrentCopySelecton; ///< Array to store copied text. - TextInputPopup mPopupPanel; ///< Panel to house cut and paste, select all buttons. - - Timer mScrollTimer; - Vector2 mScrollDisplacement; - Vector3 mCurrentHandlePosition; - SelectionHandleId mCurrentSelectionId; - Vector3 mCurrentSelectionHandlePosition; - SelectionParameters mRequestedSelection; - Vector4 mSelectionHandleFlipMargin; - Vector4 mBoundingRectangleWorldCoordinates; - - Clipboard mClipboard; ///< Handle to clipboard - - // Styling - Vector4 mMaterialColor; // Color of the highlight - Vector4 mPopupOffsetFromText; // Offset of Popup from the TextInput. - - bool mOverrideAutomaticAlignment:1; ///< Whether to override the alignment automatically set by the text content (e.g. european LTR or arabic RTL) - bool mCursorRTLEnabled:1; ///< Enable state of Alternate RTL Cursor (need to keep track of this as it's not always enabled) - bool mClosestCursorPositionEOL:1; ///< closest cursor position is end of line. - bool mCursorBlinkStatus:1; ///< \e true shows the cursor, \e false hiddes it. - - bool mCursorVisibility:1; ///< Visibility status of Cursor - bool mGrabHandleVisibility:1; ///< Visibility status of the grab handle. - - bool mIsCursorInScrollArea:1; ///< Whether the cursor is inside the boundaries of the text-input. - bool mIsGrabHandleInScrollArea:1; ///< Whether the grab handle is inside the boundaries of the text-input. - - bool mEditModeActive:1; ///< true to indicate TextInput is in edit mode. - bool mEditOnTouch:1; ///< true indicates edit mode starts by touching/tapping the TextInput - bool mTextSelection:1; ///< true indicates text selection is enabled. - bool mExceedEnabled:1; ///< Whether text-input editing text beyond its boundary is enabled or not. By default is enabled. - bool mGrabHandleEnabled:1; ///< Flag to enable the grab handle instead of the default magnifier. - bool mIsSelectionHandleFlipEnabled:1; ///< Flag to enable the selection handle flip - - bool mPreEditFlag:1; ///< Flag to indicate if key string received is still in pre-edit mode (Ecore IMF keyboard) - bool mIgnoreCommitFlag:1; ///< Flag to indicate if the commit string should be ignored, maybe due to a keyboard reset. - bool mIgnoreFirstCommitFlag:1; ///< Whether to ignore the first commit. - bool mSelectingText:1; ///< Ignore surrounding text as selecting text - - bool mPreserveCursorPosition:1; ///< Indicates that the commit message is from a reset and does not require the cursor to be moved - - bool mSelectTextOnCommit:1; - - bool mUnderlinedPriorToPreEdit:1; ///< As predictive text adds underline style this flag enables us to revert back or keep underline. - - bool mCommitByKeyInput:1; ///< Set if a commit is done by key input rather than automatically (usually when a space bar or enter is pressed). - - bool mPlaceHolderSet:1; ///< Whether the place holder text is set. - bool mMarkUpEnabled:1; ///< enable to scan for mark-up - - Toolkit::TextInput::InputSignalType mInputStartedSignal; ///< Signal emitted when input starts - Toolkit::TextInput::InputSignalType mInputFinishedSignal; ///< Signal emitted when input ends - Toolkit::TextInput::StyleChangedSignalType mStyleChangedSignal; ///< Signal emitted when style changes. - Toolkit::TextInput::TextModifiedSignalType mTextModifiedSignal; ///< Signal emitted when text modified. - Toolkit::TextInput::MaxInputCharactersReachedSignalType mMaxInputCharactersReachedSignal; ///< Signal emitted when max input characters is reached. - Toolkit::TextInput::InputSignalType mCutAndPasteToolBarDisplayed; ///< Signal emitted when toolbar displayed - Toolkit::TextInput::InputTextExceedBoundariesSignalType mInputTextExceedBoundariesSignal; ///< Signal emitted when input text exceeds the boundaries of the text-input. -}; - -} // namespace Internal - -// Helpers for public-api forwarding methods - -inline Toolkit::Internal::TextInput& GetImpl(Toolkit::TextInput& textInput) -{ - DALI_ASSERT_ALWAYS(textInput); - - Dali::RefObject& handle = textInput.GetImplementation(); - - return static_cast(handle); -} - -inline const Toolkit::Internal::TextInput& GetImpl(const Toolkit::TextInput& textInput) -{ - DALI_ASSERT_ALWAYS(textInput); - - const Dali::RefObject& handle = textInput.GetImplementation(); - - return static_cast(handle); -} - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp deleted file mode 100644 index e92e4d0..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp +++ /dev/null @@ -1,917 +0,0 @@ -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include - -using namespace Dali; - -#define GET_LOCALE_TEXT(string) dgettext("sys_string", string) - -namespace -{ -const Vector2 DEFAULT_POPUP_INDICATOR_OFFSET(0.0f, 60.0f); - -// 1. For selection: should be above top of highlighted selection, or below bottom of highlighted selection + end handle. -// 2. For cursor: should be above top of cursor, or below bottom of cursor + grab handle. - -/** - * Image resource paths - */ -const char* const POPUP_BACKGROUND = DALI_IMAGE_DIR "popup_bubble_bg.#.png"; -const char* const POPUP_BACKGROUND_EFFECT = DALI_IMAGE_DIR "popup_bubble_bg_ef.#.png"; -const char* const POPUP_BACKGROUND_LINE = DALI_IMAGE_DIR "popup_bubble_bg_line.#.png"; - -const char* const POPUP_TAIL_BOTTOM = DALI_IMAGE_DIR "popup_bubble_tail_bottom.png"; -const char* const POPUP_TAIL_BOTTOM_EFFECT = DALI_IMAGE_DIR "popup_bubble_tail_bottom_ef.png"; -const char* const POPUP_TAIL_BOTTOM_LINE = DALI_IMAGE_DIR "popup_bubble_tail_bottom_line.png"; -const char* const POPUP_TAIL_TOP = DALI_IMAGE_DIR "popup_bubble_tail_top.png"; -const char* const POPUP_TAIL_TOP_EFFECT = DALI_IMAGE_DIR "popup_bubble_tail_top_ef.png"; -const char* const POPUP_TAIL_TOP_LINE = DALI_IMAGE_DIR "popup_bubble_tail_top_line.png"; - -const char* const OPTION_ICON_CLIPBOARD = DALI_IMAGE_DIR "copy_paste_icon_clipboard.png"; -const char* const OPTION_ICON_COPY = DALI_IMAGE_DIR "copy_paste_icon_copy.png"; -const char* const OPTION_ICON_CUT = DALI_IMAGE_DIR "copy_paste_icon_cut.png"; -const char* const OPTION_ICON_PASTE = DALI_IMAGE_DIR "copy_paste_icon_paste.png"; -const char* const OPTION_ICON_SELECT = DALI_IMAGE_DIR "copy_paste_icon_select.png"; -const char* const OPTION_ICON_SELECT_ALL = DALI_IMAGE_DIR "copy_paste_icon_select_all.png"; - -/** - * Constant values for building the GUI - */ -const Vector4 POPUP_MARGIN( 14.0f, 14.0f, 14.0f, 14.0f ); ///< Margin around the popup visible background Image. -const Vector4 POPUP_BORDER( 2.0f, 2.0f, 2.0f, 2.0f ); ///< The Border of the popup. -const Vector2 POPUP_MIN_SIZE( 0.0f, 126.0f ); ///< The minimum size of the popup. -const Vector2 POPUP_MAX_SIZE( 720.0f, 126.0f ); ///< The maximum size of the popup. -const float POPUP_TAIL_Y_OFFSET( -2.25f ); ///< The y offset of the tail. -const Vector2 POPUP_TAIL_SIZE( 36.0f, 36.0f ); ///< The size of the tail. -const Vector2 POPUP_DIVIDER_SIZE( 1.0f, 126.0f ); ///< The size of the divider. - -const Vector4 OPTION_PADDING( 16.0f, 16.0f, 24.0f, 19.0f ); ///< The padding within the option to position icon and text away from the border. The order is left, right, top and bottom -const Vector2 OPTION_MAX_SIZE( 220.0f, 126.0f ); ///< The maximum size of the option. -const Vector2 OPTION_MIN_SIZE( 128.0f, 126.0f ); ///< The minimum size of the option. -const Vector2 OPTION_ICON_SIZE( 45.0f, 45.0f ); ///< The size of the icon. -const Vector2 OPTION_TEXT_MIN_SIZE( 128.0f, 30.0f ); ///< The minimum size of the text. -const float OPTION_GAP_ICON_TEXT( 8.0f ); ///< The gap between the icon and the text - -const float HIDE_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup hide animation in seconds. -const float SHOW_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup show animation in seconds. - -/** - * Default Colors - */ -const Vector4 DEFAULT_POPUP_BACKGROUND( Vector4( .20f, 0.29f, 0.44f, 1.0f ) ); -const Vector4 DEFAULT_POPUP_BACKGROUND_PRESSED( Vector4( 0.07f, 0.10f, 0.17f, 1.0f ) ); -const Vector4 DEFAULT_POPUP_LINE_COLOR( Vector4( 0.36f, 0.45f, 0.59f, 1.0f ) ); -const Vector4 DEFAULT_OPTION_ICON( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); -const Vector4 DEFAULT_OPTION_ICON_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); -const Vector4 DEFAULT_OPTION_TEXT( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); -const Vector4 DEFAULT_OPTION_TEXT_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); - -} // unnamed namespace - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace -{ - -// Signals - -const char* const SIGNAL_PRESSED = "pressed"; -const char* const SIGNAL_HIDE_FINISHED = "hide-finished"; -const char* const SIGNAL_SHOW_FINISHED = "show-finished"; - -} - -const char* const TextInputPopup::OPTION_SELECT_WORD = "option-select_word"; // "Select Word" popup option. -const char* const TextInputPopup::OPTION_SELECT_ALL("option-select_all"); // "Select All" popup option. -const char* const TextInputPopup::OPTION_CUT("option-cut"); // "Cut" popup option. -const char* const TextInputPopup::OPTION_COPY("option-copy"); // "Copy" popup option. -const char* const TextInputPopup::OPTION_PASTE("option-paste"); // "Paste" popup option. -const char* const TextInputPopup::OPTION_CLIPBOARD("option-clipboard"); // "Clipboard" popup option. - -TextInputPopup::TextInputPopup() -: mState(StateHidden), - mRoot( Layer::New() ), - mButtons(), - mVisiblePopUpSize(), - mPopupTailXPosition( 0.0f ), - mContentSize(), - mBackgroundColor( DEFAULT_POPUP_BACKGROUND ), - mBackgroundPressedColor( DEFAULT_POPUP_BACKGROUND_PRESSED ), - mLineColor( DEFAULT_POPUP_LINE_COLOR ), - mIconColor( DEFAULT_OPTION_ICON ), - mIconPressedColor( DEFAULT_OPTION_ICON_PRESSED ), - mTextColor( DEFAULT_OPTION_TEXT ), - mTextPressedColor( DEFAULT_OPTION_TEXT_PRESSED ), - mSelectOptionPriority(1), - mSelectAllOptionPriority(2), - mCutOptionPriority(3), - mCopyOptionPriority(4), - mPasteOptionPriority(5), - mClipboardOptionPriority(6), - mPressedSignal(), - mHideFinishedSignal(), - mShowFinishedSignal() -{ - mRoot.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mRoot.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); -} - -void TextInputPopup::AddToParent( Actor parent ) -{ - Actor existingParent = mRoot.GetParent(); - - if ( !existingParent ) - { - parent.Add( mRoot ); - } -} - -void TextInputPopup::RemoveFromParent() -{ - Actor parent = mRoot.GetParent(); - - if ( parent ) - { - parent.Remove( mRoot ); - } -} - -void TextInputPopup::CreateLayer( const Vector2& size ) -{ - mLayer = Layer::New(); - mLayer.SetParentOrigin(ParentOrigin::CENTER); - mLayer.SetAnchorPoint(AnchorPoint::CENTER); - mLayer.SetSize( size ); // matches stencil size - mLayer.SetName("popup-mLayer"); -} - -void TextInputPopup::CreateStencil( const Vector2& size ) -{ - mStencil = CreateSolidColorActor( Color::BLUE ); - mStencil.SetParentOrigin( ParentOrigin::CENTER ); - mStencil.SetAnchorPoint( AnchorPoint::CENTER ); - mStencil.SetDrawMode( DrawMode::STENCIL ); - mStencil.SetVisible( true ); - mStencil.SetName( "popup-stencil" ); - mStencil.SetSize( size ); -} - -void TextInputPopup::OnScrollStarted( const Vector3& position ) -{ - mButtons.SetSensitive( false ); -} - -void TextInputPopup::OnScrollCompleted( const Vector3& position ) -{ - mButtons.SetSensitive( true ); -} - -void TextInputPopup::CreateScrollView() -{ - mScrollView = Toolkit::ScrollView::New(); - mScrollView.SetName("popup-scroll-view"); - mScrollView.SetAnchorPoint( AnchorPoint::CENTER ); - mScrollView.SetParentOrigin( ParentOrigin::CENTER ); - mScrollView.SetScrollingDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 40.0f ) ); - mScrollView.SetAxisAutoLock( true ); - mScrollView.ScrollStartedSignal().Connect( this, &TextInputPopup::OnScrollStarted ); - mScrollView.ScrollCompletedSignal().Connect( this, &TextInputPopup::OnScrollCompleted ); -} - -void TextInputPopup::UpdateScrollViewRulerAndSize( const Vector2& visibleSize ) -{ - mScrollView.SetSize( visibleSize.x, visibleSize.y ); - - RulerPtr rulerX = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed. - RulerPtr rulerY = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed. - rulerY->Disable(); - rulerX->SetDomain( RulerDomain( 0, mContentSize.width, true ) ); - mScrollView.SetRulerX(rulerX); - mScrollView.SetRulerY(rulerY); -} - - -void TextInputPopup::Clear() -{ - if ( mBackground ) - { - UnparentAndReset( mTail ); - UnparentAndReset( mStencil ); - UnparentAndReset( mBackground ); - UnparentAndReset( mButtons ); - UnparentAndReset( mScrollView ); - mDividerContainer.clear(); - RemoveFromParent(); - mState = StateHidden; - } -} - -ImageActor TextInputPopup::CreateOptionIcon( Image iconImage, const Vector4& color ) -{ - ImageActor icon = ImageActor::New( iconImage ); - icon.SetSize( OPTION_ICON_SIZE ); - icon.SetParentOrigin( ParentOrigin::TOP_CENTER ); - icon.SetAnchorPoint( AnchorPoint::TOP_CENTER ); - icon.SetColor( color ); - icon.SetY( OPTION_PADDING.z - POPUP_BORDER.y ); - return icon; -} - -Toolkit::TextView TextInputPopup::CreateOptionCaption( const std::string& caption, const Vector4& color ) -{ - TextStyle style; - style.SetTextColor( color ); - - PointSize pointSize( Font::PixelsToPoints( OPTION_TEXT_MIN_SIZE.y ) ); - style.SetFontPointSize( pointSize ); - - MarkupProcessor::StyledTextArray styledCaption; - styledCaption.push_back( MarkupProcessor::StyledText( Text( caption ), style ) ); - - Toolkit::TextView textView = Toolkit::TextView::New( styledCaption ); - textView.SetWidthExceedPolicy( Toolkit::TextView::EllipsizeEnd ); - textView.SetHeightExceedPolicy( Toolkit::TextView::EllipsizeEnd ); - textView.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); - textView.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); - textView.SetY( -OPTION_PADDING.w + POPUP_BORDER.w ); - - MarkupProcessor::StyledTextArray styledCaptionEllipsize; - MarkupProcessor::SetTextStyle( Text("..."), styledCaptionEllipsize, style ); - textView.SetEllipsizeText( styledCaptionEllipsize ); - - const float textWidth = textView.GetWidthForHeight( OPTION_TEXT_MIN_SIZE.y ); - textView.SetSize( textWidth, OPTION_TEXT_MIN_SIZE.y ); - - return textView; -} - -void TextInputPopup::CreateBackground() -{ - // Create background-panel if not already created (required if we have at least one option) - if ( !mBackground ) - { - Image bgImg = ResourceImage::New( POPUP_BACKGROUND ); - mBackground = ImageActor::New( bgImg ); - mBackground.SetAnchorPoint( AnchorPoint::CENTER ); - mBackground.SetParentOrigin( ParentOrigin::CENTER ); - mBackground.SetName( "text-input-popup-background" ); - mBackground.SetColor( mBackgroundColor ); - - Image bgEffectImg = ResourceImage::New( POPUP_BACKGROUND_EFFECT ); - mBackgroundEffect = ImageActor::New( bgEffectImg ); - mBackgroundEffect.SetAnchorPoint( AnchorPoint::CENTER ); - mBackgroundEffect.SetParentOrigin( ParentOrigin::CENTER ); - mBackgroundEffect.SetName( "text-input-popup-background-effect" ); - mBackgroundEffect.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - mBackgroundEffect.SetZ( 1.0f ); - mBackground.Add( mBackgroundEffect ); - - Image bgLine = ResourceImage::New( POPUP_BACKGROUND_LINE ); - mBackgroundLine = ImageActor::New( bgLine ); - mBackgroundLine.SetAnchorPoint( AnchorPoint::CENTER); - mBackgroundLine.SetParentOrigin( ParentOrigin::CENTER ); - mBackgroundLine.SetName( "text-input-popup-background-effect" ); - mBackgroundLine.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - mBackgroundLine.SetColor( mLineColor ); - mBackgroundLine.SetZ( 0.1f ); - mBackgroundEffect.Add( mBackgroundLine ); - - Hide(false); - } -} - -void TextInputPopup::CreateTail() -{ - if ( !mTail ) - { - Image tail = ResourceImage::New( POPUP_TAIL_BOTTOM ); - mTail = ImageActor::New( tail ); - mTail.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); - mTail.SetAnchorPoint( AnchorPoint::TOP_CENTER ); - mTail.SetName( "text-input-popup-tail" ); - mTail.SetPosition( 0.0f, POPUP_TAIL_Y_OFFSET - POPUP_BORDER.w, 1.2f ); - mTail.SetColor( mBackgroundColor ); - - Image tailEffect = ResourceImage::New( POPUP_TAIL_BOTTOM_EFFECT ); - mTailEffect = ImageActor::New( tailEffect ); - mTailEffect.SetParentOrigin( ParentOrigin::CENTER ); - mTailEffect.SetAnchorPoint( AnchorPoint::CENTER ); - mTailEffect.SetName( "text-input-popup-tail-effect" ); - mTailEffect.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - mTailEffect.SetZ( 0.1f ); - mTail.Add( mTailEffect ); - - Image tailLine = ResourceImage::New( POPUP_TAIL_BOTTOM_LINE ); - mTailLine = ImageActor::New( tailLine ); - mTailLine.SetParentOrigin( ParentOrigin::CENTER ); - mTailLine.SetAnchorPoint( AnchorPoint::CENTER ); - mTailLine.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - mTailLine.SetName( "text-input-popup-tail-line" ); - mTailLine.SetColor( mLineColor ); - mTailLine.SetZ( 0.1f ); - mTailEffect.Add( mTailLine ); - } -} - -ImageActor TextInputPopup::CreateDivider() -{ - ImageActor divider = Toolkit::CreateSolidColorActor( mLineColor ); - divider.SetParentOrigin( ParentOrigin::TOP_LEFT ); - divider.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - divider.SetSize( POPUP_DIVIDER_SIZE.width , mContentSize.height ); - divider.SetPosition( mContentSize.width - POPUP_DIVIDER_SIZE.width, 0.0f ); - - // Keep track of all the dividers. As their height's need to be updated to the max of all - // buttons currently added. - mDividerContainer.push_back( divider ); - - return divider; -} - -ImageActor TextInputPopup::CreatePressedBackground( const Vector2& requiredSize ) -{ - ImageActor pressedBg = Toolkit::CreateSolidColorActor( mBackgroundPressedColor ); - pressedBg.SetDrawMode( DrawMode::OVERLAY ); - pressedBg.SetParentOrigin( ParentOrigin::CENTER ); - pressedBg.SetAnchorPoint( AnchorPoint::CENTER ); - pressedBg.SetSize( requiredSize ); - return pressedBg; -} - -TextInputPopup::ButtonRequirement TextInputPopup::CreateRequiredButton( TextInputPopup::Buttons buttonId, std::size_t orderOfPriority, - const std::string& name, const std::string& caption, Image iconImage, bool enabled ) -{ - TextInputPopup::ButtonRequirement currentButton; - currentButton.buttonId = buttonId; - currentButton.orderOfPriority = orderOfPriority; - currentButton.name = name; - currentButton.caption = caption; - currentButton.iconImage = iconImage; - currentButton.enabled = enabled; - - return currentButton; -} - -void TextInputPopup::CreateOrderedListOfOptions() -{ - mOrderListOfButtons.clear(); - - for ( std::size_t index= 0; index < ButtonsEnumEnd; index++ ) - { - TextInputPopup::ButtonRequirement currentButton; - - // Create button for each possible option using Option priority - switch ( index ) - { - case ButtonsCut: - { - Image cutIcon = ResourceImage::New( OPTION_ICON_CUT ); - currentButton = CreateRequiredButton( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), cutIcon, false ); - break; - } - case ButtonsCopy: - { - Image copyIcon = ResourceImage::New( OPTION_ICON_COPY ); - currentButton = CreateRequiredButton( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), copyIcon, false ); - break; - } - case ButtonsPaste: - { - Image pasteIcon = ResourceImage::New( OPTION_ICON_PASTE ); - currentButton = CreateRequiredButton( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), pasteIcon, false ); - break; - } - case ButtonsSelect: - { - Image selectIcon = ResourceImage::New( OPTION_ICON_SELECT ); - currentButton = CreateRequiredButton( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), selectIcon, false ); - break; - } - case ButtonsSelectAll: - { - Image selectAllIcon = ResourceImage::New( OPTION_ICON_SELECT_ALL ); - currentButton = CreateRequiredButton( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), selectAllIcon, false ); - break; - } - case ButtonsClipboard: - { - Image clipboardIcon = ResourceImage::New( OPTION_ICON_CLIPBOARD ); - currentButton = CreateRequiredButton( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), clipboardIcon, false ); - break; - } - } - - bool match = false; - - // Insert button in list of buttons in order of priority setting. - for( std::vector::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it ) - { - const ButtonRequirement& button( *it ); - if ( currentButton.orderOfPriority < button.orderOfPriority ) - { - if ( currentButton.orderOfPriority != 0 ) // If order priority 0 then do not add button as not required. - { - mOrderListOfButtons.insert( it, currentButton ); - } - match = true; - } - } - - if ( !match ) - { - mOrderListOfButtons.push_back( currentButton ); - } - } -} - -Vector2 TextInputPopup::GetConstrainedTextSize( const Vector2& textSize ) -{ - return Vector2( std::min( textSize.width, OPTION_MAX_SIZE.width - OPTION_PADDING.x - OPTION_PADDING.y ), textSize.height ); -} - -void TextInputPopup::AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption) -{ - // 1. Create container for text and icon when not pressed. - Actor optionContainer = Actor::New(); - optionContainer.SetParentOrigin( ParentOrigin::TOP_LEFT ); - optionContainer.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - - // 2. Add text. - Toolkit::TextView captionTextView = CreateOptionCaption( caption, mTextColor ); - optionContainer.Add( captionTextView ); - - // 3. Add icon. - ImageActor icon = CreateOptionIcon( iconImage, mIconColor ); - optionContainer.Add( icon ); - - // 4. Calculate the size of option. - const Vector2 textSize = Vector2( captionTextView.GetNaturalSize() ); - captionTextView.SetSize( GetConstrainedTextSize( textSize ) ); - - - const Vector2 optionSize( std::max( textSize.x, OPTION_ICON_SIZE.x ) + OPTION_PADDING.x + OPTION_PADDING.z, - OPTION_PADDING.z + OPTION_ICON_SIZE.y + OPTION_GAP_ICON_TEXT + textSize.y + OPTION_MAX_SIZE.y ); - - - Vector2 constrainedOptionSize = Min( Max( optionSize, OPTION_MIN_SIZE ), OPTION_MAX_SIZE ); - - constrainedOptionSize.height = constrainedOptionSize.height - POPUP_BORDER.y - POPUP_BORDER.z; - - // 5. Create a option. - Toolkit::PushButton option = Toolkit::PushButton::New(); - option.SetParentOrigin( ParentOrigin::TOP_LEFT ); - option.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - option.SetSize( constrainedOptionSize ); - option.SetX( mContentSize.x ); - option.SetName( name ); - option.SetAnimationTime( 0.0f ); - option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed ); - mButtons.Add( option ); - - // 6. Set the normal option image. - option.SetButtonImage( optionContainer ); - - // 7. Update the content size. - mContentSize.x += constrainedOptionSize.x; - mContentSize.y = std::max ( constrainedOptionSize.y, mContentSize.y ); - - // 8. Create the pressed container. - Actor optionPressedContainer = Actor::New(); - - // 9. Add option pressed background. - Vector2 optionPressedBackgroundSize( constrainedOptionSize.x - POPUP_BORDER.x, mContentSize.y - POPUP_BORDER.y - POPUP_BORDER.w ); - ImageActor optionPressedBackground = CreatePressedBackground( optionPressedBackgroundSize ); - optionPressedContainer.Add( optionPressedBackground ); - - // 10. Add pressed text - Toolkit::TextView pressedCaptionTextView = CreateOptionCaption( caption, mTextPressedColor ); - pressedCaptionTextView.SetSize( GetConstrainedTextSize( Vector2( pressedCaptionTextView.GetNaturalSize() ) ) ); - optionPressedBackground.Add( pressedCaptionTextView ); - - // 11. Add pressed icon - ImageActor pressedIcon = CreateOptionIcon( iconImage, mIconPressedColor ); - optionPressedBackground.Add( pressedIcon ); - - // 12. Set the pressed option image - option.SetSelectedImage( optionPressedContainer ); - - // 13. Add the divider - if ( !finalOption ) - { - ImageActor divider = CreateDivider(); - mButtons.Add( divider ); - } -} - -void TextInputPopup::Hide(bool animate) -{ - if( mRoot ) - { - if(mAnimation) - { - mAnimation.Clear(); - mAnimation.Reset(); - } - - if(animate) - { - mAnimation = Animation::New( HIDE_POPUP_ANIMATION_DURATION ); - mAnimation.AnimateTo( Property(mRoot, Actor::Property::SCALE), Vector3::ZERO, AlphaFunctions::EaseOut ); - mAnimation.AnimateTo( Property(mRoot, Actor::Property::COLOR_ALPHA), 0.0f, AlphaFunctions::EaseOut ); - mAnimation.Play(); - - mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnHideFinished ); - mState = StateHiding; - } - else - { - mRoot.SetProperty(Actor::Property::SCALE, Vector3::ZERO); - mRoot.SetProperty(Actor::Property::COLOR_ALPHA, 0.0f); - mState = StateHidden; - } - } -} - -void TextInputPopup::Show( Actor target, bool animate ) -{ - if( mRoot ) - { - mRoot.SetSensitive( true ); - - if(mAnimation) - { - mAnimation.Clear(); - mAnimation.Reset(); - } - - if ( target ) - { - AddToParent( target ); - } - - if(animate) - { - mAnimation = Animation::New( SHOW_POPUP_ANIMATION_DURATION ); - mAnimation.AnimateTo( Property(mRoot, Actor::Property::SCALE), Vector3::ONE, AlphaFunctions::EaseOut ); - mAnimation.AnimateTo( Property(mRoot, Actor::Property::COLOR_ALPHA), 1.0f, AlphaFunctions::EaseOut ); - mAnimation.Play(); - - mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnShowFinished ); - mState = StateShowing; - } - else - { - mRoot.SetProperty(Actor::Property::SCALE, Vector3::ONE); - mRoot.SetProperty(Actor::Property::COLOR_ALPHA, 1.0f); - mState = StateShown; - } - } -} - -TextInputPopup::State TextInputPopup::GetState(void) const -{ - return mState; -} - -Actor TextInputPopup::GetRootActor() const -{ - return mRoot; -} - -// Styling - -void TextInputPopup::SetCutPastePopupColor( const Vector4& color ) -{ - mBackgroundColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupColor() const -{ - return mBackgroundColor; -} - -void TextInputPopup::SetCutPastePopupPressedColor( const Vector4& color ) -{ - mBackgroundPressedColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupPressedColor() const -{ - return mBackgroundPressedColor; -} - -void TextInputPopup::SetCutPastePopupBorderColor( const Vector4& color ) -{ - mLineColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupBorderColor() const -{ - return mLineColor; -} - -void TextInputPopup::SetCutPastePopupIconColor( const Vector4& color ) -{ - mIconColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupIconColor() const -{ - return mIconColor; -} - -void TextInputPopup::SetCutPastePopupIconPressedColor( const Vector4& color ) -{ - mIconPressedColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupIconPressedColor() -{ - return mIconPressedColor; -} - -void TextInputPopup::SetCutPastePopupTextColor( const Vector4& color ) -{ - mTextColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupTextColor() -{ - return mTextColor; -} - -void TextInputPopup::SetCutPastePopupTextPressedColor( const Vector4& color ) -{ - mTextPressedColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupTextPressedColor() -{ - return mTextPressedColor; -} - -void TextInputPopup::TogglePopupButtonOnOff( TextInputPopup::Buttons requiredButton, bool enable ) -{ - bool match ( false ); - for( std::vector::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it ) - { - ButtonRequirement& button( *it ); - if ( requiredButton == button.buttonId ) - { - button.enabled = enable; - match = true; - } - } -} - -void TextInputPopup::SetButtonPriorityPosition( TextInputPopup::Buttons button, unsigned int priority ) -{ - switch ( button ) - { - case ButtonsCut: - { - mCutOptionPriority = priority; - break; - } - case ButtonsCopy: - { - mCopyOptionPriority = priority; - break; - } - case ButtonsPaste: - { - mPasteOptionPriority = priority; - break; - } - case ButtonsSelect: - { - mSelectOptionPriority = priority; - break; - } - case ButtonsSelectAll: - { - mSelectAllOptionPriority = priority; - break; - } - case ButtonsClipboard: - { - mClipboardOptionPriority = priority; - break; - } - case ButtonsEnumEnd: - { - DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice"); - break; - } - } - CreateOrderedListOfOptions(); // Update list of options as priority changed. -} - -unsigned int TextInputPopup::GetButtonPriorityPosition( TextInputPopup::Buttons button ) const -{ - unsigned int priority = 0; - - switch ( button ) - { - case ButtonsCut: - { - priority = mCutOptionPriority; - break; - } - case ButtonsCopy: - { - priority = mCopyOptionPriority; - break; - } - case ButtonsPaste: - { - priority = mPasteOptionPriority; - break; - } - case ButtonsSelect: - { - priority = mSelectOptionPriority; - break; - } - case ButtonsSelectAll: - { - priority = mSelectAllOptionPriority; - break; - } - case ButtonsClipboard: - { - priority = mClipboardOptionPriority; - break; - } - case ButtonsEnumEnd: - { - DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice"); - break; - } - } - - return priority; -} - -void TextInputPopup::AddPopupOptions() -{ - mContentSize = Vector2( POPUP_MIN_SIZE.width, ( POPUP_BORDER.y + POPUP_BORDER.z ) ); - - // 1. Create the background. - CreateBackground(); - - // 2. Create the tail. - CreateTail(); - - // 3. Create the scroll view and Actor to hold buttons. - CreateScrollView(); - - // Clear previous buttons - if ( mButtons ) - { - UnparentAndReset( mButtons ); - } - - mButtons = Actor::New(); - mButtons.SetParentOrigin( ParentOrigin::CENTER ); - mButtons.SetAnchorPoint( AnchorPoint::CENTER ); - - // 4. Create the options and add into the scroll view. - for( std::vector::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it ) - { - const ButtonRequirement& button( *it ); - if ( button.enabled ) - { - AddOption( button.name, button.caption, button.iconImage, it != ( endIt - 1 ) ? false : true ); - } - } - - // 5. Calculate size of content and of popup including borders - const Vector2 popupSize = Vector2( std::min ( ( POPUP_BORDER.x + mContentSize.width + POPUP_BORDER.z ), POPUP_MAX_SIZE.width ) , POPUP_BORDER.y + mContentSize.height + POPUP_BORDER.w ); - - mVisiblePopUpSize = Vector3( popupSize.width - POPUP_BORDER.x - POPUP_BORDER.z , mContentSize.height, 1.0f); - - mBackground.SetSize( popupSize.x + 28 - POPUP_BORDER.x - POPUP_BORDER.z, popupSize.y + 28 - POPUP_BORDER.y - POPUP_BORDER.w ); - mButtons.SetSize( mVisiblePopUpSize.GetVectorXY() ); - - // 6. Set the scroll view ruler. - UpdateScrollViewRulerAndSize( mVisiblePopUpSize.GetVectorXY() ); - - // 7. Create stencil - const Vector2 stencilSize = Vector2( mVisiblePopUpSize.GetVectorXY() ); - - CreateLayer( stencilSize ); - CreateStencil( stencilSize ); - - mScrollView.Add ( mButtons ); - mLayer.Add( mScrollView); - mLayer.Add( mStencil); - mRoot.Add( mTail ); - mRoot.Add( mBackground ); - mRoot.Add( mLayer ); - - // 8. Set the root size. - mRoot.SetSize( popupSize ); // Make Root Actor reflect the size of its content -} - -const Vector3& TextInputPopup::GetVisibileSize() const -{ - return mVisiblePopUpSize; -} - -void TextInputPopup::SetTailPosition( const Vector3& position, bool yAxisFlip ) -{ - mPopupTailXPosition = std::max( position.x, POPUP_TAIL_SIZE.width*0.5f - mVisiblePopUpSize.width*0.5f + POPUP_BORDER.x ); - - std::min( mPopupTailXPosition, mVisiblePopUpSize.width*0.5f - POPUP_BORDER.x - POPUP_TAIL_SIZE.width*0.5f ); - - mTail.SetX( mPopupTailXPosition ); - - if ( yAxisFlip ) - { - Image tail = ResourceImage::New( POPUP_TAIL_TOP ); - Image tailEffect = ResourceImage::New( POPUP_TAIL_TOP_EFFECT ); - Image tailLine = ResourceImage::New( POPUP_TAIL_TOP_LINE ); - - mTail.SetImage( tail ); - mTailEffect.SetImage( tailEffect ); - mTailLine.SetImage( tailLine ); - - mTail.SetParentOrigin( ParentOrigin::TOP_CENTER ); - mTail.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); - mTail.SetY( POPUP_BORDER.y - POPUP_TAIL_Y_OFFSET ); - } -} - -bool TextInputPopup::OnButtonPressed( Toolkit::Button button ) -{ - mPressedSignal.Emit( button ); - return false; -} - -void TextInputPopup::OnHideFinished(Animation& source) -{ - source.FinishedSignal().Disconnect( this, &TextInputPopup::OnHideFinished ); - Clear(); - mState = StateHidden; - mHideFinishedSignal.Emit( *this ); -} - -void TextInputPopup::OnShowFinished(Animation& source) -{ - source.FinishedSignal().Disconnect( this, &TextInputPopup::OnShowFinished ); - mState = StateShown; - mShowFinishedSignal.Emit( *this ); -} - -TextInputPopup::PressedSignalType& TextInputPopup::PressedSignal() -{ - return mPressedSignal; -} - -TextInputPopup::VisibilityChangeFinishedSignalType& TextInputPopup::HideFinishedSignal() -{ - return mHideFinishedSignal; -} - -TextInputPopup::VisibilityChangeFinishedSignalType& TextInputPopup::ShowFinishedSignal() -{ - return mShowFinishedSignal; -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h b/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h deleted file mode 100644 index 2f9a91d..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h +++ /dev/null @@ -1,469 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -class Button; - -namespace Internal -{ - -class TextInputPopup : public ConnectionTracker -{ - -public: - - enum State - { - StateHidden, - StateHiding, - StateShowing, - StateShown - }; - - enum Buttons - { - ButtonsCut, - ButtonsCopy, - ButtonsPaste, - ButtonsSelect, - ButtonsSelectAll, - ButtonsClipboard, - ButtonsEnumEnd - }; - - struct ButtonRequirement - { - TextInputPopup::Buttons buttonId; - std::size_t orderOfPriority; - std::string name; - std::string caption; - Image iconImage; - bool enabled; - }; - - static const char* const OPTION_SELECT_WORD; - static const char* const OPTION_SELECT_ALL; - static const char* const OPTION_CUT; - static const char* const OPTION_COPY; - static const char* const OPTION_PASTE; - static const char* const OPTION_CLIPBOARD; - - // Popup Button Pressed - typedef Signal< bool( Toolkit::Button ) > PressedSignalType; - - // Popup Hide / Show Finished - typedef Signal< void( TextInputPopup& ) > VisibilityChangeFinishedSignalType; - - /** - * Signal emitted when the button is touched. - */ - PressedSignalType& PressedSignal(); - - /** - * Signal emitted when popup is completely hidden - * @note Only occurs after a Show() call with animation enabled. - */ - VisibilityChangeFinishedSignalType& HideFinishedSignal(); - - /** - * Signal emitted when popup is completely shown - * @note Only occurs after a Hide() call with animation enabled. - */ - VisibilityChangeFinishedSignalType& ShowFinishedSignal(); - -public: - - /** - * Default constructor - * Creates an empty popup base actor (no content i.e. invisible) - */ - TextInputPopup(); - - /** - * Clears popup options (popup no longer exists) - */ - void Clear(); - - /** - * Create the label - * @return the newly created Image actor to be used as the icon - */ - ImageActor CreateOptionIcon( Image iconImage, const Vector4& color ); - - /** - * Create the caption - * @param[in] styledCaption The text to be displayed - * @return the newly created label - */ - Toolkit::TextView CreateOptionCaption( const std::string& caption, const Vector4& color ); - - /** - * Creates and sets up the background - */ - void CreateBackground(); - - /** - * Create and set up the tail - */ - void CreateTail(); - - /** - * Create divider if multiple options - * @return Return a divider image actor - */ - ImageActor CreateDivider(); - - /** - * Create a background to be used when option pressed - * @param[in] requiredSize size Image actor should be - * @return Returns an Image Actor to be used a pressed background - */ - ImageActor CreatePressedBackground( const Vector2& requiredSize ); - - /** - * Creates a ordered vector of button options - */ - void CreateOrderedListOfOptions(); - - /** - * Get the TextSize after constrained by the Popup margins. - * @param[in] textSize Natural size of text - * @return Vector2 constrained text size. - * - */ - Vector2 GetConstrainedTextSize( const Vector2& textSize ); - - /** - * Adds a popup option. - * @note Creates popup frame if not already created. - * @param[in] name The unique name for this option. - * @param[in] caption The caption (label) for this option - * @param[in] iconImage Image to displayed with text. - * @param[in] finalOption Flag to indicate that this is the final option. - * (set to true on the last option you add) - */ - void AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption); - - /** - * Hides the popup - * @param[in] animate (optional) whether to animate popup to hide state over time (i.e. tween). - */ - void Hide(bool animate = true); - - /** - * Shows the popup - * @param[in] animate (optional) whether to animate popup to show state over time (i.e. tween). - * @param[in] target Actor to parent popup. - */ - void Show( Actor target, bool animate = true ); - - /** - * Returns the current state of the popup. - * @return The state of the popup see enum State - */ - State GetState(void) const; - - /** - * Get the root actor which the buttons are added to. - * @return the root actor - */ - Actor GetRootActor() const; - - /** - * Set the Cut and Paste buttons color when in normal state - * @param[in] color color to use - */ - void SetCutPastePopupColor( const Vector4& color ); - - /** - * Get the set color of the Copy and Paste Popup buttons - * @return color - */ - const Vector4& GetCutPastePopupColor() const; - - /** - * Set the Cut and Paste button color when pressed. - * @param[in] color color to use - */ - void SetCutPastePopupPressedColor( const Vector4& color ); - - /** - * Get the Cut and Paste pressed button color. - * @return color - */ - const Vector4& GetCutPastePopupPressedColor() const; - - /** - * Set the border color of the popup - * @param[in] color required color - */ - void SetCutPastePopupBorderColor( const Vector4& color ); - - /** - * Get the border color - * @return Vector4 the color of the border - */ - const Vector4& GetCutPastePopupBorderColor() const; - - /** - * Toggle if a popup button should be enabled (shown) or not - * @param[in] requiredButton Button Id to enable or disable - * @param[in] enable toggle to enable (true) or disable (false) - */ - void TogglePopupButtonOnOff( TextInputPopup::Buttons requiredButton, bool enable ); - - /** - * Set the Button Priority Position - * @param[in] button Button id for priority to be set on - * @param[in] priority Priority level, 1 is highest so will appear first. 0 priority will not show the button. - */ - void SetButtonPriorityPosition( TextInputPopup::Buttons button, unsigned int priority ); - - /** - * Set the icon color of the popup - * @param[in] color required color - */ - void SetCutPastePopupIconColor( const Vector4& color ); - - /** - * Get the popup icon color - * @return Vector4 the color of the popup icon - */ - const Vector4& GetCutPastePopupIconColor() const; - - /** - * Set the pressed icon color of the popup - * @param[in] color required color - */ - void SetCutPastePopupIconPressedColor( const Vector4& color ); - - /** - * Get the popup pressed icon color - * @return Vector4 the color of the popup pressed icon - */ - const Vector4& GetCutPastePopupIconPressedColor(); - - /** - * Set the text color of the popup - * @param[in] color required color - */ - void SetCutPastePopupTextColor( const Vector4& color ); - - /** - * Get the popup text color - * @return Vector4 the color of the popup text - */ - const Vector4& GetCutPastePopupTextColor(); - - /** - * Set the pressed text color of the popup - * @param[in] color required color - */ - void SetCutPastePopupTextPressedColor( const Vector4& color ); - - /** - * Get the popup pressed text color - * @return Vector4 the color of the popup pressed text - */ - const Vector4& GetCutPastePopupTextPressedColor(); - - /** - * Get the Button Priority Position - * @param[in] button Button id to get priority of - * @return the button priority, 1 is highest, 0 is not shown. - */ - unsigned int GetButtonPriorityPosition( TextInputPopup::Buttons button ) const; - - /** - * Adds Popup options which have been enabled. - */ - void AddPopupOptions(); - - /** - * Get Visible size of the Popup, excludes content that needs scrolling - * @return Vector3 size of Popup - */ - const Vector3& GetVisibileSize() const; - - /** - * Sets the positon of the PopUp tail relative to TextInput - * @param[in] position Position to set - * @param[in] yAxisFlip If tail should be flipped in y axis - */ - void SetTailPosition( const Vector3& position, const bool yAxisFlip ); - -private: - - /** - * Creates a Button with the required parameters. - * @param[in] buttonId enum representing the button - * @param[in] orderOfPriority Position in toolbar button should be position, 1 is first from left to right. - * @param[in] name Given name for Button actor - * @param[in] caption Text to display in button - * @param[in] iconImage Icon to display in button - * @param[in] enabled Toggle if button should be used or not, this is decided by the current state/conditions. - */ - TextInputPopup::ButtonRequirement CreateRequiredButton( TextInputPopup::Buttons buttonId, std::size_t orderOfPriority, - const std::string& name, const std::string& caption, Image iconImage, bool enabled ); - - /** - * @brief Adds popup to the given parent - * @paran[in] parent target to add Popup to - */ - void AddToParent( Actor parent ); - - /** - * @brief Removes Popup from Parent - */ - void RemoveFromParent(); - - /** - * Applies constraint to keep Popup in view within the desired area. - */ - void ApplyConfinementConstraint(); - - /** - * Applies constraint to keep the Tail attached to Popup - */ - void ApplyTailConstraint(); - - /** - * Create Layer to be used with stencil to allow scrolling of buttons which do not fit in visible popup - * @param[in] size of the layer. - */ - void CreateLayer( const Vector2& size ); - - /** - * Create a stencil to clip the scroll view content - * @param[in] size of the stencil. - */ - void CreateStencil( const Vector2& size ); - - /** - * Popup has started to scroll - * @param[in] position current scroll view position - */ - void OnScrollStarted( const Vector3& position ); - - /** - * Popup has stopped scrolling - * @param[in] position current scroll view position - */ - void OnScrollCompleted( const Vector3& position ); - - /** - * Create a scroll view to hold the popup buttons and allow scrolling if too many buttons to fit within the visible boundary - */ - void CreateScrollView(); - - /** - * Set the scroll view size and ruler. - * @param[in] visibleSize size of the visible scroll view - */ - void UpdateScrollViewRulerAndSize( const Vector2& visibleSize ); - - /** - * Called when a button is pressed in the Popup - * @param[in] button The button pressed. - */ - bool OnButtonPressed( Toolkit::Button button ); - - /** - * Invoked upon popup Hide animation completing. - * @note Only called for animating hide, not called for instantaneous (animate = false) - * @param[in] source The animation which completed. - */ - void OnHideFinished(Animation& source); - - /** - * Invoked upon popup Show animation completing. - * @note Only called for animating show, not called for instantaneous (animate = false) - * @param[in] source The animation which completed. - */ - void OnShowFinished(Animation& source); - -private: - - State mState; ///< Popup State. - Layer mRoot; ///< The actor which all popup content is added to (i.e. panel and buttons) - Actor mButtons; ///< Actor which holds all the buttons, sensitivity can be set on all buttons via this actor - ImageActor mBackground; ///< The background popup panel - ImageActor mBackgroundEffect; ///< The background effect - ImageActor mBackgroundLine; ///< The background line - ImageActor mTail; ///< The tail for the popup - ImageActor mTailEffect; ///< the tail effect - ImageActor mTailLine; ///< The border/outline around the tail - - Vector3 mVisiblePopUpSize; ///< Visible Size of Popup excluding content that needs scrolling. - float mPopupTailXPosition; ///< X position of PopUp tail. - - Vector2 mContentSize; ///< Size of Content (i.e. Buttons) - ActorContainer mDividerContainer; ///< List of dividers added to popup. - Animation mAnimation; ///< Popup Hide/Show animation. - - Layer mLayer; ///< Layer to be used with Stencil - Actor mStencil; ///< Stencil to clip scrollview - Toolkit::ScrollView mScrollView; ///< Scrollview to house the popup - - std::vector mOrderListOfButtons; // List of buttons in the order to be displayed and a flag to indicate if needed. - - Vector4 mBackgroundColor; // Color of the background of the text input popup - Vector4 mBackgroundPressedColor; // Color of the option background. - Vector4 mLineColor; // Color of the line around the text input popup - Vector4 mIconColor; // Color of the popup icon. - Vector4 mIconPressedColor; // Color of the popup icon when pressed. - Vector4 mTextColor; // Color of the popup text. - Vector4 mTextPressedColor; // Color of the popup text when pressed. - - // Priority of Options/Buttons in the Cut and Paste pop-up, higher priority buttons are displayed first, left to right. - std::size_t mSelectOptionPriority; // Position of Select Button - std::size_t mSelectAllOptionPriority; // Position of Select All button - std::size_t mCutOptionPriority; // Position of Cut button - std::size_t mCopyOptionPriority; // Position of Copy button - std::size_t mPasteOptionPriority; // Position of Paste button - std::size_t mClipboardOptionPriority; // Position of Clipboard button - - PressedSignalType mPressedSignal; ///< Signal emitted when a button within the popup is pressed. - VisibilityChangeFinishedSignalType mHideFinishedSignal; ///< Signal emitted when popup is completely hidden - VisibilityChangeFinishedSignalType mShowFinishedSignal; ///< Signal emitted when popup is completely shown - -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_ITEM_VIEW_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h b/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h deleted file mode 100644 index 92f6bad..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h +++ /dev/null @@ -1,268 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES - -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * @brief Class to create and Popup bar made up of buttons. - * It provides signals when a button is pressed. - * The Popup must be positioned by it's owner. - * The future plan is to reuse the Toolkit Popup control to house the buttons. - */ - -class TextInputPopupNew : public ConnectionTracker -{ - -public: - - enum State - { - StateHidden, - StateHiding, - StateShowing, - StateShown - }; - - // Popup Button Pressed - typedef Signal< bool( Toolkit::Button ) > PopUpPressedSignal; - - // Popup Hide Finished - typedef Signal< void( TextInputPopupNew& ) > PopUpVisibilityChangeFinishedSignal; - - /** - * Signal emitted when the button is touched. - */ - PopUpPressedSignal& PressedSignal() { return mPressedSignal; } - - /** - * Signal emitted when popup is completely hidden - * @note Only occurs after a Show() call with animation enabled. - */ - PopUpVisibilityChangeFinishedSignal& HideFinishedSignal() { return mHideFinishedSignal; } - - /** - * Signal emitted when popup is completely shown - * @note Only occurs after a Hide() call with animation enabled. - */ - PopUpVisibilityChangeFinishedSignal& ShowFinishedSignal() { return mShowFinishedSignal; } - -public: - - /** - * Default constructor - * Creates an empty popup base actor (no content i.e. invisible) - */ - TextInputPopupNew() - : mState(StateHidden) - { }; - - /** - * Destructor - */ - ~TextInputPopupNew(){}; - - /** - * @return The root actor of for this popup is returned. - */ - Actor Self() { return mRootActor; }; - - /** - * Clears popup options (popup no longer exists) - */ - void Clear(){}; - - /** - * Create the label - * @param[in] styledCaption The text to be displayed - * @return the newly created label - */ - Toolkit::TextView CreateLabel( const MarkupProcessor::StyledTextArray& styledCaption ){return Toolkit::TextView();}; - - /** - * Create the label - * @param[in] iconImage the image to be used - * @return the newly created Image actor to be used as the icon - */ - ImageActor CreateIcon( Image iconImage ) {return ImageActor();}; - - /** - * Creates and sets up the popup background - */ - void CreatePopUpBackground(){}; - - /** - * Create divider if multiple options - */ - void CreateDivider(){}; - - /** - * Create a background to be used when button pressed - * @param[in] requiredSize size Image actor should be - * @param[in] finalFlag flag to be set if option is the final one. - * @return Returns an Image Actor to be used a pressed background - */ - ImageActor CreatePressedBackground( const Vector3 requiredSize, const bool finalFlag ){ return ImageActor(); }; - - /** - * Adds a popup option button. - * @note Creates popup frame if not already created. - * @param[in] name The unique name for this option. - * @param[in] caption The caption (label) for this option - * @param[in] iconImage Image to displayed with text. - * @param[in] finalOption Flag to indicate that this is the final option. - * (set to true on the last option you add) - */ - void AddButton(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption ){}; - - /** - * Hides the popup - * @param[in] animate (optional) whether to animate popup to hide state over time (i.e. tween). - */ - void Hide(bool animate = true){}; - - /** - * Shows the popup - * @param[in] animate (optional) whether to animate popup to show state over time (i.e. tween). - * @param[in] target Actor to parent popup. - */ - void Show( Actor target, bool animate = true ){}; - - /** - * @brief Get the calculated size of the PopUp - * This can not be set directly as is calculated depending on the content added. - * - * @return Vector3 size of PopUp. - */ - Vector3 GetSize() const { return Vector3::ZERO;}; - - /** - * Returns the current state of the popup. - * @return The state of the popup see enum State - */ - State GetState(void) const{ return StateHidden;}; - - /** - * Get the root actor which the buttons are added to. - * @return the root actor - */ - Actor GetRootActor() const { return Actor(); }; - - /** - * @brief Creates the PopUp with the required buttons for the provided states. - * @param[in] isAllTextSelectedAlready Is all the text already selected - * @param[in] isTextEmpty Contains some text - * @param[in] hasClipboardGotContent Something to paste from clipboard - * @param[in] isSubsetOfTextAlreadySelected Some but not all text is selected - */ - void CreateCutCopyPastePopUp( bool isAllTextSelectedAlready, bool isTextEmpty, bool hasClipboardGotContent, bool isSubsetOfTextAlreadySelected ){}; - - /** - * @brief Applies constraint to keep Popup in view within the desired area. - * @param[in] bounding box in which the PopUp must remain. - * - */ - void ApplyConfinementConstraint( Vector4 boundingBox ){}; - -private: - - /** - * @brief Adds popup to the given parent - * @paran[in] parent target to add Popup to - */ - void AddToParent( Actor parent ){}; - - /** - * Removes popup from Parent. - */ - void RemoveFromStage(){}; - - /** - * Called when a button is pressed in the popup - * @param[in] button The button pressed. - */ - bool OnButtonPressed( Toolkit::Button button ){return false;}; - - /** - * Invoked upon popup Hide animation completing. - * @note Only called for animating hide, not called for instantaneous (animate = false) - * @param[in] source The animation which completed. - */ - void OnHideFinished(Animation& source){}; - - /** - * Invoked upon popup Show animation completing. - * @note Only called for animating show, not called for instantaneous (animate = false) - * @param[in] source The animation which completed. - */ - void OnShowFinished(Animation& source); - -private: - - /** - * @brief Copy Constructor - * @param[in] popup - * Undefined/Hidden. - */ - TextInputPopupNew(const TextInputPopupNew& popup ); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - TextInputPopupNew& operator=(const TextInputPopupNew& rhs); - -private: - - State mState; // Popup State. - Actor mRootActor; // The actor which all popup content is added to (i.e. panel and buttons) - Vector3 mPopupSize; // Size of the PopUp determined by it's content and max/min size constraints. - ImageActor mBackground; // The background popup panel - ImageActor mTail; // The tail for the popup - Vector3 mContentSize; // Size of Content (i.e. Buttons) - ActorContainer mButtonContainer; // List of buttons added to popup. - ActorContainer mDividerContainer; // List of dividers added to popup. - Animation mAnimation; // Popup Hide/Show animation. - - PopUpPressedSignal mPressedSignal; // Signal emitted when a button within the popup is pressed. - PopUpVisibilityChangeFinishedSignal mHideFinishedSignal; // Signal emitted when popup is completely hidden - PopUpVisibilityChangeFinishedSignal mShowFinishedSignal; // Signal emitted when popup is completely shown - -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.cpp deleted file mode 100644 index 7475678..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES - -using namespace Dali; - -namespace -{ - /** - * Selection state enumeration (FSM) - */ - enum SelectionState - { - SelectionNone, ///< Currently not encountered selected section. - SelectionStarted, ///< Encountered selected section - SelectionFinished ///< Finished selected section - }; - - const Vector4 LIGHTBLUE( 10.0f/255.0f, 140.0f/255.0f, 210.0f/255.0f, 1.0f ); // todo make this a setting - - const float CHARACTER_THRESHOLD( 2.5f ); // todo check if unified method to do this in Text -} - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -// Default constructor -TextHighlight::TextHighlight( TextViewCharacterPositioning& textViewCharacterPositioning ) : - mTextViewCharacterPositioning( textViewCharacterPositioning ) -{ -} - -TextHighlight::~TextHighlight() -{ -} - -void TextHighlight::GetVisualTextSelection(std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection, - Toolkit::TextView::TextLayoutInfo& textLayoutInfo ) -{ - std::vector::iterator it = textLayoutInfo.mCharacterLogicalToVisualMap.begin(); - std::vector::iterator startSelectionIt = textLayoutInfo.mCharacterLogicalToVisualMap.begin() + std::min(startSelection, endSelection); - std::vector::iterator endSelectionIt = textLayoutInfo.mCharacterLogicalToVisualMap.begin() + std::max(startSelection, endSelection); - std::vector::iterator end = textLayoutInfo.mCharacterLogicalToVisualMap.end(); - - selectedVisualText.resize( mTextViewCharacterPositioning.GetNumberOfCharactersInText() ); - - // Deselect text prior to startSelectionIt - for(;it!=startSelectionIt;++it) - { - selectedVisualText[*it] = false; - } - - // Select text from startSelectionIt -> endSelectionIt - for(;it!=endSelectionIt;++it) - { - selectedVisualText[*it] = true; - } - - // Deselect text after endSelection - for(;it!=end;++it) - { - selectedVisualText[*it] = false; - } - - selectedVisualText.resize( mTextViewCharacterPositioning.GetNumberOfCharactersInText(), false ); -} - -// Calculate the dimensions of the quads they will make the highlight mesh -TextHighlight::HighlightInfo TextHighlight::CalculateHighlightInfo( std::size_t handlePositionStart, std::size_t handlePositionEnd, Toolkit::TextView::TextLayoutInfo& textLayoutInfo ) -{ - // At the moment there is no public API to modify the block alignment option. - - TextHighlight::HighlightInfo newHighlightInfo; - //newHighlightInfo.mQuadList.clear(); // clear last quad information. - - if ( !mTextViewCharacterPositioning.IsTextEmpty() && !textLayoutInfo.mCharacterLogicalToVisualMap.empty() ) - { - // Get vector of flags representing characters that are selected (true) vs unselected (false). - std::vector selectedVisualText; - GetVisualTextSelection(selectedVisualText, handlePositionStart, handlePositionEnd, textLayoutInfo ); - std::vector::iterator selectedIt(selectedVisualText.begin()); - std::vector::iterator selectedEndIt(selectedVisualText.end()); - - SelectionState selectionState = SelectionNone; ///< Current selection status of cursor over entire text. - float rowLeft = 0.0f; - float rowRight = 0.0f; - // Keep track of the TextView's min/max extents. Should be able to query this from TextView. - float maxRowLeft = std::numeric_limits::max(); - float maxRowRight = 0.0f; - - Toolkit::TextView::CharacterLayoutInfoContainer::iterator it = textLayoutInfo.mCharacterLayoutInfoTable.begin(); - Toolkit::TextView::CharacterLayoutInfoContainer::iterator end = textLayoutInfo.mCharacterLayoutInfoTable.end(); - - Toolkit::TextView::CharacterLayoutInfoContainer::iterator lastIt = it; - - // Scan through entire text. - while(it != end) - { - // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection. - - Toolkit::TextView::CharacterLayoutInfo& charInfo(*it); - bool charSelected( false ); - if( selectedIt != selectedEndIt ) - { - charSelected = *selectedIt++; - } - - if(selectionState == SelectionNone) - { - if(charSelected) - { - selectionState = SelectionStarted; - rowLeft = charInfo.mPosition.x - textLayoutInfo.mScrollOffset.x; - rowRight = rowLeft + charInfo.mSize.width; - } - } - else if(selectionState == SelectionStarted) - { - // break selection on: - // 1. new line causing selection break. (\n or wordwrap) - // 2. character not selected. - if(charInfo.mPosition.y - lastIt->mPosition.y > CHARACTER_THRESHOLD || - !charSelected) - { - // finished selection. - // TODO: TextView should have a table of visual rows, and each character a reference to the row - // that it resides on. That way this enumeration is not necessary. - Vector2 min, max; - if(lastIt->mIsNewParagraphChar) - { - // If the last character is a new line, then to get the row rect, we need to scan from the character before the new line. - lastIt = std::max( textLayoutInfo.mCharacterLayoutInfoTable.begin(), lastIt - 1 ); - } - const Size rowSize( mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( lastIt - textLayoutInfo.mCharacterLayoutInfoTable.begin(), min, max ) ); - maxRowLeft = std::min(maxRowLeft, min.x); - maxRowRight = std::max(maxRowRight, max.x); - float rowBottom = lastIt->mPosition.y - textLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - - // Still selected, and block-align mode then set rowRight to max, so it can be clamped afterwards - if(charSelected) - { - rowRight = std::numeric_limits::max(); - } - newHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - - selectionState = SelectionNone; - - // Still selected? start a new selection - if( charSelected ) - { - // if block-align mode then set rowLeft to min, so it can be clamped afterwards - rowLeft = 0.0f; - rowRight = ( charInfo.mPosition.x - textLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width; - selectionState = SelectionStarted; - } - } - else - { - // build up highlight(s) with this selection data. - rowLeft = std::min( charInfo.mPosition.x - textLayoutInfo.mScrollOffset.x, rowLeft ); - rowRight = std::max( ( charInfo.mPosition.x - textLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width, rowRight ); - } - } - - lastIt = it++; - } - - // If reached end, and still on selection, then close selection. - if(it == end) - { - if(selectionState == SelectionStarted) - { - // finished selection. - Vector2 min, max; - if(lastIt != end && lastIt->mIsNewParagraphChar) - { - lastIt = std::max( textLayoutInfo.mCharacterLayoutInfoTable.begin(), lastIt - 1 ); - } - if( lastIt != end ) - { - const Size rowSize( mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( lastIt - textLayoutInfo.mCharacterLayoutInfoTable.begin(), min, max ) ); - maxRowLeft = std::min(maxRowLeft, min.x); - maxRowRight = std::max(maxRowRight, max.x); - float rowBottom = lastIt->mPosition.y - textLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - newHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - } - } - } - - // Get the top left and bottom right corners. - const Toolkit::TextView::CharacterLayoutInfo& firstCharacter( *textLayoutInfo.mCharacterLayoutInfoTable.begin() ); - const Vector2 topLeft( maxRowLeft, firstCharacter.mPosition.y - firstCharacter.mSize.height ); - const Vector2 bottomRight( topLeft.x + textLayoutInfo.mTextSize.width, topLeft.y + textLayoutInfo.mTextSize.height ); - - // Clamp quads so they appear to clip to borders of the whole text. - newHighlightInfo.Clamp2D( topLeft, bottomRight ); - - // For block-align align Further Clamp quads to max left and right extents - // BlockAlign: Will adjust highlight to block: - // i.e. - // H[ello] (top row right = max of all rows right) - // [--this-] (middle rows' left = min of all rows left, middle rows' right = max of all rows right) - // [is some] (middle rows' left = min of all rows left, middle rows' right = max of all rows right) - // [text] (bottom row left = min of all rows left) - // (common in SMS messaging selection) - // - // As opposed to the default which is tight text highlighting. - // H[ello] - // [this] - // [is some] - // [text] - // (common in regular text editors/web browser selection) - newHighlightInfo.Clamp2D( Vector2(maxRowLeft, topLeft.y), Vector2(maxRowRight, bottomRight.y ) ); - - } - - return newHighlightInfo; -} - -void TextHighlight::UpdateHighlight( TextHighlight::HighlightInfo& newHighlightInfo ) -{ -// Construct a Mesh with a texture to be used as the highlight 'box' for selected text -// -// Example scenarios where mesh is made from 3, 1, 2, 2 ,3 or 3 quads. -// -// [ TOP ] [ TOP ] [TOP ] [ TOP ] [ TOP ] [ TOP ] -// [ MIDDLE ] [BOTTOM] [BOTTOM] [ MIDDLE ] [ MIDDLE ] -// [ BOTTOM] [ MIDDLE ] [ MIDDLE ] -// [BOTTOM] [ MIDDLE ] -// [BOTTOM] -// -// Each quad is created as 2 triangles. -// Middle is just 1 quad regardless of its size. -// -// (0,0) (0,0) -// 0* *2 0* *2 -// TOP TOP -// 3* *1 3* *1 -// 4* *1 4* *6 -// MIDDLE BOTTOM -// 6* *5 7* *5 -// 6* *8 -// BOTTOM -// 9* *7 -// - - // vertex and triangle buffers should always be present if MeshActor is alive. - //HighlightInfo newHighlightInfo = CalculateHighlightInfo( handlePositionStart, handlePositionEnd ); - MeshData::VertexContainer vertices; - Dali::MeshData::FaceIndices faceIndices; - - if( !newHighlightInfo.mQuadList.empty() ) - { - std::vector::iterator iter = newHighlightInfo.mQuadList.begin(); - std::vector::iterator endIter = newHighlightInfo.mQuadList.end(); - - // vertex position defaults to (0 0 0) - MeshData::Vertex vertex; - // set normal for all vertices as (0 0 1) pointing outward from TextInput Actor. - vertex.nZ = 1.0f; - - for(std::size_t v = 0; iter != endIter; ++iter,v+=4 ) - { - // Add each quad geometry (a sub-selection) to the mesh data. - - // 0-----1 - // |\ | - // | \ A | - // | \ | - // | B \ | - // | \| - // 2-----3 - - QuadCoordinates& quad = *iter; - // top-left (v+0) - vertex.x = quad.min.x; - vertex.y = quad.min.y; - vertices.push_back( vertex ); - - // top-right (v+1) - vertex.x = quad.max.x; - vertex.y = quad.min.y; - vertices.push_back( vertex ); - - // bottom-left (v+2) - vertex.x = quad.min.x; - vertex.y = quad.max.y; - vertices.push_back( vertex ); - - // bottom-right (v+3) - vertex.x = quad.max.x; - vertex.y = quad.max.y; - vertices.push_back( vertex ); - - // triangle A (3, 1, 0) - faceIndices.push_back( v + 3 ); - faceIndices.push_back( v + 1 ); - faceIndices.push_back( v ); - - // triangle B (0, 2, 3) - faceIndices.push_back( v ); - faceIndices.push_back( v + 2 ); - faceIndices.push_back( v + 3 ); - } - - mMeshData.SetVertices( vertices ); - mMeshData.SetFaceIndices( faceIndices ); - - mHighlightMesh.UpdateMeshData(mMeshData); - } -} - -Mesh TextHighlight::CreateHighLightMesh() -{ - mMeshData = MeshData( ); - mMeshData.SetHasNormals( true ); - - mCustomMaterial = Material::New("CustomMaterial"); - mCustomMaterial.SetDiffuseColor( LIGHTBLUE ); - - mMeshData.SetMaterial( mCustomMaterial ); - - mHighlightMesh = Mesh::New( mMeshData ); - - return mHighlightMesh; -} - -void TextHighlight::HighlightInfo::AddQuad( float x1, float y1, float x2, float y2 ) -{ - QuadCoordinates quad(x1, y1, x2, y2); - mQuadList.push_back( quad ); -} - -void TextHighlight::HighlightInfo::Clamp2D(const Vector2& min, const Vector2& max) -{ - for(std::size_t i = 0;i < mQuadList.size(); i++) - { - QuadCoordinates& quad = mQuadList[i]; - - quad.min.Clamp(min, max); - quad.max.Clamp(min, max); - } -} - -} // Internal - -} // namespace Toolkit - -} // namespace Dali - diff --git a/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h b/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h deleted file mode 100644 index 74a3421..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * @brief TextHighlight is a decoration which highlights selected text. - * - * The class creates a highlight mesh used to show selected text between handles. - * Not responsible for positioning. - */ -class TextHighlight -{ - /** - * structure to hold coordinates of each quad, which will make up the mesh. - */ - struct QuadCoordinates - { - /** - * Default constructor - */ - QuadCoordinates() - { - } - - /** - * Constructor - * @param[in] x1 left co-ordinate - * @param[in] y1 top co-ordinate - * @param[in] x2 right co-ordinate - * @param[in] y2 bottom co-ordinate - */ - QuadCoordinates(float x1, float y1, float x2, float y2) - : min(x1, y1), - max(x2, y2) - { - } - - Vector2 min; ///< top-left (minimum) position of quad - Vector2 max; ///< bottom-right (maximum) position of quad - }; - - typedef std::vector QuadContainer; - -public: - - /** - * structure for information required to build the highlight mesh - */ - struct HighlightInfo - { - /** - * Adds a Quad (2D rectangular sub-selection) - * @param[in] x1 left co-ordinate - * @param[in] y1 top co-ordinate - * @param[in] x2 right co-ordinate - * @param[in] y2 bottom co-ordinate - */ - void AddQuad( float x1, float y1, float x2, float y2 ); - - /** - * Clamps all quads to fit within a min -> max 2D boundary. - */ - void Clamp2D(const Vector2& min, const Vector2& max); - - QuadContainer mQuadList; ///< List of quads (sub-selections that form to create complete selection) - }; - - /** - * Constructor - * @param[in] textViewCharacterPositioning TextViewCharacterPositioning to be used for positioning information. - */ - TextHighlight( TextViewCharacterPositioning& textViewCharacterPositioning ); - - /** - * Destructor - */ - ~TextHighlight(); - - /** - * Gets the table of the visual text positions which has a flag - * for each Character. The flag is either true (character selected) - * or false (character de-selected) - * @note startSelection can be greater or less than endSelection - * - * @param[in,out] selectedVisualText The vector to be resized and populated with the selected flags - * @param[in] startSelection The start selection point for the text - * @param[in] endSelection The end selection point for the text - * @param[in] endSelection The end selection point for the text - * @param[in] textLayoutInfo TextView character layout information - */ - void GetVisualTextSelection(std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection, - Toolkit::TextView::TextLayoutInfo& textLayoutInfo); - - /** - * Iterates between selection handles and computes the info required to build the highlight mesh - * @param[in] handlePositionStart starting handle position - * @param[in] handlePositionEnd ending handle position - * @return textHighlight target TextHighlight - */ - TextHighlight::HighlightInfo CalculateHighlightInfo( std::size_t handlePositionStart, std::size_t handlePositionEnd, Toolkit::TextView::TextLayoutInfo& textLayoutInfo ); - - /** - * Calculates new Mesh data so highlight moves with selection handles. - * @param[in] newHighlightInfo HighlightInfo calculated by CalculateHighlightInfo - */ - void UpdateHighlight( TextHighlight::HighlightInfo& newHighlightInfo ); - - /** - * Creates the Mesh data needed by the Mesh Actor - */ - Mesh CreateHighLightMesh(); - -private: - - /** - * @brief Copy Constructor - * @param[in] textHight - * Undefined/Hidden. - */ - TextHighlight(const TextHighlight& textHight ); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - TextHighlight& operator=(const TextHighlight& rhs); - -private: - - TextViewCharacterPositioning& mTextViewCharacterPositioning; - - Mesh mHighlightMesh; ///< Mesh Data for highlight - MeshData mMeshData; ///< Container to hold meshData for highlight - Material mCustomMaterial; ///< Custom material used for highlight - HighlightInfo mNewHighlightInfo; ///< Geometry info to create highlight. - -}; - - -} // namespace Internal - - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h b/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h deleted file mode 100644 index 235923a..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class TextInputTextStyle; - -typedef IntrusivePtr TextInputTextStylePtr; - -/** - * Stores the Input Text Style and provides functions to retrieve and manipulate it. - */ - -class TextInputTextStyle : ConnectionTracker -{ - -public: - - /** - * @brief Constructor - */ - TextInputTextStyle(){}; - - /** - * @brief Destructor - */ - ~TextInputTextStyle(){}; - - /** - * @brief Returns the current Input Style, this is the style that newly inputed text will inherit. - * @return TextStyle object representing new style. - */ - TextStyle GetInputStyle() const{return mInputStyle;}; - - /** - * @brief Sets the Input style so newly inputed text will inherit this. - * @param[in] newStyle the style to now use for Input - * @return returns true if style changed. False if new style is the same as current setting. - */ - bool SetInputStyle( const TextStyle newStyle, const TextStyle::Mask mask = TextStyle::ALL ){return false;}; - - /** - * @brief Gets the Current Font used for newly inputed text - * @return the Font currently set for new text - */ - Dali::Font GetInputFont() const{return Dali::Font();}; - - /** - * Signals - */ - - /* Input style changed signal.*/ - typedef Signal< void( const TextStyle& style ) > StyleChangedSignalType; - - /** - * @brief Signal emitted when style changes. - * @return The signal to connect to - */ - StyleChangedSignalType& StyleChangedSignal(); - -private: - - /** - * @brief Copy Constructor - * @param[in] textStyle - * Undefined/Hidden. - */ - TextInputTextStyle(const TextInputTextStyle& textStyle ); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - TextInputTextStyle& operator=(const TextInputTextStyle& rhs); - -private: - - TextStyle mInputStyle; // Stores the current input style. - StyleChangedSignalType mStyleChangedSignal; // Signal emitted when style changes. -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__ - - diff --git a/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h b/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h deleted file mode 100644 index 3f754bf..0000000 --- a/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h +++ /dev/null @@ -1,338 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class TextInputTextStyle; - -/** - * Class which contains functions related to the TextView. - * Functions which are needed by various parts of the TextInput to determine the position of characters. - * Functions to Set the TextView so text justification, alignment and wrapping behaviour in the desired manner for text input. - * The functionality of this class may be divided in future. - */ -class TextViewCharacterPositioning -{ - -public: - - /** - * @brief Constructor - * - * @param[in] displayedTextView TextView to be used with this class. - * @param[in] textStyle TextInputTextStyle to be used - */ - TextViewCharacterPositioning( Toolkit::TextView displayedTextView, TextInputTextStyle& textStyle ):mTextStyle( textStyle ){}; - - /** - * Destructor - */ - ~TextViewCharacterPositioning(){}; - - /** - * @brief Creates the TextView to be used within this class. - */ - void CreateTextView(){}; - - /* - * @brief Get a handle to the current text view object - * If one does not exist then it's create. - * @return TextView - */ - Toolkit::TextView GetTextView() const{return Toolkit::TextView();}; - - /** - * @brief Get the TextLayoutInfo from the TextView so know the updated positions of characters. - */ - void UpdateTextLayoutInfo(){}; - - - /** - * @brief Get the TextLayoutInfo structure for the TextView - * @return the TextLayoutInfo structure - */ - const Toolkit::TextView::TextLayoutInfo& GetLayoutInfo() const{return mTextLayoutInfo;}; - - - /** - * @brief Get the number of characters visually represented in the text - * @return the number of characters - */ - std::size_t GetNumberOfCharactersInText() const{return 0;}; - - /** - * @brief Check if any text exists in TextView's character layout table - * @return bool true if empty - */ - bool IsTextEmpty() const{return false;}; - - /** - * @brief Get the height of the line at the given cursor position - * @param[in] position - * @return float the height of the line - */ - float GetLineHeight( std::size_t position ) const{return 0.0f;}; - - /** - * @brief Sets if the inputed text can exceed the text-input boundary. - * By default is enabled. - * @param[in] enable Whether the inputed text can exceed its boundary. - */ - void SetTextExceedEnabled( bool enable ) {}; - - /** - * @brief Retrieves whether inputed text can exceed the text-input boundary. - * @return \e true if text inputed can exceed the boundary, otherwise \e false. - */ - bool IsTextExceedEnabled() const{ return false;}; - - /** - * @brief From the given x and y vector the closest character position is returned - * @param[in] source the x and y position - * @return the position in the string of the character closest to the source. - */ - std::size_t ReturnClosestIndex( const Vector2& source ){return 0;}; - - /** - * @brief If no text exists then this function uses the text alignment to position cursor. - * @param[in] cursorPosition - */ - void GetActualPositionFromCharacterPositionWhenNoText( Vector3& cursorPosition ) const{}; - - /** - * @brief Function to position cursor when a word is wrapped to another line - * @param[in] characterPosition that actual position is required for - * @return the actual position of the cursor. - */ - Vector3 PositionCursorAfterWordWrap( std::size_t characterPosition ) const{return Vector3::ZERO;}; - - /** - * @brief Returns the x-position of the current line justification - * (relative to left of text-view container) - * @return x position for line justification - */ - float GetLineJustificationPosition() const{return 0.0f;}; - - /** - * @brief Retrieve the dimensions (and min-max) of this row of text that the character resides on. - * @param[in] characterPosition the position in the 'string' of characters. - * @param[out] min the top-left position of the rectangle representing this row - * @param[out] max the bottom-right position of the rectangle representing this row - * @return The size of the rectangle representing this row (max - min) - */ - Size GetRowRectFromCharacterPosition(std::size_t characterPosition, Vector2& min, Vector2& max) const{return Vector2::ZERO;}; - - /** - * @brief Retrieve the character position of the first character on the row of text - * that this character resides on. - * @param[in] logicalPosition the position in the 'string' of characters. - * @return logical character position of start of row. - */ - std::size_t GetRowStartFromCharacterPosition(std::size_t logicalPosition) const{return 0;}; - - /** - * @brief Gets the visual position of a logical position. - * @note This is preferred over directly accessing the Map, as it resolves visual - * positions outside of the character map range. - * @param[in] logicalPosition The logical position - * @return Visual position is returned. - */ - std::size_t GetVisualPosition(std::size_t logicalPosition) const{return 0;}; - - /** - * @brief Return a vector which is the actual position for the given character position - * The character position is where a cursor would be position for that character. - * @param[in] characterPosition the logical (input) position in the 'string' of characters. - * - * @return Vector3 the actual x,y,z position - */ - Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition ) const{return Vector3::ZERO;}; - - /** - * @brief Return a vector which is the actual position for the given character position - * The character position is where a cursor would be positioned for that character to be inserted. - * An additional alternatePosition is also set in circumstances where the possible writing - * of characters would be in the opposite direction. - * e.g. "HelloشقشلاهؤEnglish" - * | | - * * + - * [*] - Primary actual position for cursor i.e. continuing writing LTR (English) - * [+] - Alternate actual position for cursor i.e. writing RTL (Arabic) - * - * @param[in] characterPosition the logical (input) position in the 'string' of characters. - * @param[out] directionRTL Whether the actual x,y,z position is after LTR (false) or RTL (true) text. - * @param[out] alternatePosition the actual x,y,z position of the cursor if user types - * in alternate direction to current flow of text. - * @param[out] alternatePositionValid whether this alternate position is valid. - * @return Vector3 the actual x,y,z position - */ - Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const{return Vector3::ZERO;}; - - /** - * @brief Get the currently displayed text. - * @return The currently displayed text. - */ - std::string GetText() const{return std::string();}; - - /** - * @brief Get the text currently being displayed together with mark-up tags. - * @return string, the currently displayed string with mark-up. - */ - std::string GetMarkupText() const{return std::string();}; - - /** - * @brief Sets whether markup processing should be carried out. - * - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ){}; - - /** - * @brief Returns whether markup processing is enabled or not - * - * @return true is markup processing is enabled - */ - bool IsMarkupProcessingEnabled() const{ return false;}; - - // Styled Text - - /** - * @brief Check if styled text is empty - * @return bool returns true if styled text is empty - */ - bool IsStyledTextEmpty() const{ return false;}; - - /** - * @brief The size of the style text - * @return std::size_t returns number of characters in styled text - */ - std::size_t StyledTextSize() const{return 0;}; - - /** - * @brief Get the styled text array - * @return reference to MarkupProcessor::StyledTextArray - */ - MarkupProcessor::StyledTextArray& GetStyledTextArray(){return mStyledText;}; - - /** - * @brief Get the style for the character at the given position - * @param[in] position of character style is required for - * @return a copy of the style structure for the character at the given position - */ - TextStyle GetStyleAt( std::size_t position ) const{return TextStyle();}; - -/** - * @briefApplies the given style to all text, selected or not selected. - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @param[in] style style to apply - * @param[in] mask mask style should be applied to - * @param[in] begin start position of range to apply style - * @param[in] end end position of range to apply style - */ - void ApplyStyleToRange( const TextStyle& style, const TextStyle::Mask mask, const std::size_t begin, const std::size_t end ){}; - - // Snapshot - /** - * @copydoc TextView::SetSnapshotModeEnabled() - */ - void SetSnapshotModeEnabled( bool enable ){}; - - /** - * @copydoc TextView::IsSnapshotModeEnabled() - */ - bool IsSnapshotModeEnabled() const{ return false;}; - - // Scrolling - /** - * @copydoc TextView::SetScrollEnabled() - */ - void SetScrollEnabled( bool enable ){}; - - /** - * @copydoc TextView::SetScrollPosition() - */ - void SetScrollPosition( const Vector2& position ){}; - - /** - * @copydoc TextView::IsScrollEnabled() - */ - bool IsScrollEnabled() const{ return false;}; - - /** - * @copydoc TextView::GetScrollPosition() - */ - Vector2 GetScrollPosition() const{return Vector2::ZERO;}; - - /** - * @copydoc TextView::GetScrollPosition() - */ - bool IsScrollPositionTrimmed() const{ return false;}; - -private: - - /** - * @brief Copy Constructor - * @param[in] characterPositioning - * Undefined. - */ - TextViewCharacterPositioning(const TextViewCharacterPositioning& characterPositioning ); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined. - */ - TextViewCharacterPositioning& operator=(const TextViewCharacterPositioning& rhs); - -private: - - Toolkit::TextView mDisplayedTextView; // A text view object used to display the text. - TextInputTextStyle& mTextStyle; // Holds the style object related to input style - - MarkupProcessor::StyledTextArray mStyledText; // String currently displayed by TextView with style info. - - Toolkit::TextView::TextLayoutInfo mTextLayoutInfo; // It contains a table layout info per character sorted by the character's visual index (retrieved from TextView), - // a reorder map that stores each character's visual (output) index according to its logical (input) index, - // a reorder map that stores each character's logical (input) index according to its visual (output) index - - bool mExceedEnabled:1; // flag set by user to determine if text can exceed the control's size - bool mMarkUpEnabled:1; // If Markup is being passed with the text -}; - - -} // namespace Internal - - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__ diff --git a/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp b/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp deleted file mode 100644 index 33983d8..0000000 --- a/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp +++ /dev/null @@ -1,2565 +0,0 @@ -/* - * 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/license/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 -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewRelayout -{ - -const float MINIMUM_FADE_BOUNDARY = 0.05f; // When the fade boundary is the same as the text-view boundary, this constant reduces it in order to avoid a zero division. - -RelayoutParameters::RelayoutParameters() -: mPositionOffset(), - mParagraphSize(), - mWordSize(), - mCharacterSize(), - mIndices(), - mCharacterGlobalIndex( 0u ), - mIsFirstCharacter( false ), - mIsFirstCharacterOfWord( false ), - mIsNewLine( false ), - mIsNewParagraphCharacter( false ), - mIsWhiteSpace( false ), - mIsVisible( false ) -{ -} - -RelayoutParameters::~RelayoutParameters() -{ -} - -FadeParameters::FadeParameters() -: mRightFadeBoundary( 0.f ), - mRightFadeThreshold( 0.f ), - mRightFadeBoundaryOffset( 0.f ), - mRightFadeThresholdOffset( 0.f ), - mRightAlphaCoeficients(), - mLeftFadeBoundary( 0.f ), - mLeftFadeThreshold( 0.f ), - mLeftFadeBoundaryOffset( 0.f ), - mLeftFadeThresholdOffset( 0.f ), - mLeftAlphaCoeficients(), - mTopFadeBoundary( 0.f ), - mTopFadeThreshold( 0.f ), - mTopFadeBoundaryOffset( 0.f ), - mTopFadeThresholdOffset( 0.f ), - mTopAlphaCoeficients(), - mBottomFadeBoundary( 0.f ), - mBottomFadeThreshold( 0.f ), - mBottomFadeBoundaryOffset( 0.f ), - mBottomFadeThresholdOffset( 0.f ), - mBottomAlphaCoeficients(), - mIsPartiallyVisible( false ) -{ -} - -FadeParameters::~FadeParameters() -{ -} - -EllipsizeParameters::EllipsizeParameters() -: mPosition(), - mLineDescender( 0.f ), - mLineWidth( 0.f ), - mEllipsizeBoundary(), - mFirstIndex( 0u ), - mLastIndex( 0u ), - mEllipsizeLine( false ), - mIsLineWidthFullyVisible( false ), - mIsLineHeightFullyVisible( false ), - mIsNextLineFullyVisibleHeight( false ), - mCreateEllipsizedTextActors( false ), - mLineFits( false ), - mWordFits( false ) -{ -} - -EllipsizeParameters::~EllipsizeParameters() -{ -} - -UnderlineInfo::UnderlineInfo() -: mMaxHeight( 0.f ), - mMaxThickness( 0.f ), - mPosition( 0.f ) -{ -} - -UnderlineInfo::~UnderlineInfo() -{ -} - -TextUnderlineStatus::TextUnderlineStatus() -: mUnderlineInfo(), - mCharacterGlobalIndex( 0u ), - mLineGlobalIndex( 0u ), - mCurrentUnderlineStatus( false ) -{ -} - -TextUnderlineStatus::~TextUnderlineStatus() -{ -} - -LineLayoutInfo::LineLayoutInfo() -: mLineLength( 0.f ), - mMaxCharHeight( 0.f ), - mMaxAscender( 0.f ) -{ -} - -LineLayoutInfo::~LineLayoutInfo() -{ -} - -/** - * Whether the given text-actor exceeds the left or the right boundary of the text-view. - * - * @param[in] position The position of the text-actor. - * @param[in] size The size of the text-actor. - * @param[in] parantSize The size of the text-view. - * - * @return \e true if the text-actor exceeds the left or the right boundary of the text-view. - */ -bool IsExceedingWidth( const Vector3& position, const Size& size, const Size& parentSize ) -{ - return ( ( position.x < 0.f ) || - ( position.x + size.width > parentSize.width ) ); -} - -/** - * Whether the given text-actor exceeds the top or the bottom boundary of the text-view. - * - * @param[in] position The position of the text-actor. - * @param[in] size The size of the text-actor. - * @param[in] parantSize The size of the text-view. - * - * @return \e true if the text-actor exceeds the top or the bottom boundary of the text-view. - */ -bool IsExceedingHeight( const Vector3& position, const Size& size, const Size& parentSize ) -{ - return ( ( position.y > parentSize.height ) || - ( position.y < size.height ) ); -} - -/** - * Calculates the line length adding the new word or character width. - * - * It also returns the length of white spaces if they are at the end of the line. - * - * @param[in] isWhiteSpace Whether the word is a white space. - * @param[in] width The width of the character or word. - * @param[in] parentWidth The parent width. - * @param[out] found Whether the sum of the new character or word is exceding the parent's width. - * @param[out] lineLength The length of the portion of line which doesn't exceed the parant's width - * @param[out] endWhiteSpaceLength The length of white spaces which are at the end of the line. - */ -void CalculateLineLength( bool isWhiteSpace, float width, float parentWidth, bool& found, float& lineLength, float& endWhiteSpaceLength ) -{ - if( lineLength + width > parentWidth ) - { - found = true; - lineLength -= endWhiteSpaceLength; - } - else - { - lineLength += width; - - if( isWhiteSpace ) - { - endWhiteSpaceLength += width; - } - else - { - endWhiteSpaceLength = 0.f; - } - } -} - -struct CurrentTextActorInfo -{ - TextActor textActor; - Text text; - Vector3 position; - Size size; - Vector4 color; - TextViewProcessor::CharacterLayoutInfo* characterLayout; -}; - -void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - const float lineHeight ) -{ - currentTextActorInfo.textActor.SetTextColor( currentTextActorInfo.color ); - if( ( NULL != currentTextActorInfo.characterLayout ) && - ( NULL != currentTextActorInfo.characterLayout->mGradientInfo ) ) - { - currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.characterLayout->mGradientInfo->mGradientColor ); - currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.characterLayout->mGradientInfo->mStartPoint ); - currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.characterLayout->mGradientInfo->mEndPoint ); - } - - // The italics offset is used in the offscreen rendering. When text is in italics, it may exceed the text-view's boundary - // due to the trick used to implement it. - const Radian& italicsAngle = currentTextActorInfo.textActor.GetItalicsAngle(); - const float italicsOffset = lineHeight * std::tan( italicsAngle ); - relayoutData.mTextLayoutInfo.mMaxItalicsOffset = std::max( relayoutData.mTextLayoutInfo.mMaxItalicsOffset, italicsOffset ); - - // Sets the sort modifier value. - currentTextActorInfo.textActor.SetSortModifier( visualParameters.mSortModifier ); - - // Enables or disables the blending. - currentTextActorInfo.textActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF ); -} - -void CalculateLineLayout( float parentWidth, - const TextViewProcessor::TextInfoIndices& indices, - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo, - HorizontalWrapType splitPolicy, - float shrinkFactor, - LineLayoutInfo& subLineInfo ) -{ - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - - float endWhiteSpaceLength = 0.f; - - std::size_t characterIndex = indices.mCharacterIndex; - float lineOffset = 0.f; - bool found = false; - bool isFirstCharacter = true; - for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex, - wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - ( wordIt != wordEndIt ) && !found; - ++wordIt ) - { - const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt ); - - const float shrunkWordWidth = wordLayoutInfo.mSize.width * shrinkFactor; - const bool isWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType; - - bool splitByCharacter = false; - - switch( splitPolicy ) - { - case WrapByCharacter: - { - splitByCharacter = true; - break; - } - case WrapByWord: - case WrapByParagraphCharacter: // Fall through - { - splitByCharacter = false; - break; - } - case WrapByWordAndSplit: - { - splitByCharacter = ( shrunkWordWidth > parentWidth ); - break; - } - case WrapByParagraphCharacterAndSplit: - { - if( ( 0u != characterIndex ) || - ( ( 0u == characterIndex ) && ( lineOffset + shrunkWordWidth > parentWidth ) ) ) - { - splitByCharacter = true; - } - else - { - lineOffset += shrunkWordWidth; - splitByCharacter = false; - } - } - } - - if( splitByCharacter ) - { - for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + characterIndex, - charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - ( charIt != charEndIt ) && !found; - ++charIt ) - { - const TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt ); - CalculateLineLength( isWhiteSpace, characterLayoutInfo.mSize.width * shrinkFactor, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength ); - if( !found || isFirstCharacter ) - { - subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, characterLayoutInfo.mSize.height ); - subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, characterLayoutInfo.mAscender ); - } - - // All characters for word 'wordIndex' have been processed. - // Next word need to process all characters, so the characterIndex is reset to 0. - characterIndex = 0u; - isFirstCharacter = false; - } - - lineOffset += subLineInfo.mLineLength; - } - else - { - CalculateLineLength( isWhiteSpace, shrunkWordWidth, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength ); - if( !found || isFirstCharacter ) - { - subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, wordLayoutInfo.mSize.height ); - subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, wordLayoutInfo.mAscender ); - } - isFirstCharacter = false; - } - } - - subLineInfo.mMaxCharHeight *= shrinkFactor; - subLineInfo.mMaxAscender *= shrinkFactor; -} - - -/** - * Sets a character of a line of a bidirectional paragraph in the new position. - * - * @param[in] wordsLayoutInfo Layout info of all the words of the paragraph. - * @param[in] index Index within the paragraph to the character to be set in the new position. - * @param[in,out] character Reference to the character in the new position. - */ -void SetCharacter( const TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo, - std::size_t index, - TextViewProcessor::CharacterLayoutInfo& character ) -{ - // Traverse all the characters of the paragraph till the one pointed by index is found. - std::size_t traversedCharacters = 0u; - for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = wordsLayoutInfo.begin(), - wordEndIt = wordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - const TextViewProcessor::WordLayoutInfo& word( *wordIt ); - - const std::size_t numberOfCharacters = word.mCharactersLayoutInfo.size(); - if( index < traversedCharacters + numberOfCharacters ) - { - character = *( word.mCharactersLayoutInfo.begin() + ( index - traversedCharacters ) ); - return; - } - traversedCharacters += numberOfCharacters; - } -} - -/** - * Reorders the layout info of each line of the paragraph. - * - * Uses the visual to logical conversion table to order the text, styles and character's layout (metrics). - * - * @param[in] characterGlobalIndex Index within the whole text of the first character of the paragraph. - * @param[in,out] rtlParagraph Layout info for the paragraph with rtl text. - * @param[in,out] relayoutData The text-view's data structures. - */ -void ReorderLayout( std::size_t characterGlobalIndex, - TextViewProcessor::ParagraphLayoutInfo& paragraph, - TextView::RelayoutData& relayoutData ) -{ - // Clear any previous right to left layout. - if( NULL != paragraph.mRightToLeftLayout ) - { - paragraph.mRightToLeftLayout->Clear(); - paragraph.mRightToLeftLayout->mPreviousLayoutCleared = true; - } - else - { - // Create a new right to left layout if there isn't any. - paragraph.mRightToLeftLayout = new TextViewProcessor::RightToLeftParagraphLayout(); - } - - // Reorder Text and Styles. - - // Reserve space for the styles. - paragraph.mRightToLeftLayout->mTextStyles.Reserve( paragraph.mTextStyles.Count() ); - - // Traverses all the bidirectional info per line. - for( Vector::ConstIterator it = paragraph.mBidirectionalLinesInfo.Begin(), endIt = paragraph.mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - TextProcessor::BidirectionalLineInfo* info( *it ); - - const std::size_t characterParagraphIndex = info->mCharacterParagraphIndex; - const Vector& visualToLogicalMap = info->mVisualToLogicalMap; - - // The text can be appended as it's already reordered. - paragraph.mRightToLeftLayout->mText.Append( info->mText ); - - // The visual to logical map needs to be used to reorder the styles. - for( std::size_t index = 0u, size = visualToLogicalMap.Count(); index < size; ++index ) - { - paragraph.mRightToLeftLayout->mTextStyles.PushBack( *( paragraph.mTextStyles.Begin() + ( characterParagraphIndex + *( visualToLogicalMap.Begin() + index ) ) ) ); - } - } - - // Reorder Layout Info. - - // Reserve space for the new word layout. - paragraph.mRightToLeftLayout->mWordsLayoutInfo.reserve( paragraph.mWordsLayoutInfo.size() ); - - // Traverses all the bidirectional info per line. - for( Vector::ConstIterator it = paragraph.mBidirectionalLinesInfo.Begin(), endIt = paragraph.mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - TextProcessor::BidirectionalLineInfo* info( *it ); - - // Reserve space for all characters. - TextViewProcessor::CharacterLayoutInfoContainer characters; - characters.resize( info->mNumberOfCharacters ); - - // Uses the visual to logical map to set every character in its new position. - for( std::size_t index = 0u; index < info->mNumberOfCharacters; ++index ) - { - SetCharacter( paragraph.mWordsLayoutInfo, - info->mCharacterParagraphIndex + info->mVisualToLogicalMap[index], - *( characters.begin() + index ) ); - } - - // Sets the new 'x' position for each character. - // Updates the text-view's layout info table with the new position of the character. - float xPosition = 0.f; - std::size_t index = 0u; - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator it = characters.begin(), endIt = characters.end(); it != endIt; ++it, ++index ) - { - TextViewProcessor::CharacterLayoutInfo& character( *it ); - - // Set the 'x' position. - character.mPosition.x = xPosition; - - // Update layout info table. - relayoutData.mCharacterLayoutInfoTable[characterGlobalIndex + info->mVisualToLogicalMap[index]].mPosition = character.mPosition; - - // Update the position for the next character. - xPosition += character.mSize.width; - } - - // Split the reordered text in words. - std::size_t previousPosition = 0u; - Vector positions; - TextProcessor::SplitInWords( info->mText, positions ); - - // Whether last character is a word or a paragraph separator. - const std::size_t lastCharacterIndex = info->mText.GetLength() - 1u; - const bool isLastCharacterParagraphSeparator = info->mText.IsNewLine( lastCharacterIndex ); - const bool isLastCharacterWordSeparator = info->mText.IsWhiteSpace( lastCharacterIndex ); - - // Sets the characters into the words they belong to. - for( Vector::ConstIterator it = positions.Begin(), endIt = positions.End(); it != endIt; ++it ) - { - const std::size_t position = *it; - - TextViewProcessor::WordLayoutInfo word; - word.mCharactersLayoutInfo.insert( word.mCharactersLayoutInfo.end(), - characters.begin() + previousPosition, - characters.begin() + position ); - - if( !word.mCharactersLayoutInfo.empty() ) - { - // Updates the layout of the word. - TextViewProcessor::UpdateLayoutInfo( word ); - - paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word ); - } - - // white space or new paragraph. - TextViewProcessor::WordLayoutInfo space; - - space.mCharactersLayoutInfo.insert( space.mCharactersLayoutInfo.end(), - characters.begin() + position, - characters.begin() + position + 1u ); - - space.mType = TextViewProcessor::WordSeparator; - - TextViewProcessor::UpdateLayoutInfo( space ); - - paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( space ); - - previousPosition = position + 1u; - } - - // The last word. - if( previousPosition < paragraph.mRightToLeftLayout->mText.GetLength() ) - { - TextViewProcessor::WordLayoutInfo word; - word.mCharactersLayoutInfo.insert( word.mCharactersLayoutInfo.end(), - characters.begin() + previousPosition, - characters.end() ); - - if( isLastCharacterParagraphSeparator ) - { - word.mType = TextViewProcessor::ParagraphSeparator; - } - else if( isLastCharacterWordSeparator ) - { - word.mType = TextViewProcessor::WordSeparator; - } - TextViewProcessor::UpdateLayoutInfo( word ); - - paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word ); - } - } -} - -/** - * Creates the bidirectional info needed to reorder each line of the paragraph. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in,out] paragraph Layout info for the paragraph. - * @param[in] characterGlobalIndex Index to the character within the whole text. - * @param[in] lineLayoutInfoIndex Index to the table of lines. - */ -void CreateBidirectionalInfoForLines( TextView::RelayoutData& relayoutData, - TextViewProcessor::ParagraphLayoutInfo& paragraph, - std::size_t& characterGlobalIndex, - std::size_t& lineLayoutInfoIndex ) -{ - const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number or laid out lines. - bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last laid out line. - - // Clear previously created bidirectional info. - paragraph.ClearBidirectionalInfo(); - - // For each character, it sets the character's direction. - - // Initialize the paragraph direction. Used to set the direction of weak characters. - const bool isParagraphRightToLeft = paragraph.mBidirectionalParagraphInfo->IsRightToLeftParagraph(); - bool isPreviousRightToLeft = isParagraphRightToLeft; - - for( std::size_t index = 0u; index < paragraph.mNumberOfCharacters; ++index ) - { - // Get the character's layout information (the one is shared with text-input) - Toolkit::TextView::CharacterLayoutInfo& info = *( relayoutData.mCharacterLayoutInfoTable.begin() + ( characterGlobalIndex + index ) ); - - // Gets the character's direction. - const Character::CharacterDirection direction = paragraph.mText[index].GetCharacterDirection(); - if( Character::RightToLeft == direction ) - { - info.mIsRightToLeftCharacter = true; - } - else if( Character::Neutral == direction ) - { - // For neutral characters it check's the next and previous directions. - // If they are equals set that direction. If they are not, sets the paragraph direction. - // If there is no next, sets the previous direction. - - // Check next character's direction. - bool isNextRightToLeft = isPreviousRightToLeft; - if( index < paragraph.mNumberOfCharacters - 1u ) - { - const Character::CharacterDirection nextDirection = paragraph.mText[index + 1u].GetCharacterDirection(); - isNextRightToLeft = Character::RightToLeft == nextDirection; - } - - info.mIsRightToLeftCharacter = isPreviousRightToLeft == isNextRightToLeft ? isPreviousRightToLeft : isParagraphRightToLeft; - } - else - { - info.mIsRightToLeftCharacter = false; - } - - isPreviousRightToLeft = info.mIsRightToLeftCharacter; - } - - std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph). - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - TextViewProcessor::WordLayoutInfo& word( *wordIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt ) - { - TextProcessor::BidirectionalLineInfo* bidirectionalLineInfo = NULL; - - // Check if there is a new line. - const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ); - - if( newLine ) - { - // Point to the next line. - ++lineLayoutInfoIndex; - if( lineLayoutInfoIndex >= lineLayoutInfoSize ) - { - // Arrived at last line. - lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector. - } - - // Number of characters of the line. - const size_t numberOfCharacters = ( lineLayoutEnd ? relayoutData.mTextLayoutInfo.mNumberOfCharacters : relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ) - characterGlobalIndex; - - // There is right to left characters in this line. It needs to be reordered. - bidirectionalLineInfo = new TextProcessor::BidirectionalLineInfo(); - bidirectionalLineInfo->mCharacterParagraphIndex = characterParagraphIndex; - bidirectionalLineInfo->mNumberOfCharacters = numberOfCharacters; - - // Set all the Text's characters in the visual order and creates the mapping tables. - TextProcessor::ReorderLine( paragraph.mBidirectionalParagraphInfo, - bidirectionalLineInfo ); - - paragraph.mBidirectionalLinesInfo.PushBack( bidirectionalLineInfo ); - - for( std::size_t index = 0u; index < numberOfCharacters; ++index ) - { - relayoutData.mCharacterLogicalToVisualMap.push_back( characterGlobalIndex + bidirectionalLineInfo->mLogicalToVisualMap[index] ); - relayoutData.mCharacterVisualToLogicalMap.push_back( characterGlobalIndex + bidirectionalLineInfo->mVisualToLogicalMap[index] ); - } - } - - ++characterGlobalIndex; - ++characterParagraphIndex; - } // characters - } // words -} - -void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData ) -{ - // Reset conversion tables shared through public-api - relayoutData.mCharacterLogicalToVisualMap.clear(); - relayoutData.mCharacterVisualToLogicalMap.clear(); - - std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text). - std::size_t lineLayoutInfoIndex = 0u; // Index to the line info. - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - - if( NULL != paragraph.mBidirectionalParagraphInfo ) - { - // There is right to left text in this paragraph. - - // Stores the current global character index as is needed in both functions. - const std::size_t currentGlobalIndex = characterGlobalIndex; - - // Creates the bidirectional info needed to reorder each line of the paragraph. - CreateBidirectionalInfoForLines( relayoutData, - paragraph, - characterGlobalIndex, - lineLayoutInfoIndex ); - - // Reorder each line of the paragraph - ReorderLayout( currentGlobalIndex, paragraph, relayoutData ); - } - else - { - // Identity in case the paragraph has no right to left text. - for( std::size_t index = 0u; index < paragraph.mNumberOfCharacters; ++index ) - { - const std::size_t globalIndex = characterGlobalIndex + index; - relayoutData.mCharacterLogicalToVisualMap.push_back( globalIndex ); - relayoutData.mCharacterVisualToLogicalMap.push_back( globalIndex ); - } - characterGlobalIndex += paragraph.mNumberOfCharacters; - } - } // paragraphs -} - -float CalculateXoffset( Toolkit::Alignment::Type horizontalTextAlignment, float parentWidth, float wholeTextWidth ) -{ - float xOffset( 0.f ); - switch( horizontalTextAlignment ) - { - case Toolkit::Alignment::HorizontalLeft: - { - // nothing to do. - break; - } - case Toolkit::Alignment::HorizontalCenter: - { - xOffset = 0.5f * ( parentWidth - wholeTextWidth ); - break; - } - case Toolkit::Alignment::HorizontalRight: - { - xOffset = parentWidth - wholeTextWidth; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateXoffset: Wrong horizontal text alignment. Did you set a vertical one?" ); - } - } - - return xOffset; -} - -float CalculateYoffset( Toolkit::Alignment::Type verticalTextAlignment, float parentHeight, float wholeTextHeight ) -{ - float yOffset( 0.f ); - switch( verticalTextAlignment ) - { - case Toolkit::Alignment::VerticalTop: - { - // nothing to do. - break; - } - case Toolkit::Alignment::VerticalCenter: - { - yOffset = 0.5f * ( parentHeight - wholeTextHeight ); - break; - } - case Toolkit::Alignment::VerticalBottom: - { - yOffset = parentHeight - wholeTextHeight; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateXoffset: Wrong vertical text alignment. Did you set an horizontal one?" ); - } - } - - return yOffset; -} - -float CalculateJustificationOffset( Toolkit::TextView::LineJustification justification, float wholeTextWidth, float lineLength ) -{ - float offset = 0.f; - switch( justification ) - { - case Toolkit::TextView::Left: - { - offset = 0.f; - break; - } - case Toolkit::TextView::Center: - { - offset = 0.5f * ( wholeTextWidth - lineLength ); - break; - } - case Toolkit::TextView::Right: - { - offset = wholeTextWidth - lineLength; - break; - } - case Toolkit::TextView::Justified: - { - offset = 0.f; - break; - } - } - - return offset; -} - -bool IsVisible( const Vector3& position, const Size& size, const Size& parentSize, VisibilityTestType type ) -{ - bool visible = false; - - switch( type ) - { - case FULLY_VISIBLE: - { - // Whether the text-actor is fully inside the boundaries of the text-view. - visible = ( ( position.x >= 0.f ) && ( position.x + size.width <= parentSize.width ) && - ( position.y >= size.height ) && ( position.y <= parentSize.height ) ); - break; - } - case FULLY_VISIBLE_WIDTH: - { - // Whether the text-actor is between the left and right boundaries of the text-view. - visible = ( ( position.x >= 0.f ) && ( position.x + size.width <= parentSize.width ) ); - break; - } - case FULLY_VISIBLE_HEIGHT: - { - // Whether the text-actor is between the top and bottom boundaries of the text-view. - visible = ( ( position.y >= size.height ) && ( position.y <= parentSize.height ) ); - break; - } - case PARTIALLY_VISIBLE: - { - // Whether the text-actor is partially inside the boundaries of the text-view. - visible = ( ( position.x < parentSize.width ) && - ( position.x + size.width > 0.f ) && - ( position.y > 0.f ) && - ( position.y - size.height < parentSize.height ) ); - break; - } - case PARTIALLY_VISIBLE_WIDTH: - { - // Whether the text-actor is partially inside the area defined by the left and the right boundaries of the text-view. - // It may not be partially inside the text-view. - visible = ( ( position.x < parentSize.width ) && - ( position.x + size.width > 0.f ) ); - break; - } - case PARTIALLY_VISIBLE_HEIGHT: - { - // Whether the text-actor is partially inside the area defined by the top and the bottom boundaries of the text-view. - // It may not be partially inside the text-view. - visible = ( ( position.y > 0.f ) && - ( position.y - size.height < parentSize.height ) ); - break; - } - } - - return visible; -} - -Vector2 CalculateRectParameters( const Vector2& p0, const Vector2& p1 ) -{ - const float gradient = ( p1.y - p0.y ) / ( p1.x - p0.x ); - - return Vector2( gradient, p0.y - gradient * p0.x ); -} - -void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // Calculates an offset to align the whole text within the text-view's boundary accordingly with the set alignment and justification options. - // The offset could be negative if the whole text is bigger than the boundary of the text-view. - - // If the exceed policy is ellipsize at the end, negative offsets are not wanted. - // In that case, it will align the line to the left and/or top, and ellipsize the end. - const bool ellipsizeAlignToLeft = ( layoutParameters.mExceedPolicy == TextView::EllipsizeEndOriginal ) || - ( layoutParameters.mExceedPolicy == TextView::EllipsizeEnd ) || - ( layoutParameters.mExceedPolicy == TextView::SplitEllipsizeEnd ); - const bool ellipsizeAlignToTop = ( layoutParameters.mExceedPolicy == TextView::EllipsizeEnd ) || - ( layoutParameters.mExceedPolicy == TextView::SplitEllipsizeEnd ); - - RelayoutParameters relayoutParameters; - - // Calculates the vertical and horizontal offsets. - const float textHorizontalOffset = CalculateXoffset( layoutParameters.mHorizontalAlignment, relayoutData.mTextViewSize.width, relayoutData.mTextSizeForRelayoutOption.width ); - const float textVerticalOffset = CalculateYoffset( layoutParameters.mVerticalAlignment, relayoutData.mTextViewSize.height, relayoutData.mTextSizeForRelayoutOption.height ); - - // Index to the global character (within the whole text). - std::size_t characterGlobalIndex = 0u; - - // Index to the line info. - std::size_t lineLayoutInfoIndex = 0u; - - relayoutParameters.mIndices.mParagraphIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - float justificationOffset = 0.f; - - const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines. - bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line. - - relayoutParameters.mIndices.mWordIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), - endWordLayoutIt = wordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++characterGlobalIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - // Check if there is a new line. - const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ); - - if( newLine ) - { - // Calculate line justification offset. - justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, relayoutData.mLines[lineLayoutInfoIndex].mSize.width ); - - // Point to the next line. - ++lineLayoutInfoIndex; - if( lineLayoutInfoIndex >= lineLayoutInfoSize ) - { - // Arrived at last line. - lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector. - } - } - - // Deletes the offsets if the exceed policies are EllipsizeEnd. - const float horizontalOffset = textHorizontalOffset + justificationOffset; - characterLayoutInfo.mOffset.x = ( ellipsizeAlignToLeft && ( horizontalOffset < 0.f ) ) ? 0.f : horizontalOffset; - characterLayoutInfo.mOffset.y = ( ellipsizeAlignToTop && ( textVerticalOffset < 0.f ) ) ? 0.f : textVerticalOffset; - - // Updates the size and position table for text-input with the alignment offset. - Vector3 positionOffset( characterLayoutInfo.mPosition ); - - // Update layout info table. - std::vector::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[characterGlobalIndex]; - Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt ); - - characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x; - characterTableInfo.mPosition.y = positionOffset.y + characterLayoutInfo.mOffset.y; - - positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor; - } // end characters - } // end words - } // end paragraphs -} - -void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - TextView::RelayoutData& relayoutData ) -{ - // No bearing used. - // - // gggggggggg - // gggggggggg - // gggg gggg - // gggg gggg - // gggg gggg - // gggg gggg - // gggg gggg - // gggg gggg - // ggggg gggggggggg bb ggggg - // gg gg gggggggggg bb gg gg - // gg gg gggg bb gg gg - // gg gg gggg bb gg gg - // ggggg gg gggg bbbbbbb ggggg - // gg gg gggg bb bb gg - // g gg gggggggggg bb bb g gg - // ggggg gggggggggg bbbbbbb ggggg - // - // Bearing used. - // - // gggggggggg - // gggggggggg - // gggg gggg bb - // gggg gggg bb - // gggg gggg bb - // ggggg gggg gggg bb ggggg - // gg gg gggg gggg bbbbbbb gg gg - // gg gg gggg gggg bb bb gg gg - // gg gg gggggggggg bb bb gg gg - // ggggg gggggggggg bbbbbbb ggggg - // gg gggg gg - // g gg gggg g gg - // ggggg gg gggg ggggg - // gg gggg - // gggggggggg - // gggggggggg - - const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1u ) ); - const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - ( characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender ); - - characterLayoutInfo.mPosition.y -= bearingOffset * relayoutData.mShrinkFactor; -} - -void UpdateLayoutInfoTable( Vector4& minMaxXY, - TextViewProcessor::WordLayoutInfo& wordLayoutInfo, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - RelayoutParameters& relayoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // updates min and max position to calculate the text size for multiline policies. - minMaxXY.x = std::min( minMaxXY.x, characterLayoutInfo.mPosition.x ); - minMaxXY.z = std::max( minMaxXY.z, characterLayoutInfo.mPosition.x + characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor ); - - minMaxXY.y = std::min( minMaxXY.y, characterLayoutInfo.mPosition.y - characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ); - minMaxXY.w = std::max( minMaxXY.w, characterLayoutInfo.mPosition.y ); - - // Adds layout info to be retrieved by external controls or applications. - Vector3 positionOffset( characterLayoutInfo.mPosition ); - - const float descender = characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender; - - const Toolkit::TextView::CharacterLayoutInfo characterLayoutTableInfo( Size( characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor, - characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ), - positionOffset, - ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ), - false, // whether the character is right to left. The value is set in a next step in the CreateBidirectionalInfoForLines function - true, // whether the character is visible. - descender ); - - relayoutData.mCharacterLayoutInfoTable.push_back( characterLayoutTableInfo ); - - positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor; -} - -void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - const TextStyle& style, - RelayoutParameters& relayoutParameters, - FadeParameters& fadeParameters, - TextView::RelayoutData& relayoutData ) -{ - if( ( TextView::Fade != layoutParameters.mExceedPolicy ) && - ( TextView::SplitFade != layoutParameters.mExceedPolicy ) && - ( TextView::FadeOriginal != layoutParameters.mExceedPolicy ) && - ( TextView::OriginalFade != layoutParameters.mExceedPolicy ) ) - { - // nothing to fade - return; - } - - // Calculates visibility of a text-actor according the exceed policies. - - // position + alignment offset. - const Vector3 position( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x, - characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y, - characterLayoutInfo.mPosition.z ); - - // Whether the text actor is fully, partially or non visible (according exceed policies). - switch( layoutParameters.mExceedPolicy ) - { - case TextView::Fade: - { - // All text-actors which are not completely inside the text-view's boundaries are set as non visible. - // All text-actors which are partially inside the text-view's boundaries are set as partially visible. - if( !IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE ) ) - { - relayoutParameters.mIsVisible = false; - if( IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - PARTIALLY_VISIBLE ) ) - { - fadeParameters.mIsPartiallyVisible = true; - - // Checks if a text-actor is exceeding more than one boundary as this case is not supported. - if( IsExceedingWidth( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize ) && - IsExceedingHeight( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize ) ) - { - // Combination not fully supported by text-view. - // Need to check if text-actor really supports this combination. - fadeParameters.mIsPartiallyVisible = false; - } - } - } - break; - } - case TextView::FadeOriginal: - { - // All text-actors which are not completely between the left and right text-view's boundaries are set as non visible. - // All text-actors which are partially inside the text-view's boundaries are set as partially visible. - if( !IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_WIDTH ) ) - { - relayoutParameters.mIsVisible = false; - if( IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - PARTIALLY_VISIBLE_WIDTH ) ) - { - fadeParameters.mIsPartiallyVisible = true; - } - } - break; - } - case TextView::OriginalFade: - case TextView::SplitFade: // Fallthrough - { - // All text-actors which are not completely between the top and bottom text-view's boundaries are set as non visible. - // All text-actors which are partially inside the text-view's boundaries are set as partially visible. - if( !IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_HEIGHT ) ) - { - relayoutParameters.mIsVisible = false; - if( IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - PARTIALLY_VISIBLE_HEIGHT ) ) - { - fadeParameters.mIsPartiallyVisible = true; - } - } - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateVisibilityForFade. Wrong exceed policies." ) - break; - } - } - - if( relayoutParameters.mIsVisible || fadeParameters.mIsPartiallyVisible ) - { - characterLayoutInfo.mIsVisible = true; - - const Size size = characterLayoutInfo.mSize * relayoutData.mShrinkFactor; - const float characterPositionPlusWidth = position.x + size.width; - const float characterPositionMinusHeight = position.y - size.height; - - // Calculates which edges need to be faded-out. - bool rightFadeOut = false; - bool leftFadeOut = false; - bool bottomFadeOut = false; - bool topFadeOut = false; - - switch( layoutParameters.mExceedPolicy ) - { - case TextView::Fade: - { - // All text-actors exceeding any of the boundaries will be faded-out. - rightFadeOut = ( characterPositionPlusWidth > fadeParameters.mRightFadeThreshold ); - leftFadeOut = ( position.x < fadeParameters.mLeftFadeThreshold ); - bottomFadeOut = ( position.y > fadeParameters.mBottomFadeThreshold ); - topFadeOut = ( characterPositionMinusHeight < fadeParameters.mTopFadeThreshold ); - break; - } - case TextView::FadeOriginal: - { - // Only text-actors exceeding the left or the right boundaries will be faded-out. - rightFadeOut = ( characterPositionPlusWidth > fadeParameters.mRightFadeThreshold ); - leftFadeOut = ( position.x < fadeParameters.mLeftFadeThreshold ); - break; - } - case TextView::SplitFade: - case TextView::OriginalFade: //Fallthrough - { - // Only text-actors exceeding the top or the bottom boundaries will be faded-out. - bottomFadeOut = ( position.y > fadeParameters.mBottomFadeThreshold ); - topFadeOut = ( characterPositionMinusHeight < fadeParameters.mTopFadeThreshold ); - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateVisibilityForFade. Wrong exceed policies." ); - break; - } - } - - // Calculates gradient parameters for a text-actor. - Vector4 gradientColor = Vector4::ZERO; - Vector2 startPoint = Vector2::ZERO; - Vector2 endPoint = Vector2::ZERO; - - if( !( rightFadeOut && leftFadeOut ) ) - { - // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the left and the right boundaries. - if( rightFadeOut ) - { - gradientColor = style.GetTextColor(); - - // Calculates gradient coeficients. - characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mRightAlphaCoeficients.x * position.x + fadeParameters.mRightAlphaCoeficients.y ); - gradientColor.a *= std::max( 0.f, fadeParameters.mRightAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mRightAlphaCoeficients.y ); - - startPoint = Vector2( std::max( 0.f, std::min( 1.f, ( fadeParameters.mRightFadeThresholdOffset - position.x ) / size.width ) ), 0.5f ); - endPoint = Vector2( std::min( 1.f, std::max( 0.f, ( relayoutData.mTextViewSize.width - position.x ) / size.width ) ), 0.5f ); - - if( NULL == characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo(); - } - } - else if( leftFadeOut ) - { - gradientColor = style.GetTextColor(); - - // Calculates gradient coeficients. - characterLayoutInfo.mColorAlpha = std::min( 1.f, fadeParameters.mLeftAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mLeftAlphaCoeficients.y ); - gradientColor.a *= gradientColor.a * std::max( 0.f, fadeParameters.mLeftAlphaCoeficients.x * position.x + fadeParameters.mLeftAlphaCoeficients.y ); - - startPoint = Vector2( std::max( 0.f, std::min( 1.f, ( fadeParameters.mLeftFadeThresholdOffset - position.x ) / size.width ) ), 0.5f ); - endPoint = Vector2( std::min( 1.f, std::max( 0.f, -position.x / size.width ) ), 0.5f ); - - if( NULL == characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo(); - } - } - } - - if( !( bottomFadeOut && topFadeOut ) ) - { - // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the top and the bottom boundaries. - if( bottomFadeOut ) - { - gradientColor = style.GetTextColor(); - - // Calculates gradient coeficients. - characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mBottomAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mBottomAlphaCoeficients.y ); - gradientColor.a *= std::max( 0.f, fadeParameters.mBottomAlphaCoeficients.x * position.y + fadeParameters.mBottomAlphaCoeficients.y ); - - startPoint = Vector2( 0.5f, std::max( 0.f, std::min( 1.f, ( fadeParameters.mBottomFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) ) ); - endPoint = Vector2( 0.5f, std::min( 1.f, std::max( 0.f, ( relayoutData.mTextViewSize.height - characterPositionMinusHeight ) / size.height ) ) ); - - if( NULL == characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo(); - } - } - else if( topFadeOut ) - { - gradientColor = style.GetTextColor(); - - // Calculates gradient coeficients. - characterLayoutInfo.mColorAlpha *= gradientColor.a * std::min( 1.f, fadeParameters.mTopAlphaCoeficients.x * position.y + fadeParameters.mTopAlphaCoeficients.y ); - gradientColor.a *= std::max( 0.f, fadeParameters.mTopAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mTopAlphaCoeficients.y ); - - startPoint = Vector2( 0.5f, std::max( 0.f, std::min( 1.f, ( fadeParameters.mTopFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) ) ); - endPoint = Vector2( 0.5f, std::min( 1.f, std::max( 0.f, -characterPositionMinusHeight / size.height ) ) ); - - if( NULL == characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo(); - } - } - } - - if( NULL != characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo->mGradientColor = gradientColor; - characterLayoutInfo.mGradientInfo->mStartPoint = startPoint; - characterLayoutInfo.mGradientInfo->mEndPoint = endPoint; - } - } - else - { - characterLayoutInfo.mIsVisible = false; - } -} - -bool CalculateVisibilityForEllipsizeEndOriginal( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - const EllipsizeParameters& ellipsizeParameters ) -{ - bool isPartiallyVisible = false; - - if( !IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - FULLY_VISIBLE_WIDTH ) ) - { - // The character doesn't fit in the text-view's width. - characterLayoutInfo.mIsVisible = false; - - // Checks if the character is partially visible (it's cut by the boundary) - isPartiallyVisible = IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - PARTIALLY_VISIBLE_WIDTH ); - } - else - { - // The character fits in the text-view's width. Set it to visible. - characterLayoutInfo.mIsVisible = true; - } - - return isPartiallyVisible; -} - -bool CalculateVisibilityForEllipsizeEnd( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - const EllipsizeParameters& ellipsizeParameters ) -{ - bool isPartiallyVisible = false; - - if( !IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - FULLY_VISIBLE ) ) - { - // The character is not fully visible. Needs to check if it's partially visible. - characterLayoutInfo.mIsVisible = false; - - // Checks if the character doesn't cut the bottom edge of the text-view. - const bool fullyVisibleHeight = IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - FULLY_VISIBLE_HEIGHT ); - - // Checks if the character cuts the right edge of the text-view. - const bool partiallyVisibleWidth = IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - PARTIALLY_VISIBLE_WIDTH ); - - // Character will be ellipsized if it cuts the right edge of the text-view but fits completely in the text-view's height. - isPartiallyVisible = ( fullyVisibleHeight && partiallyVisibleWidth ); - } - else - { - // The character fits in the boundary of the text-view. Set it to visible. - characterLayoutInfo.mIsVisible = true; - } - - return isPartiallyVisible; -} - -void CalculateVisibilityForEllipsize( const Internal::TextView::LayoutParameters& layoutParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ) -{ - // Calculates visibility for EllipsizeEnd exceed policies. - - // It defines a boundary on the right side of the text-view by substracting the ellipsize-text's size (...) to the text-view's size. - // If a character is cut by this boundary and the whole line (if the multi-line policy is split-by-new-line-char) - // or the whole word (if the multi-line policy is split-by-word) doesn't fit in the text-view's width, then it's replaced by the ellipsize-text. - - // Position of the character used to do the visibility test. - ellipsizeParameters.mPosition = Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x, - characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y, - characterLayoutInfo.mPosition.z ); - - // Text will be ellipsized if a character is partially visible (it's cut by the boundary defined in the right side of the text-view). - bool isPartiallyVisible = false; - - // Checks if the whole line or the whole word fits in the text-view's width accordingly with the multiline policy. - const bool fitsInWidth = ( Toolkit::TextView::SplitByNewLineChar == layoutParameters.mMultilinePolicy ) ? ellipsizeParameters.mLineFits: ellipsizeParameters.mWordFits; - - // Will only ellipsize the text if it cuts the right vertical edge and it doesn't fit in the text-view's width. - if( fitsInWidth ) - { - // The line or word fits completely inside the text-view's width. Nothing else to do. - characterLayoutInfo.mIsVisible = true; - } - else - { - // The line or word doesn't fit in the text-view's width. - - // Calculates visibility for each type of ellipsize policies. - switch( layoutParameters.mExceedPolicy ) - { - case TextView::EllipsizeEndOriginal: - { - // Ellipsizes the text if it doesn't fit in the width but it doesn't ellipsize if the text doesn't fit in the height. - - isPartiallyVisible = CalculateVisibilityForEllipsizeEndOriginal( characterLayoutInfo, - ellipsizeParameters ); - - break; - } - case TextView::SplitEllipsizeEnd: - case TextView::EllipsizeEnd: - { - // Ellipsizes the text if it doesn't fit in the width and fully fits in the text-view's height. - - isPartiallyVisible = CalculateVisibilityForEllipsizeEnd( characterLayoutInfo, - ellipsizeParameters ); - - break; - } - default: - { - DALI_ASSERT_DEBUG( !"TextViewRelayout::CalculateVisibilityForEllipsize. Wrong exceed value." ); - break; - } - } - } - - // If the current character is not fully visible but is partially visible, it is cut by the boundary of the text-view. - // In that case, the charater needs to be replaced by the ellipsize text. - ellipsizeParameters.mCreateEllipsizedTextActors = ( !characterLayoutInfo.mIsVisible && isPartiallyVisible ); -} - -void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ) -{ - // The default ellipsize text is '...' and all dots have the same style. However, a differernt ellipsize text could be set and it can have characters with differernt styles. - // The code bellow creates the text-actors needed for the ellipsize text. - - // Set ellipsize's position by the end of visible text. - Vector3 ellipsizePosition = ellipsizeParameters.mPosition; - // Stores current ellipsize text. - Text ellipsizeText; - // Stores current ellipsize style. - TextStyle ellipsizeStyle; - // Stores the current size. - Size ellipsizeSize; - //Whether current glyph is an emoticon. - bool isColorGlyph = false; - - float bearingOffset = 0.f; - - // Create ellipsize text-actor. - std::size_t characterIndex = 0u; - for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator ellipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.begin(), - endEllipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.end(); - ellipsizeCharacterLayoutIt != endEllipsizeCharacterLayoutIt; - ++ellipsizeCharacterLayoutIt, ++characterIndex ) - { - const TextViewProcessor::CharacterLayoutInfo& ellipsizeCharacterLayoutInfo( *ellipsizeCharacterLayoutIt ); - const TextStyle& style = *( *( relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin() + characterIndex ) ); - - if( isColorGlyph || - ( isColorGlyph != ellipsizeCharacterLayoutInfo.mIsColorGlyph ) || - ( ellipsizeStyle != style ) ) - { - // The style is different, so a new text-actor is needed. - if( !ellipsizeText.IsEmpty() ) - { - // It only creates a text-actor if there is any text. - RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache ); - ellipsizeGlyphActor.SetSize( ellipsizeSize ); - ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) ); - - // Updates the position for the next text-actor. - ellipsizePosition.x += ellipsizeSize.width; - - // Adds the text-actor to the list. - relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor ); - } - - // Resets the current ellipsize info. - ellipsizeText = Text( relayoutData.mTextLayoutInfo.mEllipsisText[characterIndex] ); - ellipsizeStyle = style; - ellipsizeSize = ellipsizeCharacterLayoutInfo.mSize; - isColorGlyph = ellipsizeCharacterLayoutInfo.mIsColorGlyph; - - bearingOffset = ( ellipsizeParameters.mLineDescender - ( ellipsizeCharacterLayoutInfo.mSize.height - ellipsizeCharacterLayoutInfo.mAscender ) ) * relayoutData.mShrinkFactor; - } - else - { - // Updates text and size with the new character. - ellipsizeText.Append( relayoutData.mTextLayoutInfo.mEllipsisText[characterIndex] ); - TextViewProcessor::UpdateSize( ellipsizeSize, ellipsizeCharacterLayoutInfo.mSize ); - } - } - - if( !ellipsizeText.IsEmpty() ) - { - // Creates the last glyph-actor. - RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache ); - ellipsizeGlyphActor.SetSize( ellipsizeSize ); - ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) ); - - // Adds the glyph-actor to the list. - relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor ); - } -} - -void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, - EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ) -{ - // Traverses the text layout info from the first character of the line - // to the last one setting to each character its visibility. If needed, it adds the ellipsize text (...). - - // Indices to the first character of the line. - TextViewProcessor::TextInfoIndices firstIndices; - TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mFirstIndex, - relayoutData.mTextLayoutInfo, - firstIndices ); - - // Indices to the last character of the line. - TextViewProcessor::TextInfoIndices lastIndices; - TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mLastIndex, - relayoutData.mTextLayoutInfo, - lastIndices ); - - // Defines a boundary by substracting the ellipsize-text's width to the text-view's width. - // This is the boundary used to check if a character have to be ellipsized. - ellipsizeParameters.mEllipsizeBoundary = relayoutData.mTextViewSize; - ellipsizeParameters.mEllipsizeBoundary.width -= relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + firstIndices.mParagraphIndex, - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + lastIndices.mParagraphIndex + 1u; - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - ellipsizeParameters.mLineFits = ellipsizeParameters.mIsLineWidthFullyVisible && ellipsizeParameters.mIsLineHeightFullyVisible && ellipsizeParameters.mIsNextLineFullyVisibleHeight; - - if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight ) - { - ellipsizeParameters.mEllipsizeBoundary.width = ellipsizeParameters.mLineWidth; - } - - bool firstWord = true; - bool lastWord = false; - - std::size_t wordCount = 0u; - - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin() + firstIndices.mWordIndex, - endWordLayoutIt = wordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u; - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++wordCount ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - if( wordCount == lastIndices.mWordIndex - firstIndices.mWordIndex ) - { - lastWord = true; - } - - const std::size_t firstCharacterIndex = firstWord ? firstIndices.mCharacterIndex : 0u; - const std::size_t lastCharacterIndex = lastWord ? lastIndices.mCharacterIndex : wordLayoutInfo.mCharactersLayoutInfo.size() - 1u; - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + firstCharacterIndex, - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + lastCharacterIndex + 1u; - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - if( ellipsizeParameters.mEllipsizeLine ) - { - // Calculates the character visibility and whether it needs to be replace by ellipsized text. - CalculateVisibilityForEllipsize( layoutParameters, - characterLayoutInfo, - ellipsizeParameters, - relayoutData ); - - if( ellipsizeParameters.mCreateEllipsizedTextActors ) - { - // Create ellipsize text-actors if the character needs to be replaced. - CreateEllipsizeTextActor( ellipsizeParameters, - relayoutData ); - } - } - else - { - if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) || - ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy )) - { - if( !ellipsizeParameters.mIsLineHeightFullyVisible ) - { - // Make characters invisible. - characterLayoutInfo.mIsVisible = false; - } - } - } - } // end characters - firstWord = false; - } // end words - } // end paragraphs -} - -void SetTextVisible( TextView::RelayoutData& relayoutData ) -{ - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - std::size_t characterIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), - endWordLayoutIt = wordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++characterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - characterLayoutInfo.mIsVisible = true; - delete characterLayoutInfo.mGradientInfo; - characterLayoutInfo.mGradientInfo = NULL; - characterLayoutInfo.mColorAlpha = ( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) )->GetTextColor().a; - } // end characters - } // end words - } // end paragraphs - - // Updates the visibility for text-input.. - for( std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin(), - endIt = relayoutData.mCharacterLayoutInfoTable.end(); - it != endIt; - ++it ) - { - Toolkit::TextView::CharacterLayoutInfo& characterLayoutInfo( *it ); - - characterLayoutInfo.mIsVisible = true; - } -} - -void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - RelayoutParameters relayoutParameters; - FadeParameters fadeParameters; - - // Calculates the fade thresholds (from where the text starts to fade out). If any of the fade boundaries is zero, it sets a very small value just to avoid a zero division. - fadeParameters.mRightFadeBoundary = static_cast( visualParameters.mFadeBoundary.mRight ); - fadeParameters.mRightFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mRight > 0u ? fadeParameters.mRightFadeBoundary : MINIMUM_FADE_BOUNDARY ); - fadeParameters.mRightFadeThreshold = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundary; - fadeParameters.mRightFadeThresholdOffset = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundaryOffset; - fadeParameters.mLeftFadeBoundary = static_cast( visualParameters.mFadeBoundary.mLeft ); - fadeParameters.mLeftFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mLeft > 0u ? fadeParameters.mLeftFadeBoundary : MINIMUM_FADE_BOUNDARY ); - fadeParameters.mLeftFadeThreshold = fadeParameters.mLeftFadeBoundary; - fadeParameters.mLeftFadeThresholdOffset = fadeParameters.mLeftFadeBoundaryOffset; - fadeParameters.mTopFadeBoundary = static_cast( visualParameters.mFadeBoundary.mTop ); - fadeParameters.mTopFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mTop > 0u ? fadeParameters.mTopFadeBoundary : MINIMUM_FADE_BOUNDARY ); - fadeParameters.mTopFadeThreshold = fadeParameters.mTopFadeBoundary; - fadeParameters.mTopFadeThresholdOffset = fadeParameters.mTopFadeBoundaryOffset; - fadeParameters.mBottomFadeBoundary = static_cast( visualParameters.mFadeBoundary.mBottom ); - fadeParameters.mBottomFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mBottom > 0u ? fadeParameters.mBottomFadeBoundary : MINIMUM_FADE_BOUNDARY ); - fadeParameters.mBottomFadeThreshold = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundary; - fadeParameters.mBottomFadeThresholdOffset = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundaryOffset; - - // Calculates the fade out rect coeficients for the right, left, top and bottom sides of the text-view. - fadeParameters.mRightAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mRightFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.width, 0.f ) ); - fadeParameters.mLeftAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mLeftFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) ); - fadeParameters.mTopAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mTopFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) ); - fadeParameters.mBottomAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mBottomFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.height, 0.f ) ); - - // Traverses all characters and calculates the visibility. - - std::size_t infoTableCharacterIndex = 0u; - - relayoutParameters.mIndices.mParagraphIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - std::size_t characterIndex = 0u; - relayoutParameters.mIndices.mWordIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), - endWordLayoutIt = wordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - relayoutParameters.mIsFirstCharacterOfWord = true; - relayoutParameters.mWordSize = wordLayoutInfo.mSize; - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex, ++characterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - relayoutParameters.mIsVisible = true; - fadeParameters.mIsPartiallyVisible = false; - - // Calculates the visibility for the current character. - CalculateVisibilityForFade( layoutParameters, - characterLayoutInfo, - *( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) ), - relayoutParameters, - fadeParameters, - relayoutData ); - - // Updates the visibility for text-input.. - std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[infoTableCharacterIndex]; - - Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it ); - - characterLayoutTableInfo.mIsVisible = relayoutParameters.mIsVisible; - - relayoutParameters.mIsFirstCharacterOfWord = false; - } // end character - } // end words - } // end paragraphs -} - -void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - // TODO check ellipsis with rtl text. - - // Traverses the lines and checks which ones doesn't fit in the text-view's boundary. - for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineInfoIt = relayoutData.mLines.begin(), endLineInfoIt = relayoutData.mLines.end(); - lineInfoIt != endLineInfoIt; - ++lineInfoIt ) - { - const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineInfoIt ); - - // To check if a line fits in the text-view's boundary, - // get the position of the first character is needed and do the test - // with the line size. - - // An bearing offset may have been applied to the first character so it's needed to - // get the start position of the line. - - // Some parameters used in the CalculateVisibilityForEllipsize() function. - EllipsizeParameters ellipsizeParameters; - - // Retrieves the first index and the last index of the line. - ellipsizeParameters.mFirstIndex = lineInfo.mCharacterGlobalIndex; - ellipsizeParameters.mLastIndex = 0u; - if( ( lineInfoIt + 1u ) != endLineInfoIt ) - { - const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *( lineInfoIt + 1u ) ); - ellipsizeParameters.mLastIndex = nextLineInfo.mCharacterGlobalIndex - 1u; - } - else - { - ellipsizeParameters.mLastIndex = relayoutData.mCharacterLayoutInfoTable.size() - 1u; - } - - // Retrieves the first character of the line and build the position of the line with the bearing. - const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + ellipsizeParameters.mFirstIndex ); - - // Calculates the bearing offset applied to the first character. - const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender; - - // Build the position of the line by removing the bearing offset from the first character's position. - const Vector3 position( characterInfo.mPosition.x, - characterInfo.mPosition.y + bearingOffset, - characterInfo.mPosition.z ); - - // Checks if the line needs to be ellipsized, - ellipsizeParameters.mIsLineWidthFullyVisible = IsVisible( position, - lineInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_WIDTH ); - - // If the exceed policy is EllipsizeEndOriginal it's enough to check - // if the line fits in the width. - ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsLineWidthFullyVisible; - - // If the exceed policy is EllipsizeEnd, it's needed to check if the next line exceeds the text-view's height. - // If the next line exceeds the text-view height then it's going to be invisible and current line needs to be ellipsized. - ellipsizeParameters.mIsLineHeightFullyVisible = true; - ellipsizeParameters.mIsNextLineFullyVisibleHeight = true; - if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) || - ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ) ) - { - // Need to check if there is lines which doesn't fit in the height. - - ellipsizeParameters.mIsLineHeightFullyVisible = IsVisible( position, - lineInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_HEIGHT ); - - ellipsizeParameters.mEllipsizeLine = ellipsizeParameters.mEllipsizeLine && ellipsizeParameters.mIsLineHeightFullyVisible; - - if( ellipsizeParameters.mIsLineHeightFullyVisible && !ellipsizeParameters.mEllipsizeLine ) - { - // Current line is not ellipsized. - // Need to check if there is a next line and if it's not visible. If there is, current line needs to be ellipsized. - Toolkit::TextView::LineLayoutInfoContainer::const_iterator nextLineInfoIt = lineInfoIt + 1u; - if( nextLineInfoIt != endLineInfoIt ) - { - // Retrives the position of the first character of the line and remove - // the bearing offset to build to build the position of the line. - const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *nextLineInfoIt ); - const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + nextLineInfo.mCharacterGlobalIndex ); - - const float bearingOffset = ( ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender ) * relayoutData.mShrinkFactor; - - const Vector3 position( characterInfo.mPosition.x, - characterInfo.mPosition.y + bearingOffset, - characterInfo.mPosition.z ); - - ellipsizeParameters.mIsNextLineFullyVisibleHeight = IsVisible( position, - nextLineInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_HEIGHT ); - - // If the next line is not visible, current line have to be ellipsized. - ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsNextLineFullyVisibleHeight; - } - } - } - - if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight ) - { - ellipsizeParameters.mLineWidth = position.x + lineInfo.mSize.width - relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width; - } - - // Sets the line descender. - ellipsizeParameters.mLineDescender = lineInfo.mSize.height - lineInfo.mAscender; - - // At this point, ellipsizeLine distinguish if a piece of line have to be ellipsized or not. - EllipsizeLine( layoutParameters, ellipsizeParameters, relayoutData ); - } -} - -void UpdateVisibility( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - switch( layoutParameters.mExceedPolicy ) - { - case TextView::FadeOriginal: - case TextView::OriginalFade: - case TextView::Fade: - case TextView::SplitFade: // Fall through - { - UpdateVisibilityForFade( layoutParameters, - visualParameters, - relayoutData ); - break; - } - case TextView::EllipsizeEndOriginal: - case TextView::SplitEllipsizeEnd: - case TextView::EllipsizeEnd: // Fall through - { - // Set first all characters to visible as UpdateVisibilityForEllipsize() doesn't traverse all of them. - SetTextVisible( relayoutData ); - - UpdateVisibilityForEllipsize( layoutParameters, - visualParameters, - relayoutData ); - break; - } - default: - { - SetTextVisible( relayoutData ); - break; - } - } -} - -/** - * Creates an image actor for the emoticon. - * - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] characterLayout Layout info for the character. - * @param[in] character The character. - */ -void CreateEmoticon( const TextView::VisualParameters& visualParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayout, - const Character& character ) -{ - // The character is an emoticon. - ImageActor imageActor = ImageActor::DownCast( characterLayout.mGlyphActor ); - if( !imageActor ) - { - imageActor = ImageActor::New(); - - GlyphImage image = GlyphImage::New( character ); - - if( image ) - { - imageActor.SetImage( image ); - } - } - - imageActor.SetPosition( Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x, - characterLayout.mPosition.y + characterLayout.mOffset.y, - characterLayout.mPosition.z ) ); - imageActor.SetSize( characterLayout.mSize ); - - // Sets the sort modifier value. - imageActor.SetSortModifier( visualParameters.mSortModifier ); - - characterLayout.mGlyphActor = imageActor; -} - -/** - * Creates text-actors for the given text. - * - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in,out] paragraph Layout info for the paragraph. - * @param[in,out] wordLayout Layout info for the word. - * @param[in,out] characterLayout Layout info for the character. - * @param[in] character The character. - * @param[in] style The character's style. - * @param[in,out] currentTextActorInfo Temporary stores the text-actor's info to be set. - * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles. - * @param[in,out] textActorCreated Whether a text-actor - */ -void CreateTextActor( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - const TextViewProcessor::ParagraphLayoutInfo& paragraph, - TextViewProcessor::WordLayoutInfo& wordLayout, - TextViewProcessor::CharacterLayoutInfo& characterLayout, - const Character& character, - const TextStyle& style, - CurrentTextActorInfo& currentTextActorInfo, - bool createGlyphActors, - bool& textActorCreated ) -{ - textActorCreated = false; - - // Set the text-actor for the current traversed text. - if( currentTextActorInfo.textActor ) - { - if( ( NULL != currentTextActorInfo.characterLayout ) && - currentTextActorInfo.characterLayout->mSetText ) - { - currentTextActorInfo.textActor.SetText( currentTextActorInfo.text ); - currentTextActorInfo.characterLayout->mSetText = false; - } - currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position ); - currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size ); - - SetVisualParameters( currentTextActorInfo, - visualParameters, - relayoutData, - paragraph.mSize.height ); - } - - float rightToLeftOffset = 0.f; - if( character.IsWhiteSpace() ) - { - // In left to right text, a word never starts with a white space but - // it may happen in right to left text as the text is reversed. - // The text alignment and justification offset is calculated without this white space. - // It causes a missalignment which can be corrected by removing the size of the white space. - rightToLeftOffset = characterLayout.mSize.width * relayoutData.mShrinkFactor; - } - - // Whether this word is not a white space or if it is, it is underlined. - // Don't want to create text-actors for white spaces unless they are underlined. - bool isNotWhiteSpace = ( TextViewProcessor::NoSeparator == wordLayout.mType ) || ( ( TextViewProcessor::WordSeparator == wordLayout.mType ) && style.IsUnderlineEnabled() ); - - if( isNotWhiteSpace ) - { - currentTextActorInfo.text = Text( character ); - } - else - { - currentTextActorInfo.text = Text(); - } - currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x - rightToLeftOffset, - characterLayout.mPosition.y + characterLayout.mOffset.y, - characterLayout.mPosition.z ); - currentTextActorInfo.size = characterLayout.mSize * relayoutData.mShrinkFactor; - - currentTextActorInfo.color = style.GetTextColor(); - currentTextActorInfo.color.a = characterLayout.mColorAlpha; - - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - - if( createGlyphActors && isNotWhiteSpace ) - { - textActorCreated = true; - if( textActor ) - { - // Try to reuse first the text-actor of this character. - textActor.SetTextStyle( style ); - } - else - { - // If there is no text-actor, try to retrieve one from the cache. - textActor = relayoutData.mTextActorCache.RetrieveTextActor(); - - // If still there is no text-actor, create one. - if( !textActor ) - { - TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF ); - textActor = TextActor::New( Text(), parameters ); - textActor.SetRelayoutEnabled( false ); - } - else - { - textActor.SetTextStyle( style ); - } - } - characterLayout.mSetText = true; - currentTextActorInfo.characterLayout = &characterLayout; - - characterLayout.mGlyphActor = textActor; - } - - // Update the current text-actor. - currentTextActorInfo.textActor = textActor; -} - -/** - * Traverses the whole paragraph initializating renderable-actor handles and updating them with the new size and position. - * - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in,out] paragraph Layout info for the paragraph. - * @param[in,out] characterGlobalIndex Index to the character within the whole text. - * @param[in,out] lineLayoutInfoIndex Index to the table of lines. - * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles. - */ -void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - TextViewProcessor::ParagraphLayoutInfo& paragraphLayout, - std::size_t& characterGlobalIndex, - std::size_t& lineLayoutInfoIndex, - bool createGlyphActors ) -{ - CurrentTextActorInfo currentTextActorInfo; - currentTextActorInfo.characterLayout = NULL; - - const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines. - bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line. - bool textActorCreated = false; // Whether a text actor has been created for this the current group of characters traversed. - - TextStyle currentStyle; // style for the current text-actor. - - TextViewProcessor::GradientInfo* currentGradientInfo = NULL; // gradient color for the current text-actor. - // start point for the current text-actor. - // end point for the current text-actor. - - bool currentIsColorGlyph = false; // Whether current glyph is an emoticon. - - std::vector textActorsToRemove; // Keep a vector of text-actors to be included into the cache. - - // Retrieve the layout info to traverse. If there is right to left text it retrieves the right to left layout. - const bool isRightToLeftLayout = NULL != paragraphLayout.mRightToLeftLayout; - - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayout.mWordsLayoutInfo; - Text& text = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mText : paragraphLayout.mText; - Vector& textStyles = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mTextStyles : paragraphLayout.mTextStyles; - - // In case the previous right to left layout has been cleared, all text-actors have been removed as well. If this bool is set to true, text-actors will be created again. - createGlyphActors = createGlyphActors || ( ( isRightToLeftLayout ) ? paragraphLayout.mRightToLeftLayout->mPreviousLayoutCleared : false ); - - std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph). - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - TextViewProcessor::WordLayoutInfo& wordLayout( *wordIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = wordLayout.mCharactersLayoutInfo.begin(), characterEndIt = wordLayout.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayout( *characterIt ); - - // Check if there is a new line. - const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ); - - if( newLine ) - { - // Point to the next line. - ++lineLayoutInfoIndex; - if( lineLayoutInfoIndex >= lineLayoutInfoSize ) - { - // Arrived at last line. - lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector. - } - textActorCreated = false; - } - - // Do not create a glyph-actor if there is no text. - const Character character = text[characterParagraphIndex]; - const TextStyle& style = *( *( textStyles.Begin() + characterParagraphIndex ) ); - - // Check if the character has the same gradient info than the current one. - bool differentGradientInfo = false; - if( characterLayout.mGradientInfo && currentGradientInfo ) - { - differentGradientInfo = ( characterLayout.mGradientInfo->mGradientColor != currentGradientInfo->mGradientColor ) || - ( characterLayout.mGradientInfo->mStartPoint != currentGradientInfo->mStartPoint ) || - ( characterLayout.mGradientInfo->mEndPoint != currentGradientInfo->mEndPoint ); - } - else if( ( NULL != currentGradientInfo ) || ( NULL != characterLayout.mGradientInfo ) ) - { - differentGradientInfo = true; - } - - if( ( createGlyphActors && !textActorCreated ) || - characterLayout.mIsColorGlyph || - differentGradientInfo || - ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) || - ( style != currentStyle ) ) - { - characterLayout.mSetText = false; - characterLayout.mSetStyle = false; - - if( characterLayout.mIsColorGlyph ) - { - CreateEmoticon( visualParameters, - characterLayout, - character ); - - characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); - } - else - { - // There is a new style or a new line. - - CreateTextActor( visualParameters, - relayoutData, - paragraphLayout, - wordLayout, - characterLayout, - character, - style, - currentTextActorInfo, - createGlyphActors, - textActorCreated ); - - if( textActorCreated ) - { - characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); - } - } - - // Update style to be checked with next characters. - currentStyle = style; - currentGradientInfo = characterLayout.mGradientInfo; - currentIsColorGlyph = characterLayout.mIsColorGlyph; - } - else - { - DALI_ASSERT_DEBUG( !characterLayout.mIsColorGlyph && "TextViewProcessor::InitializeTextActorInfo. An image-actor doesn't store more than one emoticon." ); - - // Same style than previous one. - - // Add the character to the current text-actor and update the size. - if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != wordLayout.mType ) ) - { - currentTextActorInfo.text.Append( character ); - - currentTextActorInfo.position.y = std::min( currentTextActorInfo.position.y, ( characterLayout.mPosition.y + characterLayout.mOffset.y ) ); - currentTextActorInfo.size.width += characterLayout.mSize.width * relayoutData.mShrinkFactor; - currentTextActorInfo.size.height = std::max( currentTextActorInfo.size.height, characterLayout.mSize.height * relayoutData.mShrinkFactor ); - } - } - - if( ( createGlyphActors ) && - !characterLayout.mIsColorGlyph && - !textActorCreated ) - { - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - if( textActor ) - { - // There is a previously created text-actor for this character. - // If this character has another one put it into the cache. - textActor.SetText( "" ); - textActorsToRemove.push_back( textActor ); - } - - if( characterLayout.mGlyphActor ) - { - characterLayout.mGlyphActor.Reset(); - } - } - ++characterGlobalIndex; - ++characterParagraphIndex; - } // characters - } // words - - if( !currentTextActorInfo.text.IsEmpty() ) - { - if( currentTextActorInfo.textActor ) - { - if( ( NULL != currentTextActorInfo.characterLayout ) && - currentTextActorInfo.characterLayout->mSetText ) - { - currentTextActorInfo.textActor.SetText( currentTextActorInfo.text ); - currentTextActorInfo.characterLayout->mSetText = false; - } - currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position ); - currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size ); - - SetVisualParameters( currentTextActorInfo, - visualParameters, - relayoutData, - paragraphLayout.mSize.height ); - } - } - - // Insert the spare text-actors into the cache. - relayoutData.mTextActorCache.InsertTextActors( textActorsToRemove ); -} - -void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - bool createGlyphActors ) -{ - if( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - // nothing to do if there is no paragraphs. - return; - } - - std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text). - std::size_t lineLayoutInfoIndex = 0u; // Index to the line info. - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - - UpdateTextActorInfoForParagraph( visualParameters, - relayoutData, - paragraph, - characterGlobalIndex, - lineLayoutInfoIndex, - createGlyphActors ); - } // paragraphs - - // Set visual parameters for ellipsis renderable actors. - for( std::vector::iterator it = relayoutData.mEllipsizedGlyphActors.begin(), - endIt = relayoutData.mEllipsizedGlyphActors.end(); - it != endIt; - ++it ) - { - RenderableActor glyphActor = ( *it ); - - glyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - glyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); - - // Sets the sort modifier value. - glyphActor.SetSortModifier( visualParameters.mSortModifier ); - - // Enables or disables the blending. - glyphActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF ); - } -} - -void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelayout::TextUnderlineStatus& textUnderlineStatus ) -{ - // Traverse the whole text to find all groups of consecutive underlined characters in the same line. - // - // Note that relayoutData.mTextLayoutInfo contains layout info per paragraph but these paragraphs are the result of split the whole text every time a '\n' is found. - // According with the layout option, one of this paragraphs could be laid-out in more than one line. - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - - std::size_t characterIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraph.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraph.mRightToLeftLayout->mWordsLayoutInfo : paragraph.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - TextViewProcessor::WordLayoutInfo& word( *wordIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt, ++characterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& character( *characterIt ); - const TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) ); - - // Check if current character is the first of a new line - const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) && - ( textUnderlineStatus.mCharacterGlobalIndex == ( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ).mCharacterGlobalIndex ); - if( isNewLine ) - { - ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one. - } - - if( style.IsUnderlineEnabled() ) - { - if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't. - isNewLine ) // Current character is underlined and is the first of current line. - { - // Create a new underline info for the current underlined characters. - UnderlineInfo underlineInfo; - underlineInfo.mMaxHeight = character.mSize.height; - underlineInfo.mMaxThickness = character.mUnderlineThickness; - underlineInfo.mPosition = character.mUnderlinePosition; - - textUnderlineStatus.mUnderlineInfo.push_back( underlineInfo ); - - textUnderlineStatus.mCurrentUnderlineStatus = true; // Set the current text is underlined. - } - else - { - // Retrieve last underline info and update it if current underline thickness is bigger. - UnderlineInfo& underlineInfo( *( textUnderlineStatus.mUnderlineInfo.end() - 1u ) ); - - underlineInfo.mMaxHeight = std::max( underlineInfo.mMaxHeight, character.mSize.height ); - - if( character.mUnderlineThickness > underlineInfo.mMaxThickness ) - { - underlineInfo.mMaxThickness = character.mUnderlineThickness; - underlineInfo.mPosition = character.mUnderlinePosition; - } - } - } - else - { - textUnderlineStatus.mCurrentUnderlineStatus = false; - } - - ++textUnderlineStatus.mCharacterGlobalIndex; - } // end characters. - } // end words. - } // end paragraphs. -} - -void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) -{ - // Stores for each group of consecutive underlined characters in each line its maximum thicknes, its position of that thickness and the maximum character's height. - TextViewRelayout::TextUnderlineStatus textUnderlineStatus; - - // Traverse the whole text to find all groups of consecutive underlined characters in the same line. - CalculateUnderlineInfo( relayoutData, textUnderlineStatus ); - - if( textUnderlineStatus.mUnderlineInfo.empty() ) - { - // There is no underlined text. Just exit. - return; - } - - // At this point textUnderlineStatus.mUnderlineInfo has for each group of consecutive underlined characters their maximum thickness, position and maximum height. - // Traverse the whole text and set the previously stored underline info in the text style. - - std::vector::const_iterator underlineInfoIt = textUnderlineStatus.mUnderlineInfo.begin(); - std::vector::const_iterator underlineInfoEndIt = textUnderlineStatus.mUnderlineInfo.end(); - - UnderlineInfo underlineInfo; - - if( underlineInfoIt < underlineInfoEndIt ) - { - underlineInfo = ( *underlineInfoIt ); - } - - // Whether current text is underlined. - textUnderlineStatus.mCurrentUnderlineStatus = false; - textUnderlineStatus.mCharacterGlobalIndex = 0u; - textUnderlineStatus.mLineGlobalIndex = 0u; - - float currentLineHeight = 0.f; - float currentLineAscender = 0.f; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - std::size_t characterIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraph.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraph.mRightToLeftLayout->mWordsLayoutInfo : paragraph.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - TextViewProcessor::WordLayoutInfo& word( *wordIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt, ++characterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& character( *characterIt ); - TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) ); - - // Check if current character is the first of a new line - - bool isNewLine = false; - - if( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) - { - const Toolkit::TextView::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ); - isNewLine = ( textUnderlineStatus.mCharacterGlobalIndex == lineLayoutInfo.mCharacterGlobalIndex ); - - if( isNewLine ) - { - currentLineHeight = lineLayoutInfo.mSize.height; - currentLineAscender = lineLayoutInfo.mAscender; - ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one. - } - } - - if( style.IsUnderlineEnabled() ) - { - if( textUnderlineStatus.mCurrentUnderlineStatus ) - { - if( isNewLine ) - { - // Retrieves the thickness and position for the next piece of underlined text. - if( underlineInfoIt < underlineInfoEndIt ) - { - ++underlineInfoIt; - if( underlineInfoIt < underlineInfoEndIt ) - { - underlineInfo = *underlineInfoIt; - } - } - } - } - - textUnderlineStatus.mCurrentUnderlineStatus = true; - - // Before setting the position it needs to be adjusted to match the base line. - const float bearingOffset = ( currentLineHeight - currentLineAscender ) - ( character.mSize.height - character.mAscender ); - const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset; - - // Sets the underline's parameters. - style.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset ); - - // Mark the character to be set the new style into the text-actor. - character.mSetStyle = true; - } - else - { - if( textUnderlineStatus.mCurrentUnderlineStatus ) - { - textUnderlineStatus.mCurrentUnderlineStatus = false; - - // Retrieves the thickness and position for the next piece of underlined text. - if( underlineInfoIt < underlineInfoEndIt ) - { - ++underlineInfoIt; - if( underlineInfoIt < underlineInfoEndIt ) - { - underlineInfo = *underlineInfoIt; - } - } - } - } - - ++textUnderlineStatus.mCharacterGlobalIndex; - } // end of characters. - } // end of word. - } // end of paragraphs. -} - -void RemoveGlyphActors( Actor textView, - const std::vector& glyphActors ) -{ - // Removes previously inserted renderable-actors. - // The SplitByNewLineChar::Relayout(), SplitByWord::Relayout() and SplitByChar::Relayout() functions add - // renderable-actors to the text-view. A handle to these renderable-actors are stored and passed to this function - // in order to remove 'only' renderable-actors added by these functions. - // Any other actor added by a programmer or application won't be removed. - - for( std::vector::const_reverse_iterator it = glyphActors.rbegin(), endIt = glyphActors.rend(); it != endIt; ++it ) - { - textView.Remove( *it ); - } -} - -void InsertToTextView( Actor textView, - TextView::RelayoutData& relayoutData ) -{ - // Add text-actors to the text-view. - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - // Retrieve the layout info to traverse. If there is right to left text it retrieves the right to left layout. - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), - endWordLayoutIt = wordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - if( characterLayoutInfo.mIsVisible && characterLayoutInfo.mGlyphActor ) // White spaces and '\n' characters doesn't have a text-actor. - { - //Add to the text-view. - textView.Add( characterLayoutInfo.mGlyphActor ); - relayoutData.mGlyphActors.push_back( characterLayoutInfo.mGlyphActor ); - } - } // end character - } // end words - } // end paragraphs - - for( std::vector::iterator it = relayoutData.mEllipsizedGlyphActors.begin(), - endIt = relayoutData.mEllipsizedGlyphActors.end(); - it != endIt; - ++it ) - { - RenderableActor glyphActor = ( *it ); - - //Add to the text-view. - textView.Add( glyphActor ); - relayoutData.mGlyphActors.push_back( glyphActor ); - } - relayoutData.mEllipsizedGlyphActors.clear(); -} - -RenderableActor CreateGlyphActor( const Text& text, const TextStyle& style, TextActorCache& cache ) -{ - TextActor textActor = cache.RetrieveTextActor(); - - if( textActor ) - { - // Update the text-actor. - textActor.SetText( text ); - textActor.SetTextStyle( style ); - } - else - { - // The text-actor cache is empty. Create a new one. - TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF ); - textActor = TextActor::New( text, parameters ); - } - - // Exclude from size negotiation - textActor.SetRelayoutEnabled( false ); - - return textActor; -} - -} // namespace TextViewRelayout - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/relayout-utilities.h b/dali-toolkit/internal/controls/text-view/relayout-utilities.h deleted file mode 100644 index 5150186..0000000 --- a/dali-toolkit/internal/controls/text-view/relayout-utilities.h +++ /dev/null @@ -1,517 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_RELAYOUT_UTILITIES_H__ -#define __DALI_TOOLKIT_INTERNAL_RELAYOUT_UTILITIES_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -//Forward declarations. -class TextActorCache; - -namespace TextViewRelayout -{ - -extern const float MINIMUM_FADE_BOUNDARY; // When the fade boundary is the same as the text-view boundary, this constant reduces it in order to avoid a zero division. - -/** - * Define how to wrap a paragraph in lines. - */ -enum HorizontalWrapType -{ - WrapByCharacter, ///< Wrap the paragraph per character (It may split a word in two). - WrapByWord, ///< Wrap the paragraph by word. - WrapByWordAndSplit, ///< Wrap the paragraph by word and split a word if it doesn't fit. - WrapByParagraphCharacter, ///< Wrap the paragraph when a '\n' is found. - WrapByParagraphCharacterAndSplit ///< Wrap the paragraph when a '\n' is found and split if it doesn't fit. -}; - -/** - * Different types of visibility tests (text-actor - text-view). - */ -enum VisibilityTestType -{ - FULLY_VISIBLE, ///< The text-actor is completely inside the text-view. - FULLY_VISIBLE_WIDTH, ///< The text-actor is completely between the right and the left boundaries of the text-view. - FULLY_VISIBLE_HEIGHT, ///< The text-actor is completely between the top and the bottom boundaries of the text-view. - PARTIALLY_VISIBLE, ///< The text-actor is partially inside the text-view. - PARTIALLY_VISIBLE_WIDTH, ///< The text-actor is partially inside the width of the text-view. It may be completely above and bellow the top and bottom boundaries of the text-view. - PARTIALLY_VISIBLE_HEIGHT ///< The text-actor is partially inside the height of the text-view. It may be completely on the left and on the right the left and right boundaries of the text-view. -}; - -/** - * Temporary parameters used in the relayout process. - */ -struct RelayoutParameters -{ - /** - * Default constructor. - * - * Initializes all members to their defaults. - */ - RelayoutParameters(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~RelayoutParameters(); - - Vector3 mPositionOffset; ///< Offset (position.x + size.width, position.y, position.z) of the previous text-actor. - Size mParagraphSize; ///< Current paragraphs's size. - Size mWordSize; ///< Current word's size. - Size mCharacterSize; ///< Current character's size. - TextViewProcessor::TextInfoIndices mIndices; ///< Current indices to paragraph, word and character. - std::size_t mCharacterGlobalIndex; ///< Index to a single character within the whole text. - bool mIsFirstCharacter:1; ///< Whether is the first character of the whole text. - bool mIsFirstCharacterOfWord:1; ///< Whether is the first character of the word. - bool mIsNewLine:1; ///< Whether the current character is the first character of a new line. - bool mIsNewParagraphCharacter:1; ///< Whether the current character is a new paragraph character. - bool mIsWhiteSpace:1; ///< Whether the current character is a white space. - bool mIsVisible:1; ///< Whether the current character is visible. -}; - -/** - * Parameters used to calculate the gradient of text-actors when fading is enabled. - */ -struct FadeParameters -{ - /** - * Default constructor. - * - * Initializes all members to their defaults. - */ - FadeParameters(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~FadeParameters(); - - float mRightFadeBoundary; ///< Distance from the right edge of the text-view to the right edge of the fade boundary. - float mRightFadeThreshold; ///< Point from where fade out starts (by right edge). - float mRightFadeBoundaryOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - float mRightFadeThresholdOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - Vector2 mRightAlphaCoeficients; ///< The fade out rect coeficients for the right side of the text-view. - float mLeftFadeBoundary; ///< Distance from the left edge of the text-view to the left edge of the fade boundary. - float mLeftFadeThreshold; ///< Point from where fade out starts (by left edge). - float mLeftFadeBoundaryOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - float mLeftFadeThresholdOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - Vector2 mLeftAlphaCoeficients; ///< The fade out rect coeficients for the left side of the text-view. - float mTopFadeBoundary; ///< Distance from the top edge of the text-view to the top edge of the fade boundary. - float mTopFadeThreshold; ///< Point from where fade out starts (by top edge). - float mTopFadeBoundaryOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - float mTopFadeThresholdOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - Vector2 mTopAlphaCoeficients; ///< The fade out rect coeficients for the top side of the text-view. - float mBottomFadeBoundary; ///< Distance from the bottom edge of the text-view to the bottom edge of the fade boundary. - float mBottomFadeThreshold; ///< Point from where fade out starts (by bottom edge). - float mBottomFadeBoundaryOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - float mBottomFadeThresholdOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - Vector2 mBottomAlphaCoeficients; ///< The fade out rect coeficients for the bottom side of the text-view. - bool mIsPartiallyVisible:1; ///< Whether the current character is partially visible. -}; - -/** - * Parameters used to calculate the ellipsize. - */ -struct EllipsizeParameters -{ - /** - * Default constructor. - * - * Initializes all members to their defaults. - */ - EllipsizeParameters(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~EllipsizeParameters(); - - Vector3 mPosition; ///< Position of the first character of the ellipsize text. - float mLineDescender; ///< Distance from the base line to the bottom. - float mLineWidth; ///< Current line's width. - Size mEllipsizeBoundary; ///< Where to start to ellipsize a line. - std::size_t mFirstIndex; ///< Global index within the whole text of the first character of the line. - std::size_t mLastIndex; ///< Global index within the whole text of the last character of the line. - bool mEllipsizeLine:1; ///< Whether current line must be ellipsized. - bool mIsLineWidthFullyVisible:1; ///< Whether current line fits in text-view's width. - bool mIsLineHeightFullyVisible:1; ///< Whether current line fits in text-view's height. - bool mIsNextLineFullyVisibleHeight:1; ///< Whether next line fits in text-view's height. - bool mCreateEllipsizedTextActors:1; ///< Whether to create text-actors for the ellipsized text. - bool mLineFits:1; ///< Whether the current line fits in the boundary of the text-view. - bool mWordFits:1; ///< Whether the current word fits in the boundary of the text-view. -}; - -/** - * Stores underline info for a group of consecutive characters in the same line. - */ -struct UnderlineInfo -{ - /** - * Default constructor. - * - * Initializes all members to their defaults. - */ - UnderlineInfo(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~UnderlineInfo(); - - float mMaxHeight; ///< The maximum height. - float mMaxThickness; ///< The maximum underline's thickness. - float mPosition; ///< The underline's position of the character with the maximum underline's thickness. -}; - -/** - * Stores underline info for each group of consecutive underlined characters. - * It also stores some status used when traversing the whole text. - */ -struct TextUnderlineStatus -{ - /** - * Default constructor. - * - * Initializes each member to its default. - */ - TextUnderlineStatus(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~TextUnderlineStatus(); - - std::vector mUnderlineInfo; ///< Underline info for each group of consecutive underlined characters. - std::size_t mCharacterGlobalIndex; ///< Global index (within the whole text) to current character. - std::size_t mLineGlobalIndex; ///< Index to current line. It takes into account the current layout configuration (is not the number of \n) - bool mCurrentUnderlineStatus:1; ///< Whether current character is underlined. -}; - -/** - * Stores layout information of a line. - */ -struct LineLayoutInfo -{ - /** - * Default constructor. - * - * Initializes each member to its default. - */ - LineLayoutInfo(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~LineLayoutInfo(); - - float mLineLength; ///< The length of the portion of the paragraph which fits on the text-view width. - float mMaxCharHeight; ///< The maximum height of all characters of the portion of the paragraph which fits on the text-view width. - float mMaxAscender; ///< The maximum ascender of all characters of the portion of the paragraph which fits on the text-view width. -}; - -/** - * Calculates the layout info of the portion of the paragraph which fits on the text-view width. - * - * @param[in] parentWidth Text-view width - * @param[in] indices Indices to the word and character. - * @param[in] paragraphLayoutInfo Layout info for the paragraph. - * @param[in] splitPolicy Whether a paragraph is wraped by word, by character or by word and character. - * @param[in] shrinkFactor Shrink factor used. - * @param[out] layoutInfo Layout information of the part of the paragraph which fits in the text-view width. - */ -void CalculateLineLayout( float parentWidth, - const TextViewProcessor::TextInfoIndices& indices, - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo, - HorizontalWrapType splitPolicy, - float shrinkFactor, - LineLayoutInfo& layoutInfo ); - -/** - * Reorders the text layout of each line of each paragraph of the text. - * - * @param[in,out] relayoutData The text-view's data structures. - */ -void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData ); - -/** - * Calculates the \e x offset position for the whole text. - * - * @param[in] horizontalTextAlignment The horizontal alignment type. - * @param[in] parentWidth The parent's width. - * @param[in] wholeTextWidth The whole text's width. - * @return The \e x position offset. - */ -float CalculateXoffset( Toolkit::Alignment::Type horizontalTextAlignment, float parentWidth, float wholeTextWidth ); - -/** - * Calculates the \e y offset position for the whole text. - * - * @param[in] verticalTextAlignment The vertical alignment type. - * @param[in] parentHeight The parent's height. - * @param[in] wholeTextHeight The whole text's height. - * @return The \e y position offset. - */ -float CalculateYoffset( Toolkit::Alignment::Type verticalTextAlignment, float parentHeight, float wholeTextHeight ); - -/** - * Calculates the \e x offset position for one line. - * - * @param[in] justification The line justification type. - * @param[in] wholeTextWidth The whole text's width. - * @param[in] lineLength The line's length. - * @return The \e x position offset. - * - */ -float CalculateJustificationOffset( Toolkit::TextView::LineJustification justification, float wholeTextWidth, float lineLength ); - -/** - * Whether text-actor is visible for Fade and Ellipsize exceed policies. - * - * It does different visibility tests according the given parameter \e type. @see VisibilityTestType. - * - * @param[in] position Position of the character. - * @param[in] size Size of the character. - * @param[in] parentSize Parent's size. - * @param[in] type One of FULLY_VISIBLE, PARTIALLY_VISIBLE, PARTIALLY_VISIBLE_WIDTH or PARTIALLI_VISIBLE_HEIGHT. - * @return \e true if is visible. - */ -bool IsVisible( const Vector3& position, const Size& size, const Size& parentSize, VisibilityTestType type ); - -/** - * Calculates the coeficients of the rect equation for the two given points. - * - * @param[in] p0 A point of the rect. - * @param[in] p1 Another point of the rect. - * - * @return The \e gradient is returned in the \e x member and the \e constant \e term is returned in the \e y value. - */ -Vector2 CalculateRectParameters( const Vector2& p0, const Vector2& p1 ); - -/** - * Aligns the whole text within the text-view. - * - * @param[in] layoutParameters The layout parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Calculates the bearing for the given character. - * - * @param[in,out] characterLayoutInfo Character layout info. - * @param[in,out] relayoutData The text-view's data structures. - */ -void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - TextView::RelayoutData& relayoutData ); - -/** - * Updates the character's layout info table. - * - * This table is used to pass the size, the position and other layout info to other controls/actors. - * - * @param[in,out] minMaxXY The boundary box of the whole text. - * @param[in,out] wordLayoutInfo Word layout info. - * @param[in,out] characterLayoutInfo Character layout info. - * @param[in,out] relayoutParameters Temporary layout parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateLayoutInfoTable( Vector4& minMaxXY, - TextViewProcessor::WordLayoutInfo& wordLayoutInfo, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - RelayoutParameters& relayoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Calculates the text-actor visibility and fade parameters. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] characterLayoutInfo Character layout info. - * @param[in] style The style of the character. Used to get the color (and alpha) of the character. - * @param[in,out] relayoutParameters Temporary layout parameters. - * @param[in,out] fadeParameters Temporary fade parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - const TextStyle& style, - RelayoutParameters& relayoutParameters, - FadeParameters& fadeParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Calculates the text-actor visibility and creates eliipsize text-actors. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] characterLayoutInfo Character layout info. - * @param[in,out] ellipsizeParameters Temporary ellipsize parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void CalculateVisibilityForEllipsize( const Internal::TextView::LayoutParameters& layoutParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Creates the actors needed for the ellipsized text. - * - * @param[in,out] ellipsizeParameters Temporary ellipsize parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Replace the text which exceeds the boundary by the ellipsis text. - * - * @param[in] layoutParameters The layout parameters. - * @param[in,out] ellipsisParameters Temporary ellipsis parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, - EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Traverse all text data structure setting its visibility to true. - * - * @param[in,out] relayoutData The text-view's data structures. - */ -void SetTextVisible( TextView::RelayoutData& relayoutData ); - -/** - * Calculates the visibility and fade parameters. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); -/** - * Calculates the visibility for text ellipsize. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); -/** - * Calculates the visibility and fade parameters. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateVisibility( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Traverse all text initializing all non initialized text-actor handles - * and updating text-actor handles with new size, position, ... - * - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in] createGlyphActors Whether to create RenderableActor for text-actors or emojis. - */ -void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - bool createGlyphActors ); - -/** - * Traverses the whole text and for each piece of underlined text, - * it calculates the maximum thickness and the position of that particular piece of underlined text. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData ); - -/** - * Traverses the whole text and for each piece of underlined text, - * it sets the previously calculated maximum thickness and the position of that particular piece of underlined text. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void SetUnderlineInfo( TextView::RelayoutData& relayoutData ); - -/** - * Remove renderable-actor from the text-view. - * - * @param[in,out] textView The text-view. - * @param[in] glyphActors renderable-actors to be removed from the text-view. - */ -void RemoveGlyphActors( Actor textView, - const std::vector& glyphActors ); - -/** - * Inserts the text-actors into the text-view and the text-actor's list. - * - * @param[in,out] textView The text-view. - * @param[in,out] relayoutData The text-view's data structures. - */ -void InsertToTextView( Actor textView, - TextView::RelayoutData& relayoutData ); - -/** - * Retrieves a new glyph-actor from the cache of text-actors or creating a new one if it's empty. - * - * @param[in] text The text-actor's text. - * @param[in] style The text-actor's style. - * @param[in] cache The cache of text-actors. - * - * @return a RenderableActor with the text's glyph. - */ -RenderableActor CreateGlyphActor( const Text& text, const TextStyle& style, TextActorCache& cache ); - -} // namespace TextViewRelayout - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_RELAYOUT_UTILITIES_H__ diff --git a/dali-toolkit/internal/controls/text-view/split-by-char-policies.cpp b/dali-toolkit/internal/controls/text-view/split-by-char-policies.cpp deleted file mode 100644 index 5eb829f..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-char-policies.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByChar -{ - -namespace -{ - -Vector3 NoShrinkWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - - if( ( relayoutParameters.mIsNewLine || - relayoutParameters.mIsFirstCharacter || - ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) ) ) - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - // Calculate the line length and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByCharacter, - 1.f, // Shrink factor - subLineInfo ); - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - TextViewRelayout::RelayoutParameters relayoutParameters; - - // clear - relayoutData.mCharacterLayoutInfoTable.clear(); - relayoutData.mLines.clear(); - relayoutData.mTextSizeForRelayoutOption = Size(); - - // Calculate the text size for split by char. - Vector4 minMaxXY( std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::min(), - std::numeric_limits::min() ); - - relayoutData.mShrinkFactor = 1.f; // Shrink factor used when the exceed policy contains ShrinkToFit - - relayoutParameters.mPositionOffset = Vector3::ZERO; - relayoutParameters.mIsFirstCharacter = true; - relayoutParameters.mIndices.mParagraphIndex = 0u; - relayoutParameters.mCharacterGlobalIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - relayoutParameters.mIsNewLine = true; - relayoutParameters.mParagraphSize = paragraphLayoutInfo.mSize; - relayoutParameters.mIndices.mWordIndex = 0u; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType; - relayoutParameters.mIsNewParagraphCharacter = TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType; - - relayoutParameters.mIsFirstCharacterOfWord = true; - relayoutParameters.mWordSize = wordLayoutInfo.mSize; - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - relayoutParameters.mCharacterSize = characterLayoutInfo.mSize; - - switch( layoutParameters.mExceedPolicy ) - { - case TextView::OriginalShrink: - case TextView::SplitOriginal: - case TextView::SplitFade: - case TextView::SplitEllipsizeEnd: - case TextView::SplitShrink: - case TextView::ShrinkOriginal: - case TextView::ShrinkFade: - case TextView::Shrink: - case TextView::EllipsizeEndOriginal: - case TextView::EllipsizeEnd: // Fall Through - { - DALI_LOG_WARNING( "SplitByChar::CalculateSizeAndPosition() policy not implemented.\n" ); - break; - } - case TextView::OriginalFade: - case TextView::FadeOriginal: - case TextView::Original: - case TextView::Fade: // Fall Through - { - characterLayoutInfo.mPosition = NoShrinkWhenExceedPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f ); - break; - } - default: - { - DALI_LOG_WARNING( "SplitByChar::CalculateSizeAndPosition() policy combination not possible.\n" ); - } - } - - // Get last line info and calculate the bearing (used to align glyphs with the baseline). - TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData ); - - // updates min and max position to calculate the text size for split by char. - TextViewRelayout::UpdateLayoutInfoTable( minMaxXY, - wordLayoutInfo, - characterLayoutInfo, - relayoutParameters, - relayoutData ); - - ++relayoutParameters.mCharacterGlobalIndex; - relayoutParameters.mIsFirstCharacter = false; - relayoutParameters.mIsNewLine = false; - } // end characters - } // end words - } // end paragraphs - - if( relayoutData.mCharacterLayoutInfoTable.empty() ) - { - relayoutData.mTextSizeForRelayoutOption = Size(); - } - else - { - relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x; - relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y; - } - - // Check if the last character is a new paragraph character. In that case the height should be added. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( paragraphLayoutInfo.mWordsLayoutInfo.empty() ) // if it's empty, it means the last character is a new paragraph character. - { - relayoutData.mTextSizeForRelayoutOption.height += paragraphLayoutInfo.mSize.height; - } - } -} - -} // namespace - -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION ) - { - CalculateSizeAndPosition( layoutParameters, - relayoutData ); - - TextViewRelayout::ReorderRightToLeftLayout( relayoutData ); - - TextViewRelayout::SetUnderlineInfo( relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT ) - { - TextViewRelayout::UpdateAlignment( layoutParameters, - relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY ) - { - TextViewRelayout::UpdateVisibility( layoutParameters, - visualParameters, - relayoutData ); - } - - const bool initializeTextActors = relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS; - const bool updateTextActors = relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE; - if( initializeTextActors || updateTextActors ) - { - TextViewRelayout::UpdateTextActorInfo( visualParameters, - relayoutData, - initializeTextActors ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) - { - TextViewRelayout::InsertToTextView( textView, - relayoutData ); - } -} - -} // namespace SplitByChar - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/split-by-char-policies.h b/dali-toolkit/internal/controls/text-view/split-by-char-policies.h deleted file mode 100644 index a0624ca..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-char-policies.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_SPLIT_BY_CHAR_POLICIES_H__ -#define __DALI_TOOLKIT_INTERNAL_SPLIT_BY_CHAR_POLICIES_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByChar -{ - -/** - * Sets text-actor's size and position accordingly with the given text-view's size and layout parameters. - * Visible text-actors are added to the text-view. Non visible actors are not added. - * - * @param[in] textView The handle to the text-view actor. - * @param[in] relayoutOperationMask Mask which defines which operations need to be done in the relayout process. - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in] relayoutData The text-view's data structures which are modified by this function. - */ -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); - -} // namespace SplitByChar - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_SPLIT_BY_CHAR_POLICIES_H__ diff --git a/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.cpp b/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.cpp deleted file mode 100644 index f74966d..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByNewLineChar -{ - -namespace -{ - -Vector3 SplitPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - - if( relayoutParameters.mIsNewLine || - relayoutParameters.mIsFirstCharacter || - ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) ) - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByParagraphCharacterAndSplit, - 1.f, // Shrink factor - subLineInfo ); - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // clear - relayoutData.mCharacterLayoutInfoTable.clear(); - relayoutData.mLines.clear(); - relayoutData.mTextSizeForRelayoutOption = Size(); - relayoutData.mShrinkFactor = 1.f; - - // Calculates the text size for split by char. - Vector4 minMaxXY( std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::min(), - std::numeric_limits::min() ); - - TextViewRelayout::RelayoutParameters relayoutParameters; - - if( TextView::ShrinkOriginal == layoutParameters.mExceedPolicy ) - { - if( relayoutData.mTextLayoutInfo.mWholeTextSize.width > relayoutData.mTextViewSize.width ) - { - relayoutData.mShrinkFactor = relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mWholeTextSize.width; - } - } - else if( TextView::Shrink == layoutParameters.mExceedPolicy ) - { - if( ( relayoutData.mTextLayoutInfo.mWholeTextSize.width > relayoutData.mTextViewSize.width ) || - ( relayoutData.mTextLayoutInfo.mWholeTextSize.height > relayoutData.mTextViewSize.height ) ) - { - relayoutData.mShrinkFactor = std::min( relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mWholeTextSize.width, - relayoutData.mTextViewSize.height / relayoutData.mTextLayoutInfo.mWholeTextSize.height ); - } - } - - relayoutParameters.mIsFirstCharacter = true; - relayoutParameters.mIndices.mParagraphIndex = 0u; - relayoutParameters.mPositionOffset = Vector3::ZERO; - relayoutParameters.mCharacterGlobalIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - relayoutParameters.mParagraphSize = paragraphLayoutInfo.mSize * relayoutData.mShrinkFactor; - - relayoutParameters.mIsNewLine = true; - relayoutParameters.mIndices.mWordIndex = 0u; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType; - relayoutParameters.mIsNewParagraphCharacter = TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType; - - relayoutParameters.mIsFirstCharacterOfWord = true; - relayoutParameters.mWordSize = wordLayoutInfo.mSize; - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - relayoutParameters.mCharacterSize = characterLayoutInfo.mSize; - - relayoutParameters.mCharacterSize = characterLayoutInfo.mSize; - - switch( layoutParameters.mExceedPolicy ) - { - case TextView::OriginalShrink: - case TextView::SplitShrink: - case TextView::ShrinkFade: // Fall Through - { - DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() policy not implemented.\n" ); - break; - } - case TextView::Original: // Fall Through - case TextView::ShrinkOriginal: // Fall Through - case TextView::Shrink: // Fall Through - case TextView::OriginalFade: // Fall Through - case TextView::FadeOriginal: // Fall Through - case TextView::Fade: // Fall Through - case TextView::EllipsizeEndOriginal: // Fall Through - case TextView::EllipsizeEnd: // Fall Through - { - if( relayoutParameters.mIsNewLine ) - { - relayoutParameters.mPositionOffset.x = 0.f; - relayoutParameters.mPositionOffset.y += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor; - } - - characterLayoutInfo.mPosition = relayoutParameters.mPositionOffset; - - relayoutParameters.mPositionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor; - - if( relayoutParameters.mIsNewLine || - relayoutParameters.mIsFirstCharacter ) - { - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = relayoutParameters.mParagraphSize; // Size of this piece of paragraph. - lineInfo.mAscender = paragraphLayoutInfo.mAscender * relayoutData.mShrinkFactor; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - } - break; - } - case TextView::SplitOriginal: - case TextView::SplitFade: - case TextView::SplitEllipsizeEnd: // Fall Through - { - characterLayoutInfo.mPosition = SplitPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f ); - break; - } - default: - { - DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() Layout configuration not possible.\n" ); - break; - } - } - - // Get last line info and calculate the bearing (used to align glyphs with the baseline). - TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData ); - - // updates min and max position to calculate the text size for split by new line char. - TextViewRelayout::UpdateLayoutInfoTable( minMaxXY, - wordLayoutInfo, - characterLayoutInfo, - relayoutParameters, - relayoutData ); - - ++relayoutParameters.mCharacterGlobalIndex; - relayoutParameters.mIsFirstCharacter = false; - relayoutParameters.mIsNewLine = false; - } // end characters - } // end words - } // end paragraphs - - if( relayoutData.mCharacterLayoutInfoTable.empty() ) - { - relayoutData.mTextSizeForRelayoutOption = Size(); - } - else - { - relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x; - relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y; - } - - // Check if the last character is a new paragraph character. In that case the height should be added. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( paragraphLayoutInfo.mWordsLayoutInfo.empty() ) // if it's empty, it means the last character is a new paragraph character. - { - relayoutData.mTextSizeForRelayoutOption.height += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor; - } - } -} - -} // namespace - -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION ) - { - CalculateSizeAndPosition( layoutParameters, - relayoutData ); - - TextViewRelayout::ReorderRightToLeftLayout( relayoutData ); - - TextViewRelayout::SetUnderlineInfo( relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT ) - { - TextViewRelayout::UpdateAlignment( layoutParameters, - relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY ) - { - TextViewRelayout::UpdateVisibility( layoutParameters, - visualParameters, - relayoutData ); - } - - const bool initializeTextActors = relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS; - const bool updateTextActors = relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE; - if( initializeTextActors || updateTextActors ) - { - TextViewRelayout::UpdateTextActorInfo( visualParameters, - relayoutData, - initializeTextActors ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) - { - TextViewRelayout::InsertToTextView( textView, - relayoutData ); - } -} - -} // namespace SplitByNewLineChar - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h b/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h deleted file mode 100644 index 4869d60..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_SPLIT_BY_NEW_LINE_CHAR_POLICIES_H__ -#define __DALI_TOOLKIT_INTERNAL_SPLIT_BY_NEW_LINE_CHAR_POLICIES_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByNewLineChar -{ - -/** - * Sets text-actor's size and position accordingly with the given text-view's size and layout parameters. - * Visible text-actors are added to the text-view. Non visible actors are not added. - * - * @param[in] textView The handle to the text-view actor. - * @param[in] relayoutOperationMask Mask which defines which operations need to be done in the relayout process. - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in] relayoutData The text-view's data structures which are modified by this function. - */ -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); - -} // namespace SplitByNewLineChar - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_SPLIT_BY_NEW_LINE_CHAR_POLICIES_H__ diff --git a/dali-toolkit/internal/controls/text-view/split-by-word-policies.cpp b/dali-toolkit/internal/controls/text-view/split-by-word-policies.cpp deleted file mode 100644 index b5bd9f6..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-word-policies.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByWord -{ - -namespace -{ - -Vector3 OriginalPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - - if( relayoutParameters.mIsNewLine || - relayoutParameters.mIsFirstCharacter || - ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + relayoutParameters.mWordSize.width > relayoutData.mTextViewSize.width ) ) ) - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - // Calculates the length of the portion of the paragraph which doesn't exceed the text-view's width and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByWord, - 1.f, // Shrink factor - subLineInfo ); - - if( subLineInfo.mLineLength < Math::MACHINE_EPSILON_1000 ) - { - // It may mean there is a word which is actually longer than the width of the text-view. - // In that case the length of this word is needed. - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + relayoutParameters.mIndices.mWordIndex ) ); - subLineInfo.mLineLength = wordLayoutInfo.mSize.width; - } - } - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -/** - * Calculates character position. - * @param[in] relayoutParameters Temporary layout parameters (previous size, previous position, ... ) - * @param[in] layoutParameters The layout parameters. - * @param[in] relayoutData The text-view's data structures. - * @return The character's position. - */ -Vector3 SplitWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - - if( ( relayoutParameters.mIsNewLine || relayoutParameters.mIsFirstCharacter ) || - ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + relayoutParameters.mWordSize.width > relayoutData.mTextViewSize.width ) ) || - ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) ) - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - // Calculates the line length and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByWordAndSplit, - 1.f, // Shrink factor. - subLineInfo ); - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -/** - * Calculates character position. - * @param[in] relayoutParameters Temporary layout parameters (previous size, previous position, ... ) - * @param[in] layoutParameters The layout parameters. - * @param[in] relayoutData The text-view's data structures. - * @return The character's position. - */ -Vector3 ShrinkWidthWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - const Size wordSize = relayoutParameters.mWordSize * relayoutData.mShrinkFactor; - - if( ( relayoutParameters.mIsNewLine || relayoutParameters.mIsFirstCharacter ) || // isNewLine is true when '\n' is found. - ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + wordSize.width > relayoutData.mTextViewSize.width ) ) ) // The word doesn't fit in the parent width. - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - // Calculates the line length and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByWord, - relayoutData.mShrinkFactor, - subLineInfo ); - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * relayoutData.mShrinkFactor, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -void CalculatePositionsForShrinkWhenExceed( TextView::RelayoutData& relayoutData, - const TextView::LayoutParameters& layoutParameters, - const float shrinkFactor, - float& newTextHeight ) -{ - const float parentWidth = relayoutData.mTextViewSize.width; - TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo; - - // Reset the text height. This value is returned in order to shrink further or not the text. - newTextHeight = 0.f; - - // Whether the first character is being processed. - bool isFirstChar = true; - - // Stores the size of the previous character. - Size previousSize; - // Stores the position of the previous character. - Vector3 previousPosition; - - // Reset the index of paragraphs. - TextViewProcessor::TextInfoIndices indices; - - // Whether the last character of the whole text is a new paragraph char. - // This information is used to increase or not the height of the whole text by one line. - // Increase the whole text's height by one line is useful i.e. in TextInput to place the cursor - // after pressing 'Enter' in the last paragraph. - bool isLastCharacterNewParagraphChar = false; - // Stores the height of the last character. This height used to be added to the whole text height if - // isLastCharacterNewParagraphChar is true. - float lastCharHeight = 0.f; - - relayoutData.mLines.clear(); - std::size_t characterGlobalIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt, ++indices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt ); - - // The next character is in a new line. - bool isNewLine = true; - - // Reset the index of words. - indices.mWordIndex = 0u; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt, ++indices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt ); - - // Reset the index of the character. - indices.mCharacterIndex = 0u; - - // Whether current character is the first of the word. - bool isFirstCharOfWord = true; - const float wordOffset = previousPosition.x + previousSize.width; - - isLastCharacterNewParagraphChar = ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - charIt != charEndIt; - ++charIt, ++indices.mCharacterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt ); - lastCharHeight = characterLayoutInfo.mSize.height * shrinkFactor; - - const float previousPositionY = isFirstChar ? 0.f : previousPosition.y; - - if( ( isNewLine || isFirstChar ) || - ( isFirstCharOfWord && ( wordOffset + wordLayoutInfo.mSize.width * shrinkFactor > parentWidth ) ) ) - { - isFirstChar = false; - - // Calculates the line length and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - TextViewRelayout::CalculateLineLayout( parentWidth, - indices, - paragraphLayoutInfo, - TextViewRelayout::WrapByWord, - shrinkFactor, - subLineInfo ); - - characterLayoutInfo.mPosition = Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor, 0.f ); - - newTextHeight += subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor; - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = characterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - } - else - { - characterLayoutInfo.mPosition = previousPosition + Vector3( previousSize.width, 0.f, 0.f ); - } - - // Get last line info and calculate the bearing. - const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1u ) ); - const float bearingOffset = ( ( lineInfo.mSize.height - lineInfo.mAscender ) - ( characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender ) ) * shrinkFactor; - - previousSize = characterLayoutInfo.mSize * shrinkFactor; - previousPosition = characterLayoutInfo.mPosition; - characterLayoutInfo.mPosition.y -= bearingOffset; - isFirstCharOfWord = false; - isNewLine = false; - - ++characterGlobalIndex; - } - } - } - - if( isLastCharacterNewParagraphChar ) - { - newTextHeight += lastCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor; - } -} - -float RelayoutForShrinkToFit( TextView::RelayoutData& relayoutData, - const TextView::LayoutParameters& layoutParameters ) -{ - const Size& textViewSize = relayoutData.mTextViewSize; - TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo; - - // First step is assure the longest word fits in the text view width. - float shrinkFactor = ( textLayoutInfo.mMaxWordWidth > textViewSize.width ? textViewSize.width / textLayoutInfo.mMaxWordWidth : 1.f ); - - // Out parameter. Will store the new text height after relayout the text. - float newTextHeight = 0.f; - - // Relayout the text for the given character's sizes. - CalculatePositionsForShrinkWhenExceed( relayoutData, - layoutParameters, - shrinkFactor, - newTextHeight ); - - if( newTextHeight > textViewSize.height ) - { - // After relayouting, the text exceeds the text view height. - // Find a new scale factor to fit all the text in the text view size is needed. - - // The next algorithm does some iterations to calculate an acceptable scale factor. - // Some magic numbers are defined. - - const float MIN_RATIO( 0.90f ); // The algorithm finishes if the ratio - const float MAX_RATIO( 1.00f ); // new_text_height / text_view_height is between this two values - const unsigned int MAX_ITERATIONS( 8u ); // or max_iteration is reached. - - float ratio = newTextHeight / textViewSize.height; - - float maxScaleFactor = shrinkFactor; // bigger scale factors than maxScaleFactor will produce a too big text. - float minScaleFactor = shrinkFactor * ( textViewSize.height / newTextHeight ); // smaller scale factors than minScaleFactor will produce a too small text. - - for( unsigned int iterations = 0u; ( ( MIN_RATIO > ratio ) || ( ratio > MAX_RATIO ) ) && ( iterations < MAX_ITERATIONS ); ++iterations ) - { - // Calculates the new scale factor. - // The new scale factor is always between the min and max scale factors. - // If ratio < 1 it means the text is too small and a bigger scale factor is needed. In this case the algorithm selects a new scale factor close to - // minScaleFactor. Alternatively if the text is too big a new scale factor close to maxScaleFactor is selected. - // This allows the text shrink or grow smoothly. - shrinkFactor = minScaleFactor + ( ratio < 1.f ? 0.4f : 0.6f ) * ( maxScaleFactor - minScaleFactor ); - - CalculatePositionsForShrinkWhenExceed( relayoutData, // Relayout the text for the given character's sizes. - layoutParameters, - shrinkFactor, - newTextHeight ); - - // Calculates the new text size ratio. It allows update the min and max scale factors. - // If the ratio is not good enough a new scale factor between min and max could be used in next iteration. - ratio = newTextHeight / textViewSize.height; - if( ratio < 1.f ) - { - minScaleFactor = shrinkFactor; - } - else - { - maxScaleFactor = shrinkFactor; - } - } - - if( ratio > MAX_RATIO ) - { - // The algorithm didn't find an acceptable scale factor. - // In that case the text is shrunk to fit in the boundaries of the text view actor. - shrinkFactor = minScaleFactor; - - CalculatePositionsForShrinkWhenExceed( relayoutData, - layoutParameters, - shrinkFactor, - newTextHeight ); - } - } - - return shrinkFactor; -} - -void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - TextViewRelayout::RelayoutParameters relayoutParameters; - - // clear - relayoutData.mCharacterLayoutInfoTable.clear(); - relayoutData.mLines.clear(); - relayoutData.mTextSizeForRelayoutOption = Size(); - - // Calculates the text size for split by char. - Vector4 minMaxXY( std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::min(), - std::numeric_limits::min() ); - - relayoutData.mShrinkFactor = 1.f; // Shrink factor used when the exceed policy contains ShrinkToFit - - if( TextView::Shrink == layoutParameters.mExceedPolicy ) - { - // Relays-out the text for the shrink to fit policy. - relayoutData.mShrinkFactor = RelayoutForShrinkToFit( relayoutData, layoutParameters ); - } - else if( TextView::ShrinkOriginal == layoutParameters.mExceedPolicy ) - { - relayoutData.mShrinkFactor = ( relayoutData.mTextLayoutInfo.mMaxWordWidth > relayoutData.mTextViewSize.width ? relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mMaxWordWidth : 1.f ); - } - - relayoutParameters.mPositionOffset = Vector3::ZERO; - relayoutParameters.mIsFirstCharacter = true; - relayoutParameters.mIndices.mParagraphIndex = 0u; - relayoutParameters.mCharacterGlobalIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - relayoutParameters.mIsNewLine = true; - relayoutParameters.mParagraphSize = paragraphLayoutInfo.mSize; - relayoutParameters.mIndices.mWordIndex = 0u; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType; - relayoutParameters.mIsNewParagraphCharacter = TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType; - - relayoutParameters.mIsFirstCharacterOfWord = true; - relayoutParameters.mWordSize = wordLayoutInfo.mSize; - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - ( characterLayoutIt != endCharacterLayoutIt ); - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - relayoutParameters.mCharacterSize = characterLayoutInfo.mSize; - - switch( layoutParameters.mExceedPolicy ) - { - case TextView::OriginalShrink: - case TextView::SplitShrink: - case TextView::ShrinkFade: - { - DALI_LOG_WARNING( "SplitByWord::CalculateSizeAndPosition() policy not implemented.\n" ); - break; - } - case TextView::Original: - case TextView::OriginalFade: - case TextView::FadeOriginal: - case TextView::Fade: - case TextView::EllipsizeEndOriginal: - case TextView::EllipsizeEnd: // Fall Through - { - characterLayoutInfo.mPosition = OriginalPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f ); - break; - } - case TextView::SplitOriginal: - case TextView::SplitFade: - case TextView::SplitEllipsizeEnd: - { - characterLayoutInfo.mPosition = SplitWhenExceedPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f ); - break; - } - case TextView::ShrinkOriginal: - { - characterLayoutInfo.mPosition = ShrinkWidthWhenExceedPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor, 0.f, 0.f ); - break; - } - case TextView::Shrink: - { - // Does nothing. All the job has been done in the RelayoutForShrinkToFit() function. - break; - } - default: - { - DALI_LOG_WARNING( "SplitByWord::CalculateSizeAndPosition() policy combination not possible.\n" ); - } - } - - // Get last line info and calculate the bearing (used to align glyphs with the baseline). - if( TextView::Shrink != layoutParameters.mExceedPolicy ) - { - TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData ); - } - - // updates min and max position to calculate the text size for split by word. - TextViewRelayout::UpdateLayoutInfoTable( minMaxXY, - wordLayoutInfo, - characterLayoutInfo, - relayoutParameters, - relayoutData ); - - ++relayoutParameters.mCharacterGlobalIndex; - relayoutParameters.mIsFirstCharacter = false; - relayoutParameters.mIsFirstCharacterOfWord = false; - relayoutParameters.mIsNewLine = false; - } // end characters - } // end words - } // end paragraphs - - if( relayoutData.mCharacterLayoutInfoTable.empty() ) - { - relayoutData.mTextSizeForRelayoutOption = Size(); - } - else - { - relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x; - relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y; - } - - // Check if the last character is a new paragraph character. In that case the height should be added. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( paragraphLayoutInfo.mWordsLayoutInfo.empty() ) // if it's empty, it means the last character is a new paragraph character. - { - relayoutData.mTextSizeForRelayoutOption.height += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor; - } - } -} - -} // namespace - -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION ) - { - CalculateSizeAndPosition( layoutParameters, - relayoutData ); - - TextViewRelayout::ReorderRightToLeftLayout( relayoutData ); - - TextViewRelayout::SetUnderlineInfo( relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT ) - { - TextViewRelayout::UpdateAlignment( layoutParameters, - relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY ) - { - TextViewRelayout::UpdateVisibility( layoutParameters, - visualParameters, - relayoutData ); - } - const bool initializeTextActors = relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS; - const bool updateTextActors = relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE; - if( initializeTextActors || updateTextActors ) - { - TextViewRelayout::UpdateTextActorInfo( visualParameters, - relayoutData, - initializeTextActors ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) - { - TextViewRelayout::InsertToTextView( textView, - relayoutData ); - } -} - -} // namespace SplitByWord - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/split-by-word-policies.h b/dali-toolkit/internal/controls/text-view/split-by-word-policies.h deleted file mode 100644 index df4ce3a..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-word-policies.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_SPLIT_BY_WORD_POLICIES_H__ -#define __DALI_TOOLKIT_INTERNAL_SPLIT_BY_WORD_POLICIES_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByWord -{ - -/** - * Sets text-actor's size and position accordingly with the given text-view's size and layout parameters. - * Visible text-actors are added to the text-view. Non visible actors are not added. - * - * @param[in] textView The handle to the text-view actor. - * @param[in] relayoutOperationMask Mask which defines which operations need to be done in the relayout process. - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in] relayoutData The text-view's data structures which are modified by this function. - */ -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); - -} // namespace SplitByWord - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_SPLIT_BY_WORD_POLICIES_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-actor-cache.cpp b/dali-toolkit/internal/controls/text-view/text-actor-cache.cpp deleted file mode 100644 index f33cccc..0000000 --- a/dali-toolkit/internal/controls/text-view/text-actor-cache.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -TextActorCache::TextActorCache() -: mTextActors() -{ -} - -TextActorCache::~TextActorCache() -{ -} - -void TextActorCache::InsertTextActors( const std::vector& textActors ) -{ - mTextActors.insert( mTextActors.end(), textActors.rbegin(), textActors.rend() ); -} - -TextActor TextActorCache::RetrieveTextActor() -{ - // Text-actors are inserted in the order needed to retrieve always the last one. - - // Returns a non initialized handle if the cache is empty. - TextActor textActor; - - if( !mTextActors.empty() ) - { - textActor = mTextActors.back(); - mTextActors.pop_back(); - } - - return textActor; -} - -void TextActorCache::ClearTexts() -{ - for( std::vector::iterator it = mTextActors.begin(); it != mTextActors.end(); ++it ) - { - (*it).SetText(""); - } -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-actor-cache.h b/dali-toolkit/internal/controls/text-view/text-actor-cache.h deleted file mode 100644 index c826c27..0000000 --- a/dali-toolkit/internal/controls/text-view/text-actor-cache.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_ACTOR_CACHE_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_ACTOR_CACHE_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * Stores text-actors to be reused. - * - * Is it asumed that the first text-actor of a group of text-actors added to the cache is the first one to be rehused. - */ -class TextActorCache -{ - -public: - /** - * Default constructor. - */ - TextActorCache(); - - /** - * Destructor. - */ - ~TextActorCache(); - - /** - * Inserts the given text-actors into the cache. - * - * First text-actor of the vector is the first one to be reused. - * - * @param[in] textActors The text-actors to be inserted into the cache. - */ - void InsertTextActors( const std::vector& textActors ); - - /** - * Retrieves a text-actor from the cache. - * - * @return A handle to a text-actor. It returns a non initialized handle if the cache has no text-actors. - */ - TextActor RetrieveTextActor(); - - /** - * Clears the text of the text-actor in the cache. - */ - void ClearTexts(); - -private: - std::vector mTextActors; ///< Stores cached text-actors. -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_ACTOR_CACHE_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp b/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp deleted file mode 100644 index d6b4146..0000000 --- a/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ - -BidirectionalParagraphInfo::BidirectionalParagraphInfo() -: mDirection( FRIBIDI_TYPE_ON ), - mCharactersTypeBuffer(), - mLevelsBuffer(), - mLogicalUnicodeBuffer() -{ -} - -BidirectionalParagraphInfo::~BidirectionalParagraphInfo() -{ -} - -BidirectionalParagraphInfo::BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info ) -: mDirection( info.mDirection ), - mCharactersTypeBuffer( info.mCharactersTypeBuffer ), - mLevelsBuffer( info.mLevelsBuffer ), - mLogicalUnicodeBuffer( info.mLogicalUnicodeBuffer ) -{ -} - -BidirectionalParagraphInfo& BidirectionalParagraphInfo::operator=( const BidirectionalParagraphInfo& info ) -{ - if( this != &info ) - { - mDirection = info.mDirection; - mCharactersTypeBuffer = info.mCharactersTypeBuffer; - mLevelsBuffer = info.mLevelsBuffer; - mLogicalUnicodeBuffer = info.mLogicalUnicodeBuffer; - } - - return *this; -} - -bool BidirectionalParagraphInfo::IsRightToLeftParagraph() const -{ - bool isRightToLeft = false; - - switch( mDirection ) - { - case FRIBIDI_PAR_LTR: // Left-To-Right paragraph. - case FRIBIDI_PAR_ON: // DirectiOn-Neutral paragraph. - case FRIBIDI_PAR_WLTR: // Weak Left To Right paragraph. - { - isRightToLeft = false; - break; - } - case FRIBIDI_PAR_RTL: // Right-To-Left paragraph. - case FRIBIDI_PAR_WRTL: // Weak Right To Left paragraph. - { - isRightToLeft = true; - break; - } - } - - return isRightToLeft; -} - -BidirectionalLineInfo::BidirectionalLineInfo() -: mCharacterParagraphIndex(), - mNumberOfCharacters(), - mText(), - mVisualToLogicalMap(), - mLogicalToVisualMap() -{ -} - -BidirectionalLineInfo::~BidirectionalLineInfo() -{ -} - -BidirectionalLineInfo::BidirectionalLineInfo( const BidirectionalLineInfo& info ) -: mCharacterParagraphIndex( info.mCharacterParagraphIndex ), - mNumberOfCharacters( info.mNumberOfCharacters ), - mText( info.mText ), - mVisualToLogicalMap( info.mVisualToLogicalMap ), - mLogicalToVisualMap( info.mLogicalToVisualMap ) -{ -} - -BidirectionalLineInfo& BidirectionalLineInfo::operator=( const BidirectionalLineInfo& info ) -{ - if( this != &info ) - { - mCharacterParagraphIndex = info.mCharacterParagraphIndex; - mNumberOfCharacters = info.mNumberOfCharacters; - mText = info.mText; - mVisualToLogicalMap = info.mVisualToLogicalMap; - mLogicalToVisualMap = info.mLogicalToVisualMap; - } - - return *this; -} - -bool BeginsRightToLeftCharacter( const Text& text ) -{ - for( size_t i = 0u, length = text.GetLength(); i < length; ++i ) - { - Character::CharacterDirection direction = text[i].GetCharacterDirection(); - if( direction != Character::Neutral ) - { - return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak ); - } - } - - return false; -} - -bool ContainsRightToLeftCharacter( const Dali::Text& text ) -{ - for( size_t i = 0u, length = text.GetLength(); i < length; ++i ) - { - Character::CharacterDirection direction = ( text[i] ).GetCharacterDirection(); - if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) ) - { - return true; - } - } - - return false; -} - -void ProcessBidirectionalText( Text& paragraph, BidirectionalParagraphInfo* info ) -{ - if( paragraph.IsEmpty() ) - { - // nothing to do if the paragraph is empty. - return; - } - - const std::size_t stringSize = paragraph.GetText().size(); - - // Text buffer in logical order. Coded in unicode. - info->mLogicalUnicodeBuffer.resize( stringSize + 1u, 0u ); - FriBidiChar* logicalUnicodeBufferPointer = &info->mLogicalUnicodeBuffer[0u]; - - // Converts from utf8 to unicode. - const std::size_t length = fribidi_charset_to_unicode( FRIBIDI_CHAR_SET_UTF8, paragraph.GetText().c_str(), stringSize, logicalUnicodeBufferPointer ); - - // Character type buffer. - info->mCharactersTypeBuffer.resize( length, 0u ); - - // Levels buffer. - info->mLevelsBuffer.resize( length, 0u ); - - // Joining type buffer. - std::vector joiningTypeBuffer; - joiningTypeBuffer.resize( length, 0u ); - - // Pointers to the buffers. - FriBidiCharType* charactersTypeBufferPointer = &info->mCharactersTypeBuffer[0u]; - FriBidiLevel* levelsBufferPointer = &info->mLevelsBuffer[0u]; - FriBidiJoiningType* joiningTypeBufferPointer = &joiningTypeBuffer[0u]; - - // Retrieves the type of each character. - fribidi_get_bidi_types( logicalUnicodeBufferPointer, length, charactersTypeBufferPointer ); - - // Retrieves the paragraph direction. - info->mDirection = fribidi_get_par_direction( charactersTypeBufferPointer, length ); - - // Retrieve the embedding levels. - fribidi_get_par_embedding_levels( charactersTypeBufferPointer, length, &info->mDirection, levelsBufferPointer ); - - // Retrieve the joining types. - fribidi_get_joining_types( logicalUnicodeBufferPointer, length, joiningTypeBufferPointer ); - - fribidi_join_arabic( charactersTypeBufferPointer, length, levelsBufferPointer, joiningTypeBufferPointer ); - - const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC; - - fribidi_shape( flags, levelsBufferPointer, length, joiningTypeBufferPointer, logicalUnicodeBufferPointer ); - - std::vector bidiTextConverted; - - bidiTextConverted.resize( length * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6. - // Currently Dali doesn't support this UTF-8 extension. Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character. - - fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, logicalUnicodeBufferPointer, length, &bidiTextConverted[0] ); - - paragraph = Text( &bidiTextConverted[0u] ); -} - -void ReorderLine( BidirectionalParagraphInfo* paragraphInfo, - BidirectionalLineInfo* lineInfo ) -{ - const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC; - - lineInfo->mVisualToLogicalMap.Resize( lineInfo->mNumberOfCharacters, 0u ); - lineInfo->mLogicalToVisualMap.Resize( lineInfo->mNumberOfCharacters, 0u ); - - std::vector visualUnicodeBuffer; - visualUnicodeBuffer.insert( visualUnicodeBuffer.end(), - paragraphInfo->mLogicalUnicodeBuffer.begin() + lineInfo->mCharacterParagraphIndex, - paragraphInfo->mLogicalUnicodeBuffer.begin() + ( lineInfo->mCharacterParagraphIndex + lineInfo->mNumberOfCharacters ) ); - - // Pointers to the buffers. - FriBidiCharType* charactersTypeBufferPointer = ¶graphInfo->mCharactersTypeBuffer[lineInfo->mCharacterParagraphIndex]; - FriBidiLevel* levelsBufferPointer = ¶graphInfo->mLevelsBuffer[lineInfo->mCharacterParagraphIndex]; - FriBidiChar* visualUnicodeBufferPointer = &visualUnicodeBuffer[0u]; - FriBidiStrIndex* visualToLogicalMapPointer = &lineInfo->mVisualToLogicalMap[0u]; - - // Initialize the visual to logical mapping table to the identity. Otherwise fribidi_reorder_line fails to retrieve a valid mapping table. - for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index ) - { - lineInfo->mVisualToLogicalMap[ index ] = index; - } - - fribidi_reorder_line( flags, - charactersTypeBufferPointer, - lineInfo->mNumberOfCharacters, - 0u, - paragraphInfo->mDirection, - levelsBufferPointer, - visualUnicodeBufferPointer, - visualToLogicalMapPointer ); - - // Fill the logical to visual mapping table. - for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index ) - { - lineInfo->mLogicalToVisualMap[ lineInfo->mVisualToLogicalMap[ index ] ] = index; - } - - std::vector bidiTextConverted; - - bidiTextConverted.resize( lineInfo->mNumberOfCharacters * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6. - // Currently Dali doesn't support this UTF-8 extension. - // Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character. - - fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, visualUnicodeBufferPointer, lineInfo->mNumberOfCharacters, &bidiTextConverted[0u] ); - - lineInfo->mText = Text( &bidiTextConverted[0u] ); -} - -} // namespace TextProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h b/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h deleted file mode 100644 index 1ed24cd..0000000 --- a/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__ -#define __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -// EXTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ - -/** - * Stores the text containing right to left characters and info for each character needed by fribidi to reorder a line. - */ -struct BidirectionalParagraphInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - BidirectionalParagraphInfo(); - - /** - * Default destructor. - */ - ~BidirectionalParagraphInfo(); - - /** - * Copy constructor. - */ - BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info ); - - /** - * Assignment operator. - */ - BidirectionalParagraphInfo& operator=( const BidirectionalParagraphInfo& info ); - - - /** - * @return Whether the paragraph is right to left. - */ - bool IsRightToLeftParagraph() const; - - FriBidiParType mDirection; ///< The paragraph direction. - std::vector mCharactersTypeBuffer; ///< Character type buffer. - std::vector mLevelsBuffer; ///< Levels buffer. - std::vector mLogicalUnicodeBuffer; ///< Text buffer in logical order. Coded in unicode. -}; - -/** - * Stores the reordered text, the conversion tables for a paragraph's line, - * the index to the first character of the line and the number of characters. - */ -struct BidirectionalLineInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - BidirectionalLineInfo(); - - /** - * Default destructor. - */ - ~BidirectionalLineInfo(); - - /** - * Copy constructor. - */ - BidirectionalLineInfo( const BidirectionalLineInfo& info ); - - /** - * Assignment operator. - */ - BidirectionalLineInfo& operator=( const BidirectionalLineInfo& info ); - - std::size_t mCharacterParagraphIndex; ///< Index within the paragraph of the first character of the line. - std::size_t mNumberOfCharacters; ///< Number of characters of the line. - Text mText; ///< Text in visual order. - Vector mVisualToLogicalMap; ///< The character position map from the visual output text to the logical input text. - Vector mLogicalToVisualMap; ///< The character position map from the logical input text to the visual output text. -}; - -/** - * Whether the text begins with right-to-left (bidirectional) character. - * @param [in] text The given text. - * @return \e true if the text begins right-to-left character. - */ -bool BeginsRightToLeftCharacter( const Text& text ); - -/** - * Whether the text contains any right-to-left (bidirectional) character. - * @param [in] text The given text. - * @return \e true if the text contains right-to-left character. - */ -bool ContainsRightToLeftCharacter( const Text& text ); - -/** - * Processes a bidirectional paragraph's text. - * - * It stores the paragraph's direction (the direction of the first non neutral character), - * the direction of all characters, and the ligatures in case of arabic glyphs. - * - * It doesn't reorder the paragraph as this task must be done per line. - * The stored info is needed to reorder each line of the paragraph. - * - * @param[in] paragraph The paragraph to be processed. - * @param[out] info Struct containing the needed info to reorder each line of the paragraph. - */ -void ProcessBidirectionalText( Text& paragraph, - BidirectionalParagraphInfo* info ); - -/** - * Reorders one line of the paragraph according the Unicode Bidirectional Algorithm. - * - * The result is the text in the visual order and the conversion tables: logical <--> visual order - * - * @param[in] paragraphInfo Struct containing the needed info to reorder each line of the paragraph. - * @param[in,out] lineInfo Struct containing (in) A character index pointing the first character of the line and the number of characters, (out) the reordered line and the conversion tables. - */ -void ReorderLine( BidirectionalParagraphInfo* paragraphInfo, - BidirectionalLineInfo* lineInfo ); - -} // namespace TextProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__ - diff --git a/dali-toolkit/internal/controls/text-view/text-processor.cpp b/dali-toolkit/internal/controls/text-view/text-processor.cpp deleted file mode 100644 index 99b7b59..0000000 --- a/dali-toolkit/internal/controls/text-view/text-processor.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ - -void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray, - std::vector& paragraphs, - std::vector< Vector >& styles ) -{ - // Stores the text for a paragraph. - Text paragraph; - - // Stores the styles for each character of the paragraph. - Vector stylesForParagraph; - - // Traverses all styled texts of the array. - for( MarkupProcessor::StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it ) - { - const MarkupProcessor::StyledText& styledText( *it ); - - // Traverses all the characters of the styled text (It may have more than one). - for( size_t i = 0u, length = styledText.mText.GetLength(); i < length; ++i ) - { - const Dali::Character character = styledText.mText[i]; - - if( character.IsNewLine() ) // LF - { - // The character is a new paragraph character. - - // Append the new paragraph character. - paragraph.Append( character ); - - // Creates a new text style for the character and insert it to the vector of styles for that paragraph. - TextStyle* style = new TextStyle( styledText.mStyle ); - stylesForParagraph.PushBack( style ); - - // Inserts the paragraph and the styles to the vector of paragraphs and the vector of styles. - paragraphs.push_back( paragraph ); - styles.push_back( stylesForParagraph ); - - // Clears the text and the vector of styles for the next paragraph. - paragraph = Text(); - stylesForParagraph.Clear(); - } - else - { - // The character is not a new paragraph character. - - // Append it to the paragraph's text - paragraph.Append( character ); - - // Add the style to the vector of styles for that paragraph. - TextStyle* style = new TextStyle( styledText.mStyle ); - stylesForParagraph.PushBack( style ); - } - } - } - - // This paragraph could be empty if the last character of the previous paragraph is a 'new paragraph' character - // and is the last of the text. - paragraphs.push_back( paragraph ); - styles.push_back( stylesForParagraph ); -} - -void SplitInWords( const Dali::Text& paragraph, - Vector& positions ) -{ - const std::size_t length = paragraph.GetLength(); - - // Magic number: Let's soupose there is ~6 characters per word. Used to do less memory reallocation inside Vector. - const size_t magicNumberOfWords = ( length / 6u ) + 1u; - - // Find the positions of the new paragraph characters. - positions.Reserve( magicNumberOfWords ); - - // Find the position of all white spaces. A new paragraph character is also considered a white space but it doesn't matter at this point. - paragraph.Find( Text::WHITE_SPACE, 0u, length - 1u, positions ); -} - -/** - * Wheather the character of the text pointed by the given offset is a white space. - * - * @param[in] text The text. - * @param[in] offset Offset pointing the character. - * - * @return \e true if the character pointed by the offset is a white space. - */ -bool IsWhiteSpace( const MarkupProcessor::StyledTextArray& text, size_t offset ) -{ - DALI_ASSERT_DEBUG( offset < text.size() ); - - // assume 1 Character per StyledText - return ( *( text.begin() + offset ) ).mText[0u].IsWhiteSpace(); -} - -void FindNearestWord( const MarkupProcessor::StyledTextArray& text, size_t offset, size_t& start, size_t& end) -{ - const size_t size(text.size()); - offset = std::min(offset, size-1u); - - size_t i(offset); - size_t j(offset); - - // if currently looking at whitespace, then search left and right for non-whitespace. - if(IsWhiteSpace(text, offset)) - { - // scan left until non-white space / beginning of string. - while(i > 0u && IsWhiteSpace(text, i)) - { - i--; - } - - // scan right until non-white space / end of string. - while(j < size && IsWhiteSpace(text, j)) - { - j++; - } - } - - // check if r.h.s. word is closer than l.h.s. word - if( (j - offset) < // distance to closest right word < - (offset - i) ) // distance to closest left word - { - // point left and right markers on start of right word - i = j; - } - else - { - // point left and right markers on end of left word - j = i; - } - - // expand left and right markers to encompase entire word - while(i > 0u && !IsWhiteSpace(text, i-1u)) - { - i--; - } - - while(j < size && !IsWhiteSpace(text, j)) - { - j++; - } - - // If both markers at same position and is whitespace then word is a whitespace word - if ( i == j ) - { - while(j < size && IsWhiteSpace(text, j)) - { - j++; - } - - while(i > 0 && IsWhiteSpace(text, i-1)) - { - i--; - } - } - - start = i; - end = j; -} - -} // namespace TextProcessor - -} // namespace Internal - -} // namespace DaliToolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-processor.h b/dali-toolkit/internal/controls/text-view/text-processor.h deleted file mode 100644 index 9814c09..0000000 --- a/dali-toolkit/internal/controls/text-view/text-processor.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __DALI_TOOLKIT_TEXT_PROCESSOR_H__ -#define __DALI_TOOLKIT_TEXT_PROCESSOR_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ -// Forward declarations. -struct BidirectionalParagraphInfo; - -/** - * Splits the given text in paragraphs. - * - * @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but - * not necessarily the case for text in TextView) - * - * @param [in] styledTextArray The given text. - * @param [out] paragraphs The text split in paragraphs. - * @param [out] styles The styles of each character of each paragraph. - */ -void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray, - std::vector& paragraphs, - std::vector< Vector >& styles ); - -/** - * Finds the position of all word separators (currently white spaces and new paragraph characters '\n') in the given text. - * - * @param [in] paragraph The given paragraph. - * @param [out] positions Positions within the paragraph of all word sepatators. - */ -void SplitInWords( const Text& paragraph, - Vector& positions ); - -/** - * Finds the nearest word in a string to a specified - * offset (in Characters). - * - * @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but - * not necessarily the case for text in TextView) - * - * @param[in] text The text to search through. - * @param[in] offset The current offset position to begin search from. - * @param[out] start The start position of nearest word - * @param[out] end The end position of nearest word - */ -void FindNearestWord( const MarkupProcessor::StyledTextArray& text, size_t offset, size_t& start, size_t& end); - -} // namespace TextProcessor - -} // namespace Internal - -} // namespace DaliToolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_TEXT_PROCESSOR_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp b/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp deleted file mode 100644 index ddcf00f..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -///////////////////// -// Layout info. -///////////////////// - -GradientInfo::GradientInfo() -: mGradientColor(), - mStartPoint(), - mEndPoint() -{ -} - -GradientInfo::~GradientInfo() -{ -} - -GradientInfo::GradientInfo( const GradientInfo& info ) -: mGradientColor( info.mGradientColor ), - mStartPoint( info.mStartPoint ), - mEndPoint( info.mEndPoint ) -{ -} - -GradientInfo& GradientInfo::operator=( const GradientInfo& info ) -{ - if( this != &info ) - { - mGradientColor = info.mGradientColor; - mStartPoint = info.mStartPoint; - mEndPoint = info.mEndPoint; - } - - return *this; -} - -CharacterLayoutInfo::CharacterLayoutInfo() -: mSize(), - mBearing( 0.f ), - mAscender( 0.f ), - mUnderlineThickness( 0.f ), - mUnderlinePosition( 0.f ), - mPosition(), - mOffset(), - mGlyphActor(), - mColorAlpha( 1.f ), - mGradientInfo( NULL ), - mIsVisible( true ), - mSetText( false ), - mSetStyle( false ), - mIsColorGlyph( false ) -{ -} - -CharacterLayoutInfo::~CharacterLayoutInfo() -{ - // Deletes the gradient info. - delete mGradientInfo; -} - -CharacterLayoutInfo::CharacterLayoutInfo( const CharacterLayoutInfo& character ) -: mSize( character.mSize ), - mBearing( character.mBearing ), - mAscender( character.mAscender ), - mUnderlineThickness( character.mUnderlineThickness ), - mUnderlinePosition( character.mUnderlinePosition ), - mPosition( character.mPosition ), - mOffset( character.mOffset ), - mGlyphActor( character.mGlyphActor ), - mColorAlpha( character.mColorAlpha ), - mGradientInfo( ( NULL == character.mGradientInfo ) ? NULL : new GradientInfo( *character.mGradientInfo ) ), // Copies the gradient info. - mIsVisible( character.mIsVisible ), - mSetText( character.mSetText ), - mSetStyle( character.mSetStyle ), - mIsColorGlyph( character.mIsColorGlyph ) -{ -} - -CharacterLayoutInfo& CharacterLayoutInfo::operator=( const CharacterLayoutInfo& character ) -{ - mSize = character.mSize; - mAscender = character.mAscender; - mBearing = character.mBearing; - mUnderlineThickness = character.mUnderlineThickness; - mUnderlinePosition = character.mUnderlinePosition; - - mPosition = character.mPosition; - mOffset = character.mOffset; - - mGlyphActor = character.mGlyphActor; - - mColorAlpha = character.mColorAlpha; - - // Copies the gradient info. - if( NULL == character.mGradientInfo ) - { - // The source doesn't have. Deletes the current one. - delete mGradientInfo; - mGradientInfo = NULL; - } - else - { - // The source has gradient info. - if( NULL != mGradientInfo ) - { - // It it has, copy to it. - *mGradientInfo = *character.mGradientInfo; - } - else - { - // If it doesn't have, create a new one. - mGradientInfo = new GradientInfo( *character.mGradientInfo ); - } - } - - mIsVisible = character.mIsVisible; - mSetText = character.mSetText; - mSetStyle = character.mSetStyle; - mIsColorGlyph = character.mIsColorGlyph; - - return *this; -} - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-impl.cpp b/dali-toolkit/internal/controls/text-view/text-view-impl.cpp deleted file mode 100644 index 4278d4b..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-impl.cpp +++ /dev/null @@ -1,2321 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace -{ - -const char* MULTILINE_POLICY_NAME[] = {"SplitByNewLineChar", "SplitByWord", "SplitByChar"}; -const char* EXCEED_POLICY_NAME[] = {"Original", "Truncate", "Fade", "Split","ShrinkToFit","EllipsizeEnd"}; -const char* LINE_JUSTIFICATION_NAME[] = {"Left","Center","Right","Justified"}; - -// Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k. -const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f; - -// Type Registration -BaseHandle Create() -{ - return Toolkit::TextView::New(); -} - -// Setup properties, signals and actions using the type-registry. -DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextView, Toolkit::Control, Create ); - -DALI_PROPERTY_REGISTRATION( TextView, "markup-enabled", BOOLEAN, MARKUP_ENABLED ) -DALI_PROPERTY_REGISTRATION( TextView, "text", STRING, TEXT ) -DALI_PROPERTY_REGISTRATION( TextView, "multiline-policy", STRING, MULTILINE_POLICY ) -DALI_PROPERTY_REGISTRATION( TextView, "width-exceed-policy", STRING, WIDTH_EXCEED_POLICY ) -DALI_PROPERTY_REGISTRATION( TextView, "height-exceed-policy", STRING, HEIGHT_EXCEED_POLICY ) -DALI_PROPERTY_REGISTRATION( TextView, "line-justification", STRING, LINE_JUSTIFICATION ) -DALI_PROPERTY_REGISTRATION( TextView, "fade-boundary", VECTOR4, FADE_BOUNDARY ) -DALI_PROPERTY_REGISTRATION( TextView, "line-height-offset", FLOAT, LINE_HEIGHT_OFFSET ) -DALI_PROPERTY_REGISTRATION( TextView, "horizontal-alignment", STRING, HORIZONTAL_ALIGNMENT ) -DALI_PROPERTY_REGISTRATION( TextView, "vertical-alignment", STRING, VERTICAL_ALIGNMENT ) - -DALI_SIGNAL_REGISTRATION( TextView, "scrolled", SIGNAL_TEXT_SCROLLED ) - -DALI_TYPE_REGISTRATION_END() - -/** - * Whether the text-view-processor operation sets, inserts, replaces, removes text. - * - * @param[in] metadata The text-view-processor operation. - * - * @return \e true if the given text-view-processor operation is modifying the text. - */ -bool IsTextViewProcessorRelayoutOperation( const TextView::TextViewProcessorMetadata& metadata ) -{ - return ( ( metadata.mType == TextView::TextSet ) || - ( metadata.mType == TextView::TextInserted ) || - ( metadata.mType == TextView::TextReplaced ) || - ( metadata.mType == TextView::TextRemoved ) || - ( metadata.mType == TextView::NewStyle )); -} - -/** - * Whether the text-view-processor operation sets a new line height offset. - * - * @param[in] metadata The text-view-processor operation. - * - * @return \e true if the given text-view-processor operation sets a new line height offset. - */ -bool IsTextViewProcessorLineHeightOffsetOperation( const TextView::TextViewProcessorMetadata& metadata ) -{ - return ( metadata.mType == TextView::NewLineHeight ); -} - -/** - * Whether the text-view-processor operation sets a new style. - * - * @param[in] metadata The text-view-processor operation. - * - * @return \e true if the given text-view-processor operation sets a new style. - */ -bool IsTextViewProcessorNewStyleOperation( const TextView::TextViewProcessorMetadata& metadata ) -{ - return ( metadata.mType == TextView::NewStyle ); -} - -} // namespace - -TextView::TextViewProcessorMetadata::TextViewProcessorMetadata() -: mType( TextView::TextSet ), - mPosition( 0u ), - mNumberOfCharacters( 0u ), - mText(), - mStyleMask(TextStyle::NONE) -{ -} - -Toolkit::TextView TextView::New() -{ - // Create the implementation, temporarily owned on stack - IntrusivePtr textView = new TextView(); - - // Pass ownership to CustomActor - Toolkit::TextView handle( *textView ); - - // Second-phase init of the implementation - // This can only be done after the CustomActor connection has been made... - textView->Initialize(); - - // Disables by default the offscreen rendering. - textView->SetSnapshotModeEnabled( false ); - - return handle; -} - -void TextView::SetText( const std::string& text ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() ); - - // Calls SetText() with the styled text array. - SetText( styledText ); -} - -void TextView::SetText( const MarkupProcessor::StyledTextArray& text ) -{ - // mTextViewProcessorOperations stores the InsertTextAt and RemoveTextFrom operations to transform the initial text to mCurrentStyledText. - // Once again, if a new text is set, any previous call to InsertTextAt or RemoveTextFrom can be discarted. - - std::vector::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorRelayoutOperation ); - mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() ); - - // Creates metadata with the Set operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::TextSet; - metadata.mText = text; - - // Store metadata. - mTextViewProcessorOperations.push_back( metadata ); - - // Updates current styled text. - mCurrentStyledText = text; - - // Request to be relaid out - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; -} - -void TextView::InsertTextAt( std::size_t position, const std::string& text ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() ); - - // Calls InsertTextAt() with the styled text array. - InsertTextAt( position, styledText ); -} - -void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text ) -{ - std::string textStr; - MarkupProcessor::GetPlainString( text, textStr ); - - if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) || - TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) ) - { - // Temporary fix. Creates the whole layout if there is rtl text. - - MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText; - textToSet.insert( textToSet.begin() + position, text.begin(), text.end() ); - SetText( textToSet ); - } - else - { - // Creates metadata with the Insert operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::TextInserted; - metadata.mPosition = position; - metadata.mText = text; - - // Store metadata. - mTextViewProcessorOperations.push_back( metadata ); - - // Updates current styled text. - mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() ); - - // Request to be relaid out - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - } -} - -void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() ); - - // Calls ReplaceTextFromTo() with the styled text array. - ReplaceTextFromTo( position, numberOfCharacters, styledText ); -} - -void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text ) -{ - std::string textStr; - MarkupProcessor::GetPlainString( text, textStr ); - - if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) || - TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) ) - { - // Temporary fix. Creates the whole layout if there is rtl text. - - // Updates current styled text. - MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText; - - MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position; - textToSet.erase( it, it + numberOfCharacters ); - it = textToSet.begin() + position; - textToSet.insert( it, text.begin(), text.end() ); - - SetText( textToSet ); - } - else - { - // Creates metadata with the Insert operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::TextReplaced; - metadata.mPosition = position; - metadata.mNumberOfCharacters = numberOfCharacters; - metadata.mText = text; - - // Store metadata. - mTextViewProcessorOperations.push_back( metadata ); - - // Updates current styled text. - MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position; - mCurrentStyledText.erase( it, it + numberOfCharacters ); - it = mCurrentStyledText.begin() + position; - mCurrentStyledText.insert( it, text.begin(), text.end() ); - - // Request to be relaid out - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - } -} - -void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ) -{ - if( TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) ) - { - // Temporary fix. Creates the whole layout if there is rtl text. - - // Updates current styled text. - MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText; - MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position; - textToSet.erase( it, it + numberOfCharacters ); - - SetText( textToSet ); - } - else - { - // Creates metadata with the Remove operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::TextRemoved; - metadata.mPosition = position; - metadata.mNumberOfCharacters = numberOfCharacters; - - // Store metadata. - mTextViewProcessorOperations.push_back( metadata ); - - // Updates current styled text. - MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position; - mCurrentStyledText.erase( it, it + numberOfCharacters ); - - // Request to be relaid out - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - } -} - -std::string TextView::GetText() const -{ - // Traverses the styled text array getting only the text. - // Note that for some languages a 'character' could be represented by more than one 'char' - - std::string text; - for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); it != endIt; ++it ) - { - text.append( (*it).mText.GetText() ); - } - - return text; -} - -void TextView::SetLineHeightOffset( PointSize offset ) -{ - if( fabsf( mLayoutParameters.mLineHeightOffset - offset ) > Math::MACHINE_EPSILON_1000 ) - { - // Removes any previous operation which modifies the line height offset. - std::vector::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorLineHeightOffsetOperation ); - mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() ); - - // Creates metadata with the new line height operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::NewLineHeight; - - mTextViewProcessorOperations.push_back( metadata ); - - // Updates line height offset. - mLayoutParameters.mLineHeightOffset = offset; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_SIZE_POSITION | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } -} - -PointSize TextView::GetLineHeightOffset() const -{ - return PointSize( mLayoutParameters.mLineHeightOffset ); -} - -void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask ) -{ - if( !mCurrentStyledText.empty() ) - { - const bool checkFontName = mask & TextStyle::FONT; - const bool checkFontSize = mask & TextStyle::SIZE; - const bool checkFontStyle = mask & TextStyle::STYLE; - - // Check first if metrics have changed. - bool metricsChanged = false; - for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); ( it != endIt ) && !metricsChanged; ++it ) - { - const MarkupProcessor::StyledText& styledText( *it ); - - metricsChanged = ( checkFontName && ( styledText.mStyle.GetFontName() != style.GetFontName() ) ) || - ( checkFontStyle && ( styledText.mStyle.GetFontStyle() != style.GetFontStyle() ) ) || - ( checkFontSize && ( fabsf( styledText.mStyle.GetFontPointSize() - style.GetFontPointSize() ) > Math::MACHINE_EPSILON_1000 ) ); - } - - if( metricsChanged ) - { - MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask ); - - // If metrics change, new text measurements are needed. - SetText( mCurrentStyledText ); - } - else - { - // Deletes any previous operation which sets a new style. - std::vector::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorNewStyleOperation ); - mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() ); - - // Creates metadata with the new style operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::NewStyle; - - MarkupProcessor::StyledText text; - text.mStyle = style; - metadata.mText.push_back( text ); - metadata.mStyleMask = mask; - - mTextViewProcessorOperations.push_back( metadata ); - - MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask ); - - RelayoutRequest(); - - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_TEXT_ACTOR_UPDATE ); - } - } - } - - // Sets the new style to the ellipsize text - // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors. - if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() ) - { - for( Vector::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(), - endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End(); - it != endIt; - ++it ) - { - (*it)->Copy( style, mask ); - } - - SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles ); - } -} - -void TextView::SetTextAlignment( Toolkit::Alignment::Type align ) -{ - if( align != ( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ) ) - { - Toolkit::Alignment::Type horizontalAlignment( ( align & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft : - ( align & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter : - ( align & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) ); - Toolkit::Alignment::Type verticalAlignment( ( align & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop : - ( align & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter : - ( align & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) ); - - mLayoutParameters.mHorizontalAlignment = horizontalAlignment; - mLayoutParameters.mVerticalAlignment = verticalAlignment; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY ); - } - } -} - -Toolkit::Alignment::Type TextView::GetTextAlignment() const -{ - return static_cast( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ); -} - -void TextView::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ) -{ - if( policy != mLayoutParameters.mMultilinePolicy ) - { - mLayoutParameters.mMultilinePolicy = policy; - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - - RelayoutRequest(); - } -} - -Toolkit::TextView::MultilinePolicy TextView::GetMultilinePolicy() const -{ - return mLayoutParameters.mMultilinePolicy; -} - -void TextView::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ) -{ - // The layout info could be invalid depending on the current exceed policy and the new one. - // i.e. if the current policy is Split and the new one is ShrinkToFit then - // the layout info generated for each char is not needed. - if( policy != mLayoutParameters.mWidthExceedPolicy ) - { - mLayoutParameters.mWidthExceedPolicy = policy; - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - - RelayoutRequest(); - } -} - -Toolkit::TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const -{ - return mLayoutParameters.mWidthExceedPolicy; -} - -void TextView::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ) -{ - if( policy != mLayoutParameters.mHeightExceedPolicy ) - { - mLayoutParameters.mHeightExceedPolicy = policy; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_SIZE_POSITION | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } -} - -Toolkit::TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const -{ - return mLayoutParameters.mHeightExceedPolicy; -} - -void TextView::SetLineJustification( Toolkit::TextView::LineJustification justification ) -{ - if( justification != mLayoutParameters.mLineJustification ) - { - mLayoutParameters.mLineJustification = justification; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_SIZE_POSITION | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } -} - -Toolkit::TextView::LineJustification TextView::GetLineJustification() const -{ - return mLayoutParameters.mLineJustification; -} - -void TextView::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ) -{ - if( ( fadeBoundary.mLeft != mVisualParameters.mFadeBoundary.mLeft ) || - ( fadeBoundary.mRight != mVisualParameters.mFadeBoundary.mRight ) || - ( fadeBoundary.mTop != mVisualParameters.mFadeBoundary.mTop ) || - ( fadeBoundary.mBottom != mVisualParameters.mFadeBoundary.mBottom ) ) - { - mVisualParameters.mFadeBoundary = fadeBoundary; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } -} - -const Toolkit::TextView::FadeBoundary& TextView::GetFadeBoundary() const -{ - return mVisualParameters.mFadeBoundary; -} - -void TextView::SetEllipsizeText( const std::string& ellipsizeText ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() ); - - // Creates the ellipsis layout info and sets the text and styles. - SetEllipsizeText( styledText ); -} - -void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText ) -{ - // Converts the styled text array into a Text and a vector of TextStyles. - Text text; - Vector styles; - for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it ) - { - const MarkupProcessor::StyledText& styledText( *it ); - - text.Append( styledText.mText ); - styles.PushBack( new TextStyle( styledText.mStyle ) ); - } - - // Creates the ellipsis layout info and sets the text and styles. - SetEllipsizeText( text, styles ); -} - -void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector& ellipsizeStyles ) -{ - // Sets the text and styles for the ellipsis text. - mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText; - mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles; - - // Creates the ellipsis layout info. - CreateEllipsizeLayout(); - - // Request to be relaid out - RelayoutRequest(); - - mRelayoutOperations = RELAYOUT_ALL; -} - -std::string TextView::GetEllipsizeText() const -{ - return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText(); -} - -void TextView::GetTextLayoutInfo() -{ - const bool relayoutSizeAndPositionNeeded = mRelayoutOperations & RELAYOUT_SIZE_POSITION; - const bool relayoutAlignmentNeeded = mRelayoutOperations & RELAYOUT_ALIGNMENT; - const bool relayoutVisibilityNeeded = mRelayoutOperations & RELAYOUT_VISIBILITY; - - if( relayoutSizeAndPositionNeeded || relayoutAlignmentNeeded || relayoutVisibilityNeeded ) - { - Vector3 textViewSize = GetControlSize(); - - if( ( ( textViewSize.width < Math::MACHINE_EPSILON_1000 ) || - ( textViewSize.height < Math::MACHINE_EPSILON_1000 ) ) && - ( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) && - ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) && - ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) ) - { - // In case the control size is not set but the layout settings are the default (split by new line character and original exceed policies) - // the text natural size can be used. - textViewSize = GetNaturalSize(); - } - - if( ( textViewSize.width > Math::MACHINE_EPSILON_1000 ) && - ( textViewSize.height > Math::MACHINE_EPSILON_1000 ) ) - { - // Check if the text-view has glyph-actors. - const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty(); - - RelayoutOperationMask mask = NO_RELAYOUT; - if( relayoutSizeAndPositionNeeded ) - { - mask = static_cast( mask | RELAYOUT_SIZE_POSITION ); - } - if( relayoutAlignmentNeeded ) - { - mask = static_cast( mask | RELAYOUT_ALIGNMENT ); - } - if( relayoutVisibilityNeeded ) - { - mask = static_cast( mask | RELAYOUT_VISIBILITY ); - } - - if( hasGlyphActors ) - { - // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo() - // add them to the text-actor cache. - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - mRelayoutData.mGlyphActors.clear(); - } - - // Relays-out but doesn't add glyph-actors to the text-view. - DoRelayOut( textViewSize.GetVectorXY(), mask ); - - if( hasGlyphActors ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } - } -} - -void TextView::GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo ) -{ - GetTextLayoutInfo(); - - textLayoutInfo.mCharacterLayoutInfoTable = mRelayoutData.mCharacterLayoutInfoTable; - textLayoutInfo.mLines = mRelayoutData.mLines; - - textLayoutInfo.mCharacterLogicalToVisualMap = mRelayoutData.mCharacterLogicalToVisualMap; - textLayoutInfo.mCharacterVisualToLogicalMap = mRelayoutData.mCharacterVisualToLogicalMap; - - textLayoutInfo.mTextSize = mRelayoutData.mTextSizeForRelayoutOption; - - textLayoutInfo.mScrollOffset = mVisualParameters.mCameraScrollPosition; -} - -void TextView::SetSortModifier( float depthOffset ) -{ - mVisualParameters.mSortModifier = depthOffset; - - for( std::vector::iterator it = mRelayoutData.mGlyphActors.begin(), endIt = mRelayoutData.mGlyphActors.end(); - it != endIt; - ++it ) - { - ( *it ).SetSortModifier( depthOffset ); - } - - if( mOffscreenImageActor ) - { - mOffscreenImageActor.SetSortModifier( depthOffset ); - } -} - -void TextView::SetSnapshotModeEnabled( bool enable ) -{ - if( enable != mVisualParameters.mSnapshotModeEnabled ) - { - // Remove first all glyph-actors - if( !mRelayoutData.mGlyphActors.empty() ) - { - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - } - - mVisualParameters.mSnapshotModeEnabled = enable; - if( !mLockPreviousSnapshotMode ) - { - // mPreviousSnapshotModeEnabled stores the snapshot mode value before SetScrollEnabled( true ) is - // called. However, if SetSnapshotModeEnabled() is called after SetScrollEnabled() then the stored value - // is updated. - // As SetSnapshotModeEnabled() is also called from SetScrollEnabled(), the mLockPreviousSnapshotMode prevents - // to smash the stored value. - mPreviousSnapshotModeEnabled = enable; - } - - if( mVisualParameters.mSnapshotModeEnabled ) - { - // Create a root actor and an image actor for offscreen rendering. - mOffscreenRootActor = Layer::New(); - mOffscreenImageActor = ImageActor::New(); - - mOffscreenRootActor.SetColorMode( USE_OWN_COLOR ); - mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION ); - mOffscreenRootActor.SetInheritOrientation( false ); - mOffscreenRootActor.SetInheritScale( false ); - mOffscreenRootActor.SetDepthTestDisabled( true ); - - mOffscreenRootActor.SetPosition( 0.f, 0.f, 0.f ); - - mOffscreenImageActor.SetAnchorPoint( ParentOrigin::CENTER ); - mOffscreenImageActor.SetParentOrigin( ParentOrigin::CENTER ); - mOffscreenImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA, - BlendingFactor::ONE, BlendingFactor::ONE ); - - Actor self = Self(); - self.Add( mOffscreenRootActor ); - self.Add( mOffscreenImageActor ); - mOffscreenImageActor.SetScale( Vector3( 1.f, -1.f, 1.f ) ); - } - else - { - Actor self = Self(); - - if( mOffscreenRootActor ) - { - self.Remove( mOffscreenRootActor ); - } - - if( mOffscreenImageActor ) - { - self.Remove( mOffscreenImageActor ); - } - - DestroyOffscreenRenderingResources(); - } - - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - RelayoutRequest(); - } -} - -bool TextView::IsSnapshotModeEnabled() const -{ - return mVisualParameters.mSnapshotModeEnabled; -} - -void TextView::SetMarkupProcessingEnabled( bool enable ) -{ - mMarkUpEnabled = enable; -} - -bool TextView::IsMarkupProcessingEnabled() const -{ - return mMarkUpEnabled; -} - -void TextView::SetScrollEnabled( bool enable ) -{ - if( enable != mVisualParameters.mScrollEnabled ) - { - mVisualParameters.mScrollEnabled = enable; - - if( mVisualParameters.mScrollEnabled ) - { - // Offscreen rendering is needed to enable text scroll. - - // Stores previous value of the snapshot mode. - mPreviousSnapshotModeEnabled = IsSnapshotModeEnabled(); - - { - // SetSnapshotModeEnabled() modifies the mPreviousSnapshotModeEnabled just in case it's called after SetScrollEnabled(), - // this lock prevents to modify the mPreviousSnapshotModeEnabled when SetSnapshotModeEnabled() from this method. - Lock lock( mLockPreviousSnapshotMode ); - SetSnapshotModeEnabled( true ); - } - - // Creates the pan gesture detector and attach the text-view. - mPanGestureDetector = PanGestureDetector::New(); - mPanGestureDetector.DetectedSignal().Connect( this, &TextView::OnTextPan ); - mPanGestureDetector.Attach( Self() ); - } - else - { - // Removes the pan gesture detector. - if( mPanGestureDetector ) - { - mPanGestureDetector.Detach( Self() ); - mPanGestureDetector.DetectedSignal().Disconnect( this, &TextView::OnTextPan ); - mPanGestureDetector.Reset(); - } - - // Restores the previous state for snapshot mode. - SetSnapshotModeEnabled( mPreviousSnapshotModeEnabled ); - } - } -} - -bool TextView::IsScrollEnabled() const -{ - return mVisualParameters.mScrollEnabled; -} - -void TextView::SetScrollPosition( const Vector2& position ) -{ - if( position != mVisualParameters.mCameraScrollPosition ) - { - // Guard against destruction during signal emission - // Note that Emit() methods are called indirectly from within DoSetScrollPosition() - Toolkit::TextView handle( GetOwner() ); - - DoSetScrollPosition( position ); - - // Check if the new scroll position has been trimmed. - mVisualParameters.mScrollPositionTrimmed = ( position != mVisualParameters.mCameraScrollPosition ); - } -} - -const Vector2& TextView::GetScrollPosition() const -{ - return mVisualParameters.mCameraScrollPosition; -} - -bool TextView::IsScrollPositionTrimmed() const -{ - return mVisualParameters.mScrollPositionTrimmed; -} - -Toolkit::TextView::ScrolledSignalType& TextView::ScrolledSignal() -{ - return mScrolledSignal; -} - -bool TextView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) -{ - Dali::BaseHandle handle( object ); - - bool connected( true ); - Toolkit::TextView textView = Toolkit::TextView::DownCast( handle ); - - if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_SCROLLED ) ) - { - textView.ScrolledSignal().Connect( tracker, functor ); - } - else - { - // signalName does not match any signal - connected = false; - } - - return connected; -} - -TextView::LayoutParameters::LayoutParameters() -: mMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ), - mExceedPolicy( TextView::Original ), - mWidthExceedPolicy( Toolkit::TextView::Original ), - mHeightExceedPolicy( Toolkit::TextView::Original ), - mHorizontalAlignment( Toolkit::Alignment::HorizontalCenter ), - mVerticalAlignment( Toolkit::Alignment::VerticalCenter ), - mLineJustification( Toolkit::TextView::Left ), - mLineHeightOffset( 0.f ), - mMarkUpEnabled( false ) -{ -} - -TextView::LayoutParameters::~LayoutParameters() -{ -} - -TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy, - Toolkit::TextView::ExceedPolicy widthExceedPolicy, - Toolkit::TextView::ExceedPolicy heightExceedPolicy, - Toolkit::Alignment::Type alignmentType, - Toolkit::TextView::LineJustification lineJustification, - float lineHeightOffset, - bool markUpEnabled ) -: mMultilinePolicy( multilinePolicy ), - mExceedPolicy( TextView::Original ), - mWidthExceedPolicy( widthExceedPolicy ), - mHeightExceedPolicy( heightExceedPolicy ), - mHorizontalAlignment(), - mVerticalAlignment(), - mLineJustification( lineJustification ), - mLineHeightOffset( lineHeightOffset ), - mMarkUpEnabled( markUpEnabled ) -{ - // Sets alignment - Toolkit::Alignment::Type horizontalAlignment( ( alignmentType & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft : - ( alignmentType & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter : - ( alignmentType & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) ); - Toolkit::Alignment::Type verticalAlignment( ( alignmentType & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop : - ( alignmentType & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter : - ( alignmentType & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) ); - - mHorizontalAlignment = horizontalAlignment; - mVerticalAlignment = verticalAlignment; -} - -TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters ) -: mMultilinePolicy( layoutParameters.mMultilinePolicy ), - mExceedPolicy( TextView::Original ), - mWidthExceedPolicy( layoutParameters.mWidthExceedPolicy ), - mHeightExceedPolicy( layoutParameters.mHeightExceedPolicy ), - mHorizontalAlignment( layoutParameters.mHorizontalAlignment ), - mVerticalAlignment( layoutParameters.mVerticalAlignment ), - mLineJustification( layoutParameters.mLineJustification ), - mLineHeightOffset( layoutParameters.mLineHeightOffset ), - mMarkUpEnabled( layoutParameters.mMarkUpEnabled ) -{ -} - -TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextView::LayoutParameters& layoutParameters ) -{ - mMultilinePolicy = layoutParameters.mMultilinePolicy; - mWidthExceedPolicy = layoutParameters.mWidthExceedPolicy; - mHeightExceedPolicy = layoutParameters.mHeightExceedPolicy; - mHorizontalAlignment = layoutParameters.mHorizontalAlignment; - mVerticalAlignment = layoutParameters.mVerticalAlignment; - mLineJustification = layoutParameters.mLineJustification; - mLineHeightOffset = layoutParameters.mLineHeightOffset; - mMarkUpEnabled = layoutParameters.mMarkUpEnabled; - - return *this; -} - -TextView::VisualParameters::VisualParameters() -: mFadeBoundary(), - mSortModifier( 0.f ), - mCameraScrollPosition( 0.f, 0.f ), - mSnapshotModeEnabled( false ), - mScrollEnabled( false ), - mScrollPositionTrimmed( false ) -{ -} - -TextView::VisualParameters::VisualParameters( const VisualParameters& visualParameters ) -: mFadeBoundary( visualParameters.mFadeBoundary ), - mSortModifier( visualParameters.mSortModifier ), - mCameraScrollPosition( visualParameters.mCameraScrollPosition ), - mSnapshotModeEnabled( visualParameters.mSnapshotModeEnabled ), - mScrollEnabled( visualParameters.mScrollEnabled ), - mScrollPositionTrimmed( visualParameters.mScrollPositionTrimmed ) -{ -} - -TextView::VisualParameters& TextView::VisualParameters::operator=( const TextView::VisualParameters& visualParameters ) -{ - mFadeBoundary = visualParameters.mFadeBoundary; - mSortModifier = visualParameters.mSortModifier; - mCameraScrollPosition = visualParameters.mCameraScrollPosition; - mSnapshotModeEnabled = visualParameters.mSnapshotModeEnabled; - mScrollEnabled = visualParameters.mScrollEnabled; - mScrollPositionTrimmed = visualParameters.mScrollPositionTrimmed; - - return *this; -} - -TextView::RelayoutData::RelayoutData() -: mTextViewSize(), - mShrinkFactor( 1.f ), - mTextLayoutInfo(), - mCharacterLogicalToVisualMap(), - mCharacterVisualToLogicalMap(), - mGlyphActors(), - mCharacterLayoutInfoTable(), - mLines(), - mTextSizeForRelayoutOption() -{ -} - -TextView::RelayoutData::RelayoutData( const TextView::RelayoutData& relayoutData ) -: mTextViewSize( relayoutData.mTextViewSize ), - mShrinkFactor( relayoutData.mShrinkFactor ), - mTextLayoutInfo( relayoutData.mTextLayoutInfo ), - mCharacterLogicalToVisualMap( relayoutData.mCharacterLogicalToVisualMap ), - mCharacterVisualToLogicalMap( relayoutData.mCharacterVisualToLogicalMap ), - mGlyphActors( relayoutData.mGlyphActors ), - mCharacterLayoutInfoTable( relayoutData.mCharacterLayoutInfoTable ), - mLines( relayoutData.mLines ), - mTextSizeForRelayoutOption( relayoutData.mTextSizeForRelayoutOption ) -{ -} - -TextView::RelayoutData& TextView::RelayoutData::operator=( const TextView::RelayoutData& relayoutData ) -{ - mTextViewSize = relayoutData.mTextViewSize; - mShrinkFactor = relayoutData.mShrinkFactor; - mTextLayoutInfo = relayoutData.mTextLayoutInfo; - mCharacterLogicalToVisualMap = relayoutData.mCharacterLogicalToVisualMap; - mCharacterVisualToLogicalMap = relayoutData.mCharacterVisualToLogicalMap; - mGlyphActors = relayoutData.mGlyphActors; - mCharacterLayoutInfoTable = relayoutData.mCharacterLayoutInfoTable; - mLines = relayoutData.mLines; - mTextSizeForRelayoutOption = relayoutData.mTextSizeForRelayoutOption; - - return *this; -} - -TextView::TextView() -: Control( REQUIRES_STYLE_CHANGE_SIGNALS ), - mCurrentStyledText(), - mTextViewProcessorOperations(), - mLayoutParameters( Toolkit::TextView::SplitByNewLineChar, - Toolkit::TextView::Original, - Toolkit::TextView::Original, - static_cast( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ), - Toolkit::TextView::Left, - PointSize( 0.f ), - false ), - mVisualParameters(), - mRelayoutData(), - mRelayoutOperations( NO_RELAYOUT ), - mOffscreenRootActor(), - mOffscreenImageActor(), - mOffscreenCameraActor(), - mCurrentOffscreenSize(), - mFrameBufferImage(), - mRenderTask(), - mPanGestureDetector(), - mLockPreviousSnapshotMode( false ), - mPreviousSnapshotModeEnabled( false ), - mMarkUpEnabled( false ) -{ - // Creates the ellipsis layout info. - CreateEllipsizeLayout(); -} - -TextView::~TextView() -{ - // Destroys offscreen rendering resources. - DestroyOffscreenRenderingResources(); - - // Destroys scroll pan gesture detector. - if( mPanGestureDetector ) - { - mPanGestureDetector.Reset(); - } -} - -Vector3 TextView::GetNaturalSize() -{ - if( !mTextViewProcessorOperations.empty() ) - { - // There are SetText, Inserts or Removes to do. It means the current layout info is not updated. - - if( !mRelayoutData.mGlyphActors.empty() ) - { - // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo() - // add them to the text-actor cache. - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - mRelayoutData.mGlyphActors.clear(); - - mRelayoutOperations = static_cast( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - - PerformTextViewProcessorOperations(); - } - - return Vector3( mRelayoutData.mTextLayoutInfo.mWholeTextSize.width, mRelayoutData.mTextLayoutInfo.mWholeTextSize.height, 0.f ); -} - -float TextView::GetHeightForWidth( float width ) -{ - float height = 0.f; - - if( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) && - ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) && - ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) - { - // If multiline and exceed policies are 'SplitByNewLineChar' and 'Original' is better get the height from the - // natural size. GetNaturalSize() for this configuration is faster than DoRelayOut(). - height = GetNaturalSize().height; - } - else - { - // Check if the given width is different than the current one. - const bool differentWidth = ( fabsf( width - mRelayoutData.mTextViewSize.width ) > Math::MACHINE_EPSILON_1000 ); - - // Check if the text-view has glyph-actors. - const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty(); - - // Check which layout operations need to be done. - const bool relayoutSizeAndPositionNeeded = ( mRelayoutOperations & RELAYOUT_SIZE_POSITION ) || differentWidth; - - if( relayoutSizeAndPositionNeeded ) - { - if( hasGlyphActors ) - { - // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo() - // add them to the text-actor cache. - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - mRelayoutData.mGlyphActors.clear(); - } - - // Use the given width. - const Vector2 textViewSize( width, GetControlSize().height ); - - // Relays-out but doesn't add glyph-actors to the text-view. - DoRelayOut( textViewSize, RELAYOUT_SIZE_POSITION ); - } - - // Retrieve the text height after relayout the text. - height = mRelayoutData.mTextSizeForRelayoutOption.height; - - if( differentWidth ) - { - // Revert the relayout operation mask - mRelayoutOperations = static_cast( mRelayoutOperations | RELAYOUT_SIZE_POSITION ); - } - - if( hasGlyphActors ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - - if( differentWidth || hasGlyphActors ) - { - RelayoutRequest(); - } - } - - return height; -} - -float TextView::GetWidthForHeight( float height ) -{ - // TODO: Needs implementing properly, for now just return the natural width. - return GetNaturalSize().width; -} - - -void TextView::OnInitialize() -{ - // The actor handle needs to be inialised for this to work - Self().SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS ); -} - - -void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange ) -{ - // Creates the ellipsis layout info. - CreateEllipsizeLayout(); - - SetText( mCurrentStyledText ); -} - -void TextView::OnControlSizeSet( const Vector3& size ) -{ - if( size.GetVectorXY() != mRelayoutData.mTextViewSize ) - { - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - - // Request to be relaid out - RelayoutRequest(); - } -} - -void TextView::OnRelayout( const Vector2& size, RelayoutContainer& container ) -{ - if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) - { - // Not worth to relayout if width or height is equal to zero. - return; - } - - if( size != mRelayoutData.mTextViewSize ) - { - // if new size is different than the prevoius one, set positions and maybe sizes of all glyph-actor is needed. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_SIZE_POSITION | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } - - if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) || - ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) ) - { - if( mRelayoutOperations & RELAYOUT_ALIGNMENT ) - { - // If the text of the alignment changes and a fade exceed policy is set, - // some characters may need new TextActor. - mRelayoutOperations = RELAYOUT_ALL; - } - } - - // Remove glyph-actors from text-view - if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) ) - { - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - mRelayoutData.mGlyphActors.clear(); - } - - if( NO_RELAYOUT != mRelayoutOperations ) - { - // Relays-out and add glyph-actors to the text-view. - DoRelayOut( size, mRelayoutOperations ); - ProcessSnapshot( size ); - } - - // Quite likely the texts of the text-actors are not going to be reused, so clear them. - mRelayoutData.mTextActorCache.ClearTexts(); -} - -void TextView::PerformTextViewProcessorOperations() -{ - // Traverse the relayout operation vector ... - - // Optimizes some operations. - OptimizeTextViewProcessorOperations(); - - for( std::vector::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it ) - { - const TextViewProcessorMetadata& relayoutMetadata( *it ); - - switch( relayoutMetadata.mType ) - { - case TextView::TextSet: - { - TextViewProcessor::CreateTextInfo( relayoutMetadata.mText, - mLayoutParameters, - mRelayoutData ); - break; - } - case TextView::TextInserted: - { - TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition, - relayoutMetadata.mText, - mLayoutParameters, - mRelayoutData ); - break; - } - case TextView::TextReplaced: - { - TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition, - relayoutMetadata.mNumberOfCharacters, - relayoutMetadata.mText, - mLayoutParameters, - mRelayoutData ); - break; - } - case TextView::TextRemoved: - { - TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition, - relayoutMetadata.mNumberOfCharacters, - mLayoutParameters, - mRelayoutData, - TextViewProcessor::CLEAR_TEXT ); // clears the text of the text-actors. - break; - } - case TextView::NewLineHeight: - { - TextViewProcessor::UpdateTextInfo( mLayoutParameters.mLineHeightOffset, - mRelayoutData.mTextLayoutInfo ); - break; - } - case TextView::NewStyle: - { - TextViewProcessor::UpdateTextInfo( ( *relayoutMetadata.mText.begin() ).mStyle, - relayoutMetadata.mStyleMask, - mRelayoutData ); - break; - } - } - } - - // Clear all operations when they are done. - mTextViewProcessorOperations.clear(); -} - -void TextView::OptimizeTextViewProcessorOperations() -{ - // TODO: check if some operation can be discarted. i.e. InsertTextAt( 0, "a" ); RemoveTextFrom( 0, 1 ); - - // At the moment it only replaces a 'remove 1 character' followed by 'insert 1 character' in the same position by a 'replace' operation. - // This sequence is used by text-input with predictive text. Change this two operations by a replace allows the text-view processor to - // use the cache without clearing the text-actors. - - std::vector textViewProcessorOperations; - - for( std::vector::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it ) - { - const TextViewProcessorMetadata& relayoutMetadata( *it ); - - switch( relayoutMetadata.mType ) - { - case TextView::TextRemoved: - { - bool optimizationDone = false; - - if( it + 1u != endIt ) - { - const TextViewProcessorMetadata& nextRelayoutMetadata( *( it + 1u ) ); - if( TextView::TextInserted == nextRelayoutMetadata.mType ) - { - if( relayoutMetadata.mPosition == nextRelayoutMetadata.mPosition ) - { - optimizationDone = true; - TextViewProcessorMetadata newRelayoutMetadata; - newRelayoutMetadata.mType = TextView::TextReplaced; - newRelayoutMetadata.mPosition = relayoutMetadata.mPosition; - newRelayoutMetadata.mNumberOfCharacters = relayoutMetadata.mNumberOfCharacters; - newRelayoutMetadata.mText = nextRelayoutMetadata.mText; - textViewProcessorOperations.push_back( newRelayoutMetadata ); - - // do not access the TextInserted operation in next iteration. - ++it; - } - } - } - - if( !optimizationDone ) - { - textViewProcessorOperations.push_back( relayoutMetadata ); - } - break; - } - default: - { - textViewProcessorOperations.push_back( relayoutMetadata ); - } - } - } - - mTextViewProcessorOperations = textViewProcessorOperations; -} - -void TextView::DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask ) -{ - // Traverse the relayout operation vector. It fills the natural size, layout and glyph-actor data structures. - if( !mTextViewProcessorOperations.empty() ) - { - PerformTextViewProcessorOperations(); - } - - CombineExceedPolicies(); - - Actor rootActor; - if( mVisualParameters.mSnapshotModeEnabled ) - { - rootActor = mOffscreenRootActor; - } - else - { - rootActor = Self(); - } - - mRelayoutData.mTextViewSize = textViewSize; - switch( mLayoutParameters.mMultilinePolicy ) - { - case Toolkit::TextView::SplitByNewLineChar: // multiline policy == SplitByNewLineChar. - { - SplitByNewLineChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData ); - break; - } // SplitByNewLineChar - - case Toolkit::TextView::SplitByWord: // multiline policy == SplitByWord. - { - SplitByWord::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData ); - break; - } // SplitByWord - - case Toolkit::TextView::SplitByChar: // multiline policy == SplitByChar. - { - SplitByChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData ); - break; - } // SplitByChar - } // switch( mMultilinePolicy ) - - // Remove done operations from the mask. - mRelayoutOperations = static_cast( mRelayoutOperations & ~relayoutOperationMask ); -} - -void TextView::ProcessSnapshot( const Size& textViewSize ) -{ - if( mVisualParameters.mSnapshotModeEnabled ) - { - // If layout options change, it's needed generate a new image. - - if( mOffscreenRootActor ) - { - // Set the root actor visible. - // The root actor is set to non visible after the render task is processed. - mOffscreenRootActor.SetVisible( true ); - - // The offscreen root actor must have same size as text view. Otherwise, text alignment won't work. - mOffscreenRootActor.SetSize( textViewSize ); - } - - if( ( mRelayoutData.mTextSizeForRelayoutOption.width > Math::MACHINE_EPSILON_1000 ) && - ( mRelayoutData.mTextSizeForRelayoutOption.height > Math::MACHINE_EPSILON_1000 ) ) - { - // Set the image actor visible. - // The image actor is set to non visible if there is no text to render. - mOffscreenImageActor.SetVisible( true ); - - // Calculates the offscreen image's size. It takes into account different points: - // * If text has italics, add a small offset is needed in order to not to cut the text next to the right edge. - // * There is a maximum texture size the graphic subsystem can load on the memory. - // * If the scroll is enabled, the offscreen image's size is never bigger than the text-view's size. - - const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, - mVisualParameters.mScrollEnabled ? textViewSize.width : std::max( mRelayoutData.mTextSizeForRelayoutOption.width, textViewSize.width ) + mRelayoutData.mTextLayoutInfo.mMaxItalicsOffset ), - std::min( MAX_OFFSCREEN_RENDERING_SIZE, - mVisualParameters.mScrollEnabled ? textViewSize.height : std::max( mRelayoutData.mTextSizeForRelayoutOption.height, textViewSize.height ) ) ); - - const bool sizeChanged = offscreenSize != mCurrentOffscreenSize; - - if( sizeChanged ) - { - // Creates a frame buffer for offscreen rendering when the size is negotiated. - mFrameBufferImage = FrameBufferImage::New( offscreenSize.width, - offscreenSize.height, - Pixel::RGBA8888 ); - - // Stores current text-view size to avoid create new Dali resources if text changes. - mCurrentOffscreenSize = offscreenSize; - - if( !mOffscreenCameraActor ) - { - // Creates a new camera actor. - mOffscreenCameraActor = CameraActor::New(); - mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER ); - mOffscreenCameraActor.SetAnchorPoint( AnchorPoint::CENTER ); - mOffscreenCameraActor.SetOrientation(Degree(180.f), Vector3::YAXIS); - - mOffscreenCameraActor.SetType( Dali::Camera::FREE_LOOK ); // Inherits position from the offscreen root actor. - - mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text - } - - // Calculate camera parameters for current text size. - mOffscreenCameraActor.SetOrthographicProjection( offscreenSize ); - } - - if( mVisualParameters.mScrollEnabled ) - { - // Updates the offscreen camera position with the new scroll offset. - mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x ); - mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y ); - } - else - { - // Text's size could be bigger than text-view's size. In that case the camera must be aligned to cover the whole text. - AlignOffscreenCameraActor( textViewSize, offscreenSize ); - } - - if( !mRenderTask ) - { - // Creates a new render task. - mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask(); - - mRenderTask.SetSourceActor( mOffscreenRootActor ); - mRenderTask.SetInputEnabled( false ); - mRenderTask.SetClearColor( Color::TRANSPARENT ); - mRenderTask.SetClearEnabled( true ); - mRenderTask.SetExclusive( true ); - - // Connects the signal to the TextView::RenderTaskFinished method in order to make the root actor non visible when the render task is processed. - mRenderTask.FinishedSignal().Connect( this, &TextView::RenderTaskFinished ); - } - - if( sizeChanged ) - { - mRenderTask.SetCameraActor( mOffscreenCameraActor ); - mRenderTask.SetTargetFrameBuffer( mFrameBufferImage ); - } - - // Process the render task only once every time the text changes or the text-view's size canges. - mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); - } - else - { - // If there is no text just make any previous generated image invisible instead to process a render task with no text. - mOffscreenImageActor.SetVisible( false ); - } - } -} - -void TextView::AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize ) -{ - float xPosition = 0.f; - float yPosition = 0.f; - Vector3 parentOrigin = ParentOrigin::CENTER; - Vector3 anchorPoint = AnchorPoint::CENTER; - - switch( mLayoutParameters.mHorizontalAlignment ) - { - case Toolkit::Alignment::HorizontalLeft: - { - xPosition = 0.5f * ( offscreenSize.width - textViewSize.width ); - parentOrigin.x = 0.f; - anchorPoint.x = 0.f; - break; - } - case Toolkit::Alignment::HorizontalCenter: - { - // nothing to do. - break; - } - case Toolkit::Alignment::HorizontalRight: - { - xPosition = 0.5f * ( textViewSize.width - offscreenSize.width ); - parentOrigin.x = 1.f; - anchorPoint.x = 1.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." ) - } - } - - switch( mLayoutParameters.mVerticalAlignment ) - { - case Toolkit::Alignment::VerticalTop: - { - yPosition = 0.5f * ( offscreenSize.height - textViewSize.height ); - parentOrigin.y = 0.f; - anchorPoint.y = 0.f; - break; - } - case Toolkit::Alignment::VerticalCenter: - { - // nothing to do. - break; - } - case Toolkit::Alignment::VerticalBottom: - { - yPosition = 0.5f * ( textViewSize.height - offscreenSize.height ); - parentOrigin.y = 1.f; - anchorPoint.y = 1.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." ) - } - } - - mOffscreenCameraActor.SetX( xPosition ); - mOffscreenCameraActor.SetY( yPosition ); - - mOffscreenImageActor.SetParentOrigin( parentOrigin ); - mOffscreenImageActor.SetAnchorPoint( anchorPoint ); -} - -void TextView::RenderTaskFinished( Dali::RenderTask& renderTask ) -{ - // not to process the offscreen root actor by setting its visibility to false. - mOffscreenRootActor.SetVisible( false ); - - // Sets the new size and the new frame buffer to the image actor. - // Image actor must have same size as text. Otherwise text can be truncated. - mOffscreenImageActor.SetSize( mCurrentOffscreenSize ); - mOffscreenImageActor.SetImage( mFrameBufferImage ); -} - -void TextView::DestroyOffscreenRenderingResources() -{ - if( mRenderTask ) - { - mRenderTask.FinishedSignal().Disconnect( this, &TextView::RenderTaskFinished ); - - if( Stage::IsInstalled() ) - { - Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask ); - } - - mRenderTask.Reset(); - } - - // Remove and reset the root actor, image actor and camera actor as text-view is not rendering offscreen. - if( mOffscreenCameraActor ) - { - mOffscreenRootActor.Remove( mOffscreenCameraActor ); - - mOffscreenCameraActor.Reset(); - } - - if( mOffscreenRootActor ) - { - mOffscreenRootActor.Reset(); - } - - if( mOffscreenImageActor ) - { - mOffscreenImageActor.Reset(); - } - - mCurrentOffscreenSize = Size( 0.f, 0.f ); - - if( mFrameBufferImage ) - { - mFrameBufferImage.Reset(); - } -} - -void TextView::OnTextPan( Actor actor, const PanGesture& gesture ) -{ - if( 1u == gesture.numberOfTouches ) - { - DoSetScrollPosition( mVisualParameters.mCameraScrollPosition - gesture.displacement ); - } -} - -void TextView::TrimScrollPosition() -{ - const Vector3& textViewSize = GetControlSize(); - - // Before use the text's size, relayout the text is needed to get the actual text size. - GetTextLayoutInfo(); - - // Calculates the range within the text could be scrolled. (When the text is aligned in the center). - float maxHorizontalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.width - textViewSize.width ) ); - float maxVerticalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.height - textViewSize.height ) ); - float minHorizontalDisplacement = -maxHorizontalDisplacement; - float minVerticalDisplacement = -maxVerticalDisplacement; - - // Updates the range if the text is aligned on the right or left. - switch( mLayoutParameters.mHorizontalAlignment ) - { - case Toolkit::Alignment::HorizontalLeft: - { - maxHorizontalDisplacement *= 2.f; - minHorizontalDisplacement = 0.f; - break; - } - case Toolkit::Alignment::HorizontalCenter: - { - // nothing to do. - break; - } - case Toolkit::Alignment::HorizontalRight: - { - maxHorizontalDisplacement = 0.f; - minHorizontalDisplacement *= 2.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." ) - } - } - - // Updates the range if the text is aligned on the top or bottom. - switch( mLayoutParameters.mVerticalAlignment ) - { - case Toolkit::Alignment::VerticalTop: - { - maxVerticalDisplacement *= 2.f; - minVerticalDisplacement = 0.f; - break; - } - case Toolkit::Alignment::VerticalCenter: - { - //nothing to do - break; - } - case Toolkit::Alignment::VerticalBottom: - { - maxVerticalDisplacement = 0.f; - minVerticalDisplacement *= 2.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." ) - } - } - - // Trims the scroll position to be within the range. - mVisualParameters.mCameraScrollPosition.x = std::min( maxHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x ); - mVisualParameters.mCameraScrollPosition.x = std::max( minHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x ); - - mVisualParameters.mCameraScrollPosition.y = std::min( maxVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y ); - mVisualParameters.mCameraScrollPosition.y = std::max( minVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y ); -} - -void TextView::DoSetScrollPosition( const Vector2& position ) -{ - // Stores old scroll position. - Vector2 delta( mVisualParameters.mCameraScrollPosition ); - - // Updates the scroll position - mVisualParameters.mCameraScrollPosition = position; - - // Ensures the text-view is covered with text. - TrimScrollPosition(); - - // Calculate the difference with the previous scroll position - delta.x = mVisualParameters.mCameraScrollPosition.x - delta.x; - delta.y = mVisualParameters.mCameraScrollPosition.y - delta.y; - - if( mOffscreenRootActor ) - { - // If there is a render-task it needs to be refreshed. Therefore glyph-actors need to be - // set to visible. - mOffscreenRootActor.SetVisible( true ); - } - - if( mOffscreenCameraActor ) - { - // Update the offscreen camera with the new scroll position. - mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x ); - mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y ); - } - - if( mRenderTask ) - { - // Refresh the render-task. - mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); - } - - // Emit the signal. - Toolkit::TextView handle( GetOwner() ); - mScrolledSignal.Emit( handle, delta ); -} - -void TextView::CombineExceedPolicies() -{ - // Calculates the combination of exceed policies. - - switch( mLayoutParameters.mWidthExceedPolicy ) - { - case Toolkit::TextView::Original: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = Original; - break; - } - case Toolkit::TextView::Fade: - { - mLayoutParameters.mExceedPolicy = OriginalFade; - break; - } - case Toolkit::TextView::ShrinkToFit: - { - mLayoutParameters.mExceedPolicy = OriginalShrink; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - case Toolkit::TextView::Split: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = SplitOriginal; - break; - } - case Toolkit::TextView::Fade: - { - mLayoutParameters.mExceedPolicy = SplitFade; - break; - } - case Toolkit::TextView::ShrinkToFit: - { - mLayoutParameters.mExceedPolicy = SplitShrink; - break; - } - case Toolkit::TextView::EllipsizeEnd: - { - mLayoutParameters.mExceedPolicy = SplitEllipsizeEnd; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - case Toolkit::TextView::Fade: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = FadeOriginal; - break; - } - case Toolkit::TextView::Fade: - { - mLayoutParameters.mExceedPolicy = Fade; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - case Toolkit::TextView::ShrinkToFit: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = ShrinkOriginal; - break; - } - case Toolkit::TextView::Fade: - { - mLayoutParameters.mExceedPolicy = ShrinkFade; - break; - } - case Toolkit::TextView::ShrinkToFit: - { - mLayoutParameters.mExceedPolicy = Shrink; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - case Toolkit::TextView::EllipsizeEnd: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = EllipsizeEndOriginal; - break; - } - case Toolkit::TextView::EllipsizeEnd: - { - mLayoutParameters.mExceedPolicy = EllipsizeEnd; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width exceed policy" ); - } - } -} - -Actor TextView::GetRootActor() const -{ - // Get the root actor, if text-view was rendering offscreen, or the text-view itself. - - Actor rootActor; - - if( mVisualParameters.mSnapshotModeEnabled ) - { - rootActor = mOffscreenRootActor; - } - else - { - rootActor = Self(); - } - - return rootActor; -} - -void TextView::CreateEllipsizeLayout() -{ - // Creates the ellipsis layout info for the ellipsis text and styles. - mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo(); - mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() ); - TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText, - mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles, - mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo ); -} - -void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue ) -{ - bool newValue( propertyValue.Get() ); - if( newValue != IsMarkupProcessingEnabled() ) - { - SetMarkupProcessingEnabled( newValue ); - if( newValue ) - { - // If markup processing has been enabled, Ensure current text is reprocessed. - const std::string& currentText( GetText() ); - if( ! currentText.empty() ) - { - SetText( currentText ); - } - } - } -} - -void TextView::OnMultilinePolicyPropertySet( Property::Value propertyValue ) -{ - std::string policyName( propertyValue.Get() ); - if(policyName == "SplitByNewLineChar") - { - SetMultilinePolicy(Toolkit::TextView::SplitByNewLineChar); - } - else if(policyName == "SplitByWord") - { - SetMultilinePolicy(Toolkit::TextView::SplitByWord); - } - else if(policyName == "SplitByChar") - { - SetMultilinePolicy(Toolkit::TextView::SplitByChar); - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnMultilinePolicyPropertySet(). Invalid Property value." ); - } -} - -void TextView::OnWidthExceedPolicyPropertySet( Property::Value propertyValue ) -{ - std::string policyName( propertyValue.Get() ); - if(policyName == "Original") - { - SetWidthExceedPolicy(Toolkit::TextView::Original); - } - else if(policyName == "Fade") - { - SetWidthExceedPolicy(Toolkit::TextView::Fade); - } - else if(policyName == "Split") - { - SetWidthExceedPolicy(Toolkit::TextView::Split); - } - else if(policyName == "ShrinkToFit") - { - SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit); - } - else if(policyName == "EllipsizeEnd") - { - SetWidthExceedPolicy(Toolkit::TextView::EllipsizeEnd); - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnWidthExceedPolicyPropertySet(). Invalid Property value." ); - } -} - -void TextView::OnHeightExceedPolicyPropertySet( Property::Value propertyValue ) -{ - std::string policyName( propertyValue.Get() ); - if(policyName == "Original") - { - SetHeightExceedPolicy(Toolkit::TextView::Original); - } - else if(policyName == "Fade") - { - SetHeightExceedPolicy(Toolkit::TextView::Fade); - } - else if(policyName == "Split") - { - SetHeightExceedPolicy(Toolkit::TextView::Split); - } - else if(policyName == "ShrinkToFit") - { - SetHeightExceedPolicy(Toolkit::TextView::ShrinkToFit); - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnHeightExceedPolicyPropertySet(). Invalid Property value." ); - } -} - -void TextView::OnLineJustificationPropertySet( Property::Value propertyValue ) -{ - std::string policyName( propertyValue.Get() ); - if(policyName == "Left") - { - SetLineJustification(Toolkit::TextView::Left); - } - else if(policyName == "Center") - { - SetLineJustification(Toolkit::TextView::Center); - } - else if(policyName == "Right") - { - SetLineJustification(Toolkit::TextView::Right); - } - else if(policyName == "Justified") - { - SetLineJustification(Toolkit::TextView::Justified); - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnLineJustificationPropertySet(). Invalid Property value." ); - } -} - -void TextView::OnFadeBoundaryPropertySet( Property::Value propertyValue ) -{ - Vector4 value( propertyValue.Get() ); - DALI_ASSERT_ALWAYS( ( value.x >= 0.f ) && ( value.y >= 0.f ) && ( value.z >= 0.f ) && ( value.w >= 0.f ) - && "TextView::OnFadeBoundaryPropertySet(). Negative value is invalid. " ); - - Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( static_cast( value.x ) ), - PixelSize( static_cast( value.y ) ), - PixelSize( static_cast( value.z ) ), - PixelSize( static_cast( value.w ) ) ); - - SetFadeBoundary( fadeBoundary ); -} - -void TextView::OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue ) -{ - std::string value( propertyValue.Get() ); - - if( propertyIndex == Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT ) - { - if(value == "HorizontalLeft") - { - mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalLeft; - } - else if( value == "HorizontalCenter") - { - mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalCenter; - } - else if( value == "HorizontalRight") - { - mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalRight; - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." ); - } - } - else if( propertyIndex == Toolkit::TextView::Property::VERTICAL_ALIGNMENT ) - { - if( value == "VerticalTop" ) - { - mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalTop; - } - else if( value == "VerticalCenter") - { - mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalCenter; - } - else if( value == "VerticalBottom") - { - mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalBottom; - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." ); - } - } - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY ); - } -} - -std::string TextView::OnHorizontalAlignmentPropertyGet() -{ - if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalLeft ) - { - return "HorizontalLeft"; - } - else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalCenter ) - { - return "HorizontalCenter"; - } - else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalRight ) - { - return "HorizontalRight"; - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnHorizontalAlignmentPropertyGet(). Invalid value." ); - } -} - -std::string TextView::OnVerticalAlignmentPropertyGet() -{ - if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalTop ) - { - return "VerticalTop"; - } - else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalCenter ) - { - return "VerticalCenter"; - } - else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalBottom ) - { - return "VerticalBottom"; - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnVerticalAlignmentPropertyGet(). Invalid value." ); - } -} - -void TextView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) -{ - Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) ); - - if( textView ) - { - TextView& textViewImpl( GetImpl( textView ) ); - switch( index ) - { - case Toolkit::TextView::Property::MARKUP_ENABLED: - { - textViewImpl.OnMarkupEnabledPeopertySet( value ); - break; - } - case Toolkit::TextView::Property::TEXT: - { - textViewImpl.SetText( value.Get() ); - break; - } - case Toolkit::TextView::Property::MULTILINE_POLICY: - { - textViewImpl.OnMultilinePolicyPropertySet( value ); - break; - } - case Toolkit::TextView::Property::WIDTH_EXCEED_POLICY: - { - textViewImpl.OnWidthExceedPolicyPropertySet( value ); - break; - } - case Toolkit::TextView::Property::HEIGHT_EXCEED_POLICY: - { - textViewImpl.OnHeightExceedPolicyPropertySet( value ); - break; - } - case Toolkit::TextView::Property::LINE_JUSTIFICATION: - { - textViewImpl.OnLineJustificationPropertySet( value ); - break; - } - case Toolkit::TextView::Property::FADE_BOUNDARY: - { - textViewImpl.OnFadeBoundaryPropertySet( value ); - break; - } - case Toolkit::TextView::Property::LINE_HEIGHT_OFFSET: - { - Dali::PointSize pointSize( value.Get() ); - textViewImpl.SetLineHeightOffset(pointSize); - break; - } - case Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT: - case Toolkit::TextView::Property::VERTICAL_ALIGNMENT: - { - textViewImpl.OnAlignmentPropertySet( index, value ); - break; - } - } - } -} - -Property::Value TextView::GetProperty( BaseObject* object, Property::Index index ) -{ - Property::Value value; - - Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) ); - - if( textView ) - { - TextView& textViewImpl( GetImpl( textView ) ); - switch( index ) - { - case Toolkit::TextView::Property::MARKUP_ENABLED: - { - value = textViewImpl.IsMarkupProcessingEnabled(); - break; - } - case Toolkit::TextView::Property::TEXT: - { - value = textViewImpl.GetText(); - break; - } - case Toolkit::TextView::Property::MULTILINE_POLICY: - { - value = MULTILINE_POLICY_NAME[ textViewImpl.GetMultilinePolicy() ]; - break; - } - case Toolkit::TextView::Property::WIDTH_EXCEED_POLICY: - { - value = EXCEED_POLICY_NAME[ textViewImpl.GetWidthExceedPolicy() ]; - break; - } - case Toolkit::TextView::Property::HEIGHT_EXCEED_POLICY: - { - value = EXCEED_POLICY_NAME[ textViewImpl.GetHeightExceedPolicy() ]; - break; - } - case Toolkit::TextView::Property::LINE_JUSTIFICATION: - { - value = LINE_JUSTIFICATION_NAME[ textViewImpl.GetLineJustification() ]; - break; - } - case Toolkit::TextView::Property::FADE_BOUNDARY: - { - Toolkit::TextView::FadeBoundary boundary = textViewImpl.GetFadeBoundary(); - value = Vector4( static_cast( boundary.mLeft.value ), - static_cast( boundary.mRight.value ), - static_cast( boundary.mTop.value ), - static_cast( boundary.mBottom.value ) ); - break; - } - case Toolkit::TextView::Property::LINE_HEIGHT_OFFSET: - { - value = textViewImpl.GetLineHeightOffset().value; - break; - } - case Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT: - { - value = textViewImpl.OnHorizontalAlignmentPropertyGet(); - break; - } - case Toolkit::TextView::Property::VERTICAL_ALIGNMENT: - { - value = textViewImpl.OnVerticalAlignmentPropertyGet(); - break; - } - } - } - return value; -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-impl.h b/dali-toolkit/internal/controls/text-view/text-view-impl.h deleted file mode 100644 index 270d32b..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-impl.h +++ /dev/null @@ -1,770 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * TextView is a custom control for text aligning and multiline support - */ -class TextView : public Control -{ -public: - - /** - * Internal exceed policy with the valid combinations. - */ - enum ExceedPolicy - { - Original, ///< Original size (even if it exceeds the witdh or the height). - OriginalFade, ///< Original size if it exceeds the width but faded if it exceeds the height. - OriginalShrink, ///< Shrunk if it exceeds the height. - SplitOriginal, ///< Split if it exceeds the width but no action if it exceeds the height. - SplitFade, ///< Split if it exceeds the width and faded if it exceeds the height. - SplitShrink, ///< Split if it exceeds the width and shrunk if it exceeds the height. - SplitEllipsizeEnd, ///< Split if it exceeds the width and ellipsize if it exceeds the height. - Fade, ///< Faded if it exceeds any boundary. - FadeOriginal, ///< Faded if it exceeds the width but no action if it exceeds the height. - ShrinkOriginal, ///< Shrunk if it exceeds the width but no action if it exceeds the height. - ShrinkFade, ///< Shrunk if it exceeds the width and faded if it exceeds the height. - Shrink, ///< Shrunk if it exceeds any boundary. - EllipsizeEndOriginal, ///< Ellipsized by the end if it exceeds the width but no action if it exceeds the height. - EllipsizeEnd ///< Ellipsized by the end if it exceeds the width and/or the height. - }; - - // Between two OnRelayout methods, several calls to InsertTextAt, RemoveTextFrom or SetText can happen. - // TextViewProcessorMetadata stores the type of operation. A vector stores all operations between two OnRelayout calls. - - enum TextViewProcessorMetadataType - { - TextSet, ///< Sets new text. - TextInserted, ///< Inserts text into current text. - TextReplaced, ///< Replaces some text from current text. - TextRemoved, ///< Removes some text from current text. - NewLineHeight, ///< Sets a new line height offset. - NewStyle ///< Sets a new style to the whole text. - }; - - /** - * Stores info about which data structures need to be modified when the OnRelayout() method is called - */ - struct TextViewProcessorMetadata - { - TextViewProcessorMetadata(); - - TextViewProcessorMetadataType mType; ///< Stores the type of operation. - std::size_t mPosition; ///< Character position within the text. - std::size_t mNumberOfCharacters; ///< Number of characters to be removed/replaced. - MarkupProcessor::StyledTextArray mText; ///< The new text. - TextStyle::Mask mStyleMask; ///< The style mask. - }; - - /** - * Defines which operations have to be done in the relayout process. - */ - enum RelayoutOperationMask - { - NO_RELAYOUT = 0x0, ///< Does nothing. - RELAYOUT_REMOVE_TEXT_ACTORS = 0x1, ///< Removes current text-actors from the text-view. - RELAYOUT_SIZE_POSITION = 0x2, ///< Calculates size and position of the text but it doesn't calculate alignment. - RELAYOUT_ALIGNMENT = 0x4, ///< Aligns the whole text. - RELAYOUT_VISIBILITY = 0x8, ///< Calculates the visibility. - RELAYOUT_INITIALIZE_TEXT_ACTORS = 0x10, ///< Initialize text-actors (create handles). - RELAYOUT_TEXT_ACTOR_UPDATE = 0x20, ///< Updates text-actors (set size, position, style, ...) - RELAYOUT_INSERT_TO_TEXT_VIEW = 0x40, ///< Adds the text-actors to the text-view. - RELAYOUT_ALL = 0xFF ///< Does all operations. - }; - - ////////////////////////////////////////////// - - /** - * Create a new TextView. - * @return A smart-pointer to the newly allocated TextView. - */ - static Toolkit::TextView New(); - - /** - * @copydoc SetText( const std::string& text ) - */ - void SetText( const std::string& text ); - - /** - * @copydoc SetText( const StyledTextArray& text ) - */ - void SetText( const MarkupProcessor::StyledTextArray& text ); - - /** - * @copydoc InsertTextAt( std::size_t position, const std::string& text ) - */ - void InsertTextAt( std::size_t position, const std::string& text ); - - /** - * @copydoc InsertTextAt( std::size_t position, const std::string& text ) - */ - void InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text ); - - /** - * @copydoc RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ) - */ - void RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ); - - /** - * @copydoc ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ) - */ - void ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ); - - /** - * @copydoc ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ) - */ - void ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text ); - - /** - * @copydoc GetText() - */ - std::string GetText() const; - - /** - * @copydoc SetLineHeightOffset() - */ - void SetLineHeightOffset( PointSize offset ); - - /** - * @copydoc GetLineHeightOffset() - */ - PointSize GetLineHeightOffset() const; - - /** - * @copydoc SetStyleToCurrentText() - */ - void SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask ); - - /** - * @copydoc SetTextAlignment( Toolkit::Alignment::Type align ) - */ - void SetTextAlignment( Toolkit::Alignment::Type align ); - - /** - * @copydoc GetTextAlignment() - */ - Toolkit::Alignment::Type GetTextAlignment() const; - - /** - * @copydoc SetMultilinePolicy() - */ - void SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ); - - /** - * @copydoc GetMultilinePolicy() - */ - Toolkit::TextView::MultilinePolicy GetMultilinePolicy() const; - - /** - * @copydoc SetWidthExceedPolicy() - */ - void SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @copydoc GetWidthExceedPolicy() - */ - Toolkit::TextView::ExceedPolicy GetWidthExceedPolicy() const; - - /** - * @copydoc SetHeightExceedPolicy() - */ - void SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @copydoc GetHeightExceedPolicy() - */ - Toolkit::TextView::ExceedPolicy GetHeightExceedPolicy() const; - - /** - * @copydoc SetLineJustification() - */ - void SetLineJustification( Toolkit::TextView::LineJustification justification ); - - /** - * @copydoc GetLineJustification() - */ - Toolkit::TextView::LineJustification GetLineJustification() const; - - /** - * @copydoc SetFadeBoundary() - */ - void SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ); - - /** - * @copydoc GetFadeBoundary() - */ - const Toolkit::TextView::FadeBoundary& GetFadeBoundary() const; - - /** - * @copydoc SetEllipsizeText() - */ - void SetEllipsizeText( const std::string& ellipsizeText ); - - /** - * @copydoc SetEllipsizeText() - */ - void SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText ); - - /** - * @copydoc SetEllipsizeText() - */ - void SetEllipsizeText( const Text& ellipsizeText, const Vector& ellipsizeStyles ); - - /** - * @copydoc GetEllipsizeText() - */ - std::string GetEllipsizeText() const; - - /** - * Checks if relayout the text is needed. If it is, it relais out the text - * by calling DoRelayOut(). - */ - void GetTextLayoutInfo(); - - /** - * Calls GetTextLayoutInfo() and fills the given data structure. - * - * @see GetTextLayoutInfo() - */ - void GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo ); - - /** - * @copydoc SetSortModifier() - */ - void SetSortModifier( float depthOffset ); - - /** - * @copydoc SetSnapshotModeEnabled() - */ - void SetSnapshotModeEnabled( bool enable ); - - /** - * @copydoc IsSnapshotModeEnabled() - */ - bool IsSnapshotModeEnabled() const; - - /** - * @brief Sets whether markup processing should be carried out. - * - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ); - - /** - * @brief Returns whether markup processing is enabled or not - * - * @return true is markup processing is enabled - */ - bool IsMarkupProcessingEnabled() const; - - /** - * @copydoc SetScrollEnabled() - */ - void SetScrollEnabled( bool enable ); - - /** - * @copydoc IsScrollEnabled() - */ - bool IsScrollEnabled() const; - - /** - * @copydoc SetScrollPosition() - * @see DoSetScrollPosition() - */ - void SetScrollPosition( const Vector2& position ); - - /** - * @copydoc GetScrollPosition() - */ - const Vector2& GetScrollPosition() const; - - /** - * @copydoc IsScrollPositionTrimmed() - */ - bool IsScrollPositionTrimmed() const; - - /** - * @copydoc ScrolledSignal() - */ - Toolkit::TextView::ScrolledSignalType& ScrolledSignal(); - - /** - * Connects a callback function with the object's signals. - * @param[in] object The object providing the signal. - * @param[in] tracker Used to disconnect the signal. - * @param[in] signalName The signal to connect to. - * @param[in] functor A newly allocated FunctorDelegate. - * @return True if the signal was connected. - * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor. - */ - static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ); - - // Properties - - /** - * Called when a property of an object of this type is set. - * @param[in] object The object whose property is set. - * @param[in] index The property index. - * @param[in] value The new property value. - */ - static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); - - /** - * Called to retrieve a property of an object of this type. - * @param[in] object The object whose property is to be retrieved. - * @param[in] index The property index. - * @return The current value of the property. - */ - static Property::Value GetProperty( BaseObject* object, Property::Index index ); - - -private: // From Control - - /** - * @copydoc Toolkit::Control::OnInitialize() - */ - virtual void OnInitialize(); - - /** - * @copydoc Toolkit::Control::OnFontChange( ) - */ - virtual void OnFontChange( bool defaultFontChange, bool defaultFontSizeChange ); - - /** - * @copydoc Toolkit::Control::OnControlSizeSet() - */ - virtual void OnControlSizeSet( const Vector3& size ); - - /** - * @copydoc Toolkit::Control::OnRelayout() - */ - virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); - - /** - * Retrieves the text-view's natural size. - * - * @return The natural size. - */ - virtual Vector3 GetNaturalSize(); - - /** - * Retrieves the text-view's \e height for a given \e width. - * - * @param[in] width The given \e width. - * - * @return The \e height for the given \e width. - */ - virtual float GetHeightForWidth( float width ); - - /** - * Retrieves the text-view's \e width for a given \e height. - * - * @param[in] height The given \e height. - * - * @return The \e width for the given \e height. - */ - virtual float GetWidthForHeight( float height ); - -protected: - - /** - * Construct a new TextView. - */ - TextView(); - - /** - * A reference counted object may only be deleted by calling Unreference() - */ - virtual ~TextView(); - -private: - - // Undefined - TextView( const TextView& ); - - // Undefined - TextView& operator=( const TextView& rhs ); - - /** - * Executes synchronously relayout operations such as set, insert, remove or replace text, etc. - */ - void PerformTextViewProcessorOperations(); - - /** - * Optimizes some text-view processor operations. - */ - void OptimizeTextViewProcessorOperations(); - - /** - * Synchronously relays-out all text-actors. - * - * Perform text-view-processor operations, sets the new size and position of text-actors and adds them to the text-view. - * - * @param[in] textViewSize The new text-view's size. - * @param[in] relayoutOperationMask Defines which operations need to be done in the relayout process. - */ - void DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask ); - - /** - * Process Snapshot. It refresh the render-task in order to generate a new snapshot image. - * - * ProcessSnapshot is called from OnRelayout() only if text has been relaid out. - * It creates a new image buffer only if the size of the text has changed. - * - * @param[in] textViewSize The new text-view's size. - */ - void ProcessSnapshot( const Size& textViewSize ); - - /** - * Aligns the offscreen rendering camera actor to cover the whole text and the resulting image actor accordingly with the text view's alignment. - * - * @param[in] textViewSize The text view's size. - * @param[in] offscreenSize The offscreen's frame buffer's size. - */ - void AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize ); - - /** - * Callback called when the render task has processed. - * - * It makes the root actor invisible. - * - * @param[in] renderTask The processed render task. - */ - void RenderTaskFinished( Dali::RenderTask& renderTask ); - - /** - * Destroys offscreen rendering resources. - * - * It disconects the render task finished signal from the TextView::RenderTaskFinished() method, - * removes the render task from the render task list and resets the offscreen camera actor, root actor, - * image actor and the frame buffer. - */ - void DestroyOffscreenRenderingResources(); - - /** - * Called when text-view is scrolled. - * - * Sets the new scroll position. @see DoSetScrollPosition() - * - * @param[in] actor Handle of the text-view. - * @param[in] gesture Data structure with the parameters of the gesture. - */ - void OnTextPan( Actor actor, const PanGesture& gesture ); - - /** - * Ensures the text-view's boundaries are fully covered of text. - * - * i.e. if the text-view's size is 100x100 and the text's size is 150x100, the scroll position - * can be in the range -50,0 and 50,0. - */ - void TrimScrollPosition(); - - /** - * Called from SetScrollPosition() and OnTextPan() - * - * Updates the stored scroll position ensuring the text-view is always covered with text by calling - * TrimScrollPosition(), calculates the difference with the previous one and emits the Toolkit::TextView::SignalScrolled() signal. - * - * @param[in] position The new scroll position. - */ - void DoSetScrollPosition( const Vector2& position ); - - /** - * Combines width and height exceed policies. - * - * This method is a big switch() which combines two exceed policies into one. - * The aim is avoid this switch inside the relayout code. - * - * i.e. Width policy = Split. Height policy = Original. Internally the policy is SplitOriginal. - */ - void CombineExceedPolicies(); - - /** - * Retrieves the text-view's root actor which stores all text-actors. - * It could be the text-view itself or an actor used in the snapshot mode. - * - * @return the root actor. - */ - Actor GetRootActor() const; - - /** - * Creates the ellipsize text layout. - */ - void CreateEllipsizeLayout(); - - /** - * Handle SetProperty for markup processing. - * @param[in] propertyValue The new property value. - */ - void OnMarkupEnabledPeopertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for multiline policy. - * @param[in] propertyValue The new property value. - */ - void OnMultilinePolicyPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for width exceed policy. - * @param[in] propertyValue The new property value. - */ - void OnWidthExceedPolicyPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for height exceed policy. - * @param[in] propertyValue The new property value. - */ - void OnHeightExceedPolicyPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for line justification. - * @param[in] propertyValue The new property value. - */ - void OnLineJustificationPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for fade boundary. - * @param[in] propertyValue The new property value. - */ - void OnFadeBoundaryPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for alignment property. - * @param[in] propertyIndex The property index. - * @param[in] propertyValue The new property value. - */ - void OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue ); - - /** - * Handles GetProperty for horizontal alignment property. - * @return The property value of horizontal alignment. - */ - std::string OnHorizontalAlignmentPropertyGet(); - - /** - * Handles GetProperty for vertical alignment property. - * @return The property value of vertical alignment. - */ - std::string OnVerticalAlignmentPropertyGet(); - -public: - - /** - * The parameters which affects the layout of the text. - */ - struct LayoutParameters - { - /** - * Default constructor. - */ - LayoutParameters(); - - /** - * Default destructor. - */ - ~LayoutParameters(); - - /** - * Constructor - */ - LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy, - Toolkit::TextView::ExceedPolicy widthExceedPolicy, - Toolkit::TextView::ExceedPolicy heightExceedPolicy, - Toolkit::Alignment::Type alignment, - Toolkit::TextView::LineJustification lineJustification, - float lineHeightOffset, - bool markUpEnabled ); - - /** - * Copy constructor - */ - LayoutParameters( const LayoutParameters& layoutParameters ); - - /** - * Assignment operator. - */ - LayoutParameters& operator=( const LayoutParameters& layoutParameters ); - - Toolkit::TextView::MultilinePolicy mMultilinePolicy; ///< Stores the multiline policy. - TextView::ExceedPolicy mExceedPolicy; ///< Stores a combination of both policies. - Toolkit::TextView::ExceedPolicy mWidthExceedPolicy; ///< Stores the text width exceed policy. - Toolkit::TextView::ExceedPolicy mHeightExceedPolicy; ///< Stores the text height exceed policy. - Toolkit::Alignment::Type mHorizontalAlignment; ///< Stores the horizontal alignment for the whole text. - Toolkit::Alignment::Type mVerticalAlignment; ///< Stores the vertical alignment for the whole text. - Toolkit::TextView::LineJustification mLineJustification; ///< Stores the line justification. - float mLineHeightOffset; ///< Line height offset to be addded to the font line height (measured in PointSize). - bool mMarkUpEnabled:1; ///< Is markup string scanning enabled. - }; - - /** - * Some parameters which affects the text view visualization. - */ - struct VisualParameters - { - /** - * Default constructor. - */ - VisualParameters(); - - /** - * Copy constructor. - */ - VisualParameters( const VisualParameters& visualParameters ); - - /** - * Assignment operator. - */ - VisualParameters& operator=( const VisualParameters& visualParameters ); - - Toolkit::TextView::FadeBoundary mFadeBoundary; ///< Fade boundary used in fade mode. - float mSortModifier; ///< Stores the sort modifier for all text-actors. - Vector2 mCameraScrollPosition; ///< The scroll offset. - bool mSnapshotModeEnabled:1; ///< Whether text-view is rendered offscreen. - bool mScrollEnabled:1; ///< Whether the text scroll is enabled. - bool mScrollPositionTrimmed:1; ///< Whether the last scroll position set was trimmed. - }; - - /** - * The results of the relayout process. - */ - struct RelayoutData - { - /** - * Default constructor. - */ - RelayoutData(); - - /** - * Copy constructor - */ - RelayoutData( const RelayoutData& relayoutData ); - - /** - * Assignment operator. - */ - RelayoutData& operator=( const RelayoutData& relayoutData ); - - Size mTextViewSize; ///< The text-view's size used to relaid-out the text. - float mShrinkFactor; ///< Shrink factor used when the exceed policy contains ShrinkToFit. - TextViewProcessor::TextLayoutInfo mTextLayoutInfo; ///< Stores metrics, layout info (size, direction, type of word) and text-actor info for the whole text. - std::vector mCharacterLogicalToVisualMap; ///< Reorder map that stores each character's visual (output) index according to its logical (input) index - std::vector mCharacterVisualToLogicalMap; ///< Reorder map that stores each character's logical (input) index according to its visual (output) index - std::vector mGlyphActors; ///< Stores handles of those text-actors which are currently added to the text-view. - std::vector mEllipsizedGlyphActors; ///< Stores handles of those text-actors which are used to ellipsize the text. - Toolkit::TextView::CharacterLayoutInfoContainer mCharacterLayoutInfoTable; ///< Stores layout info per character sorted by the character's visual index. - Toolkit::TextView::LineLayoutInfoContainer mLines; ///< Stores an index to the first character of each line. - Size mTextSizeForRelayoutOption; ///< Stores the text size after relayout. - TextActorCache mTextActorCache; ///< Stores previously created text-actors to be reused. - }; - -private: - - MarkupProcessor::StyledTextArray mCurrentStyledText; ///< text currently displayed by the view - std::vector mTextViewProcessorOperations; ///< Stores all relayout operations which arrive between two consecutive OnRelayout() calls. - - LayoutParameters mLayoutParameters; ///< Stores some layout parameters in a struct. To be passed in layout functions. - VisualParameters mVisualParameters; ///< Some parameters which afects text-view visualization. - RelayoutData mRelayoutData; ///< struct with text-view's data structures used to pass all of them in one parameter. - RelayoutOperationMask mRelayoutOperations; ///< Which relayout operations have to be done. - - Layer mOffscreenRootActor; ///< Root actor for offscreen rendering. - ImageActor mOffscreenImageActor; ///< Image actor for offscreen rendering. - CameraActor mOffscreenCameraActor; ///< Camera actor for offscreen rendering. - Size mCurrentOffscreenSize; ///< Current used ofscreen size. - FrameBufferImage mFrameBufferImage; ///< Frame buffer used for offscreen rendering. - RenderTask mRenderTask; ///< Used to generate an offscreen rendering. - - PanGestureDetector mPanGestureDetector; ///< Pan gesture for text scrolling. - - /** - * Helper class used to prevent the modification of some members. - */ - struct Lock - { - Lock( bool& lock ) - : mLock( lock ) - { - mLock = true; - } - - ~Lock() - { - mLock = false; - } - - bool& mLock; - }; - - bool mLockPreviousSnapshotMode; ///< Whether previous stored snapshot mode should be modified. - bool mPreviousSnapshotModeEnabled:1; ///< Stores the previous snapshot mode value. - bool mMarkUpEnabled:1; ///< enable to scan for mark-up - - Toolkit::TextView::ScrolledSignalType mScrolledSignal; ///< Signal emitted when text is scrolled. -}; - -} // namespace Internal - -// Helpers for public-api forwarding methods - -inline Internal::TextView& GetImpl( TextView& textView ) -{ - DALI_ASSERT_ALWAYS( textView ); - - RefObject& handle = textView.GetImplementation(); - - return static_cast< Internal::TextView& >( handle ); -} - -inline const Internal::TextView& GetImpl( const TextView& textView ) -{ - DALI_ASSERT_ALWAYS( textView ); - - const RefObject& handle = textView.GetImplementation(); - - return static_cast< const Internal::TextView& >( handle ); -} - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_ITEM_VIEW_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.cpp b/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.cpp deleted file mode 100644 index 70a0309..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.cpp +++ /dev/null @@ -1,733 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -///////////////////// -// Layout info. -///////////////////// - -void RightToLeftParagraphLayout::Clear() -{ - mWordsLayoutInfo.clear(); - mText = Text(); - mTextStyles.Clear(); -} - -ParagraphLayoutInfo::ParagraphLayoutInfo() -: mSize(), - mAscender( 0.f ), - mLineHeightOffset( 0.f ), - mFirstCharacter( 0u ), - mNumberOfCharacters( 0u ), - mWordsLayoutInfo(), - mText(), - mTextStyles(), - mRightToLeftLayout( NULL ), - mBidirectionalParagraphInfo( NULL ), - mBidirectionalLinesInfo() -{ -} - -ParagraphLayoutInfo::~ParagraphLayoutInfo() -{ - if( NULL != mRightToLeftLayout ) - { - // TextStyle pointers are the same than the ones stored at ParagraphLayoutInfo::mTextStyles. - // Do not delete them, just clear the vector. - mRightToLeftLayout->mTextStyles.Clear(); - - delete mRightToLeftLayout; - } - - // Clears text styles. It destroys TextStyle objects. - ClearStyles(); - - // Deletes the bidirectional info for the whole paragraph. - delete mBidirectionalParagraphInfo; - - // Clears the bidirectional info for all lines. Destroys the BidirectionalLineInfo objects. - ClearBidirectionalInfo(); -} - -ParagraphLayoutInfo::ParagraphLayoutInfo( const ParagraphLayoutInfo& paragraph ) -: mSize( paragraph.mSize ), - mAscender( paragraph.mAscender ), - mLineHeightOffset( paragraph.mLineHeightOffset ), - mFirstCharacter( paragraph.mFirstCharacter ), - mNumberOfCharacters( paragraph.mNumberOfCharacters ), - mWordsLayoutInfo( paragraph.mWordsLayoutInfo ), - mText( paragraph.mText ), - mTextStyles(), - mRightToLeftLayout( NULL ), - // Copies bidirectional info for the whole paragraph. - mBidirectionalParagraphInfo( ( NULL == paragraph.mBidirectionalParagraphInfo ) ? NULL : new TextProcessor::BidirectionalParagraphInfo( *paragraph.mBidirectionalParagraphInfo ) ), - mBidirectionalLinesInfo() -{ - // Copies styles. - for( Vector::ConstIterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it ) - { - mTextStyles.PushBack( new TextStyle( *(*it) ) ); - } - - // Copies bidirectional info for each line. - for( Vector::ConstIterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - mBidirectionalLinesInfo.PushBack( new TextProcessor::BidirectionalLineInfo( *( *it ) ) ); - } -} - -ParagraphLayoutInfo& ParagraphLayoutInfo::operator=( const ParagraphLayoutInfo& paragraph ) -{ - mSize = paragraph.mSize; - mAscender = paragraph.mAscender; - mLineHeightOffset = paragraph.mLineHeightOffset; - mFirstCharacter = paragraph.mFirstCharacter; - mNumberOfCharacters = paragraph.mNumberOfCharacters; - mWordsLayoutInfo = paragraph.mWordsLayoutInfo; - mText = paragraph.mText; - - // If it has styles, destroy them. - ClearStyles(); - - // Copies styles. - for( Vector::ConstIterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it ) - { - mTextStyles.PushBack( new TextStyle( *(*it) ) ); - } - - // Copies the paragraph's bidirectiona info. - if( NULL == paragraph.mBidirectionalParagraphInfo ) - { - // The source doesn't have bidirectiona info. Deletes the current one. - delete mBidirectionalParagraphInfo; - mBidirectionalParagraphInfo = NULL; - } - else - { - // The source has bidirectional info. - if( NULL != mBidirectionalParagraphInfo ) - { - // It it has, copy to it. - *mBidirectionalParagraphInfo = *paragraph.mBidirectionalParagraphInfo; - } - else - { - // If it doesn't have, create a new one. - mBidirectionalParagraphInfo = new TextProcessor::BidirectionalParagraphInfo( *paragraph.mBidirectionalParagraphInfo ); - } - } - - // If it has bidirectiona info per line, destroy them. - ClearBidirectionalInfo(); - - // Copies bidirectional info per line. - for( Vector::ConstIterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - mBidirectionalLinesInfo.PushBack( new TextProcessor::BidirectionalLineInfo( *( *it ) ) ); - } - - return *this; -} - -void ParagraphLayoutInfo::ClearBidirectionalInfo() -{ - // Destroys the bidirectional infor per line. - for( Vector::Iterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - delete *it; - } - mBidirectionalLinesInfo.Clear(); -} - -void ParagraphLayoutInfo::ClearStyles() -{ - // Destroys the styles. - for( Vector::Iterator it = mTextStyles.Begin(), endIt = mTextStyles.End(); it != endIt; ++it ) - { - delete *it; - } - mTextStyles.Clear(); -} - -void CreateParagraphInfo( TextView::RelayoutData& relayoutData, - ParagraphLayoutInfo& paragraphLayoutInfo ) -{ - if( TextProcessor::ContainsRightToLeftCharacter( paragraphLayoutInfo.mText ) ) - { - // If the text is bidirectional, the characters will be converted and reordered - // as specified by the Unicode Bidirectional Algorithm. - - paragraphLayoutInfo.mBidirectionalParagraphInfo = new TextProcessor::BidirectionalParagraphInfo(); - - TextProcessor::ProcessBidirectionalText( paragraphLayoutInfo.mText, paragraphLayoutInfo.mBidirectionalParagraphInfo ); - } - - // Split the paragraph in words. It retrieves the positions of white spaces and the last '\n' if there is one. - Vector positions; - TextProcessor::SplitInWords( paragraphLayoutInfo.mText, positions ); - - const std::size_t lastCharacterIndex = paragraphLayoutInfo.mText.GetLength() - 1u; - const bool isLastCharacterParagraphSeparator = paragraphLayoutInfo.mText.IsNewLine( lastCharacterIndex ); - - // The number of words is ~the number of white spaces found + 1u. - // White spaces are also words. - // New line characters are also white spaces. If the last character is a white space the +1 is not needed. - const std::size_t numberOfWords = 2u * positions.Count() + ( isLastCharacterParagraphSeparator ? 0u : 1u ); - - // Reserve space for all the words. - paragraphLayoutInfo.mWordsLayoutInfo.resize( numberOfWords, WordLayoutInfo() ); - - // Traverses all positions creating and setting all character layout info objects to every word. - std::size_t wordIndex = 0u; - Vector::ConstIterator positionIt = positions.Begin(); - Vector::ConstIterator positionEndIt = positions.End(); - std::size_t from = 0u; - for( std::size_t positionIndex = 0u, size = positions.Count() + 1u; positionIndex < size; ++positionIndex ) - { - const bool isEndPosition = positionIt == positionEndIt; - const std::size_t to = isEndPosition ? lastCharacterIndex + 1u : *positionIt; - - if( from < to ) - { - // The word is not a white space. - WordLayoutInfo& wordLayoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex ); - ++wordIndex; - // Sets the index within the paragraph to the first character of the word. - wordLayoutInfo.mFirstCharacter = from; - // Creates character layout info objects. - wordLayoutInfo.mCharactersLayoutInfo.resize( ( to - from ), CharacterLayoutInfo() ); - } - - if( !isEndPosition ) - { - // Create a word for the white space. - WordLayoutInfo& wordLayoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex ); - ++wordIndex; - // Sets the index within the paragraph to the white space. - wordLayoutInfo.mFirstCharacter = to; - wordLayoutInfo.mType = WordSeparator; - - CharacterLayoutInfo characterLayoutInfo; - wordLayoutInfo.mCharactersLayoutInfo.push_back( characterLayoutInfo ); - } - - from = to + 1u; - - if( !isEndPosition ) - { - // next white space position. - ++positionIt; - } - else - { - // All white space positiona have been traversed. - // It may be some extra words. i.e if the text is \n. - // Erase them. - paragraphLayoutInfo.mWordsLayoutInfo.erase( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex, paragraphLayoutInfo.mWordsLayoutInfo.end() ); - - // Check if the last character is a new paragraph character. - if( isLastCharacterParagraphSeparator ) - { - ( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ).mType = ParagraphSeparator; - } - } - } - - // Traverse all words and fill the layout info. - for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it ) - { - WordLayoutInfo& wordLayoutInfo( *it ); - - CreateWordTextInfo( paragraphLayoutInfo.mText, - paragraphLayoutInfo.mTextStyles, - wordLayoutInfo ); - - // Update layout info for the current paragraph. - UpdateSize( paragraphLayoutInfo.mSize, wordLayoutInfo.mSize ); - paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, wordLayoutInfo.mAscender ); - paragraphLayoutInfo.mNumberOfCharacters += wordLayoutInfo.mCharactersLayoutInfo.size(); - - // Update the max word width figure. - relayoutData.mTextLayoutInfo.mMaxWordWidth = std::max( relayoutData.mTextLayoutInfo.mMaxWordWidth, wordLayoutInfo.mSize.width ); - } // end of words -} - -void UpdateLayoutInfo( ParagraphLayoutInfo& paragraphLayoutInfo, float lineHeightOffset ) -{ - // Update layout info. - - // Initialize members to be updated. - paragraphLayoutInfo.mSize = Size::ZERO; - paragraphLayoutInfo.mAscender = 0.f; - paragraphLayoutInfo.mNumberOfCharacters = 0u; - - // Traverses all words. - for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - it != endIt; - ++it ) - { - WordLayoutInfo& word( *it ); - - // Sets the index within the paragraph to the first character of the word. - word.mFirstCharacter = paragraphLayoutInfo.mNumberOfCharacters; - - // Updates the paragraph's size. - UpdateSize( paragraphLayoutInfo.mSize, word.mSize ); - - // Updates the paragraph's max asender. - paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, word.mAscender ); - - // Updates the paragraph's number of characters. - paragraphLayoutInfo.mNumberOfCharacters += word.mCharactersLayoutInfo.size(); - } - - // Sets the line height offset. - paragraphLayoutInfo.mSize.height += lineHeightOffset; - paragraphLayoutInfo.mLineHeightOffset = lineHeightOffset; -} - -void RemoveWordsFromParagraph( std::size_t wordIndex, - std::size_t numberOfWords, - float lineHeightOffset, - ParagraphLayoutInfo& paragraphLayout ) -{ - // Removes words from a paragraph. - - // * Check if words or paragraphs can be merged after removing a number of words or a paragraph separator needs to be done outside this method. - - // Remove words from layout info. - paragraphLayout.mWordsLayoutInfo.erase( paragraphLayout.mWordsLayoutInfo.begin() + wordIndex, - paragraphLayout.mWordsLayoutInfo.begin() + ( wordIndex + numberOfWords ) ); - - UpdateLayoutInfo( paragraphLayout, lineHeightOffset ); -} - -void RemoveCharactersFromParagraphInfo( TextView::RelayoutData& relayoutData, - const std::size_t numberOfCharacters, - bool& mergeWords, - bool& mergeParagraphs, - TextInfoIndices& textInfoIndicesBegin, - TextInfoIndices& textInfoIndicesEnd, - TextInfoIndices& textInfoMergeIndicesBegin, - TextInfoIndices& textInfoMergeIndicesEnd, - ParagraphLayoutInfo& paragraphLayout, - std::vector& removedTextActorsFromFirstWord, - std::vector& removedTextActorsFromLastWord ) -{ - const TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo; - - if( textInfoIndicesBegin.mWordIndex < textInfoIndicesEnd.mWordIndex ) - { - // Deleted text is from different words. The two different words may be merged. - - // Get first word. - WordLayoutInfo& firstWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex ) ); - - // Get last word. - WordLayoutInfo& lastWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) ); - - // whether first or last word need to be split and merged. - bool mergeFromBegin = false; - bool mergeToEnd = false; - - if( textInfoIndicesBegin.mCharacterIndex > 0u ) - { - // First word is going to be split. It could be merged with the last word. - mergeFromBegin = true; - textInfoMergeIndicesBegin.mWordIndex = textInfoIndicesBegin.mWordIndex; - } - else if( ( textInfoIndicesBegin.mCharacterIndex == 0u ) && ( textInfoIndicesBegin.mWordIndex > 0u ) ) - { - // First word is going to be removed completely. - // Check if previous word could be merged. - - // Get word before. - WordLayoutInfo& previousWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex - 1u ) ); - if( WordSeparator != previousWordLayout.mType ) - { - // Previous word is not a word separator, so could be merged. - mergeFromBegin = true; - textInfoMergeIndicesBegin.mWordIndex = textInfoIndicesBegin.mWordIndex - 1u; - } - } - - if( mergeFromBegin ) - { - // First word (or previous one) could be merged. Check if last one could be merged as well. - - if( textInfoIndicesEnd.mCharacterIndex + 1u < lastWordLayout.mCharactersLayoutInfo.size() ) - { - // Last word is going to be split. It could be merged with the first word. - mergeToEnd = true; - textInfoMergeIndicesEnd.mWordIndex = textInfoIndicesEnd.mWordIndex; - } - else if( ( textInfoIndicesEnd.mCharacterIndex + 1u == lastWordLayout.mCharactersLayoutInfo.size() ) && ( textInfoIndicesEnd.mWordIndex + 1u < paragraphLayout.mWordsLayoutInfo.size() ) ) - { - // Last word is going to be removed completely. - // Check if the word after could be merged. - - // Get word after. - WordLayoutInfo& afterWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex + 1u ) ); - if( WordSeparator != afterWordLayout.mType ) - { - // The word after is not a word separator, so could be merged. - mergeToEnd = true; - textInfoMergeIndicesEnd.mWordIndex = textInfoIndicesEnd.mWordIndex + 1u; - } - } - - // Merge words only if both words could be merged. - mergeWords = mergeFromBegin && mergeToEnd; - } - - if( ( textInfoIndicesEnd.mCharacterIndex + 1u == lastWordLayout.mCharactersLayoutInfo.size() ) && ( textInfoIndicesEnd.mWordIndex + 1u == paragraphLayout.mWordsLayoutInfo.size() ) ) - { - // Last word of the paragraph is going to be removed completely. - // Check if it's a paragraph separator. - - if( ParagraphSeparator == lastWordLayout.mType ) - { - // The paragraph separator is going to be removed. - if( textInfoIndicesBegin.mParagraphIndex + 1u < textLayoutInfo.mParagraphsLayoutInfo.size() ) - { - // Paragraph need to be merged. - textInfoMergeIndicesBegin.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex; - textInfoMergeIndicesEnd.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex + 1u; - mergeParagraphs= true; - - ++textInfoIndicesBegin.mParagraphIndex; // increase both indices, - textInfoIndicesEnd.mParagraphIndex +=2u; // will delete last paragraph. - } - } - } - - if( textInfoIndicesBegin.mCharacterIndex > 0u ) - { - // First word needs to be split. - - // Store text-actors before removing them. - CollectTextActors( removedTextActorsFromFirstWord, firstWordLayout, textInfoIndicesBegin.mCharacterIndex, firstWordLayout.mCharactersLayoutInfo.size() ); - - RemoveCharactersFromWord( textInfoIndicesBegin.mCharacterIndex, - firstWordLayout.mCharactersLayoutInfo.size() - textInfoIndicesBegin.mCharacterIndex, - firstWordLayout ); - - ++textInfoIndicesBegin.mWordIndex; // will delete from the word after. - } - - if( textInfoIndicesEnd.mCharacterIndex + 1u < lastWordLayout.mCharactersLayoutInfo.size() ) - { - // Last word needs to be split. - - // Store text-actors before removing them. - CollectTextActors( removedTextActorsFromLastWord, lastWordLayout, 0u, textInfoIndicesEnd.mCharacterIndex + 1u ); - - RemoveCharactersFromWord( 0u, - textInfoIndicesEnd.mCharacterIndex + 1u, - lastWordLayout ); - - if( mergeWords ) - { - // This word is going to be merged, so is not needed. - ++textInfoIndicesEnd.mWordIndex; // will delete the last word. - } - } - else if( textInfoIndicesEnd.mCharacterIndex + 1u == lastWordLayout.mCharactersLayoutInfo.size() ) - { - // The whole last word is going to be removed. - ++textInfoIndicesEnd.mWordIndex; // will delete the last word. - - if( ( WordSeparator == lastWordLayout.mType ) && mergeWords ) - { - // The last word is a word separator and the word after is going to be merged so is not needed. - ++textInfoIndicesEnd.mWordIndex; // will delete the word after the last one. - } - } - } - else - { - // Chraracters to be removed are from the same word. - - RemoveCharactersFromWordInfo( relayoutData, - numberOfCharacters, - mergeWords, - mergeParagraphs, - textInfoIndicesBegin, - textInfoIndicesEnd, - textInfoMergeIndicesBegin, - textInfoMergeIndicesEnd, - paragraphLayout, - removedTextActorsFromFirstWord ); - } // word indices -} - -void SplitParagraph( const TextInfoIndices& indices, - float lineHeightOffset, - ParagraphLayoutInfo& firstParagraphLayoutInfo, - ParagraphLayoutInfo& lastParagraphLayoutInfo ) -{ - // Splits a paragraph in two. - // A word may be split in two as well. - - // * Split the word within the paragraph. - // * Add last part of the word to the new paragraph. - // * Add words from wordPosition + 1 to the end. - // * Update layout info of the last paragraph. - // * Remove words added to the last part of the paragraph from the first paragraph. - - // early returns!! - if( ( 0u == indices.mWordIndex ) && ( 0u == indices.mCharacterIndex ) ) - { - // the whole paragraph goes to the last part. - lastParagraphLayoutInfo = firstParagraphLayoutInfo; - - firstParagraphLayoutInfo = ParagraphLayoutInfo(); - - return; - } - - if( !firstParagraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - const std::size_t numberOfWords = firstParagraphLayoutInfo.mWordsLayoutInfo.size(); - if( indices.mWordIndex == numberOfWords - 1u ) - { - const WordLayoutInfo& word( *( firstParagraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ); - if( indices.mCharacterIndex == word.mCharactersLayoutInfo.size() ) - { - // the whole paragraph goes to the first part. - - // Just delete whatever there is in the last part of the paragraph. - lastParagraphLayoutInfo = ParagraphLayoutInfo(); - - return; - } - } - } - - lastParagraphLayoutInfo = ParagraphLayoutInfo(); - - // 1) Split the word whitin the paragraph. - WordLayoutInfo& firstWordLayoutInfo( *( firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex ) ); - WordLayoutInfo lastWordLayoutInfo; - - SplitWord( indices.mCharacterIndex, - firstWordLayoutInfo, - lastWordLayoutInfo ); - - // 2) Add last part of the word to the new paragraph. - if( !lastWordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - lastParagraphLayoutInfo.mWordsLayoutInfo.push_back( lastWordLayoutInfo ); - } - - // 3) Add words from word-position + 1 to the end. - lastParagraphLayoutInfo.mWordsLayoutInfo.insert( lastParagraphLayoutInfo.mWordsLayoutInfo.end(), - firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex + 1u, - firstParagraphLayoutInfo.mWordsLayoutInfo.end() ); - - // 4) update layout info of the last paragraph. - for( WordLayoutInfoContainer::iterator it = lastParagraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = lastParagraphLayoutInfo.mWordsLayoutInfo.end(); - it != endIt; - ++it ) - { - WordLayoutInfo& layoutInfo( *it ); - - UpdateSize( lastParagraphLayoutInfo.mSize, layoutInfo.mSize ); - lastParagraphLayoutInfo.mNumberOfCharacters += layoutInfo.mCharactersLayoutInfo.size(); - lastParagraphLayoutInfo.mAscender = std::max( lastParagraphLayoutInfo.mAscender, layoutInfo.mAscender ); - } - lastParagraphLayoutInfo.mSize.height += lineHeightOffset; - lastParagraphLayoutInfo.mLineHeightOffset = lineHeightOffset; - - // 5) Remove words added to the last part of the paragraph from the first paragraph. - - // if the number of characters of the last word of the first paragraph is zero, it should be removed. - const std::size_t index = ( firstWordLayoutInfo.mCharactersLayoutInfo.empty() ? indices.mWordIndex : indices.mWordIndex + 1u ); - - firstParagraphLayoutInfo.mWordsLayoutInfo.erase( firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + index, firstParagraphLayoutInfo.mWordsLayoutInfo.end() ); - - // 6) update layout info of the first paragraph. - UpdateLayoutInfo( firstParagraphLayoutInfo, lineHeightOffset ); - - // 7) Split text and styles. - - // Copies the whole text to the last part of the paragraph. - lastParagraphLayoutInfo.mText = firstParagraphLayoutInfo.mText; - - // Removes from the first part of the paragraph the text that goes to the last part. - firstParagraphLayoutInfo.mText.Remove( indices.mCharacterParagraphIndex, firstParagraphLayoutInfo.mText.GetLength() - indices.mCharacterParagraphIndex ); - - // Removes from the last part of the paragraph the text that remains in the first part. - lastParagraphLayoutInfo.mText.Remove( 0u, indices.mCharacterParagraphIndex ); - - // Sets the character's styles for the last part of the paragraph. - lastParagraphLayoutInfo.mTextStyles.Insert( lastParagraphLayoutInfo.mTextStyles.End(), - firstParagraphLayoutInfo.mTextStyles.Begin() + indices.mCharacterParagraphIndex, - firstParagraphLayoutInfo.mTextStyles.End() ); - - // Removes the character's styles that go to the last part of the paragraph. - firstParagraphLayoutInfo.mTextStyles.Erase( firstParagraphLayoutInfo.mTextStyles.Begin() + indices.mCharacterParagraphIndex, - firstParagraphLayoutInfo.mTextStyles.End() ); -} - -void MergeParagraph( ParagraphLayoutInfo& firstParagraphLayoutInfo, - const ParagraphLayoutInfo& lastParagraphLayoutInfo ) -{ - // Merges two given paragraphs. - // - // Can't merge two paragraphs if the last word of the first one is a paragraph separator (new paragraph character) - - // Early returns. - - if( lastParagraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - // Nothing to merge if last paragraph is empty. - return; - } - - if( firstParagraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - // If first paragraph is empty, just copy the last paragraph to the first one. - firstParagraphLayoutInfo = lastParagraphLayoutInfo; - - return; - } - - // Check the last word of the first paragraph doesn't finish with a new paragraph character. - WordLayoutInfo& lastWordLayout( *( firstParagraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ); - if( ParagraphSeparator == lastWordLayout.mType ) - { - DALI_ASSERT_ALWAYS( !"TextViewProcessor::MergeParagraph(). ERROR: A paragraph can't be merged to another paragraph which finishes with a new paragraph character." ); - } - - // If the las word of the first paragraph or the first word of the last paragraph is a white space, both paragraphs can be concatenated. - // Otherwise both words need to be merged first. - const WordLayoutInfo& firstWordLayout( *lastParagraphLayoutInfo.mWordsLayoutInfo.begin() ); - - std::size_t index = 0u; - if( ( WordSeparator != lastWordLayout.mType ) && ( WordSeparator != firstWordLayout.mType ) && ( ParagraphSeparator != firstWordLayout.mType ) ) - { - // Last word of the first paragraph is not a word separator and first word of the last paragraph is not a word or paragraph separator. - // Words need to be merged. - - MergeWord( lastWordLayout, - firstWordLayout ); - - // After merging two words, the rest of the words need to be added. - ++index; // By increasing this index the word already merged won't be added again. - } - - // Merge layout info - - // Insert the layout of the words. - const std::size_t numberOfWords = firstParagraphLayoutInfo.mWordsLayoutInfo.size(); - firstParagraphLayoutInfo.mWordsLayoutInfo.insert( firstParagraphLayoutInfo.mWordsLayoutInfo.end(), - lastParagraphLayoutInfo.mWordsLayoutInfo.begin() + index, lastParagraphLayoutInfo.mWordsLayoutInfo.end() ); - - // Increase the index of the first character of each inserted word. - for( WordLayoutInfoContainer::iterator it = firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + numberOfWords, endIt = firstParagraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it ) - { - WordLayoutInfo& word( *it ); - word.mFirstCharacter += firstParagraphLayoutInfo.mNumberOfCharacters; - } - - // Update the size and other layout parameters. - UpdateSize( firstParagraphLayoutInfo.mSize, lastParagraphLayoutInfo.mSize ); - firstParagraphLayoutInfo.mAscender = std::max( firstParagraphLayoutInfo.mAscender, lastParagraphLayoutInfo.mAscender ); - firstParagraphLayoutInfo.mLineHeightOffset = std::max( firstParagraphLayoutInfo.mLineHeightOffset, lastParagraphLayoutInfo.mLineHeightOffset ); - firstParagraphLayoutInfo.mNumberOfCharacters += lastParagraphLayoutInfo.mNumberOfCharacters; - - // Merge text and styles. - firstParagraphLayoutInfo.mText.Append( lastParagraphLayoutInfo.mText ); - for( Vector::ConstIterator it = lastParagraphLayoutInfo.mTextStyles.Begin(), endIt = lastParagraphLayoutInfo.mTextStyles.End(); it != endIt; ++it ) - { - firstParagraphLayoutInfo.mTextStyles.PushBack( new TextStyle( *(*it) ) ); - } -} - -WordLayoutInfo GetLastWordLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ) -{ - WordLayoutInfo layoutInfo; - - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - layoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ); - } - - return layoutInfo; -} - -CharacterLayoutInfo GetFirstCharacterLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ) -{ - CharacterLayoutInfo layoutInfo; - - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - const WordLayoutInfo& wordInfo( *paragraphLayoutInfo.mWordsLayoutInfo.begin() ); - - layoutInfo = GetFirstCharacterLayoutInfo( wordInfo ); - } - - return layoutInfo; -} - -CharacterLayoutInfo GetLastCharacterLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ) -{ - const WordLayoutInfo wordInfo = GetLastWordLayoutInfo( paragraphLayoutInfo ); - - return GetLastCharacterLayoutInfo( wordInfo ); -} - -void CollectTextActorsFromParagraphs( std::vector& textActors, const TextLayoutInfo& textLayoutInfo, const std::size_t paragraphIndexBegin, const std::size_t paragraphIndexEnd ) -{ - for( ParagraphLayoutInfoContainer::const_iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndexBegin, paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndexEnd; - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - const ParagraphLayoutInfo& paragraph( *paragraphIt ); - - CollectTextActorsFromWords( textActors, paragraph, 0u, paragraph.mWordsLayoutInfo.size() ); - } -} - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h b/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h deleted file mode 100644 index 3e9b0f0..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PARAGRAPH_PROCESSOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PARAGRAPH_PROCESSOR_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -/** - * Creates a data structure with info to layout the paragraph, and data structures with useful info to modify the layout data structure if characters are added or removed. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - * @param[out] paragraphLayoutInfo Layout info for the whole paragraph. - */ -void CreateParagraphInfo( TextView::RelayoutData& relayoutData, - ParagraphLayoutInfo& paragraphLayoutInfo ); - -/** - * Updates the paragraph layout info. - * - * @param[in,out] paragraphLayoutInfo The paragraph layout info. - * @param[in] lineHeightOffset The offset added to the line height. - */ -void UpdateLayoutInfo( ParagraphLayoutInfo& paragraphLayoutInfo, float lineHeightOffset ); - -/** - * Removes a given number of words from the given paragraph. - * - * @pre \e wordIndex and \e wordIndex + \e numberOfWords can't exceed the bounds of the paragraph. - * - * @param[in] wordIndex Index to the word within the paragraph with the starting position to be deleted. - * @param[in] numberOfWords The number of words to be deleted. - * @param[in] lineHeightOffset The offset added to the line height. Needed to update the layout info. - * @param[in,out] paragraphLayout The input is the layout info of the paragraph. The output is the layout info of the paragraph without the removed words. - */ -void RemoveWordsFromParagraph( std::size_t wordIndex, - std::size_t numberOfWords, - float lineHeightOffset, - ParagraphLayoutInfo& paragraphLayout ); - -/** - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in] numberOfCharacters The number of characters to be deleted. - * @param[out] mergeWords Whether words need to be merged after removing characters. - * @param[out] mergeParagraphs Whether current paragraph need to be merged with the next one. - * @param[in,out] textInfoIndicesBegin Indices to the paragraph, word and characters from where to delete characters. It returns from where words need to be removed. - * @param[out] textInfoIndicesEnd If paragraphs or words need to be merged it returns info to delete them (If a word is merged, it has to be removed. Equal for paragraphs). - * @param[out] textInfoMergeIndicesBegin The indices to the first part of the paragraph and word to be merged. - * @param[out] textInfoMergeIndicesEnd The indices to the last part of the paragraph and word to be merged. - * @param[in,out] paragraphLayout Layout info of the paragraph where the word is located. - * @param[out] removedTextActorsFromFirstWord Stores removed text-actors of the word pointed by the 'begin' index. - * @param[out] removedTextActorsFromLastWord Stores removed text-actors of the word pointed by the 'end' index. - */ -void RemoveCharactersFromParagraphInfo( TextView::RelayoutData& relayoutData, - std::size_t numberOfCharacters, - bool& mergeWords, - bool& mergeParagraphs, - TextInfoIndices& textInfoIndicesBegin, - TextInfoIndices& textInfoIndicesEnd, - TextInfoIndices& textInfoMergeIndicesBegin, - TextInfoIndices& textInfoMergeIndicesEnd, - ParagraphLayoutInfo& paragraphLayout, - std::vector& removedTextActorsFromFirstWord, - std::vector& removedTextActorsFromLastWord ); - -/** - * Splits a given paragraph in two. - * - * @note It deletes whatever there is in the last part of the paragraph. - * - * @param[in] indices Index to the word within the paragraph and index to the character within the word to split the paragraph. - * @param[in] lineHeightOffset Additional space between lines. Needed to update layout info. - * @param[in,out] firstParagraphLayoutInfo The input is the layout info of the given paragraph. The output is the first part of the input paragraph. - * @param[in,out] lastParagraphLayoutInfo Layout info of the last part of the given paragraph. - */ -void SplitParagraph( const TextInfoIndices& indices, - float lineHeightOffset, - ParagraphLayoutInfo& firstParagraphLayoutInfo, - ParagraphLayoutInfo& lastParagraphLayoutInfo ); - -/** - * Merges the two given paragraphs by adding words of the last paragraph to the firs one. - * - * @note Does nothing if last part of the paragraph is empty. - * @note If the first part of the paragraph is empty it just copy the last part to it. - * @note it asserts if the last word of the first paragraph is a paragraph separator (new paragraph character) - * - * @param[in,out] firstParagraphLayoutInfo The input is the layout info of the first paragraph. The output is the layout info of the merged paragraph. - * @param[in] lastParagraphLayoutInfo Layout info of the last paragraph. - * - */ -void MergeParagraph( ParagraphLayoutInfo& firstParagraphLayoutInfo, - const ParagraphLayoutInfo& lastParagraphLayoutInfo ); - -/** - * Retrieves the layout information of the last word of the given paragraph. - * - * @param[in] paragraphLayoutInfo The paragraph layout. - * - * @return Layout information of the last word of the paragraph. - */ -WordLayoutInfo GetLastWordLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ); - -/** - * Retrieves the layout information of the first character of the given paragraph. - * - * @param[in] paragraphLayoutInfo The paragraph layout. - * - * @return Layout information of the first character of the paragraph. - */ -CharacterLayoutInfo GetFirstCharacterLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ); - -/** - * Retrieves the layout information of the last character of the given paragraph. - * - * @param[in] paragraphLayoutInfo The paragraph layout. - * - * @return Layout information of the last character of the paragraph. - */ -CharacterLayoutInfo GetLastCharacterLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ); - -/** - * Collects text-actors from the given paragraphs and stores them into the text-actor vector. - * - * @param[out] textActors Stores the text-actors of the given paragraphs. - * @param[in] textLayoutInfo Whole text with the given paragraphs. - * @param[in] paragraphIndexBegin The first paragraph. - * @param[in] paragraphIndexEnd The last paragraph. - */ -void CollectTextActorsFromParagraphs( std::vector& textActors, const TextLayoutInfo& textLayoutInfo, std::size_t paragraphIndexBegin, std::size_t paragraphIndexEnd ); - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PARAGRAPH_PROCESSOR_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.cpp b/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.cpp deleted file mode 100644 index df420cf..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -#if defined(DEBUG_ENABLED) -Debug::Filter* gTextViewProcessorLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXT_VIEW_PROCESSOR"); -#endif - -void dbgPrint( const WordLayoutInfo& word ) -{ - std::cout << " size " << word.mSize << std::endl; - std::cout << " ascender " << word.mAscender << std::endl; - std::cout << " type "; - switch( word.mType ) - { - case NoSeparator: - { - std::cout << "NoSeparator" << std::endl; - break; - } - case ParagraphSeparator: - { - std::cout << "ParagraphSeparator" << std::endl; - break; - } - case WordSeparator: - { - std::cout << "WordSeparator" << std::endl; - break; - } - } - std::cout << " first char " << word.mFirstCharacter << std::endl; - std::cout << " num char " << word.mCharactersLayoutInfo.size() << std::endl; - for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), endCharacterIt = word.mCharactersLayoutInfo.end(); - characterIt != endCharacterIt; - ++characterIt ) - { - const CharacterLayoutInfo& character( *characterIt ); - - std::cout << "[" << character.mSize << std::endl; - std::cout << " ascender " << character.mAscender << std::endl; - } -} - -void dbgPrint( const ParagraphLayoutInfo& paragraph ) -{ - std::cout << "< "; - std::cout << " text : [" << paragraph.mText.GetText() << "]" << std::endl; - std::cout << " number of styles : " << paragraph.mTextStyles.Count() << std::endl; - std::cout << paragraph.mSize; - for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin(), endWordIt = paragraph.mWordsLayoutInfo.end(); - wordIt != endWordIt; - ++wordIt ) - { - dbgPrint( *wordIt ); - } - std::cout << " >"; - std::cout << std::endl; -} - -void dbgPrint( const TextLayoutInfo& textInfo ) -{ - std::cout << "||" << std::endl; - std::cout << textInfo.mWholeTextSize; - std::cout << textInfo.mNumberOfCharacters; - for( ParagraphLayoutInfoContainer::const_iterator it = textInfo.mParagraphsLayoutInfo.begin(), endIt = textInfo.mParagraphsLayoutInfo.end(); - it != endIt; - ++it ) - { - dbgPrint( *it ); - } - std::cout << "||" << std::endl; -} - -void dbgPrint( const TextStyle& style ) -{ - std::cout << " font name : " << style.GetFontName() << std::endl; - std::cout << " font style : " << style.GetFontStyle() << std::endl; - std::cout << " font point size : " << style.GetFontPointSize() << std::endl; - std::cout << " weight : " << style.GetWeight() << std::endl; - std::cout << " text color : " << style.GetTextColor() << std::endl; - std::cout << " italics : " << style.IsItalicsEnabled() << std::endl; - std::cout << " italics angle : " << style.GetItalicsAngle() << std::endl; - std::cout << " underline : " << style.IsUnderlineEnabled() << std::endl; - std::cout << " underline thickness : " << style.GetUnderlineThickness() << std::endl; - std::cout << " underline position : " << style.GetUnderlinePosition() << std::endl; - std::cout << " shadow : " << style.IsShadowEnabled() << std::endl; - std::cout << " shadow color : " << style.GetShadowColor() << std::endl; - std::cout << " shadow offset : " << style.GetShadowOffset() << std::endl; - std::cout << " shadow size : " << style.GetShadowSize() << std::endl; - std::cout << " glow : " << style.IsGlowEnabled() << std::endl; - std::cout << " glow color : " << style.GetGlowColor() << std::endl; - std::cout << " glow intensity : " << style.GetGlowIntensity() << std::endl; - std::cout << " smooth edge : " << style.GetSmoothEdge() << std::endl; - std::cout << " outline : " << style.IsOutlineEnabled() << std::endl; - std::cout << " outline color : " << style.GetOutlineColor() << std::endl; - std::cout << " outline thickness : " << style.GetOutlineThickness() << std::endl; - std::cout << " gradient : " << style.IsGradientEnabled() << std::endl; - std::cout << " gradient color : " << style.GetGradientColor() << std::endl; - std::cout << " gradient start point : " << style.GetGradientStartPoint() << std::endl; - std::cout << " gradient end point : " << style.GetGradientEndPoint() << std::endl; - std::cout << " is font name default : " << style.IsFontNameDefault() << std::endl; - std::cout << " is font style default : " << style.IsFontStyleDefault() << std::endl; - std::cout << " is font size default : " << style.IsFontSizeDefault() << std::endl; - std::cout << " is text color default : " << style.IsTextColorDefault() << std::endl; - std::cout << " is font weight default : " << style.IsFontWeightDefault() << std::endl; - std::cout << " is smooth edge default : " << style.IsSmoothEdgeDefault() << std::endl; - std::cout << " is italics default : " << style.IsItalicsDefault() << std::endl; - std::cout << " is underline default : " << style.IsUnderlineDefault() << std::endl; - std::cout << " is shadow default : " << style.IsShadowDefault() << std::endl; - std::cout << " is glow default : " << style.IsGlowDefault() << std::endl; - std::cout << " is outline default : " << style.IsOutlineDefault() << std::endl; - std::cout << " is gradient default : " << style.IsGradientDefault() << std::endl; -} - -void dbgPrint( const TextInfoIndices& indices ) -{ - std::cout << " paragraph : " << indices.mParagraphIndex << std::endl; - std::cout << " word : " << indices.mWordIndex << std::endl; - std::cout << " char : " << indices.mCharacterIndex << std::endl; - std::cout << " char in paragraph : " << indices.mCharacterParagraphIndex << std::endl; -} - -void dbgPrint( const MarkupProcessor::StyledTextArray& textArray ) -{ - for( MarkupProcessor::StyledTextArray::const_iterator it = textArray.begin(), endIt = textArray.end(); it != endIt; ++it ) - { - const MarkupProcessor::StyledText& text( *it ); - - std::cout << text.mText.GetText(); - } -} - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h b/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h deleted file mode 100644 index 2529bb8..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_DBG_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_DBG_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -//Forward declarations. -class TextStyle; - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -//Forward declarations. -struct WordLayoutInfo; -struct ParagraphLayoutInfo; -struct TextLayoutInfo; -struct TextInfoIndices; - -#if defined(DEBUG_ENABLED) -extern Debug::Filter* gTextViewProcessorLogFilter; -#endif - -void dbgPrint( const WordLayoutInfo& word ); -void dbgPrint( const ParagraphLayoutInfo& paragraph ); -void dbgPrint( const TextLayoutInfo& textInfo ); -void dbgPrint( const TextStyle& style ); -void dbgPrint( const TextInfoIndices& indices ); -void dbgPrint( const MarkupProcessor::StyledTextArray& text ); - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_DBG_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.cpp b/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.cpp deleted file mode 100644 index 43a5f4e..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -void UpdateSize( Size& size1, const Size& size2, const SizeGrowType type ) -{ - switch( type ) - { - case GrowWidth: - { - size1.width += size2.width; - size1.height = std::max( size1.height, size2.height ); - break; - } - case GrowHeight: - { - size1.width = std::max( size1.width, size2.width ); - size1.height += size2.height; - break; - } - } -} - -TextSeparatorType GetTextSeparatorType( const Character& character ) -{ - // returns if the given character is a paragraph separator '\n', a word separator ' ' or if is not a separator (any other character). - return ( character.IsNewLine() ? ParagraphSeparator : ( character.IsWhiteSpace() ? WordSeparator : NoSeparator ) ); -} - -void ChooseFontFamilyName( const Character& character, TextStyle& style ) -{ - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::ChooseFontFamilyName\n" ); - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " input font name: [%s]\n", style.GetFontName().c_str() ); - - bool userDefinedFontFamilyName = false; - - // First check if there is a font defined in the style and it supports the given text. - if( !style.GetFontName().empty() ) - { - const FontParameters fontParams( style.GetFontName(), style.GetFontStyle() , style.GetFontPointSize() ); - const Font font = Font::New( fontParams ); - - if( !font.IsDefaultSystemFont() && font.AllGlyphsSupported( character ) ) - { - userDefinedFontFamilyName = true; - } - } - - if( !userDefinedFontFamilyName ) - { - const Font defaultSystemFont = Font::New(); - - // At this point no font is set or doesn't support the given text. - if( !defaultSystemFont.AllGlyphsSupported( character ) ) - { - // If the default system font doesn't support the given text, - // an appropiate font is selected. - style.SetFontName( Font::GetFamilyForText( character ) ); - // @TODO Font::GetFamilyForText() should return font family and font style. - } - else - { - // All characters are supported with default font, so use it - style.SetFontName( "" ); - } - } - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " output font name: [%s]\n", style.GetFontName().c_str() ); - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::ChooseFontFamilyName\n" ); -} - -void GetIndicesFromGlobalCharacterIndex( const std::size_t index, - const TextLayoutInfo& textLayoutInfo, - TextInfoIndices& indices ) -{ - // clear all indices - indices = TextInfoIndices(); - - // Early return. - if( textLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - // Text is empty. All indices are 0. - return; - } - - std::size_t currentIndex = 0u; // stores how many characters have been traversed (within the whole text). - - // Traverse all paragraphs and words until global index is found. - bool found = false; - for( ParagraphLayoutInfoContainer::const_iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin(), - paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.end(); - ( !found ) && ( paragraphIt != paragraphEndIt ); - ++paragraphIt, ++indices.mParagraphIndex ) - { - const ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt ); - std::size_t currentCharactersTraversed = currentIndex; // stores how many characters have been traversed until this paragraph. - - if( currentIndex + paragraphLayoutInfo.mNumberOfCharacters > index ) - { - // The character is in this paragraph - for( WordLayoutInfoContainer::const_iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), - wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - ( !found ) && ( wordIt != wordEndIt ); - ++wordIt, ++indices.mWordIndex ) - { - const WordLayoutInfo& wordLayoutInfo( *wordIt ); - - if( currentIndex + wordLayoutInfo.mCharactersLayoutInfo.size() > index ) - { - // The character is in this word - indices.mCharacterIndex = index - currentIndex; - indices.mCharacterParagraphIndex = index - currentCharactersTraversed; - found = true; - } - else - { - // check in the next word. - currentIndex += wordLayoutInfo.mCharactersLayoutInfo.size(); - } - } // end words. - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - --indices.mWordIndex; - } - } - else - { - // check in the next paragraph - currentIndex += paragraphLayoutInfo.mNumberOfCharacters; - } - } // end paragraphs. - - // Need to decrease indices as they have been increased in the last loop. - if( !textLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - --indices.mParagraphIndex; - } -} - -void ClearText( std::vector& textActors ) -{ - for( std::vector::iterator it = textActors.begin(), endIt = textActors.end(); it != endIt; ++it ) - { - (*it).SetText( std::string( "" ) ); - } -} - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h b/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h deleted file mode 100644 index c543e32..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_HELPER_FUNCTIONS_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_HELPER_FUNCTIONS_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -/** - * Enum type used to update a size adding other one. - * If the grow type is \e GrowWidth, size's widths are added and size's height is the max of both. - * Alternativelly if grow type is \e GrowHeight heights are added and width is the max of both. - */ -enum SizeGrowType -{ - GrowWidth, - GrowHeight, -}; - -/** - * Updates the size of a character, word, line or the whole text with a given size. - * - * For characters, words, and lines the new height will be the maximum of both sizes - * and the new width will be the sum of both. - * - * For the whole text, the new height will be the sum of both and the new width the max of both. - * - * The \e type parameter speficies which type of update is required. - * - * @param[in,out] size1 The current size to be updated. - * @param[in] size2 The size of a character, word, or a line. - * @param[in] type Type of update. - */ -void UpdateSize( Size& size1, const Size& size2, SizeGrowType type = GrowWidth ); - -/** - * Return the type of separator (white space, new line or no separator) for the given character. - * - * @param[in] character The given character. - * - * @return The type of separator. - */ -TextSeparatorType GetTextSeparatorType( const Character& character ); - -/** - * Choose a suitable font family name for the given character. - * - * It may modify the text-style of the given character by setting a suitable font-family. - * - * @param[in] character The character. - * @param[in,out] style The style of the character. - */ -void ChooseFontFamilyName( const Character& character, TextStyle& style ); - -/** - * Retrieves the line, word and character indices for the given global character's index. - * - * i.e. The retrieved indices for the character 18 (j) for the following text would be: 2, 0, 2, 0 - * - * a b c d - * e f g h - * i j k l - * m n o p - * - * @param[in] index The global character index. - * @param[in] textLayoutInfo Contains info about the number of characters per word, and line. - * @param[out] indices Index to the line, word and character within the word where the given character is located. - */ -void GetIndicesFromGlobalCharacterIndex( std::size_t index, - const TextLayoutInfo& textLayoutInfo, - TextInfoIndices& indices ); - -/** - * Clear the text of the given text-actors. - * - * @param[in] textActors The given text-actors. - */ -void ClearText( std::vector& textActors ); - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_HELPER_FUNCTIONS_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-types.h b/dali-toolkit/internal/controls/text-view/text-view-processor-types.h deleted file mode 100644 index 15005cc..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-types.h +++ /dev/null @@ -1,356 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_TYPES_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_TYPES_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -class TextStyle; - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ -// Forward declarations. -struct BidirectionalParagraphInfo; -struct BidirectionalLineInfo; -} // namespace TextProcessor - -namespace TextViewProcessor -{ - -/** - * Whether the text is a new paragraph character '\n', a white space or normal text. - */ -enum TextSeparatorType -{ - ParagraphSeparator, - WordSeparator, - NoSeparator -}; - -/** - * Whether to clear the text of the text-actors when text is removed. - */ -enum TextOperationOnRemove -{ - CLEAR_TEXT, - KEEP_TEXT -}; - - -/** - * Stores text info indices. - */ -struct TextInfoIndices -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - TextInfoIndices(); - - /** - * Constructor. - */ - TextInfoIndices( std::size_t paragraphIndex, - std::size_t wordIndex, - std::size_t characterIndex ); - - /** - * Equality operator. - * @param [in] indices The text-info indices to be compared. - * - * @return \e true if both indices are equal. - */ - bool operator==( const TextInfoIndices& indices ) const; - - std::size_t mParagraphIndex; ///< The paragraph index within the text. - std::size_t mWordIndex; ///< The word index within the paragraph. - std::size_t mCharacterIndex; ///< The character index within the word. - std::size_t mCharacterParagraphIndex; ///< The character index within the paragraph. -}; - -/** - * Stores gradient info. - * - * Used to fade in/out text-actors. - */ -struct GradientInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - GradientInfo(); - - /** - * Default destructor. - */ - ~GradientInfo(); - - /** - * Copy constructor - */ - GradientInfo( const GradientInfo& info ); - - /** - * Assignment operator. - */ - GradientInfo& operator=( const GradientInfo& info ); - - Vector4 mGradientColor; ///< Gradient color. - Vector2 mStartPoint; ///< Gradient start point. - Vector2 mEndPoint; ///< Gradient end point. -}; - -/** - * Layout information for a character. - * It stores the position, size and ascender of its respective text-actor. - */ -struct CharacterLayoutInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - CharacterLayoutInfo(); - - /** - * Default destructor. - * - * Deletes the gradient info. - */ - ~CharacterLayoutInfo(); - - /** - * Copy constructor. - */ - CharacterLayoutInfo( const CharacterLayoutInfo& character ); - - /** - * Assignment operator. - */ - CharacterLayoutInfo& operator=( const CharacterLayoutInfo& character ); - - // Metrics of the glyph. - Size mSize; ///< Height of the font and advance (the horizontal distance from the origin of the current character and the next one). - float mBearing; ///< Vertical distance from the baseline to the top of the glyph's boundary box. - float mAscender; ///< Distance from the base line to the top of the line. - float mUnderlineThickness; ///< The underline's thickness. - float mUnderlinePosition; ///< The underline's position. - - // Position and alignment offset. It depends on the lay-out. - Vector3 mPosition; ///< Position within the text-view - Vector2 mOffset; ///< Alignment and justification offset. - - RenderableActor mGlyphActor; ///< Handle to a text-actor. - float mColorAlpha; ///< Alpha component for the initial text color when text is faded. - GradientInfo* mGradientInfo; ///< Stores gradient info. - - bool mIsVisible:1; ///< Whether the text-actor is visible. - bool mSetText:1; ///< Whether a new text needs to be set in the text-actor. - bool mSetStyle:1; ///< Whether a new style needs to be set in the text-actor. - bool mIsColorGlyph:1; ///< Whether this character is an emoticon. -}; -typedef std::vector CharacterLayoutInfoContainer; - -/** - * Layout information for a word. - */ -struct WordLayoutInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - WordLayoutInfo(); - - /** - * Default destructor. - * - * Clears all characters. - */ - ~WordLayoutInfo(); - - /** - * Copy constructor. - */ - WordLayoutInfo( const WordLayoutInfo& word ); - - /** - * Assignment operator. - */ - WordLayoutInfo& operator=( const WordLayoutInfo& word ); - - Size mSize; ///< Size of the word. - float mAscender; ///< Max of all ascenders of all characters. - TextSeparatorType mType; ///< Whether this word is a word separator, a line separator or is not a separator. - std::size_t mFirstCharacter; ///< Index to the first character of the word within the paragraph. - CharacterLayoutInfoContainer mCharactersLayoutInfo; ///< Layout info for all characters. -}; -typedef std::vector WordLayoutInfoContainer; - -/** - * Stores the reordered layout for right to left text. - */ -struct RightToLeftParagraphLayout -{ - RightToLeftParagraphLayout() - : mWordsLayoutInfo(), - mText(), - mTextStyles(), - mPreviousLayoutCleared( false ) - { - } - - WordLayoutInfoContainer mWordsLayoutInfo; ///< Layout info for all words. - Text mText; ///< Stores the text. - Vector mTextStyles; ///< Stores the style per each character. - bool mPreviousLayoutCleared:1; ///< Whether the previous right to left layout has been cleared. - - /** - * Clears the word layout vector, the text and the vector of styles. - */ - void Clear(); -}; - -/** - * Layout information for a paragraph. - */ -struct ParagraphLayoutInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - ParagraphLayoutInfo(); - - /** - * Default destructor. - * - * Clears all words, deletes all text styles, the paragraph bidirectional info and all bidirectional infor for each line. - */ - ~ParagraphLayoutInfo(); - - /** - * Copy constructor. - */ - ParagraphLayoutInfo( const ParagraphLayoutInfo& paragraph ); - - /** - * Assignment operator. - */ - ParagraphLayoutInfo& operator=( const ParagraphLayoutInfo& paragraph ); - - /** - * Deletes the bidirectional info for each line. - */ - void ClearBidirectionalInfo(); - -private: - - /** - * Deletes all text styles. - */ - void ClearStyles(); - -public: - Size mSize; ///< Size of the paragraph. - float mAscender; ///< Max of all ascenders of all words. - float mLineHeightOffset; ///< Line height offset. - std::size_t mFirstCharacter; ///< Index to the first character of the paragraph. - std::size_t mNumberOfCharacters; ///< Stores the number of characters. - WordLayoutInfoContainer mWordsLayoutInfo; ///< Layout info for all words. - Text mText; ///< Stores the text. - Vector mTextStyles; ///< Stores the style per each character. - RightToLeftParagraphLayout* mRightToLeftLayout; ///< Stores the reordered layout for the paragraph. - TextProcessor::BidirectionalParagraphInfo* mBidirectionalParagraphInfo; ///< Contains bidirectional info for the whole paragraph. Set to NULL if the paragraph has left to right characters only. - Vector mBidirectionalLinesInfo; ///< Contains bidirectional info for each laid-out line. -}; -typedef std::vector ParagraphLayoutInfoContainer; - -/** - * Layout information for the whole text. - */ -struct TextLayoutInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - TextLayoutInfo(); - - /** - * Defualt destructor. - * - * Clears the paragraph vector, the ellipsis text and deletes all ellipsis styles. - */ - ~TextLayoutInfo(); - - /** - * Copy constructor. - */ - TextLayoutInfo( const TextLayoutInfo& text ); - - /** - * Assignment operator. - */ - TextLayoutInfo& operator=( const TextLayoutInfo& text ); - -private: - /** - * Deletes all the ellipsis text styles. - */ - void ClearStyles(); - -public: - Size mWholeTextSize; ///< width and height of the whole text. - float mMaxWordWidth; ///< maximum width between all words. - float mMaxItalicsOffset; ///< When rendering text-view in offscreen an extra width offset is needed to prevent italic characters to be cut if they are in the right edge. - std::size_t mNumberOfCharacters; ///< Stores the number of characters. - ParagraphLayoutInfoContainer mParagraphsLayoutInfo; ///< Layout information for all paragraphs. - WordLayoutInfo mEllipsizeLayoutInfo; ///< Layout information for the ellipsize text. - Dali::Text mEllipsisText; ///< The ellipsis text. - Vector mEllipsisTextStyles; ///< Stores the style per each character of the ellipsis text. -}; - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_TYPES_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor.cpp b/dali-toolkit/internal/controls/text-view/text-view-processor.cpp deleted file mode 100644 index 40f1fab..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor.cpp +++ /dev/null @@ -1,961 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -namespace -{ -/** - * Update text layout info. - * - * Updates the size of the whole text, the maximum width of all words and the number of characters. - * - * @param[in,out] textLayoutInfo - */ -void UpdateLayoutInfo( TextLayoutInfo& textLayoutInfo ) -{ - // Initialize members to be updated. - textLayoutInfo.mWholeTextSize = Size::ZERO; - textLayoutInfo.mMaxWordWidth = 0.f; - textLayoutInfo.mNumberOfCharacters = 0u; - - // Traverse all text updating values. - for( ParagraphLayoutInfoContainer::const_iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - const ParagraphLayoutInfo& paragraph( *paragraphIt ); - - // Updates text size with the size of all paragraphs. - UpdateSize( textLayoutInfo.mWholeTextSize, paragraph.mSize, GrowHeight ); - - // Updates number of characters. - textLayoutInfo.mNumberOfCharacters += paragraph.mNumberOfCharacters; - - // Updates the max word's width. - for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - const WordLayoutInfo& word( *wordIt ); - - textLayoutInfo.mMaxWordWidth = std::max( textLayoutInfo.mMaxWordWidth, word.mSize.width ); - } - } -} - -} // namespace - -// Constructors and assignment operators - -TextInfoIndices::TextInfoIndices() -: mParagraphIndex( 0u ), - mWordIndex( 0u ), - mCharacterIndex( 0u ), - mCharacterParagraphIndex( 0u ) -{ -} - -TextInfoIndices::TextInfoIndices( const std::size_t paragraphIndex, - const std::size_t wordIndex, - const std::size_t characterIndex ) -: mParagraphIndex( paragraphIndex ), - mWordIndex( wordIndex ), - mCharacterIndex( characterIndex ), - mCharacterParagraphIndex( 0u ) -{ -} - -bool TextInfoIndices::operator==( const TextInfoIndices& indices ) const -{ - return ( ( mParagraphIndex == indices.mParagraphIndex ) && - ( mWordIndex == indices.mWordIndex ) && - ( mCharacterIndex == indices.mCharacterIndex ) && - ( mCharacterParagraphIndex == indices.mCharacterParagraphIndex ) ); -} - -///////////////////// -// Layout info. -///////////////////// - -TextLayoutInfo::TextLayoutInfo() -: mWholeTextSize(), - mMaxWordWidth( 0.f ), - mMaxItalicsOffset( 0.f ), - mNumberOfCharacters( 0u ), - mParagraphsLayoutInfo(), - mEllipsizeLayoutInfo(), - mEllipsisText( "..." ), - mEllipsisTextStyles() -{ - // Sets default styles for the default ellipsis text. - mEllipsisTextStyles.PushBack( new TextStyle() ); - mEllipsisTextStyles.PushBack( new TextStyle() ); - mEllipsisTextStyles.PushBack( new TextStyle() ); -} - -TextLayoutInfo::~TextLayoutInfo() -{ - ClearStyles(); -} - -TextLayoutInfo::TextLayoutInfo( const TextLayoutInfo& text ) -: mWholeTextSize( text.mWholeTextSize ), - mMaxWordWidth( text.mMaxWordWidth ), - mMaxItalicsOffset( text.mMaxItalicsOffset ), - mNumberOfCharacters( text.mNumberOfCharacters ), - mParagraphsLayoutInfo( text.mParagraphsLayoutInfo ), - mEllipsizeLayoutInfo( text.mEllipsizeLayoutInfo ), - mEllipsisText( text.mEllipsisText ), - mEllipsisTextStyles() -{ - for( Vector::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it ) - { - mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) ); - } -} - -TextLayoutInfo& TextLayoutInfo::operator=( const TextLayoutInfo& text ) -{ - if( this != &text ) - { - mWholeTextSize = text.mWholeTextSize; - mMaxWordWidth = text.mMaxWordWidth; - mMaxItalicsOffset = text.mMaxItalicsOffset; - mNumberOfCharacters = text.mNumberOfCharacters; - mParagraphsLayoutInfo = text.mParagraphsLayoutInfo; - mEllipsizeLayoutInfo = text.mEllipsizeLayoutInfo; - mEllipsisText = text.mEllipsisText; - - ClearStyles(); - - for( Vector::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it ) - { - mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) ); - } - } - return *this; -} - -void TextLayoutInfo::ClearStyles() -{ - for( Vector::Iterator it = mEllipsisTextStyles.Begin(), endIt = mEllipsisTextStyles.End(); it != endIt; ++it ) - { - delete *it; - } - mEllipsisTextStyles.Clear(); -} - -///////////////////////////////////////////////////////////////////////////////////////////// - -void CreateTextInfo( const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // * Traverse the given text spliting it in paragraphs and each paragraph in words. - // * White spaces and new paragraph characters are alone in one word. - // * Bidirectional text is processed in each paragraph. - // It creates the conversion tables - // It does the ligatures if there is arabic glyphs. - // It doesn't reorder the text as it must be done for each line not for the paragraph. - // * Generates a layout data structure to store layout information (size, position, ascender, text direction, etc) and metrics of all characters. - // * Store text for each paragraph and the style for each character. - - // Collect previously created text-actors. - std::vector textActors; - CollectTextActorsFromParagraphs( textActors, relayoutData.mTextLayoutInfo, 0u, relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.size() ); - - if( !textActors.empty() ) - { - // Add text-actors to the cache. - relayoutData.mTextActorCache.InsertTextActors( textActors ); - relayoutData.mTextActorCache.ClearTexts(); - } - - // Store the ellipsize layout info before clearing the previous created info. - // TODO: fix this. Don't clear the ellipsis layout, store it somewhere else ... - const WordLayoutInfo ellipsizeInfo = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo; - Dali::Text ellipsisText = relayoutData.mTextLayoutInfo.mEllipsisText; - Vector ellipsisTextStyles = relayoutData.mTextLayoutInfo.mEllipsisTextStyles; - relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Clear(); - - // clear previously created info. - relayoutData.mTextLayoutInfo = TextLayoutInfo(); - relayoutData.mCharacterLogicalToVisualMap.clear(); - relayoutData.mCharacterVisualToLogicalMap.clear(); - - // Sets the ellipsize layout info. - relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = ellipsizeInfo; - relayoutData.mTextLayoutInfo.mEllipsisText = ellipsisText; - relayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsisTextStyles; - - // Split the whole text in paragraphs. - // It returns a vector of Text with all the paragraphs. - // and for each paragraph a vector of styles per character. TODO: don't create a style per character. - std::vector paragraphs; - std::vector< Vector > styles; - TextProcessor::SplitInParagraphs( text, - paragraphs, - styles ); - - // Reserve space for the current number of paragraphs. - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.resize( paragraphs.size(), ParagraphLayoutInfo() ); - - // Traverse all paragraphs - std::size_t paragraphIndex = 0u; - std::vector::iterator paragraphIt, paragraphEndIt; - std::vector< Vector >::const_iterator styleIt, styleEndIt; - for( paragraphIt = paragraphs.begin(), paragraphEndIt = paragraphs.end(), - styleIt = styles.begin(), styleEndIt = styles.end(); - ( paragraphIt != paragraphEndIt ) && ( styleIt != styleEndIt ); - ++paragraphIndex, - ++paragraphIt, - ++styleIt ) - { - // Gets the paragraph and the styles for each character. - Text& paragraph( *paragraphIt ); - const Vector& textStyles( *styleIt ); - - // Retrieve the data structure for the current paragraph. - ParagraphLayoutInfo& paragraphLayoutInfo = *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex ); - - // Sets text and styles. - paragraphLayoutInfo.mText = paragraph; - paragraphLayoutInfo.mTextStyles = textStyles; - - // Fills the paragraph data structure with the layout info. - - if( !paragraph.IsEmpty() ) - { - CreateParagraphInfo( relayoutData, - paragraphLayoutInfo ); - - // do not add the line offset if the paragraph has no characters. - paragraphLayoutInfo.mSize.height += layoutParameters.mLineHeightOffset; - paragraphLayoutInfo.mLineHeightOffset = layoutParameters.mLineHeightOffset; - } - else - { - // This paragraph has no text. i.e. the previous paragraph ends with '\n'. - // Even though, line height needs to be set in order to align the whole text correctly. - - float lineHeight = 0.f; - // Get the last character of the last paragraph. - if( 0u < paragraphIndex ) - { - const ParagraphLayoutInfo& paragraphInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + ( paragraphIndex - 1u ) ) ); - - const CharacterLayoutInfo characterInfo = GetLastCharacterLayoutInfo( paragraphInfo ); - - lineHeight = characterInfo.mSize.height; - } - - paragraphLayoutInfo.mSize.height = lineHeight; - } - - // Fills the conversion tables used to get the logical or visual position of a character is case there is right to left text. - // If there is right to left text, it needs to be updated every time the text is relaid-out. - for( std::size_t index = 0u; index < paragraphLayoutInfo.mNumberOfCharacters; ++index ) - { - relayoutData.mCharacterLogicalToVisualMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); - relayoutData.mCharacterVisualToLogicalMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); - } - - // Update layout info for the whole text. - UpdateSize( relayoutData.mTextLayoutInfo.mWholeTextSize, paragraphLayoutInfo.mSize, GrowHeight ); - relayoutData.mTextLayoutInfo.mNumberOfCharacters += paragraphLayoutInfo.mNumberOfCharacters; - } // end of paragraphs -} - -void UpdateTextInfo( std::size_t position, - const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // Update current internal data structure with added text. - - // * Creates layout info for the given text. - // * With the given position, find where to add the text. - // * If the new text is not added at the end of current text, a paragraph need to be split. - // * Merge the last paragraph of the new text to the last part or the split paragraph. - // * Add paragraphs between first and last of the new text. - // * Merge the first part of the split paragraph with the first paragraph of the new text. - // * Update the layout info for the whole text. - - // Early returns: - - if( text.empty() ) - { - // nothing to do if the input text is empty. - return; - } - - if( 0u == relayoutData.mTextLayoutInfo.mNumberOfCharacters ) - { - // Current text is empty. There is no need to update current data structure, - // just create a new one with the new input text. - CreateTextInfo( text, - layoutParameters, - relayoutData ); - return; - } - - // initial checks. - if( position > relayoutData.mTextLayoutInfo.mNumberOfCharacters ) - { - // Asserts if text is to be added out of bounds. - DALI_ASSERT_ALWAYS( !"TextViewProcessor::UpdateTextInfo (insert). Trying to insert text out of bounds." ); - } - - - // TODO - // If in the insertion is involved right to left text, - // check the neighbour characters is needed. - // i.e. Arabic characters may have four different glyphs (isolated, end, middle, begin). - // So check the neighbours on each side is needed in order to render - // the correct ligatures. - - - TextView::RelayoutData relayoutDataForNewText; - - // Creates layout info for the given text. - // It doesn't create text-actors as text could be added to an existing one. - CreateTextInfo( text, - layoutParameters, - relayoutDataForNewText ); - - // Fills the conversion tables used to get the logical or visual position of a character is case there is right to left text. - // If there is right to left text, it needs to be updated every time the text is relaid-out. - std::size_t index = 0u; - for( std::size_t i = 0u; i < relayoutDataForNewText.mTextLayoutInfo.mNumberOfCharacters; ++i ) - { - relayoutData.mCharacterLogicalToVisualMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); - relayoutData.mCharacterVisualToLogicalMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); - ++index; - } - - // If a paragraph is split, it stores the last part of the paragraph. - ParagraphLayoutInfo lastParagraphLayoutInfo; - - // Stores indices to the paragraph, word and character of the given position. - TextInfoIndices textInfoIndices; - - if( position < relayoutData.mTextLayoutInfo.mNumberOfCharacters ) - { - // Get paragraph, word and character indices for given position. - GetIndicesFromGlobalCharacterIndex( position, - relayoutData.mTextLayoutInfo, - textInfoIndices ); - - // 1) Split the paragraph - - // Split a paragraph in two is needed, then merge the first part of the split paragraph - // with the first paragraph of the new text, add subsequent paragraphs and merge the last paragraph - // of the new text with the last part of the split paragraph. - - // Implementation notes! - // - // These references to the first paragraph are declared in this scope because if new paragraphs are inserted in step 2, - // they become invalid, making the algorithm to crash if used again. - // In the step 3, references to the first paragraph are needed and declared again. - - // Stores the first part of the split paragraph. - ParagraphLayoutInfo& firstParagraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndices.mParagraphIndex ) ); - - SplitParagraph( textInfoIndices, - PointSize( layoutParameters.mLineHeightOffset ), - firstParagraphLayoutInfo, - lastParagraphLayoutInfo ); - } - else - { - // Position is just after the last character. - // Calculates indices for that position. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - textInfoIndices.mParagraphIndex = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.size() - 1u; - const ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - textInfoIndices.mWordIndex = paragraphLayoutInfo.mWordsLayoutInfo.size() - 1u; - - const WordLayoutInfo& wordLayoutInfo( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ); - textInfoIndices.mCharacterIndex = wordLayoutInfo.mCharactersLayoutInfo.size(); - - // Sets the character index within the paragraph. - textInfoIndices.mCharacterParagraphIndex = 0u; - for( WordLayoutInfoContainer::const_iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it ) - { - textInfoIndices.mCharacterParagraphIndex += wordLayoutInfo.mCharactersLayoutInfo.size(); - } - } - } - } - - // 2) If the new text has more than 1 paragraph, merge the last paragraph of the input text with the last part of the split paragraph. - //TODO check this cases ( num paragraphs ==1, >1, >2 ) if it could be simplified. - if( relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.size() > 1u ) - { - ParagraphLayoutInfo& lastInputParagraphLayoutInfo( *( relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - MergeParagraph( lastInputParagraphLayoutInfo, - lastParagraphLayoutInfo ); - - if( relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.size() > 2u ) - { - // Insert all paragraphs except first and last in the text. - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.insert( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndices.mParagraphIndex + 1u, - relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + 1u, - relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ); - } - - // Insert the last paragraph to the text - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.insert( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndices.mParagraphIndex + relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.size() - 1u, - lastInputParagraphLayoutInfo ); - } - else - { - // Merge the new paragraph to the last part of the split paragraph. - ParagraphLayoutInfo& inputParagraphLayoutInfo( *relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.begin() ); - - MergeParagraph( inputParagraphLayoutInfo, - lastParagraphLayoutInfo ); - } - - // 3) Merge the first paragraph of the split text with the first paragraph of the input text. - ParagraphLayoutInfo& firstParagraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndices.mParagraphIndex ) ); - ParagraphLayoutInfo& firstInputParagraphLayoutInfo( *relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.begin() ); - - MergeParagraph( firstParagraphLayoutInfo, - firstInputParagraphLayoutInfo ); - - // 4) Update text info. - - // Updates the whole text size, maximum word size, etc. - UpdateLayoutInfo( relayoutData.mTextLayoutInfo ); -} - -void UpdateTextInfo( std::size_t position, - std::size_t numberOfCharacters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData, - const TextOperationOnRemove clearText ) -{ - // Removes 'numberOfCharacters' starting from 'position'. - - // * It checks if text to be deleted is in the same paragraph or not: - // * If it is not, check which paragraphs need to be split/merged or deleted. - // * If it is but all characters of the paragraph are going to be deleted, just delete the paragraph (nothing needs to be split/merged) - // * If only some characters of the same paragraph are going to be deleted, proceed similarly: check if text to be deleted is in the same word. - // * If it is not, split/merge words. - // * Check if the whole word needs to be deleted. - // * Check if only some characters of the word need to be deleted. - // * Updates layout info. - - // * The algorithm checks if a word separator is deleted (in that case, different words need to be merged) and if a new paragraph separator is deleted (two paragraphs need to be merged). - - // Early return - - if( 0u == numberOfCharacters ) - { - DALI_ASSERT_DEBUG( !"TextViewProcessor::UpdateTextInfo. WARNING: trying to delete 0 characters!" ); - - // nothing to do if no characters are deleted. - return; - } - - // Asserts if trying to delete text out of bounds. - DALI_ASSERT_ALWAYS( position + numberOfCharacters <= relayoutData.mTextLayoutInfo.mNumberOfCharacters && "TextViewProcessor::UpdateTextInfo. ERROR: trying to delete characters out of boundary" ); - - // Remove characters from character to visual map and vs. - // If there is right to left text, it needs to be updated every time the text is relaid-out. - relayoutData.mCharacterLogicalToVisualMap.erase( relayoutData.mCharacterLogicalToVisualMap.end() - numberOfCharacters, relayoutData.mCharacterLogicalToVisualMap.end() ); - relayoutData.mCharacterVisualToLogicalMap.erase( relayoutData.mCharacterVisualToLogicalMap.end() - numberOfCharacters, relayoutData.mCharacterVisualToLogicalMap.end() ); - - // Get paragraph, word and character indices for the given start position. - TextInfoIndices textInfoIndicesBegin; - GetIndicesFromGlobalCharacterIndex( position, - relayoutData.mTextLayoutInfo, - textInfoIndicesBegin ); - - // Get paragraph, word and character indices for the given end position (start position + number of characters to be deleted). - TextInfoIndices textInfoIndicesEnd; - GetIndicesFromGlobalCharacterIndex( position + numberOfCharacters - 1u, - relayoutData.mTextLayoutInfo, - textInfoIndicesEnd ); - - // Vectors used to temporary store text-actors removed from text. - // Three vectors are needed because text-actors are not removed in order - // but insert them in order is required to reuse them later. - std::vector removedTextActorsFromBegin; - std::vector removedTextActorsFromMid; - std::vector removedTextActorsFromEnd; - - // Whether paragraphs and words need to be merged. - bool mergeParagraphs = false; - bool mergeWords = false; - - // Indices of the paragraphs and words to be merged. - TextInfoIndices textInfoMergeIndicesBegin; - TextInfoIndices textInfoMergeIndicesEnd; - - const ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex ) ); // used to check the number of characters of the paragraph - // if all characters to be deleted are in the same paragraph. - if( textInfoIndicesBegin.mParagraphIndex < textInfoIndicesEnd.mParagraphIndex ) - { - // Deleted text is from different paragraphs. It may need to split two paragraphs, and merge first part of the first one with last part of the last one. - - // whether first or last paragraph need to be split and merged with the last part. - bool mergeFirstParagraph = false; - bool mergeLastParagraph = true; - - textInfoMergeIndicesBegin.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex; - textInfoMergeIndicesEnd.mParagraphIndex = textInfoIndicesEnd.mParagraphIndex; - - if( ( textInfoIndicesBegin.mWordIndex > 0u ) || ( textInfoIndicesBegin.mCharacterIndex > 0u ) ) - { - // first character to be deleted is not the first one of the current paragraph. - ++textInfoIndicesBegin.mParagraphIndex; // won't delete current paragraph - - // As some characters remain, this paragraph could be merged with the last one. - mergeFirstParagraph = true; - } - - // Check if all characters of the last paragraph are going to be deleted. - bool wholeParagraphDeleted = false; - const ParagraphLayoutInfo& lastParagraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesEnd.mParagraphIndex ) ); - if( textInfoIndicesEnd.mWordIndex + 1u == lastParagraphLayout.mWordsLayoutInfo.size() ) - { - const WordLayoutInfo& lastWordLayout( *( lastParagraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) ); - if( textInfoIndicesEnd.mCharacterIndex + 1u == lastWordLayout.mCharactersLayoutInfo.size() ) - { - // All characters of the last paragraph are going to be deleted. - ++textInfoIndicesEnd.mParagraphIndex; // will delete the last paragraph. - - // the whole last paragraph is deleted. Need to check if the next paragraph could be merged. - mergeLastParagraph = false; - wholeParagraphDeleted = true; - } - } - - if( wholeParagraphDeleted ) - { - // It means the whole last paragraph is deleted completely. - // It's needed to check if there is another paragraph after that could be merged. - if( textInfoIndicesEnd.mParagraphIndex < relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.size() ) - { - mergeLastParagraph = true; - - // Point the first characters of the next paragraph. - textInfoIndicesEnd.mWordIndex = 0u; - textInfoIndicesEnd.mCharacterIndex = 0u; - textInfoMergeIndicesEnd.mParagraphIndex = textInfoIndicesEnd.mParagraphIndex; - } - } - - // If some characters remain in the first and last paragraph, they need to be merged. - mergeParagraphs = mergeFirstParagraph && mergeLastParagraph; - - if( mergeParagraphs ) - { - // last paragraph is going to be merged with the first one, so is not needed. - ++textInfoIndicesEnd.mParagraphIndex; // will delete the last paragraph. - } - - if( mergeFirstParagraph ) - { - // Remove characters from the first paragraph. - - // Vectors used to temporary store text-actors removed from the paragraph. - // Three vectors are needed because text-actors are not removed in order - // but insert them in order is required to reuse them later. - std::vector removedTextActorsFromFirstWord; - std::vector removedTextActorsFromFirstParagraph; - - // As paragraphIndexBegin has been increased just to not to remove the paragraph, decrease now is needed to access it. - ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex - 1u ) ); - - // Remove the characters from the text and the styles. - paragraphLayout.mText.Remove( textInfoIndicesBegin.mCharacterParagraphIndex, paragraphLayout.mNumberOfCharacters - textInfoIndicesBegin.mCharacterParagraphIndex ); - - for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin() + textInfoIndicesBegin.mCharacterParagraphIndex, - endIt = paragraphLayout.mTextStyles.End(); - it != endIt; - ++it ) - { - delete *it; - } - paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin() + textInfoIndicesBegin.mCharacterParagraphIndex, - paragraphLayout.mTextStyles.End() ); - - if( ( textInfoIndicesBegin.mWordIndex + 1u < paragraphLayout.mWordsLayoutInfo.size() ) || ( 0u == textInfoIndicesBegin.mCharacterIndex ) ) - { - // Remove extra words within current paragraph. (and current word if whole characters are removed) - // 0 == characterIndexBegin means the whole word is deleted. - const std::size_t wordIndex = ( ( 0u == textInfoIndicesBegin.mCharacterIndex ) ? textInfoIndicesBegin.mWordIndex : textInfoIndicesBegin.mWordIndex + 1u ); - - // Store text-actors before removing them. - CollectTextActorsFromWords( removedTextActorsFromFirstParagraph, paragraphLayout, wordIndex, paragraphLayout.mWordsLayoutInfo.size() ); - - RemoveWordsFromParagraph( wordIndex, - paragraphLayout.mWordsLayoutInfo.size() - wordIndex, - layoutParameters.mLineHeightOffset, - paragraphLayout ); - } - - if( ( textInfoIndicesBegin.mWordIndex < paragraphLayout.mWordsLayoutInfo.size() ) && ( textInfoIndicesBegin.mCharacterIndex > 0u ) ) - { - // Only some characters of the word need to be removed. - WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex ) ); - - // Store text-actors before removing them. - CollectTextActors( removedTextActorsFromFirstWord, wordLayout, textInfoIndicesBegin.mCharacterIndex, wordLayout.mCharactersLayoutInfo.size() ); - - const std::size_t wordNumberCharacters = wordLayout.mCharactersLayoutInfo.size(); - RemoveCharactersFromWord( textInfoIndicesBegin.mCharacterIndex, - wordLayout.mCharactersLayoutInfo.size() - textInfoIndicesBegin.mCharacterIndex, - wordLayout ); - - // discount the removed number of characters. - const std::size_t removedNumberOfCharacters = ( wordNumberCharacters - wordLayout.mCharactersLayoutInfo.size() ); - paragraphLayout.mNumberOfCharacters -= removedNumberOfCharacters; - } - UpdateLayoutInfo( paragraphLayout, layoutParameters.mLineHeightOffset ); - - // Insert the text-actors in order. - removedTextActorsFromBegin.insert( removedTextActorsFromBegin.end(), removedTextActorsFromFirstWord.begin(), removedTextActorsFromFirstWord.end() ); - removedTextActorsFromBegin.insert( removedTextActorsFromBegin.end(), removedTextActorsFromFirstParagraph.begin(), removedTextActorsFromFirstParagraph.end() ); - } - - if( mergeLastParagraph && !wholeParagraphDeleted ) - { - // Some characters from the last paragraph need to be removed. - - // Vectors used to temporary store text-actors removed from the paragraph. - // Three vectors are needed because text-actors are not removed in order - // but insert them in order is required to reuse them later. - std::vector removedTextActorsFromFirstWord; - std::vector removedTextActorsFromFirstParagraph; - - // paragraphIndexEnd was increased to delete the last paragraph if paragraphs need to be merged. - // To access now the last paragraph we need to decrease the index. - const std::size_t paragraphIndex = ( mergeParagraphs ? textInfoIndicesEnd.mParagraphIndex - 1u : textInfoIndicesEnd.mParagraphIndex ); - - // Get the last paragraph. - ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex ) ); - - // Remove the characters from the text and the styles. - const std::size_t lastCharacterIndex = textInfoIndicesEnd.mCharacterParagraphIndex + 1u; - - paragraphLayout.mText.Remove( 0u, lastCharacterIndex ); - - for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin(), - endIt = paragraphLayout.mTextStyles.Begin() + lastCharacterIndex; - it != endIt; - ++it ) - { - delete *it; - } - paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin(), - paragraphLayout.mTextStyles.Begin() + lastCharacterIndex ); - - // Check if is needed remove the whole word. (If the character index is pointing just after the end of the word) - const WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) ); - bool removeWholeWord = wordLayout.mCharactersLayoutInfo.size() == textInfoIndicesEnd.mCharacterIndex + 1u; - - if( ( textInfoIndicesEnd.mWordIndex > 0u ) || ( removeWholeWord ) ) - { - // Store text-actors before removing them. - CollectTextActorsFromWords( removedTextActorsFromFirstParagraph, - paragraphLayout, - 0u, - ( removeWholeWord ) ? textInfoIndicesEnd.mWordIndex + 1u : textInfoIndicesEnd.mWordIndex ); - - // Remove extra words. (and current word if whole characters are removed) - RemoveWordsFromParagraph( 0u, - ( removeWholeWord ) ? textInfoIndicesEnd.mWordIndex + 1u : textInfoIndicesEnd.mWordIndex, - layoutParameters.mLineHeightOffset, - paragraphLayout ); - } - - if( !removeWholeWord ) - { - // Only some characters of the word need to be deleted. - - // After removing all extra words. The word with the characters to be removed is the first one. - WordLayoutInfo& wordLayout( *paragraphLayout.mWordsLayoutInfo.begin() ); - - // Store text-actors before removing them. - CollectTextActors( removedTextActorsFromFirstWord, wordLayout, 0u, textInfoIndicesEnd.mCharacterIndex + 1u ); - - const std::size_t wordNumberCharacters = wordLayout.mCharactersLayoutInfo.size(); - RemoveCharactersFromWord( 0u, - textInfoIndicesEnd.mCharacterIndex + 1u, - wordLayout ); - - // discount the removed number of characters. - const std::size_t removedNumberOfCharacters = ( wordNumberCharacters - wordLayout.mCharactersLayoutInfo.size() ); - paragraphLayout.mNumberOfCharacters -= removedNumberOfCharacters; - } - UpdateLayoutInfo( paragraphLayout, layoutParameters.mLineHeightOffset ); - - // Insert the text-actors in order. - removedTextActorsFromEnd.insert( removedTextActorsFromEnd.end(), removedTextActorsFromFirstWord.begin(), removedTextActorsFromFirstWord.end() ); - removedTextActorsFromEnd.insert( removedTextActorsFromEnd.end(), removedTextActorsFromFirstParagraph.begin(), removedTextActorsFromFirstParagraph.end() ); - } - } // end delete text from different paragraphs - else if( ( textInfoIndicesBegin.mParagraphIndex == textInfoIndicesEnd.mParagraphIndex ) && ( paragraphLayout.mNumberOfCharacters == numberOfCharacters ) ) - { - // the whole paragraph needs to be deleted. - ++textInfoIndicesEnd.mParagraphIndex; // will delete current paragraph. - } - else - { - // deleted text is within the same paragraph. (merge paragraphs could be needed if the paragraph separator character is deleted) - - // Paragraph which contains the characters to be deleted. - ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex ) ); - - // Remove the characters from the text and the styles. - const std::size_t firstCharacterIndex = textInfoIndicesBegin.mCharacterParagraphIndex; - const std::size_t lastCharacterIndex = textInfoIndicesEnd.mCharacterParagraphIndex + 1u; - - paragraphLayout.mText.Remove( firstCharacterIndex, lastCharacterIndex - firstCharacterIndex ); - - for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin() + firstCharacterIndex, - endIt = paragraphLayout.mTextStyles.Begin() + lastCharacterIndex; - it != endIt; - ++it ) - { - delete *it; - } - paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin() + firstCharacterIndex, - paragraphLayout.mTextStyles.Begin() + lastCharacterIndex ); - - // Remove the characters from the paragraph layout info. It returns whether the current paragraph can be merged with the next one. - RemoveCharactersFromParagraphInfo( relayoutData, - numberOfCharacters, - mergeWords, - mergeParagraphs, - textInfoIndicesBegin, - textInfoIndicesEnd, - textInfoMergeIndicesBegin, - textInfoMergeIndicesEnd, - paragraphLayout, - removedTextActorsFromBegin, - removedTextActorsFromEnd ); - - if( mergeWords ) - { - // Merges words pointed by textInfoMergeIndicesBegin.mWordIndex and textInfoMergeIndicesEnd.mWordIndex calculated previously. - DALI_ASSERT_DEBUG( ( textInfoMergeIndicesBegin.mWordIndex < paragraphLayout.mWordsLayoutInfo.size() ) && "TextViewProcessor::UpdateTextInfo (delete). Word index (begin) out of bounds." ); - DALI_ASSERT_DEBUG( ( textInfoMergeIndicesEnd.mWordIndex < paragraphLayout.mWordsLayoutInfo.size() ) && "TextViewProcessor::UpdateTextInfo (delete). Word index (end) out of bounds." ); - - WordLayoutInfo& firstWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoMergeIndicesBegin.mWordIndex ) ); - WordLayoutInfo& lastWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoMergeIndicesEnd.mWordIndex ) ); - - MergeWord( firstWordLayout, - lastWordLayout ); - } - - // Store text-actors before removing them. - const std::size_t endIndex = ( mergeWords && ( textInfoIndicesEnd.mWordIndex > 0u ) ) ? textInfoIndicesEnd.mWordIndex - 1u : textInfoIndicesEnd.mWordIndex; // text-actors from the last word may have been added in the merge above. - CollectTextActorsFromWords( removedTextActorsFromMid, paragraphLayout, textInfoIndicesBegin.mWordIndex, endIndex ); - - // Remove unwanted words using previously calculated indices. (including the last part of the merged word) - paragraphLayout.mWordsLayoutInfo.erase( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex, paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ); - - // Update paragraph info. - UpdateLayoutInfo( paragraphLayout, layoutParameters.mLineHeightOffset ); - }// end delete text from same paragraph. - - if( mergeParagraphs ) - { - // Merges paragraphs pointed by textInfoMergeIndicesBegin.mParagraphIndex and textInfoMergeIndicesEnd.mParagraphIndex calculated previously. - - ParagraphLayoutInfo& firstParagraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoMergeIndicesBegin.mParagraphIndex ) ); - - const ParagraphLayoutInfo& lastParagraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoMergeIndicesEnd.mParagraphIndex ) ); - - MergeParagraph( firstParagraphLayout, - lastParagraphLayout ); - } - - // Store text-actors before removing them. - const std::size_t endIndex = ( mergeParagraphs && ( textInfoIndicesEnd.mParagraphIndex > 0u ) ) ? textInfoIndicesEnd.mParagraphIndex - 1u : textInfoIndicesEnd.mParagraphIndex; // text-actors from the last paragraph may have been added in the merge above. - CollectTextActorsFromParagraphs( removedTextActorsFromMid, - relayoutData.mTextLayoutInfo, - textInfoIndicesBegin.mParagraphIndex, - endIndex ); - - // Remove unwanted paragraphs using previously calculated indices. (including the last part of the merged paragraph) - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.erase( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex, - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesEnd.mParagraphIndex ); - - // Update text info. - UpdateLayoutInfo( relayoutData.mTextLayoutInfo ); - - // If the last character of the last paragraph is a new paragraph character, an empty paragraph need to be added. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - const WordLayoutInfo lastWordLayout = GetLastWordLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( ParagraphSeparator == lastWordLayout.mType ) - { - ParagraphLayoutInfo lastParagraphLayout; - - const CharacterLayoutInfo layoutInfo = GetLastCharacterLayoutInfo( lastWordLayout ); - lastParagraphLayout.mSize.height = layoutInfo.mSize.height; - - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.push_back( lastParagraphLayout ); - - relayoutData.mTextLayoutInfo.mWholeTextSize.height += layoutInfo.mSize.height; - } - } - - // Clear the text from the text-actors if required. - if( CLEAR_TEXT == clearText ) - { - ClearText( removedTextActorsFromEnd ); - ClearText( removedTextActorsFromMid ); - ClearText( removedTextActorsFromBegin ); - } - - // Insert text-actors into the cache. - // Text-actors are inserted in reverse order to use first the first removed. - relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromEnd ); - relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromMid ); - relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromBegin ); -} - -void UpdateTextInfo( std::size_t position, - std::size_t numberOfCharacters, - const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // Replaces 'numberOfCharacters' of text starting from 'position' with the given text. - - // TODO: Temporary implementation with remove and insert. - - // Remove. - UpdateTextInfo( position, - numberOfCharacters, - layoutParameters, - relayoutData, - KEEP_TEXT ); // Do not clear the text from the text-actors. - - // Insert. - UpdateTextInfo( position, - text, - layoutParameters, - relayoutData ); -} - -void UpdateTextInfo( float lineHeightOffset, - TextLayoutInfo& textLayoutInfo ) -{ - // Updates the space between lines with the new offset value. - - float newTextHeight = 0.f; - - for( ParagraphLayoutInfoContainer::iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt ); - - paragraphLayoutInfo.mSize.height += ( lineHeightOffset - paragraphLayoutInfo.mLineHeightOffset ); - newTextHeight += paragraphLayoutInfo.mSize.height; - - paragraphLayoutInfo.mLineHeightOffset = lineHeightOffset; - } - - textLayoutInfo.mWholeTextSize.height = newTextHeight; -} - -void UpdateTextInfo( const TextStyle& style, - const TextStyle::Mask mask, - TextView::RelayoutData& relayoutData ) -{ - // Change text style for all text-actors. - - for( ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - ParagraphLayoutInfo& paragraph( *paragraphIt ); - - std::size_t index = 0u; - for( Vector::Iterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it ) - { - (*it)->Copy( style, mask ); - - // Checks if the font family supports all glyphs. If not, chooses a most suitable one. - ChooseFontFamilyName( paragraph.mText[index], *(*it) ); - - ++index; - } - - for( WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - WordLayoutInfo& word( *wordIt ); - - for( CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt ) - { - CharacterLayoutInfo& characterLayout( *characterIt ); - - // Mark the character to be set the new style into the text-actor. - characterLayout.mSetStyle = true; - } // end characters - } // end words - } // end paragraphs -} - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor.h b/dali-toolkit/internal/controls/text-view/text-view-processor.h deleted file mode 100644 index a38eaa7..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -/** - * Creates a data structure with info to layout the text, and data structures with useful info to modify the layout data structure if characters are added or removed. - * - * @param[in] text The given styled text. - * @param[in] layoutParameters Layout configuration. - * @param[out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void CreateTextInfo( const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Updates the layout data structures with the new inserted text. - * - * @note Does nothing if text has no characters. - * @note It asserts if position is bigger than the number of characters of the whole text. - * - * @param[in] position Where the text is going to be inserted. - * @param[in] text New styled text to be inserted. - * @param[in] layoutParameters Layout configuration. - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void UpdateTextInfo( std::size_t position, - const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Updates the layout data structures by removing text. - * - * @note Does nothing if number of characters to be deleted is zero. - * @note It asserts if trying to delete text out of bounds. - * - * @param[in] position Position of the first character to be removed. - * @param[in] numberOfCharacters The number of characters to be removed. - * @param[in] layoutParameters Layout configuration. - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - * @param[in] clearText Whether to clear text-actor's text before insert the text-actors into the cache. - */ -void UpdateTextInfo( std::size_t position, - std::size_t numberOfCharacters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData, - TextOperationOnRemove clearText ); - -/** - * Updates the layout data structures by replacing text. - * - * @param[in] position Position of the first character to be replaced. - * @param[in] numberOfCharacters The number of characters to be replaced. - * @param[in] text The new styled text. - * @param[in] layoutParameters Layout configuration. - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void UpdateTextInfo( std::size_t position, - std::size_t numberOfCharacters, - const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Updates the layout data structure by modifying the space between lines. - * - * @param[in] lineHeightOffset The new space between lines. - * @param[in,out] textLayoutInfo Layout info for all characters, words, lines and the whole text. - */ -void UpdateTextInfo( float lineHeightOffset, - TextLayoutInfo& textLayoutInfo ); - -/** - * Updates the text-actor data structures by replacing the style. - * - * @note This operation is called only if the new style doesn't modify the metrics. Consequently it doesn't modify any size info. - * - * @param[in] style The new style. - * @param[in] mask The style mask. - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - */ -void UpdateTextInfo( const TextStyle& style, - TextStyle::Mask mask, - TextView::RelayoutData& relayoutData ); - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp b/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp deleted file mode 100644 index eab8cf6..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/* - * 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. - * - */ - -// FILE HEADER -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -namespace -{ - -const char* const EMOJI_FONT_NAME = "SamsungEmoji"; ///< Emoticons font family name. - -} // namespace - -///////////////////// -// Layout info. -///////////////////// - -WordLayoutInfo::WordLayoutInfo() -: mSize(), - mAscender( 0.f ), - mType( NoSeparator ), - mFirstCharacter( 0u ), - mCharactersLayoutInfo() -{ -} - -WordLayoutInfo::~WordLayoutInfo() -{ -} - -WordLayoutInfo::WordLayoutInfo( const WordLayoutInfo& word ) -: mSize( word.mSize ), - mAscender( word.mAscender ), - mType( word.mType ), - mFirstCharacter( word.mFirstCharacter ), - mCharactersLayoutInfo( word.mCharactersLayoutInfo ) -{ -} - -WordLayoutInfo& WordLayoutInfo::operator=( const WordLayoutInfo& word ) -{ - mSize = word.mSize; - mAscender = word.mAscender; - mType = word.mType; - mFirstCharacter = word.mFirstCharacter; - mCharactersLayoutInfo = word.mCharactersLayoutInfo; - - return *this; -} - -void CreateWordTextInfo( const Text& paragraph, - Vector& textStyles, - WordLayoutInfo& wordLayoutInfo ) -{ - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::CreateWordTextInfo\n" ); - // Split in characters. - std::size_t characterIndex = wordLayoutInfo.mFirstCharacter; - for( CharacterLayoutInfoContainer::iterator it = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - it != endIt; - ++it, ++characterIndex ) - { - // Gets a reference of the character's layout info. - CharacterLayoutInfo& characterLayoutInfo( *it ); - - // Gets the character and the style for that character from the paragraph. - Character character = paragraph[characterIndex]; - TextStyle* textStyle = *( textStyles.Begin() + characterIndex ); - - // Checks whether the character is an emoticon. - characterLayoutInfo.mIsColorGlyph = GlyphImage::IsColorGlyph( character ); - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " Is color glyph: %s\n", ( characterLayoutInfo.mIsColorGlyph ? "True" : "False" ) ); - - if( characterLayoutInfo.mIsColorGlyph ) - { - // If the character is an emoticon a predefined font is set. - textStyle->SetFontName( EMOJI_FONT_NAME ); - } - else - { - // Checks if the font family and the font style set in the text style supports the character. - // If not, it chooses the right font for the given character and style. - ChooseFontFamilyName( character, *textStyle ); - } - - // Gets the metrics of the font. - const Font font = Font::New( FontParameters( textStyle->GetFontName(), textStyle->GetFontStyle(), textStyle->GetFontPointSize() ) ); - const Font::Metrics metrics = font.GetMetrics( character ); - const float ascender = font.GetAscender(); - - // Fill Natural size info for current character. - - // The font line's height is used as character's height. - characterLayoutInfo.mSize.height = font.GetLineHeight(); - - // The character's advance is used as charcter's width. - characterLayoutInfo.mSize.width = metrics.GetAdvance(); - - // The ascender and bearing are used to position correctly glyphs of different font sizes. - characterLayoutInfo.mAscender = ascender; - characterLayoutInfo.mBearing = metrics.GetBearing(); - - if( character.IsNewLine() && !characterLayoutInfo.mIsColorGlyph ) - { - // A new paragraph character '\n' doesn't have any width. - characterLayoutInfo.mSize.width = 0.f; - } - - // Set's the underline thickness and position. - // Both thickness and position includes the vertical pad adjust used in effects like glow or shadow. - if( textStyle->IsUnderlineEnabled() ) - { - characterLayoutInfo.mUnderlineThickness = font.GetUnderlineThickness(); - characterLayoutInfo.mUnderlinePosition = font.GetUnderlinePosition(); - } - - // Updates the word size and ascender. - UpdateSize( wordLayoutInfo.mSize, characterLayoutInfo.mSize ); - wordLayoutInfo.mAscender = std::max( wordLayoutInfo.mAscender, characterLayoutInfo.mAscender ); - } // end of characters in the word. - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::CreateWordTextInfo\n" ); -} - -void UpdateLayoutInfo( WordLayoutInfo& wordLayout ) -{ - // Initialize layout info for the whole word. - wordLayout.mSize = Size::ZERO; - wordLayout.mAscender = 0.f; - - // Traverse the character layout info to update the word layout. - for( CharacterLayoutInfoContainer::iterator layoutIt = wordLayout.mCharactersLayoutInfo.begin(), layoutEndIt = wordLayout.mCharactersLayoutInfo.end(); - layoutIt != layoutEndIt; - ++layoutIt ) - { - // Layout info for the current character. - CharacterLayoutInfo& layoutInfo( *layoutIt ); - - // Update layout info for the current word. - UpdateSize( wordLayout.mSize, layoutInfo.mSize ); - wordLayout.mAscender = std::max( wordLayout.mAscender, layoutInfo.mAscender ); - } -} - -void RemoveCharactersFromWordInfo( TextView::RelayoutData& relayoutData, - const std::size_t numberOfCharacters, - bool& mergeWords, - bool& mergeParagraphs, - TextInfoIndices& textInfoIndicesBegin, - TextInfoIndices& textInfoIndicesEnd, - TextInfoIndices& textInfoMergeIndicesBegin, - TextInfoIndices& textInfoMergeIndicesEnd, - ParagraphLayoutInfo& paragraphLayout, - std::vector& removedTextActors ) -{ - const TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo; - - // Get the word. - WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex ) ); - - if( ParagraphSeparator == wordLayout.mType ) - { - // If the word is a paragraph separator and there is more paragraphs, then current paragraph and the paragraph after need to be merged. - if( textInfoIndicesBegin.mParagraphIndex + 1u < textLayoutInfo.mParagraphsLayoutInfo.size() ) - { - // current paragraph is not the last one. - - // Update indices to merge paragraphs. - textInfoMergeIndicesBegin.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex; - textInfoMergeIndicesEnd.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex + 1u; - - mergeParagraphs = true; - - ++textInfoIndicesBegin.mParagraphIndex; // increase both indices, - textInfoIndicesEnd.mParagraphIndex += 2u; // will delete last paragraph. - } - - ++textInfoIndicesEnd.mWordIndex; //will delete the paragraph separator; - } - else if( WordSeparator == wordLayout.mType ) - { - // If the word is a word separator. Check if the word before and the word after can be merged. - - if( ( 0u < textInfoIndicesBegin.mWordIndex ) && ( paragraphLayout.mWordsLayoutInfo.size() > textInfoIndicesBegin.mWordIndex + 1u ) ) - { - const WordLayoutInfo& wordLayoutBefore( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex - 1u ) ); - const WordLayoutInfo& wordLayoutAfter( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex + 1u ) ); - - if( ( NoSeparator == wordLayoutBefore.mType ) && ( NoSeparator == wordLayoutAfter.mType ) ) - { - // This word is a word separator (white space) and is not the first word of the paragraph nor the last one. - mergeWords = true; - - // Set indices to merge the words. - textInfoMergeIndicesBegin.mWordIndex = textInfoIndicesBegin.mWordIndex - 1u; // word before word separator. - textInfoMergeIndicesEnd.mWordIndex = textInfoIndicesBegin.mWordIndex + 1u; // word after word separator. - - textInfoIndicesEnd.mWordIndex += 2u; // will delete the word separator and the merged word. - } - else - { - ++textInfoIndicesEnd.mWordIndex; // will delete the word separator; - } - } - else - { - ++textInfoIndicesEnd.mWordIndex; // will delete the word separator; - } - } - else if( numberOfCharacters == wordLayout.mCharactersLayoutInfo.size() ) - { - // The whole word needs to be removed. - ++textInfoIndicesEnd.mWordIndex; // will delete the current word. - } - else - { - // Store text-actors before removing them. - CollectTextActors( removedTextActors, wordLayout, textInfoIndicesBegin.mCharacterIndex, textInfoIndicesBegin.mCharacterIndex + numberOfCharacters ); - - // just remove some characters from current word. - RemoveCharactersFromWord( textInfoIndicesBegin.mCharacterIndex, - numberOfCharacters, - wordLayout ); - } -} - -void RemoveCharactersFromWord( const std::size_t position, - const std::size_t numberOfCharacters, - WordLayoutInfo& wordLayout ) -{ - // Removes a given number of characters from the given word starting from the 'position' index. - - // Early return. - if( 0u == numberOfCharacters ) - { - // nothing to do if the number of characters is zero. - - return; - } - - // Remove characters from layout and text-actor info. - wordLayout.mCharactersLayoutInfo.erase( wordLayout.mCharactersLayoutInfo.begin() + position, wordLayout.mCharactersLayoutInfo.begin() + position + numberOfCharacters ); - - // Some characters have been removed from the word. Update the layout info is needed. - UpdateLayoutInfo( wordLayout ); -} - -void SplitWord( const std::size_t position, - WordLayoutInfo& firstWordLayoutInfo, - WordLayoutInfo& lastWordLayoutInfo ) -{ - // Splits a word in two. - // It moves characters from the first part of the word to the last one. - - // early returns - if( 0u == position ) - { - // the whole word goes to the last part of the word. - lastWordLayoutInfo = firstWordLayoutInfo; - - firstWordLayoutInfo = WordLayoutInfo(); - - return; - } - - if( position == firstWordLayoutInfo.mCharactersLayoutInfo.size() ) - { - // the whole word goes to the first part of the word. - - // Just delete whatever there is in the last part of the word. - lastWordLayoutInfo = WordLayoutInfo(); - - return; - } - - // Initialize output data structures. - - // Layout info - lastWordLayoutInfo = WordLayoutInfo(); - - // Split layout info. - - // Insert characters from the given index 'position' to the end. - lastWordLayoutInfo.mCharactersLayoutInfo.insert( lastWordLayoutInfo.mCharactersLayoutInfo.end(), - firstWordLayoutInfo.mCharactersLayoutInfo.begin() + position, firstWordLayoutInfo.mCharactersLayoutInfo.end() ); - - // Delete characters from the first part of the word. - firstWordLayoutInfo.mCharactersLayoutInfo.erase( firstWordLayoutInfo.mCharactersLayoutInfo.begin() + position, firstWordLayoutInfo.mCharactersLayoutInfo.end() ); - - // Update the layout info of both new words. - UpdateLayoutInfo( firstWordLayoutInfo ); - UpdateLayoutInfo( lastWordLayoutInfo ); -} - -void MergeWord( WordLayoutInfo& firstWordLayoutInfo, - const WordLayoutInfo& lastWordLayoutInfo ) -{ - // Merges two given words. - - // Early returns. - if( lastWordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - // nothing to do - return; - } - - if( firstWordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - // copy last to first - - firstWordLayoutInfo = lastWordLayoutInfo; - - return; - } - - if( ( NoSeparator != firstWordLayoutInfo.mType ) || ( NoSeparator != lastWordLayoutInfo.mType ) ) - { - // Do not merge white spaces or new paragraph characters. - DALI_ASSERT_ALWAYS( !"TextViewProcessor::MergeWord(). ERROR: White spaces or new paragraph characters can't be merged with other words." ); - } - - // Merge layout info - firstWordLayoutInfo.mCharactersLayoutInfo.insert( firstWordLayoutInfo.mCharactersLayoutInfo.end(), - lastWordLayoutInfo.mCharactersLayoutInfo.begin(), - lastWordLayoutInfo.mCharactersLayoutInfo.end() ); - - // Update the word layout info. - UpdateSize( firstWordLayoutInfo.mSize, lastWordLayoutInfo.mSize ); - firstWordLayoutInfo.mAscender = std::max( firstWordLayoutInfo.mAscender, lastWordLayoutInfo.mAscender ); -} - -CharacterLayoutInfo GetFirstCharacterLayoutInfo( const WordLayoutInfo& wordLayoutInfo ) -{ - CharacterLayoutInfo layoutInfo; - - if( !wordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - layoutInfo = *wordLayoutInfo.mCharactersLayoutInfo.begin(); - } - - return layoutInfo; -} - -CharacterLayoutInfo GetLastCharacterLayoutInfo( const WordLayoutInfo& wordLayoutInfo ) -{ - CharacterLayoutInfo layoutInfo; - - if( !wordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - layoutInfo = *( wordLayoutInfo.mCharactersLayoutInfo.end() - 1u ); - } - - return layoutInfo; -} - -void CollectTextActors( std::vector& textActors, const WordLayoutInfo& word, const std::size_t characterIndexBegin, const std::size_t characterIndexEnd ) -{ - for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin() + characterIndexBegin, - characterEndIt = word.mCharactersLayoutInfo.begin() + characterIndexEnd; - characterIt != characterEndIt; - ++characterIt ) - { - const CharacterLayoutInfo& characterLayout( *characterIt ); - - if( !characterLayout.mIsColorGlyph ) - { - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - if( textActor ) - { - textActors.push_back( textActor ); - } - } - } -} - -void CollectTextActorsFromWords( std::vector& textActors, const ParagraphLayoutInfo& paragraph, const std::size_t wordIndexBegin, const std::size_t wordIndexEnd ) -{ - for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin() + wordIndexBegin, wordEndIt = paragraph.mWordsLayoutInfo.begin() + wordIndexEnd; - wordIt != wordEndIt; - ++wordIt ) - { - const WordLayoutInfo& word( *wordIt ); - - for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt ) - { - const CharacterLayoutInfo& characterLayout( *characterIt ); - - if( !characterLayout.mIsColorGlyph ) - { - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - if( textActor ) - { - textActors.push_back( textActor ); - } - } - } - } -} - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-word-processor.h b/dali-toolkit/internal/controls/text-view/text-view-word-processor.h deleted file mode 100644 index 82f36f0..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-word-processor.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_WORD_PROCESSOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_WORD_PROCESSOR_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -/** - * Creates a data structure with info to layout the word, and data structures with useful info to modify the layout data structure if characters are added or removed. - * - * @param[in] paragraphText The paragraph's text. - * @param[in] textStyles The styles for each character of the paragraph. - * @param[out] wordLayoutInfo Layout info for all characters of the word. - */ -void CreateWordTextInfo( const Text& paragraphText, - Vector& textStyles, - WordLayoutInfo& wordLayoutInfo ); - -/** - * Updates the word size and ascender. - * - * It's called after deleting some characters, split a word in two, - * or when a new word is created when right to left text is reordered. - * - * @param[in] wordLayout The word layout info. - */ -void UpdateLayoutInfo( WordLayoutInfo& wordLayout ); - -/** - * Removes a given number of characters from the given word. - * - * It calls the RemoveCharactersFromWord() function to remove characters from the word. - * - * If the word is a white space \e mergeWords will return \e true and \e textInfoMergeIndicesBegin and \e textInfoMergeIndicesEnd will be set to merge the two adjacent words. - * If the word is a new paragraph character \e mergeParagraphs will return \e true and \e textInfoMergeIndicesBegin and \e textInfoMergeIndicesEnd will be set to merge the two paragraphs. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in] numberOfCharacters The number of characters to be deleted. - * @param[out] mergeWords Whether adjacent words need to be merged. - * @param[out] mergeParagraphs Whether current paragraph need to be merged with the next one. - * @param[in,out] textInfoIndicesBegin Indices to the paragraph, word and characters from where to delete characters. It returns from where words need to be removed. - * @param[out] textInfoIndicesEnd If paragraphs or words need to be merged it returns info to delete them (If a word is merged, it has to be removed. Equal for paragraphs). - * @param[out] textInfoMergeIndicesBegin The indices to the first part of the paragraph and word to be merged. - * @param[out] textInfoMergeIndicesEnd The indices to the last part of the paragraph and word to be merged. - * @param[in,out] paragraphLayout Layout info of the paragraph where the word is located. - * @param[out] removedTextActors Stores handles of temoved text-actors. - */ -void RemoveCharactersFromWordInfo( TextView::RelayoutData& relayoutData, - std::size_t numberOfCharacters, - bool& mergeWords, - bool& mergeParagraphs, - TextInfoIndices& textInfoIndicesBegin, - TextInfoIndices& textInfoIndicesEnd, - TextInfoIndices& textInfoMergeIndicesBegin, - TextInfoIndices& textInfoMergeIndicesEnd, - ParagraphLayoutInfo& paragraphLayout, - std::vector& removedTextActors ); -/** - * Removes a given number of characters from the given word. - * - * @pre \e positon and \e position + \e numberOfCharacters can't exceed the bounds of the word. - * - * @param[in] position Character index within the word with the starting position to be deleted. - * @param[in] numberOfCharacters The number of characters to be deleted. - * @param[in,out] wordLayout The input is the layout info of the word. The output is the layout info of the word without the removed characters. - */ -void RemoveCharactersFromWord( std::size_t position, - std::size_t numberOfCharacters, - WordLayoutInfo& wordLayout ); - -/** - * Splits a word in two. - * - * Removes part of the text from the input word and creates a new word with the removed text. - * - * i.e. The result of split 'word' by the position 3 would be 'wor' and 'd'. - * - * @note It deletes whatever there is in the last part of the word. - * - * @param[in] position Character index where to split the word. - * @param[in,out] firstWordLayoutInfo The input is the layout info of the given word. The output is the first part of the input word (from the character \e 0 to the character \e position - \e 1). - * @param[out] lastWordLayoutInfo Layout info of the last part of the given word ( from the character \e position to the end of the word). - */ -void SplitWord( std::size_t position, - WordLayoutInfo& firstWordLayoutInfo, - WordLayoutInfo& lastWordLayoutInfo ); - -/** - * Merges the two given words by adding characters of the last word to the firs one. - * - * @note Does nothing if last part of the word is empty. - * @note If the first part of the word is empty it just copy the last part to it. - * @note It asserts if the first or the last word is a word separator (white space) or a paragraph separator (new paragraph character) - * - * @param[in,out] firstWordLayoutInfo The input is the layout info of the first word. The output is the layout info of the merged word. - * @param[in] lastWordLayoutInfo Layout info of the last word. - */ -void MergeWord( WordLayoutInfo& firstWordLayoutInfo, - const WordLayoutInfo& lastWordLayoutInfo ); - -/** - * Retrieves the layout information of the first character of the given word. - * - * @param[in] wordLayoutInfo The word layout. - * - * @return Layout information of the first character of the word. - */ -CharacterLayoutInfo GetFirstCharacterLayoutInfo( const WordLayoutInfo& wordLayoutInfo ); - -/** - * Retrieves the layout information of the last character of the given word. - * - * @param[in] wordLayoutInfo The word layout. - * - * @return Layout information of the last character of the word. - */ -CharacterLayoutInfo GetLastCharacterLayoutInfo( const WordLayoutInfo& wordLayoutInfo ); - -/** - * Collects text-actors from the given word, within the given indices, and stores them into the text-actor vector. - * - * @param[out] textActors Stores the text-actors of the given word. - * @param[in] characterIndexBegin The first text-actor to be stored. - * @param[in] characterIndexEnd The last text-actor to be stored. - */ -void CollectTextActors( std::vector& textActors, const WordLayoutInfo& word, std::size_t characterIndexBegin, std::size_t characterIndexEnd ); - -/** - * Collects text-actors from the given paragraph, within the given indices, and stores them into the text-actor vector. - * - * @param[out] textActors Stores the text-actors of the given paragraph. - * @param[in] paragraph The paragraph with the words. - * @param[in] wordIndexBegin Index to the first word. - * @param[in] wordIndexEnd Index to the last word. - */ -void CollectTextActorsFromWords( std::vector& textActors, const ParagraphLayoutInfo& paragraph, std::size_t wordIndexBegin, std::size_t wordIndexEnd ); - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_WORD_PROCESSOR_H__ diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 31800b7..838592c 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -1,6 +1,8 @@ # Add local source files here toolkit_src_files = \ + $(toolkit_src_dir)/atlas-manager/atlas-manager.cpp \ + $(toolkit_src_dir)/atlas-manager/atlas-manager-impl.cpp \ $(toolkit_src_dir)/builder/builder-actor.cpp \ $(toolkit_src_dir)/builder/builder-animations.cpp \ $(toolkit_src_dir)/builder/builder-impl.cpp \ @@ -56,25 +58,9 @@ toolkit_src_files = \ $(toolkit_src_dir)/controls/slider/slider-impl.cpp \ $(toolkit_src_dir)/controls/super-blur-view/super-blur-view-impl.cpp \ $(toolkit_src_dir)/controls/table-view/table-view-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-decorator-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-handles-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-popup-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-text-highlight-impl.cpp \ - $(toolkit_src_dir)/controls/text-view/relayout-utilities.cpp \ - $(toolkit_src_dir)/controls/text-view/split-by-char-policies.cpp \ - $(toolkit_src_dir)/controls/text-view/split-by-new-line-char-policies.cpp \ - $(toolkit_src_dir)/controls/text-view/split-by-word-policies.cpp \ - $(toolkit_src_dir)/controls/text-view/text-actor-cache.cpp \ - $(toolkit_src_dir)/controls/text-view/text-processor-bidirectional-info.cpp \ - $(toolkit_src_dir)/controls/text-view/text-processor.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-character-processor.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-impl.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-paragraph-processor.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-processor-dbg.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-processor-helper-functions.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-processor.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-word-processor.cpp \ + $(toolkit_src_dir)/controls/text-controls/text-field-impl.cpp \ + $(toolkit_src_dir)/controls/text-controls/text-label-impl.cpp \ + $(toolkit_src_dir)/controls/text-controls/text-selection-popup-impl.cpp \ $(toolkit_src_dir)/controls/tool-bar/tool-bar-impl.cpp \ $(toolkit_src_dir)/controls/view/view-impl.cpp \ $(toolkit_src_dir)/focus-manager/focus-manager-impl.cpp \ @@ -87,6 +73,32 @@ toolkit_src_files = \ $(toolkit_src_dir)/shader-effects/page-turn-effect-impl.cpp \ $(toolkit_src_dir)/shader-effects/water-effect-impl.cpp \ $(toolkit_src_dir)/styling/style-manager-impl.cpp \ + $(toolkit_src_dir)/text/bidirectional-support.cpp \ + $(toolkit_src_dir)/text/character-set-conversion.cpp \ + $(toolkit_src_dir)/text/clipping/text-clipper.cpp \ + $(toolkit_src_dir)/text/logical-model-impl.cpp \ + $(toolkit_src_dir)/text/multi-language-support.cpp \ + $(toolkit_src_dir)/text/segmentation.cpp \ + $(toolkit_src_dir)/text/shaper.cpp \ + $(toolkit_src_dir)/text/text-control-interface.cpp \ + $(toolkit_src_dir)/text/text-controller.cpp \ + $(toolkit_src_dir)/text/text-io.cpp \ + $(toolkit_src_dir)/text/text-view.cpp \ + $(toolkit_src_dir)/text/text-view-interface.cpp \ + $(toolkit_src_dir)/text/visual-model-impl.cpp \ + $(toolkit_src_dir)/text/decorator/text-decorator.cpp \ + $(toolkit_src_dir)/text/layouts/layout-engine.cpp \ + $(toolkit_src_dir)/text/multi-language-support-impl.cpp \ + $(toolkit_src_dir)/text/rendering/text-backend.cpp \ + $(toolkit_src_dir)/text/rendering/text-renderer.cpp \ + $(toolkit_src_dir)/text/rendering/atlas/text-atlas-renderer.cpp \ + $(toolkit_src_dir)/text/rendering/atlas/atlas-glyph-manager.cpp \ + $(toolkit_src_dir)/text/rendering/atlas/atlas-glyph-manager-impl.cpp \ + $(toolkit_src_dir)/text/rendering/basic/text-basic-renderer.cpp \ + $(toolkit_src_dir)/text/rendering/shaders/text-basic-shader.cpp \ + $(toolkit_src_dir)/text/rendering/shaders/text-basic-shadow-shader.cpp \ + $(toolkit_src_dir)/text/rendering/shaders/text-bgra-shader.cpp \ + $(toolkit_src_dir)/text/rendering/text-backend-impl.cpp \ $(toolkit_src_dir)/transition-effects/cube-transition-effect-impl.cpp \ $(toolkit_src_dir)/transition-effects/cube-transition-cross-effect-impl.cpp \ $(toolkit_src_dir)/transition-effects/cube-transition-fold-effect-impl.cpp \ diff --git a/dali-toolkit/internal/styling/style-manager-impl.cpp b/dali-toolkit/internal/styling/style-manager-impl.cpp index fa453dd..4378e84 100644 --- a/dali-toolkit/internal/styling/style-manager-impl.cpp +++ b/dali-toolkit/internal/styling/style-manager-impl.cpp @@ -36,6 +36,7 @@ namespace const char* LANDSCAPE_QUALIFIER = "landscape"; const char* PORTRAIT_QUALIFIER = "portrait"; +const char* FONT_SIZE_QUALIFIER = "font-size-"; const char* DEFAULT_THEME = DALI_STYLE_DIR "tizen-default-theme.json"; @@ -99,7 +100,8 @@ Toolkit::StyleManager StyleManager::Get() } StyleManager::StyleManager() - : mOrientationDegrees( 0 ) // Portrait +: mOrientationDegrees( 0 ), // Portrait + mDefaultFontSize( -1 ) { // Add theme builder constants mThemeBuilderConstants[ PACKAGE_PATH_KEY ] = DEFAULT_PACKAGE_PATH; @@ -110,6 +112,8 @@ StyleManager::StyleManager() if( styleMonitor ) { styleMonitor.StyleChangeSignal().Connect( this, &StyleManager::StyleMonitorChange ); + + mDefaultFontSize = styleMonitor.GetDefaultFontSize(); } } @@ -244,9 +248,13 @@ void StyleManager::BuildQualifiedStyleName( const std::string& styleName, const void StyleManager::ApplyStyle( Toolkit::Builder builder, Toolkit::Control control ) { - // Convert control name to lower case - std::string styleName = control.GetTypeName(); - std::transform( styleName.begin(), styleName.end(), styleName.begin(), ::tolower ); + std::string styleName = control.GetStyleName(); + if( styleName.empty() ) + { + // Convert control name to lower case + styleName = control.GetTypeName(); + std::transform( styleName.begin(), styleName.end(), styleName.begin(), ::tolower ); + } // Apply the style after choosing the correct actual style (e.g. landscape or portrait) StringList qualifiers; @@ -266,6 +274,14 @@ void StyleManager::ApplyStyle( Toolkit::Builder builder, Toolkit::Control contro // Remove the last qualifier in an attempt to find a style that is valid qualifiers.pop_back(); } + + if( mDefaultFontSize >= 0 ) + { + // Apply the style for logical font size + std::stringstream fontSizeQualifier; + fontSizeQualifier << styleName << "-" << FONT_SIZE_QUALIFIER << mDefaultFontSize; + builder.ApplyStyle( fontSizeQualifier.str(), control ); + } } void StyleManager::ApplyThemeStyle( Toolkit::Control control ) @@ -380,6 +396,11 @@ void StyleManager::CacheBuilder( Toolkit::Builder builder, const std::string& ke void StyleManager::StyleMonitorChange( StyleMonitor styleMonitor, StyleChange styleChange ) { + if( styleChange.defaultFontSizeChange ) + { + mDefaultFontSize = styleMonitor.GetDefaultFontSize(); + } + mStyleChangeSignal.Emit( Toolkit::StyleManager::Get(), styleChange ); } diff --git a/dali-toolkit/internal/styling/style-manager-impl.h b/dali-toolkit/internal/styling/style-manager-impl.h index 648c11d..09d0c13 100644 --- a/dali-toolkit/internal/styling/style-manager-impl.h +++ b/dali-toolkit/internal/styling/style-manager-impl.h @@ -241,6 +241,8 @@ private: Orientation mOrientation; ///< Handle to application orientation object int mOrientationDegrees; ///< Directly set value of orientation + int mDefaultFontSize; ///< Logical size, not a point-size + std::string mThemeFile; ///< The full path of the current theme file Property::Map mThemeBuilderConstants; ///< Contants to give the theme builder diff --git a/dali-toolkit/internal/text/bidirectional-line-info-run.h b/dali-toolkit/internal/text/bidirectional-line-info-run.h new file mode 100644 index 0000000..355668d --- /dev/null +++ b/dali-toolkit/internal/text/bidirectional-line-info-run.h @@ -0,0 +1,49 @@ +#ifndef __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_LINE_INFO_RUN_H__ +#define __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_LINE_INFO_RUN_H__ + +/* + * Copyright (c) 2015 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 BidirectionalLineInfoRun + */ +struct BidirectionalLineInfoRun +{ + CharacterRun characterRun; ///< The initial character index within the whole text and the number of characters of the run. + CharacterIndex* visualToLogicalMap; ///< Pointer to the visual to logical map table. + CharacterDirection direction; ///< Direction of the first character of the paragraph. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_LINE_INFO_RUN_H__ diff --git a/dali-toolkit/internal/text/bidirectional-paragraph-info-run.h b/dali-toolkit/internal/text/bidirectional-paragraph-info-run.h new file mode 100644 index 0000000..feefa84 --- /dev/null +++ b/dali-toolkit/internal/text/bidirectional-paragraph-info-run.h @@ -0,0 +1,51 @@ +#ifndef __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_PARAGRAPH_INFO_RUN_H__ +#define __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_PARAGRAPH_INFO_RUN_H__ + +/* + * Copyright (c) 2015 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 BidirectionalParagraphInfoRun + * + * In terms of the bidirectional algorithm, a 'paragraph' is understood as a run of characters between Paragraph Separators or appropriate Newline Functions. + * A 'paragraph' may also be determined by higher-level protocols like a mark-up tag. + */ +struct BidirectionalParagraphInfoRun +{ + CharacterRun characterRun; ///< The initial character index within the whole text and the number of characters of the run. + BidiInfoIndex bidirectionalInfoIndex; ///< Index to the table with the bidirectional info per paragraph. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_PARAGRAPH_INFO_RUN_H__ diff --git a/dali-toolkit/internal/text/bidirectional-support.cpp b/dali-toolkit/internal/text/bidirectional-support.cpp new file mode 100644 index 0000000..c58c126 --- /dev/null +++ b/dali-toolkit/internal/text/bidirectional-support.cpp @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace +{ + +/** + * @brief Get the lines of a paragraph. + * + * @param[in] paragraphInfo The paragraph. + * @param[in] lines The lines. + * @param[in] lineIndex Index pointing the first line to be checked. + * @param[out] firstLine Index to the first line of the paragraph. + * @param[out] numberOfLines The number of lines. + */ +void GetLines( const BidirectionalParagraphInfoRun& paragraphInfo, + const Vector& lines, + unsigned int lineIndex, + unsigned int& firstLine, + unsigned int& numberOfLines ) +{ + firstLine = lineIndex; + numberOfLines = 0u; + + const CharacterIndex lastCharacterIndex = paragraphInfo.characterRun.characterIndex + paragraphInfo.characterRun.numberOfCharacters; + bool firstLineFound = false; + + for( Vector::ConstIterator it = lines.Begin() + lineIndex, + endIt = lines.End(); + it != endIt; + ++it ) + { + const LineRun& line = *it; + + if( ( line.characterRun.characterIndex + line.characterRun.numberOfCharacters > paragraphInfo.characterRun.characterIndex ) && + ( lastCharacterIndex > line.characterRun.characterIndex ) ) + { + firstLineFound = true; + ++numberOfLines; + } + else if( lastCharacterIndex <= line.characterRun.characterIndex ) + { + // nothing else to do. + break; + } + + if( !firstLineFound ) + { + ++firstLine; + } + } +} + +} // namespace + +void SetBidirectionalInfo( const Vector& text, + const Vector& scripts, + const Vector& lineBreakInfo, + Vector& bidirectionalInfo ) +{ + // Traverse the script runs. If there is one with a right to left script, create the bidirectional info for the paragraph containing that script is needed. + // From the bidirectional point of view, a paragraph is the piece of text between two LINE_MUST_BREAK. + + // Index pointing the first character of the current paragraph. + CharacterIndex paragraphCharacterIndex = 0u; + + // Pointer to the text buffer. + const Character* textBuffer = text.Begin(); + + // Pointer to the line break info buffer. + const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + + // The number of characters. + const Length numberOfCharacters = text.Count(); + + // Handle to the bidirectional info module in text-abstraction. + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + + for( Vector::ConstIterator it = scripts.Begin(), + endIt = scripts.End(); + it != endIt; + ++it ) + { + const ScriptRun& scriptRun = *it; + const CharacterIndex lastScriptRunIndex = scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters; + + if( TextAbstraction::IsRightToLeftScript( scriptRun.script ) && // The script is right to left. + ( lastScriptRunIndex > paragraphCharacterIndex ) ) // It isn't part of a previous paragraph. + { + // Find the paragraphs which contains this script run. + // Consider: + // 1) Different paragraphs may contain this script run. + // ------||------------------- rtl sr ------------------------||------------------- + // --||----- p -----||------------------ p -------------||-------- p ------||------ + // + // 2) The paragraph which contains this script run may contain other right to left script runs. + // -----||--- rtl sr ---||---- ltr sr ----||---------- rtl sr -----------||-------- + // -----||---------------------------------- p -----------------------------------| + + while( lastScriptRunIndex > paragraphCharacterIndex ) + { + // There is a paragraph which contains the current script. + + Length index = paragraphCharacterIndex; + while( ( index < numberOfCharacters ) && ( paragraphCharacterIndex < lastScriptRunIndex ) ) + { + if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ) ) + { + if( index >= scriptRun.characterRun.characterIndex ) + { + // The Bidirectional run must have the same number of characters than the paragraph. + BidirectionalParagraphInfoRun bidirectionalRun; + bidirectionalRun.characterRun.characterIndex = paragraphCharacterIndex; + bidirectionalRun.characterRun.numberOfCharacters = ( index - paragraphCharacterIndex ) + 1u; // The must break character is part of the paragrah. + + // Create the bidirectional info for the whole paragraph and store the index to the table with this info in the run. + bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo( textBuffer + bidirectionalRun.characterRun.characterIndex, + bidirectionalRun.characterRun.numberOfCharacters ); + + bidirectionalInfo.PushBack( bidirectionalRun ); + } + + // Update the character index of the next paragraph. + paragraphCharacterIndex = index + 1u; + } + ++index; + } + + // The last character is always a must-break, so there is no need to check if there is characters left. + } + } + } +} + +void ReplaceBidirectionalInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +void ReorderLines( const Vector& bidirectionalInfo, + Vector& lineRuns, + Vector& lineInfoRuns ) +{ + // Handle to the bidirectional info module in text-abstraction. + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + + // Keep an index to the first line to be checked if it's contained inside the paragraph. + // Avoids check the lines from the beginning for each paragraph. + unsigned int lineIndex = 0u; + + for( Vector::ConstIterator it = bidirectionalInfo.Begin(), + endIt = bidirectionalInfo.End(); + it != endIt; + ++it ) + { + const BidirectionalParagraphInfoRun& paragraphInfo = *it; + const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( paragraphInfo.bidirectionalInfoIndex ); + + // Get the lines for this paragraph. + unsigned int firstLine = 0u; + unsigned int numberOfLines = 0u; + + // Get an index to the first line and the number of lines of the current paragraph. + GetLines( paragraphInfo, + lineRuns, + lineIndex, + firstLine, + numberOfLines ); + + lineIndex = firstLine + numberOfLines; + + // Traverse the lines and reorder them + for( Vector::Iterator lineIt = lineRuns.Begin() + firstLine, + endLineIt = lineRuns.Begin() + firstLine + numberOfLines; + lineIt != endLineIt; + ++lineIt ) + { + LineRun& line = *lineIt; + + // Sets the paragraph's direction. + line.direction = direction; + + // Creates a bidirectional info for the line run. + BidirectionalLineInfoRun lineInfoRun; + lineInfoRun.characterRun.characterIndex = line.characterRun.characterIndex; + lineInfoRun.characterRun.numberOfCharacters = line.characterRun.numberOfCharacters; + lineInfoRun.direction = direction; + + // Allocate space for the conversion maps. + // The memory is freed after the visual to logical to visual conversion tables are built in the logical model. + lineInfoRun.visualToLogicalMap = reinterpret_cast( malloc( line.characterRun.numberOfCharacters * sizeof( CharacterIndex ) ) ); + + // Reorders the line. + bidirectionalSupport.Reorder( paragraphInfo.bidirectionalInfoIndex, + line.characterRun.characterIndex - paragraphInfo.characterRun.characterIndex, + line.characterRun.numberOfCharacters, + lineInfoRun.visualToLogicalMap ); + + // Push the run into the vector. + lineInfoRuns.PushBack( lineInfoRun ); + } + } +} + +void ReorderLines( LogicalModel& logicalModel, + const VisualModel& visualModel, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +bool GetMirroredText( const Vector& text, + Vector& mirroredText ) +{ + // Handle to the bidirectional info module in text-abstraction. + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + + mirroredText = text; + + return bidirectionalSupport.GetMirroredText( mirroredText.Begin(), + mirroredText.Count() ); +} + +void GetCharactersDirection( const Vector& bidirectionalInfo, + Vector& directions ) +{ + // Handle to the bidirectional info module in text-abstraction. + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + + CharacterIndex index = 0u; + CharacterDirection* directionsBuffer = directions.Begin(); + for( Vector::ConstIterator it = bidirectionalInfo.Begin(), + endIt = bidirectionalInfo.End(); + it != endIt; + ++it ) + { + const BidirectionalParagraphInfoRun& paragraph = *it; + + // Fills with left to right those paragraphs without right to left characters. + memset( directionsBuffer + index, false, ( paragraph.characterRun.characterIndex - index ) * sizeof( bool ) ); + index += paragraph.characterRun.numberOfCharacters; + + bidirectionalSupport.GetCharactersDirection( paragraph.bidirectionalInfoIndex, + directionsBuffer + paragraph.characterRun.characterIndex, + paragraph.characterRun.numberOfCharacters ); + } + + // Fills with left to right those paragraphs without right to left characters. + memset( directionsBuffer + index, false, ( directions.Count() - index ) * sizeof( bool ) ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/bidirectional-support.h b/dali-toolkit/internal/text/bidirectional-support.h new file mode 100644 index 0000000..f51e5e7 --- /dev/null +++ b/dali-toolkit/internal/text/bidirectional-support.h @@ -0,0 +1,143 @@ +#ifndef __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_SUPPORT_H__ +#define __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_SUPPORT_H__ + +/* + * Copyright (c) 2015 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 +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class LogicalModel; +class VisualModel; + +/** + * Sets the bidirectional info into the logical model. + * + * @param[in] text Vector of UTF-32 characters. + * @param[in] scripts Vector containing the script runs for the whole text. + * @param[in] lineBreakInfo The line break info. + * @param[out] bidirectionalInfo Vector with the bidirectional infor for each paragraph. + */ +void SetBidirectionalInfo( const Vector& text, + const Vector& scripts, + const Vector& lineBreakInfo, + Vector& bidirectionalInfo ); + +/** + * Replaces the bidirectional info from the logical model. + * + * @pre The @p model needs to have a text set. + * @pre The @p model needs to have the line break info set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ReplaceBidirectionalInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +/** + * Sets the visual to logical map tables. + * + * Any map tables previously set are removed. + * It sets the paragraph's direction to each line. + * + * @pre The @p logicalModel needs to have a text set. + * @pre The @p logicalModel needs to have the bidirectional info indices for each paragraph set. + * @pre The @p visualModel needs to have the laid-out lines info set. + * + * @param[in] bidirectionalInfo Vector with the bidirectional infor for each paragraph. + * @param[in,out] lineRuns The line runs converted to characters. + * @param[out] lineInfoRuns line runs with the visual to logical conversion maps. + */ +void ReorderLines( const Vector& bidirectionalInfo, + Vector& lineRuns, + Vector& lineInfoRuns ); + +/** + * Replaces the visual to logical and logical to visual map tables. + * + * @pre The @p logicalModel needs to have a text set. + * @pre The @p logicalModel needs to have the line break info set. + * @pre The @p visualModel needs to have the laid-out lines info set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] logicalModel The text's logical model. + * @param[in] visualModel The text's visual model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ReorderLines( LogicalModel& logicalModel, + const VisualModel& visualModel, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +/** + * @brief Replaces any character which could be mirrored. + * + * @param[in] text The text. + * @param[in] mirroredText The mirroredText. + * + * @return @e true if a character has been replaced. + */ +bool GetMirroredText( const Vector& text, + Vector& mirroredText ); + +/** + * @brief Retrieves the character's directions. + * + * @pre The @p logicalModel needs to have a text set. + * @pre The @p logicalModel needs to have the bidirectional info indices for each paragraph set. + * + * @param[in] bidirectionalInfo Vector with the bidirectional infor for each paragraph. + * @param[out] directions The direction, @e false is left to right and @e true is right to left, of each character of the paragraph. + */ +void GetCharactersDirection( const Vector& bidirectionalInfo, + Vector& directions ); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_SUPPORT_H__ diff --git a/dali-toolkit/internal/text/character-run.h b/dali-toolkit/internal/text/character-run.h new file mode 100644 index 0000000..221ecbd --- /dev/null +++ b/dali-toolkit/internal/text/character-run.h @@ -0,0 +1,48 @@ +#ifndef __DALI_TOOLKIT_TEXT_CHARACTER_RUN_H__ +#define __DALI_TOOLKIT_TEXT_CHARACTER_RUN_H__ + +/* + * Copyright (c) 2015 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 A run of consecutive characters. + */ +struct CharacterRun +{ + CharacterIndex characterIndex; ///< Index to the first character. + Length numberOfCharacters; ///< Number of characters in the run. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_CHARACTER_RUN_H__ diff --git a/dali-toolkit/internal/text/character-set-conversion.cpp b/dali-toolkit/internal/text/character-set-conversion.cpp new file mode 100644 index 0000000..3afecbb --- /dev/null +++ b/dali-toolkit/internal/text/character-set-conversion.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// FILE HEADER +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace +{ + const static uint8_t U1 = 1u; + const static uint8_t U2 = 2u; + const static uint8_t U3 = 3u; + const static uint8_t U4 = 4u; + const static uint8_t U0 = 0u; + const static uint8_t UTF8_LENGTH[256] = { + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // lead byte = 0xxx xxxx (U+0000 - U+007F + some extended ascii characters) + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, // + + U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, // + U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, // lead byte = 110x xxxx (U+0080 - U+07FF) + U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, // + U2, U2, // + + U3, U3, U3, U3, U3, U3, U3, U3, U3, U3, // lead byte = 1110 xxxx (U+0800 - U+FFFF) + U3, U3, U3, U3, U3, U3, // + + U4, U4, U4, U4, U4, U4, U4, U4, // lead byte = 1111 0xxx (U+10000 - U+1FFFFF) + + U0, U0, U0, U0, // Non valid. + U0, U0, U0, U0, // Non valid. + }; +} // namespace + +uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length ) +{ + uint32_t numberOfCharacters = 0u; + + const uint8_t* begin = utf8; + const uint8_t* end = utf8 + length; + + for( ; begin < end ; begin += UTF8_LENGTH[*begin], ++numberOfCharacters ); + + return numberOfCharacters; +} + +uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters ) +{ + uint32_t numberOfBytes = 0u; + + const uint32_t* begin = utf32; + const uint32_t* end = utf32 + numberOfCharacters; + + for( ; begin < end; ++begin ) + { + const uint32_t code = *begin; + + if( code < 0x80u ) + { + ++numberOfBytes; + } + else if( code < 0x800u ) + { + numberOfBytes += U2; + } + else if( code < 0x10000u ) + { + numberOfBytes += U3; + } + else if( code < 0x200000u ) + { + numberOfBytes += U4; + } + } + + return numberOfBytes; +} + +uint32_t Utf8ToUtf32( const uint8_t* const utf8, uint32_t length, uint32_t* utf32 ) +{ + uint32_t numberOfCharacters = 0u; + + const uint8_t* begin = utf8; + const uint8_t* end = utf8 + length; + + for( ; begin < end ; ++numberOfCharacters ) + { + const uint8_t leadByte = *begin; + + switch( UTF8_LENGTH[leadByte] ) + { + case U1: + { + *utf32++ = leadByte; + begin++; + break; + } + + case U2: + { + uint32_t& code = *utf32++; + code = leadByte & 0x1fu; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U3: + { + uint32_t& code = *utf32++; + code = leadByte & 0x0fu; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U4: + { + uint32_t& code = *utf32++; + code = leadByte & 0x07u; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + } + } + + return numberOfCharacters; +} + +uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, uint8_t* utf8 ) +{ + const uint32_t* begin = utf32; + const uint32_t* end = utf32 + numberOfCharacters; + + uint8_t* utf8Begin = utf8; + + for( ; begin < end; ++begin ) + { + const uint32_t code = *begin; + + if( code < 0x80u ) + { + *utf8++ = code; + } + else if( code < 0x800u ) + { + *utf8++ = static_cast( code >> 6u ) | 0xc0u; // lead byte for 2 byte sequence + *utf8++ = static_cast( code & 0x3f ) | 0x80u; // continuation byte + } + else if( code < 0x10000u ) + { + *utf8++ = static_cast( code >> 12u ) | 0xe0u; // lead byte for 2 byte sequence + *utf8++ = static_cast( ( code >> 6u ) & 0x3f ) | 0x80u; // continuation byte + *utf8++ = static_cast( code & 0x3f ) | 0x80u; // continuation byte + } + else if( code < 0x200000u ) + { + *utf8++ = static_cast( code >> 18u ) | 0xf0u; // lead byte for 2 byte sequence + *utf8++ = static_cast( ( code >> 12u ) & 0x3f ) | 0x80u; // continuation byte + *utf8++ = static_cast( ( code >> 6u ) & 0x3f ) | 0x80u; // continuation byte + *utf8++ = static_cast( code & 0x3f ) | 0x80u; // continuation byte + } + } + + return utf8 - utf8Begin; +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/character-set-conversion.h b/dali-toolkit/internal/text/character-set-conversion.h new file mode 100644 index 0000000..c8da542 --- /dev/null +++ b/dali-toolkit/internal/text/character-set-conversion.h @@ -0,0 +1,83 @@ +#ifndef __DALI_TOOLKIT_CHARACTER_SET_CONVERSION_H__ +#define __DALI_TOOLKIT_CHARACTER_SET_CONVERSION_H__ + +/* + * Copyright (c) 2015 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 Toolkit +{ + +/** + * @brief Retrieves the number of characters of the text array encoded in UTF8 + * + * @param[in] utf8 The pointer to the UTF8 array. + * @param[in] length The length of the UTF8 array. + * + * @return The number of characters. + */ +DALI_IMPORT_API uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length ); + +/** + * @brief Retrieves the number of bytes needed to encode in UTF8 the given text array encoded in UTF32. + * + * @param[in] utf32 The pointer to the UTF32 array. + * @param[in] numberOfCharacters The number of characters of the UTF32 array. + * + * @return The number of bytes. + */ +DALI_IMPORT_API uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters ); + +/** + * @brief Converts a text array encoded in UTF8 into a text array encoded in UTF32. + * + * The @p utf32 buffer needs to be big enough to store all the characters. + * + * @param[in] utf8 The pointer to the UTF8 array. + * @param[in] length The length of the UTF8 array. + * @param[out] utf32 The pointer to the UTF32 array. + * + * @return The number of characters. + */ +DALI_IMPORT_API uint32_t Utf8ToUtf32( const uint8_t* const utf8, uint32_t length, uint32_t* utf32 ); + +/** + * @brief Converts a text array encoded in UTF32 into a text array encoded in UTF8. + * + * The @p utf8 buffer needs to be big enough to store all the characters. + * + * @param[in] utf32 The pointer to the UTF32 array. + * @param[in] numberOfCharacters The number of characters of the UTF32 array. + * @param[out] utf8 The pointer to the UTF8 array. + * + * @return The number of bytes. + */ +DALI_IMPORT_API uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, uint8_t* utf8 ); + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_CHARACTER_SET_CONVERSION_H__ diff --git a/dali-toolkit/internal/text/clipping/text-clipper.cpp b/dali-toolkit/internal/text/clipping/text-clipper.cpp new file mode 100644 index 0000000..7a79e4c --- /dev/null +++ b/dali-toolkit/internal/text/clipping/text-clipper.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015 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 + +namespace +{ + +// Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k. +const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f; + +} // namespace + + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +ClipperPtr Clipper::New( const Vector2& size ) +{ + ClipperPtr clipper( new Clipper() ); + + // Second-phase init + clipper->Initialize( size ); + + return clipper; +} + +Actor Clipper::GetRootActor() const +{ + return mOffscreenRootActor; +} + +ImageActor Clipper::GetImageActor() const +{ + return mImageActor; +} + +void Clipper::Refresh( const Vector2& size ) +{ + const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.width ), + std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.height ) ); + + const bool sizeChanged = offscreenSize != mCurrentOffscreenSize; + + if( sizeChanged ) + { + // Reconfigure camera for current size. + mOffscreenCameraActor.SetOrthographicProjection( offscreenSize ); + + // Recreate frame buffer for offscreen rendering when the size changes. + FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width, + offscreenSize.height, + Pixel::RGBA8888 ); + + mImageActor.SetSize( offscreenSize ); + mImageActor.SetImage( frameBufferImage ); + mRenderTask.SetTargetFrameBuffer( frameBufferImage ); + + // Stores current sizPe to avoid create new Dali resources if text changes. + mCurrentOffscreenSize = offscreenSize; + } + + mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); +} + +void Clipper::Initialize( const Vector2& size ) +{ + const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.width ), + std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.height ) ); + + // Create a root actor and an image actor for offscreen rendering. + mOffscreenRootActor = Layer::New(); + mOffscreenRootActor.SetRelayoutEnabled( false ); + mOffscreenRootActor.SetColorMode( USE_OWN_COLOR ); + mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION ); + mOffscreenRootActor.SetInheritScale( false ); + mOffscreenRootActor.SetDepthTestDisabled( true ); + mOffscreenRootActor.SetSize( offscreenSize ); + + mImageActor = ImageActor::New(); + mImageActor.SetRelayoutEnabled( false ); + mImageActor.SetParentOrigin( ParentOrigin::CENTER ); + mImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA, + BlendingFactor::ONE, BlendingFactor::ONE ); + mImageActor.SetScale( Vector3( 1.0f, -1.0f, 1.0f ) ); + mImageActor.SetSize( offscreenSize ); + + // Creates a new camera actor. + mOffscreenCameraActor = CameraActor::New(); + mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER ); + mOffscreenCameraActor.SetOrthographicProjection( offscreenSize ); + mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text + + // Creates a new render task. + mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask(); + mRenderTask.SetSourceActor( mOffscreenRootActor ); + mRenderTask.SetClearColor( Color::TRANSPARENT ); + mRenderTask.SetClearEnabled( true ); + mRenderTask.SetExclusive( true ); + mRenderTask.SetCameraActor( mOffscreenCameraActor ); + + // Creates a frame buffer for offscreen rendering + FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width, + offscreenSize.height, + Pixel::RGBA8888 ); + mImageActor.SetImage( frameBufferImage ); + mRenderTask.SetTargetFrameBuffer( frameBufferImage ); + + // Stores current size to avoid create new Dali resources if text changes. + mCurrentOffscreenSize = offscreenSize; +} + +Clipper::Clipper() +{ +} + +Clipper::~Clipper() +{ + if( Stage::IsInstalled() ) + { + UnparentAndReset( mOffscreenRootActor ); + UnparentAndReset( mImageActor ); + + Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask ); + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/clipping/text-clipper.h b/dali-toolkit/internal/text/clipping/text-clipper.h new file mode 100644 index 0000000..d435c86 --- /dev/null +++ b/dali-toolkit/internal/text/clipping/text-clipper.h @@ -0,0 +1,118 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_CLIPPER_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_CLIPPER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class Clipper; +typedef IntrusivePtr ClipperPtr; + +/** + * @brief A helper class for clipping actors using a FrameBufferImage. + */ +class Clipper : public RefObject +{ +public: + + /** + * @brief Create a clipper. + * + * @param[in] size The size of the clipping region. + */ + static ClipperPtr New( const Vector2& size ); + + /** + * @brief Children added to this actor will be clipped with the specified region. + * + * @note This is done by rendering to a FrameBufferImage which must then be displayed; see also GetImageActor(). + * @return The root actor. + */ + Actor GetRootActor() const; + + /** + * @brief This actor will display the resulting FrameBufferImage. + * + * @return The image actor. + */ + ImageActor GetImageActor() const; + + /** + * @brief Refresh the contents of the FrameBufferImage. + * + * @param[in] size The size of the clipping region. + */ + void Refresh( const Vector2& size ); + +private: // Implementation + + /** + * @brief Second-phase init + * + * @param[in] size The size of the clipping region. + */ + void Initialize( const Vector2& size ); + + /** + * Construct a new Clipper. + */ + Clipper(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~Clipper(); + +private: + + // Undefined copy constructor and assignment operators + Clipper(const Clipper&); + Clipper& operator=(const Clipper& rhs); + +private: // Data + + Layer mOffscreenRootActor; + CameraActor mOffscreenCameraActor; + ImageActor mImageActor; + RenderTask mRenderTask; + Vector2 mCurrentOffscreenSize; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_CLIPPER_H__ diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp new file mode 100644 index 0000000..d834e48 --- /dev/null +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -0,0 +1,883 @@ +/* + * Copyright (c) 2015 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG_ENABLED +#define DECORATOR_DEBUG +#endif + +// Local Data +namespace +{ + +const char* DEFAULT_GRAB_HANDLE_IMAGE( DALI_IMAGE_DIR "insertpoint-icon.png" ); +const char* DEFAULT_SELECTION_HANDLE_ONE( DALI_IMAGE_DIR "text-input-selection-handle-left.png" ); +const char* DEFAULT_SELECTION_HANDLE_TWO( DALI_IMAGE_DIR "text-input-selection-handle-right.png" ); +//const char* DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" ); +//const char* DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" ); + +const Dali::Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.5f, 2.0f, 1.0f ); +const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f ); + +const std::size_t CURSOR_BLINK_INTERVAL = 500; // Cursor blink interval +const std::size_t MILLISECONDS = 1000; + +const float DISPLAYED_HIGHLIGHT_Z_OFFSET( -0.05f ); + +/** + * structure to hold coordinates of each quad, which will make up the mesh. + */ +struct QuadCoordinates +{ + /** + * Default constructor + */ + QuadCoordinates() + { + } + + /** + * Constructor + * @param[in] x1 left co-ordinate + * @param[in] y1 top co-ordinate + * @param[in] x2 right co-ordinate + * @param[in] y2 bottom co-ordinate + */ + QuadCoordinates(float x1, float y1, float x2, float y2) + : min(x1, y1), + max(x2, y2) + { + } + + Dali::Vector2 min; ///< top-left (minimum) position of quad + Dali::Vector2 max; ///< bottom-right (maximum) position of quad +}; + +typedef std::vector QuadContainer; + +} // end of namespace + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct Decorator::Impl : public ConnectionTracker +{ + struct CursorImpl + { + CursorImpl() + : x(0.0f), + y(0.0f), + cursorHeight(0.0f), + lineHeight(0.0f), + color(Dali::Color::WHITE) + { + } + + float x; + float y; + float cursorHeight; + float lineHeight; + + Vector4 color; + }; + + struct SelectionHandleImpl + { + SelectionHandleImpl() + : x(0.0f), + y(0.0f), + lineHeight(0.0f), + flipped(false) + { + } + + float x; + float y; + float lineHeight; ///< Not the handle height + bool flipped; + + ImageActor actor; + Actor grabArea; + + Image pressedImage; + Image releasedImage; + }; + + Impl( Dali::Toolkit::Internal::Control& parent, Observer& observer ) + : mTextControlParent(parent), + mObserver(observer), + mActiveCursor(ACTIVE_CURSOR_NONE), + mActiveGrabHandle(false), + mActiveSelection( false ), + mActiveCopyPastePopup( false ), + mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ), + mCursorBlinkDuration( 0.0f ), + mCursorBlinkStatus( true ), + mGrabDisplacementX( 0.0f ), + mGrabDisplacementY( 0.0f ), + mHighlightColor( 0.07f, 0.41f, 0.59f, 1.0f ), // light blue + mBoundingBox( Rect() ) + { + } + + /** + * Relayout of the decorations owned by the decorator. + * @param[in] size The Size of the UI control the decorater is adding it's decorations to. + */ + void Relayout( const Vector2& size, const Vector2& scrollPosition ) + { + // TODO - Remove this if nothing is active + CreateActiveLayer(); + + // Show or hide the cursors + CreateCursors(); + if( mPrimaryCursor ) + { + mPrimaryCursor.SetPosition( mCursor[PRIMARY_CURSOR].x + scrollPosition.x, + mCursor[PRIMARY_CURSOR].y + scrollPosition.y ); + mPrimaryCursor.SetSize( Size( 1.0f, mCursor[PRIMARY_CURSOR].cursorHeight ) ); + } + if( mSecondaryCursor ) + { + mSecondaryCursor.SetPosition( mCursor[SECONDARY_CURSOR].x + scrollPosition.x, + mCursor[SECONDARY_CURSOR].y + scrollPosition.y ); + mSecondaryCursor.SetSize( Size( 1.0f, mCursor[SECONDARY_CURSOR].cursorHeight ) ); + } + + // Show or hide the grab handle + if( mActiveGrabHandle ) + { + SetupTouchEvents(); + + CreateGrabHandle(); + + mGrabHandle.SetPosition( mCursor[PRIMARY_CURSOR].x + scrollPosition.x, + mCursor[PRIMARY_CURSOR].lineHeight + scrollPosition.y ); + } + else if( mGrabHandle ) + { + UnparentAndReset( mGrabHandle ); + } + + // Show or hide the selection handles/highlight + if( mActiveSelection ) + { + SetupTouchEvents(); + + CreateSelectionHandles(); + + SelectionHandleImpl& primary = mSelectionHandle[ PRIMARY_SELECTION_HANDLE ]; + primary.actor.SetPosition( primary.x + scrollPosition.x, + primary.lineHeight + scrollPosition.y ); + + SelectionHandleImpl& secondary = mSelectionHandle[ SECONDARY_SELECTION_HANDLE ]; + secondary.actor.SetPosition( secondary.x + scrollPosition.x, + secondary.lineHeight + scrollPosition.y ); + + CreateHighlight(); + UpdateHighlight(); + } + else + { + UnparentAndReset( mSelectionHandle[ PRIMARY_SELECTION_HANDLE ].actor ); + UnparentAndReset( mSelectionHandle[ SECONDARY_SELECTION_HANDLE ].actor ); + UnparentAndReset( mHighlightMeshActor ); + } + + if ( mActiveCopyPastePopup ) + { + if ( !mCopyPastePopup ) + { + mCopyPastePopup = TextSelectionPopup::New(); + mActiveLayer.Add ( mCopyPastePopup ); + } + mCopyPastePopup.SetPosition( Vector3( 200.0f, -100.0f, 0.0f ) ); //todo grabhandle or selection handle positions to be used + } + else + { + if ( mCopyPastePopup ) + { + UnparentAndReset( mCopyPastePopup ); + } + } + } + + void CreateCursor( ImageActor& cursor ) + { + cursor = CreateSolidColorActor( Color::WHITE ); + cursor.SetParentOrigin( ParentOrigin::TOP_LEFT ); // Need to set the default parent origin as CreateSolidColorActor() sets a different one. + cursor.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + cursor.SetRelayoutEnabled( false ); + } + + // Add or Remove cursor(s) from parent + void CreateCursors() + { + if( mActiveCursor == ACTIVE_CURSOR_NONE ) + { + UnparentAndReset( mPrimaryCursor ); + UnparentAndReset( mSecondaryCursor ); + } + else + { + /* Create Primary and or Secondary Cursor(s) if active and add to parent */ + if ( mActiveCursor == ACTIVE_CURSOR_PRIMARY || + mActiveCursor == ACTIVE_CURSOR_BOTH ) + { + if ( !mPrimaryCursor ) + { + CreateCursor( mPrimaryCursor ); +#ifdef DECORATOR_DEBUG + mPrimaryCursor.SetName( "PrimaryCursorActor" ); +#endif + mActiveLayer.Add( mPrimaryCursor); + } + } + + if ( mActiveCursor == ACTIVE_CURSOR_BOTH ) + { + if ( !mSecondaryCursor ) + { + CreateCursor( mSecondaryCursor ); +#ifdef DECORATOR_DEBUG + mSecondaryCursor.SetName( "SecondaryCursorActor" ); +#endif + mActiveLayer.Add( mSecondaryCursor); + } + } + else + { + UnparentAndReset( mSecondaryCursor ); + } + } + } + + bool OnCursorBlinkTimerTick() + { + // Cursor blinking + if ( mPrimaryCursor ) + { + mPrimaryCursor.SetVisible( mCursorBlinkStatus ); + } + if ( mSecondaryCursor ) + { + mSecondaryCursor.SetVisible( mCursorBlinkStatus ); + } + + mCursorBlinkStatus = !mCursorBlinkStatus; + + return true; + } + + void SetupTouchEvents() + { + if ( !mTapDetector ) + { + mTapDetector = TapGestureDetector::New(); + mTapDetector.DetectedSignal().Connect( this, &Decorator::Impl::OnTap ); + } + + if ( !mPanGestureDetector ) + { + mPanGestureDetector = PanGestureDetector::New(); + mPanGestureDetector.DetectedSignal().Connect( this, &Decorator::Impl::OnPan ); + } + } + + void CreateActiveLayer() + { + if( !mActiveLayer ) + { + Actor parent = mTextControlParent.Self(); + + mActiveLayer = Layer::New(); +#ifdef DECORATOR_DEBUG + mActiveLayer.SetName ( "ActiveLayerActor" ); +#endif + + mActiveLayer.SetParentOrigin( ParentOrigin::CENTER ); + mActiveLayer.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mActiveLayer.SetPositionInheritanceMode( USE_PARENT_POSITION ); + + parent.Add( mActiveLayer ); + } + + mActiveLayer.RaiseToTop(); + } + + void CreateGrabHandle() + { + if( !mGrabHandle ) + { + if ( !mGrabHandleImage ) + { + mGrabHandleImage = ResourceImage::New( DEFAULT_GRAB_HANDLE_IMAGE ); + } + + mGrabHandle = ImageActor::New( mGrabHandleImage ); +#ifdef DECORATOR_DEBUG + mGrabHandle.SetName( "GrabHandleActor" ); +#endif + mGrabHandle.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + mGrabHandle.SetDrawMode( DrawMode::OVERLAY ); + // Area that Grab handle responds to, larger than actual handle so easier to move +#ifdef DECORATOR_DEBUG + mGrabArea = Toolkit::CreateSolidColorActor( Vector4(0.0f, 0.0f, 0.0f, 0.0f), true, Color::RED, 1 ); + mGrabArea.SetName( "GrabArea" ); +#else + mGrabArea = Actor::New(); + mGrabArea.SetRelayoutEnabled( true ); +#endif + mGrabArea.SetParentOrigin( ParentOrigin::TOP_CENTER ); + mGrabArea.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + mGrabArea.SetResizePolicy( SIZE_RELATIVE_TO_PARENT, ALL_DIMENSIONS ); + mGrabArea.SetSizeModeFactor( DEFAULT_GRAB_HANDLE_RELATIVE_SIZE ); + mGrabHandle.Add( mGrabArea ); + + mTapDetector.Attach( mGrabArea ); + mPanGestureDetector.Attach( mGrabArea ); + + mActiveLayer.Add(mGrabHandle); + } + } + + void CreateSelectionHandles() + { + SelectionHandleImpl& primary = mSelectionHandle[ PRIMARY_SELECTION_HANDLE ]; + if ( !primary.actor ) + { + if ( !primary.releasedImage ) + { + primary.releasedImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE ); + } + + primary.actor = ImageActor::New( primary.releasedImage ); +#ifdef DECORATOR_DEBUG + primary.actor.SetName("SelectionHandleOne"); +#endif + primary.actor.SetAnchorPoint( AnchorPoint::TOP_RIGHT ); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text. + primary.actor.SetDrawMode( DrawMode::OVERLAY ); // ensure grab handle above text + primary.flipped = false; + + primary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move + primary.grabArea.SetRelayoutEnabled( true ); +#ifdef DECORATOR_DEBUG + primary.grabArea.SetName("SelectionHandleOneGrabArea"); +#endif + primary.grabArea.SetResizePolicy( SIZE_RELATIVE_TO_PARENT, ALL_DIMENSIONS ); + primary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); + primary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); + + mTapDetector.Attach( primary.grabArea ); + mPanGestureDetector.Attach( primary.grabArea ); + primary.grabArea.TouchedSignal().Connect( this, &Decorator::Impl::OnHandleOneTouched ); + + primary.actor.Add( primary.grabArea ); + mActiveLayer.Add( primary.actor ); + } + + SelectionHandleImpl& secondary = mSelectionHandle[ SECONDARY_SELECTION_HANDLE ]; + if ( !secondary.actor ) + { + if ( !secondary.releasedImage ) + { + secondary.releasedImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO ); + } + + secondary.actor = ImageActor::New( secondary.releasedImage ); +#ifdef DECORATOR_DEBUG + secondary.actor.SetName("SelectionHandleTwo"); +#endif + secondary.actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); // Change to BOTTOM_LEFT if Look'n'Feel requires handle above text. + secondary.actor.SetDrawMode( DrawMode::OVERLAY ); // ensure grab handle above text + secondary.flipped = false; + + secondary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move + secondary.grabArea.SetRelayoutEnabled( true ); +#ifdef DECORATOR_DEBUG + secondary.grabArea.SetName("SelectionHandleTwoGrabArea"); +#endif + secondary.grabArea.SetResizePolicy( SIZE_RELATIVE_TO_PARENT, ALL_DIMENSIONS ); + secondary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); + secondary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); + + mTapDetector.Attach( secondary.grabArea ); + mPanGestureDetector.Attach( secondary.grabArea ); + secondary.grabArea.TouchedSignal().Connect( this, &Decorator::Impl::OnHandleTwoTouched ); + + secondary.actor.Add( secondary.grabArea ); + mActiveLayer.Add( secondary.actor ); + } + + //SetUpHandlePropertyNotifications(); TODO + } + + void CreateHighlight() + { + if ( !mHighlightMeshActor ) + { + mHighlightMaterial = Material::New( "HighlightMaterial" ); + mHighlightMaterial.SetDiffuseColor( mHighlightColor ); + + mHighlightMeshData.SetMaterial( mHighlightMaterial ); + mHighlightMeshData.SetHasNormals( true ); + + mHighlightMesh = Mesh::New( mHighlightMeshData ); + + mHighlightMeshActor = MeshActor::New( mHighlightMesh ); +#ifdef DECORATOR_DEBUG + mHighlightMeshActor.SetName( "HighlightMeshActor" ); +#endif + mHighlightMeshActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mHighlightMeshActor.SetPosition( 0.0f, 0.0f, DISPLAYED_HIGHLIGHT_Z_OFFSET ); + + Actor parent = mTextControlParent.Self(); + parent.Add( mHighlightMeshActor ); + } + } + + void UpdateHighlight() + { + // Construct a Mesh with a texture to be used as the highlight 'box' for selected text + // + // Example scenarios where mesh is made from 3, 1, 2, 2 ,3 or 3 quads. + // + // [ TOP ] [ TOP ] [TOP ] [ TOP ] [ TOP ] [ TOP ] + // [ MIDDLE ] [BOTTOM] [BOTTOM] [ MIDDLE ] [ MIDDLE ] + // [ BOTTOM] [ MIDDLE ] [ MIDDLE ] + // [BOTTOM] [ MIDDLE ] + // [BOTTOM] + // + // Each quad is created as 2 triangles. + // Middle is just 1 quad regardless of its size. + // + // (0,0) (0,0) + // 0* *2 0* *2 + // TOP TOP + // 3* *1 3* *1 + // 4* *1 4* *6 + // MIDDLE BOTTOM + // 6* *5 7* *5 + // 6* *8 + // BOTTOM + // 9* *7 + // + + if ( mHighlightMesh && mHighlightMaterial && !mHighlightQuadList.empty() ) + { + MeshData::VertexContainer vertices; + Dali::MeshData::FaceIndices faceIndices; + + std::vector::iterator iter = mHighlightQuadList.begin(); + std::vector::iterator endIter = mHighlightQuadList.end(); + + // vertex position defaults to (0 0 0) + MeshData::Vertex vertex; + // set normal for all vertices as (0 0 1) pointing outward from TextInput Actor. + vertex.nZ = 1.0f; + + for(std::size_t v = 0; iter != endIter; ++iter,v+=4 ) + { + // Add each quad geometry (a sub-selection) to the mesh data. + + // 0-----1 + // |\ | + // | \ A | + // | \ | + // | B \ | + // | \| + // 2-----3 + + QuadCoordinates& quad = *iter; + // top-left (v+0) + vertex.x = quad.min.x; + vertex.y = quad.min.y; + vertices.push_back( vertex ); + + // top-right (v+1) + vertex.x = quad.max.x; + vertex.y = quad.min.y; + vertices.push_back( vertex ); + + // bottom-left (v+2) + vertex.x = quad.min.x; + vertex.y = quad.max.y; + vertices.push_back( vertex ); + + // bottom-right (v+3) + vertex.x = quad.max.x; + vertex.y = quad.max.y; + vertices.push_back( vertex ); + + // triangle A (3, 1, 0) + faceIndices.push_back( v + 3 ); + faceIndices.push_back( v + 1 ); + faceIndices.push_back( v ); + + // triangle B (0, 2, 3) + faceIndices.push_back( v ); + faceIndices.push_back( v + 2 ); + faceIndices.push_back( v + 3 ); + + mHighlightMeshData.SetFaceIndices( faceIndices ); + } + + BoneContainer bones(0); // passed empty as bones not required + mHighlightMeshData.SetData( vertices, faceIndices, bones, mHighlightMaterial ); + mHighlightMesh.UpdateMeshData( mHighlightMeshData ); + } + } + + void OnTap( Actor actor, const TapGesture& tap ) + { + if( actor == mGrabHandle ) + { + // TODO + } + } + + void OnPan( Actor actor, const PanGesture& gesture ) + { + if( actor == mGrabArea ) + { + if( Gesture::Started == gesture.state ) + { + mGrabDisplacementX = mGrabDisplacementY = 0; + } + + mGrabDisplacementX += gesture.displacement.x; + mGrabDisplacementY += gesture.displacement.y; + + float x = mCursor[PRIMARY_CURSOR].x + mGrabDisplacementX; + float y = mCursor[PRIMARY_CURSOR].y + mCursor[PRIMARY_CURSOR].lineHeight*0.5f + mGrabDisplacementY; + + if( Gesture::Started == gesture.state || + Gesture::Continuing == gesture.state ) + { + mObserver.GrabHandleEvent( GRAB_HANDLE_PRESSED, x, y ); + } + else if( Gesture::Finished == gesture.state || + Gesture::Cancelled == gesture.state ) + { + mObserver.GrabHandleEvent( GRAB_HANDLE_RELEASED, x, y ); + } + } + } + + bool OnHandleOneTouched( Actor actor, const TouchEvent& touch ) + { + // TODO + return false; + } + + bool OnHandleTwoTouched( Actor actor, const TouchEvent& touch ) + { + // TODO + return false; + } + + + Internal::Control& mTextControlParent; + Observer& mObserver; + + Layer mActiveLayer; // Layer for active handles and alike that ensures they are above all else. + + unsigned int mActiveCursor; + bool mActiveGrabHandle; + bool mActiveSelection; + bool mActiveCopyPastePopup; + + CursorImpl mCursor[CURSOR_COUNT]; + + Timer mCursorBlinkTimer; // Timer to signal cursor to blink + unsigned int mCursorBlinkInterval; + float mCursorBlinkDuration; + bool mCursorBlinkStatus; // Flag to switch between blink on and blink off + + ImageActor mPrimaryCursor; + ImageActor mSecondaryCursor; + + ImageActor mGrabHandle; + Actor mGrabArea; + float mGrabDisplacementX; + float mGrabDisplacementY; + + SelectionHandleImpl mSelectionHandle[SELECTION_HANDLE_COUNT]; + + MeshActor mHighlightMeshActor; ///< Mesh Actor to display highlight + Mesh mHighlightMesh; ///< Mesh for highlight + MeshData mHighlightMeshData; ///< Mesh Data for highlight + Material mHighlightMaterial; ///< Material used for highlight + Vector4 mHighlightColor; ///< Color of the highlight + QuadContainer mHighlightQuadList; ///< Sub-selections that combine to create the complete selection highlight + + TextSelectionPopup mCopyPastePopup; + + Image mCursorImage; + Image mGrabHandleImage; + + TapGestureDetector mTapDetector; + PanGestureDetector mPanGestureDetector; + + Rect mBoundingBox; +}; + +DecoratorPtr Decorator::New( Internal::Control& parent, Observer& observer ) +{ + return DecoratorPtr( new Decorator(parent, observer) ); +} + +void Decorator::SetBoundingBox( const Rect& boundingBox ) +{ + mImpl->mBoundingBox = boundingBox; +} + +const Rect& Decorator::GetBoundingBox() const +{ + return mImpl->mBoundingBox; +} + +void Decorator::Relayout( const Vector2& size, const Vector2& scrollPosition ) +{ + mImpl->Relayout( size, scrollPosition ); +} + +/** Cursor **/ + +void Decorator::SetActiveCursor( ActiveCursor activeCursor ) +{ + mImpl->mActiveCursor = activeCursor; +} + +unsigned int Decorator::GetActiveCursor() const +{ + return mImpl->mActiveCursor; +} + +void Decorator::SetPosition( Cursor cursor, float x, float y, float cursorHeight, float lineHeight ) +{ + // Adjust grab handle displacement + mImpl->mGrabDisplacementX -= x - mImpl->mCursor[cursor].x; + mImpl->mGrabDisplacementY -= y - mImpl->mCursor[cursor].y; + + mImpl->mCursor[cursor].x = x; + mImpl->mCursor[cursor].y = y; + mImpl->mCursor[cursor].cursorHeight = cursorHeight; + mImpl->mCursor[cursor].lineHeight = lineHeight; +} + +void Decorator::GetPosition( Cursor cursor, float& x, float& y, float& cursorHeight, float& lineHeight ) const +{ + x = mImpl->mCursor[cursor].x; + y = mImpl->mCursor[cursor].y; + cursorHeight = mImpl->mCursor[cursor].cursorHeight; + lineHeight = mImpl->mCursor[cursor].lineHeight; +} + +void Decorator::SetColor( Cursor cursor, const Dali::Vector4& color ) +{ + mImpl->mCursor[cursor].color = color; +} + +const Dali::Vector4& Decorator::GetColor( Cursor cursor ) const +{ + return mImpl->mCursor[cursor].color; +} + +void Decorator::StartCursorBlink() +{ + if ( !mImpl->mCursorBlinkTimer ) + { + mImpl->mCursorBlinkTimer = Timer::New( mImpl->mCursorBlinkInterval ); + mImpl->mCursorBlinkTimer.TickSignal().Connect( mImpl, &Decorator::Impl::OnCursorBlinkTimerTick ); + } + + if ( !mImpl->mCursorBlinkTimer.IsRunning() ) + { + mImpl->mCursorBlinkTimer.Start(); + } +} + +void Decorator::StopCursorBlink() +{ + if ( mImpl->mCursorBlinkTimer ) + { + mImpl->mCursorBlinkTimer.Stop(); + } +} + +void Decorator::SetCursorBlinkInterval( float seconds ) +{ + mImpl->mCursorBlinkInterval = seconds*MILLISECONDS; // Convert to milliseconds +} + +float Decorator::GetCursorBlinkInterval() const +{ + return mImpl->mCursorBlinkInterval; +} + +void Decorator::SetCursorBlinkDuration( float seconds ) +{ + mImpl->mCursorBlinkDuration = seconds; +} + +float Decorator::GetCursorBlinkDuration() const +{ + return mImpl->mCursorBlinkDuration; +} + +/** GrabHandle **/ + +void Decorator::SetGrabHandleActive( bool active ) +{ + mImpl->mActiveGrabHandle = active; +} + +bool Decorator::IsGrabHandleActive() const +{ + return mImpl->mActiveGrabHandle; +} + +void Decorator::SetGrabHandleImage( Dali::Image image ) +{ + mImpl->mGrabHandleImage = image; +} + +Dali::Image Decorator::GetGrabHandleImage() const +{ + return mImpl->mGrabHandleImage; +} + +/** Selection **/ + +void Decorator::SetSelectionActive( bool active ) +{ + mImpl->mActiveSelection = active; +} + +bool Decorator::IsSelectionActive() const +{ + return mImpl->mActiveSelection; +} + +void Decorator::SetPosition( SelectionHandle handle, float x, float y, float height ) +{ + mImpl->mSelectionHandle[handle].x = x; + mImpl->mSelectionHandle[handle].y = y; + mImpl->mSelectionHandle[handle].lineHeight = height; +} + +void Decorator::GetPosition( SelectionHandle handle, float& x, float& y, float& height ) const +{ + x = mImpl->mSelectionHandle[handle].x; + y = mImpl->mSelectionHandle[handle].y; + height = mImpl->mSelectionHandle[handle].lineHeight; +} + +void Decorator::SetImage( SelectionHandle handle, SelectionHandleState state, Dali::Image image ) +{ + if( SELECTION_HANDLE_PRESSED == state ) + { + mImpl->mSelectionHandle[handle].pressedImage = image; + } + else + { + mImpl->mSelectionHandle[handle].releasedImage = image; + } +} + +Dali::Image Decorator::GetImage( SelectionHandle handle, SelectionHandleState state ) const +{ + if( SELECTION_HANDLE_PRESSED == state ) + { + return mImpl->mSelectionHandle[handle].pressedImage; + } + + return mImpl->mSelectionHandle[handle].releasedImage; +} + +void Decorator::AddHighlight( float x1, float y1, float x2, float y2 ) +{ + mImpl->mHighlightQuadList.push_back( QuadCoordinates(x1, y1, x2, y2) ); +} + +void Decorator::ClearHighlights() +{ + mImpl->mHighlightQuadList.clear(); +} + +void Decorator::SetPopupActive( bool active ) +{ + mImpl->mActiveCopyPastePopup = active; +} + +bool Decorator::IsPopupActive() const +{ + return mImpl->mActiveCopyPastePopup ; +} + +Decorator::~Decorator() +{ + delete mImpl; +} + +Decorator::Decorator( Dali::Toolkit::Internal::Control& parent, Observer& observer ) +: mImpl( NULL ) +{ + mImpl = new Decorator::Impl( parent, observer ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/decorator/text-decorator.h b/dali-toolkit/internal/text/decorator/text-decorator.h new file mode 100644 index 0000000..939c815 --- /dev/null +++ b/dali-toolkit/internal/text/decorator/text-decorator.h @@ -0,0 +1,408 @@ +#ifndef __DALI_TOOLKIT_TEXT_DECORATOR_H__ +#define __DALI_TOOLKIT_TEXT_DECORATOR_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +class Image; +class Vector2; +class Vector4; + +namespace Toolkit +{ + +namespace Internal +{ +class Control; +} + +namespace Text +{ + +class Decorator; +typedef IntrusivePtr DecoratorPtr; + +// Used to set the cursor positions etc. +enum Cursor +{ + PRIMARY_CURSOR, ///< The primary cursor for bidirectional text (or the regular cursor for single-direction text) + SECONDARY_CURSOR, ///< The secondary cursor for bidirectional text + CURSOR_COUNT +}; + +// Determines which of the cursors are active (if any). +enum ActiveCursor +{ + ACTIVE_CURSOR_NONE, ///< Neither primary nor secondary cursor are active + ACTIVE_CURSOR_PRIMARY, ///< Primary cursor is active (only) + ACTIVE_CURSOR_BOTH ///< Both primary and secondary cursor are active +}; + +// The state information for grab handle events +enum GrabHandleState +{ + GRAB_HANDLE_TAPPED, + GRAB_HANDLE_PRESSED, + GRAB_HANDLE_RELEASED +}; + +// The set the selection-handle positions etc. +enum SelectionHandle +{ + PRIMARY_SELECTION_HANDLE, + SECONDARY_SELECTION_HANDLE, + SELECTION_HANDLE_COUNT +}; + +enum SelectionHandleState +{ + SELECTION_HANDLE_PRESSED, + SELECTION_HANDLE_RELEASED +}; + +/** + * @brief A Text Decorator is used to display cursors, handles, selection highlights and pop-ups. + * + * The decorator is responsible for clipping decorations which are positioned outside of the parent area. + * + * The Popup decoration will be positioned either above the Grab handle or above the selection handles but if doing so + * would cause the Popup to exceed the Decoration Bounding Box ( see SetBoundingBox API ) the the Popup will be repositioned below the handle(s). + * + * Selection handles will be flipped around to ensure they do not exceed the Decoration Bounding Box. ( Stay visible ). + * + * Decorator components forward input events to a controller class through an observer interface. + * The controller is responsible for selecting which components are active. + */ +class Decorator : public RefObject +{ +public: + + class Observer + { + public: + + /** + * @brief Constructor. + */ + Observer() {}; + + /** + * @brief Virtual destructor. + */ + virtual ~Observer() {}; + + /** + * @brief An input event from the grab handle. + * + * @param[in] state The grab handle state. + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + */ + virtual void GrabHandleEvent( GrabHandleState state, float x, float y ) = 0; + }; + + /** + * @brief Create a new instance of a Decorator. + * + * @param[in] parent Decorations will be added to this parent control. + * @param[in] observer A class which receives input events from Decorator components. + * @return A pointer to a new Decorator. + */ + static DecoratorPtr New( Dali::Toolkit::Internal::Control& parent, Observer& observer ); + + /** + * @brief Set the bounding box which handles, popup and similar decorations will not exceed. + * + * The default value is the width and height of the stage from the top left origin. + * If a title bar for example is on the top of the screen then the y should be the title's height and + * the boundary height the stage height minus the title's height. + * Restrictions - The boundary box should be set up with a fixed z position for the text-input and the default camera. + * + * ------------------------------------------ + * |(x,y) | + * |o---------------------------------------| + * || || + * || Bounding Box || boundary height + * || || + * |----------------------------------------| + * ------------------------------------------ + * boundary width + * + * @param[in] boundingBox Vector( x coordinate, y coordinate, width, height ) + */ + void SetBoundingBox( const Rect& boundingBox ); + + /** + * @brief Retrieve the bounding box origin and dimensions. + * + * default is set once control is added to stage, before this the return vector will be Vector4:ZERO + * @return Rect the bounding box origin, width and height + */ + const Rect& GetBoundingBox() const; + + /** + * @brief The decorator waits until a relayout before creating actors etc. + * + * @param[in] size The size of the parent control after size-negotiation. + * @param[in] scrollPosition The cursor, grab-handle positions etc. should be offset by this. + */ + void Relayout( const Dali::Vector2& size, const Vector2& scrollPosition ); + + /** + * @brief Sets which of the cursors are active. + * + * @note Cursor will only be visible if within the parent area. + * @param[in] activeCursor Which of the cursors should be active (if any). + */ + void SetActiveCursor( ActiveCursor activeCursor ); + + /** + * @brief Query which of the cursors are active. + * + * @return Which of the cursors are active (if any). + */ + unsigned int GetActiveCursor() const; + + /** + * @brief Sets the position of a cursor. + * + * @param[in] cursor The cursor to set. + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + * @param[in] cursorHeight The logical height of the cursor. + * @param[in] lineHeight The logical height of the line. + */ + void SetPosition( Cursor cursor, float x, float y, float cursorHeight, float lineHeight ); + + /** + * @brief Retrieves the position of a cursor. + * + * @param[in] cursor The cursor to get. + * @param[out] x The x position relative to the top-left of the parent control. + * @param[out] y The y position relative to the top-left of the parent control. + * @param[out] cursorHeight The logical height of the cursor. + * @param[out] lineHeight The logical height of the line. + */ + void GetPosition( Cursor cursor, float& x, float& y, float& cursorHeight, float& lineHeight ) const; + + /** + * @brief Sets the color for a cursor. + * + * @param[in] cursor Whether this color is for the primary or secondary cursor. + * @param[in] color The color to use. + */ + void SetColor( Cursor cursor, const Dali::Vector4& color ); + + /** + * @brief Retrieves the color for a cursor. + * + * @param[in] cursor Whether this color is for the primary or secondary cursor. + * @return The cursor color. + */ + const Dali::Vector4& GetColor( Cursor cursor ) const; + + /** + * @brief Start blinking the cursor; see also SetCursorBlinkDuration(). + */ + void StartCursorBlink(); + + /** + * @brief Stop blinking the cursor. + */ + void StopCursorBlink(); + + /** + * @brief Set the interval between cursor blinks. + * + * @param[in] seconds The interval in seconds. + */ + void SetCursorBlinkInterval( float seconds ); + + /** + * @brief Retrieves the blink-interval for a cursor. + * + * @return The cursor blink-interval. + */ + float GetCursorBlinkInterval() const; + + /** + * @brief The cursor will stop blinking after this duration. + * + * @param[in] seconds The duration in seconds. + */ + void SetCursorBlinkDuration( float seconds ); + + /** + * @brief Retrieves the blink-duration for a cursor. + * + * @return The cursor blink-duration. + */ + float GetCursorBlinkDuration() const; + + /** + * @brief Sets whether the grab handle is active. + * + * @note The grab handle follows the cursor position set with SetPosition(Cursor, ...) + * @param[in] active True if the grab handle should be active. + */ + void SetGrabHandleActive( bool active ); + + /** + * @brief Query whether the grab handle is active. + * + * @return True if the grab handle should be active. + */ + bool IsGrabHandleActive() const; + + /** + * @brief Sets the image for the grab handle. + * + * @param[in] image The image to use. + */ + void SetGrabHandleImage( Dali::Image image ); + + /** + * @brief Retrieves the image for the grab handle. + * + * @return The grab handle image. + */ + Dali::Image GetGrabHandleImage() const; + + /** + * @brief Sets whether the selection handles and highlight are active. + * + * @param[in] active True if the selection handles and highlight are active. + */ + void SetSelectionActive( bool active ); + + /** + * @brief Query whether the selection handles and highlight are active. + * + * @return True if the selection handles and highlight are active. + */ + bool IsSelectionActive() const; + + /** + * @brief Sets the position of a selection handle. + * + * @param[in] handle The handle to set. + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + * @param[in] lineHeight The logical line height at this position. + */ + void SetPosition( SelectionHandle handle, float x, float y, float lineHeight ); + + /** + * @brief Retrieves the position of a selection handle. + * + * @param[in] handle The handle to get. + * @param[out] x The x position relative to the top-left of the parent control. + * @param[out] y The y position relative to the top-left of the parent control. + * @param[out] cursorHeight The logical cursor height at this position. + */ + void GetPosition( SelectionHandle handle, float& x, float& y, float& cursorHeight ) const; + + /** + * @brief Sets the image for one of the selection handles. + * + * @param[in] handle The selection handle. + * @param[in] state A different image can be set for the pressed/released states. + * @param[in] image The image to use. + */ + void SetImage( SelectionHandle handle, SelectionHandleState state, Dali::Image image ); + + /** + * @brief Retrieves the image for a selection handle. + * + * @param[in] handle The selection handle. + * @param[in] state A different image can be set for the pressed/released states. + * @return The image. + */ + Dali::Image GetImage( SelectionHandle handle, SelectionHandleState state ) const; + + /** + * @brief Adds a quad to the existing selection highlights. + * + * @param[in] x1 The top-left x position. + * @param[in] y1 The top-left y position. + * @param[in] x2 The bottom-right x position. + * @param[in] y3 The bottom-right y position. + */ + void AddHighlight( float x1, float y1, float x2, float y2 ); + + /** + * @brief Removes all of the previously added highlights. + */ + void ClearHighlights(); + + /** + * @brief Set the Selection Popup to show or hide via the active flaf + * @param[in] active true to show, false to hide + */ + void SetPopupActive( bool active ); + + /** + * @brief Query whether the Selection Popup is active. + * + * @return True if the Selection Popup should be active. + */ + bool IsPopupActive() const; + + +protected: + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~Decorator(); + +private: + + /** + * @brief Private constructor. + * @param[in] parent Decorations will be added to this parent control. + * @param[in] observer A class which receives input events from Decorator components. + */ + Decorator(Dali::Toolkit::Internal::Control& parent, Observer& observer ); + + // Undefined + Decorator( const Decorator& handle ); + + // Undefined + Decorator& operator=( const Decorator& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_DECORATOR_H__ diff --git a/dali-toolkit/internal/text/font-run.h b/dali-toolkit/internal/text/font-run.h new file mode 100644 index 0000000..2a9680a --- /dev/null +++ b/dali-toolkit/internal/text/font-run.h @@ -0,0 +1,49 @@ +#ifndef __DALI_TOOLKIT_TEXT_FONT_RUN_H__ +#define __DALI_TOOLKIT_TEXT_FONT_RUN_H__ + +/* + * Copyright (c) 2015 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 Run of characters with the same font. + */ +struct FontRun +{ + CharacterRun characterRun; ///< The initial character index and the number of characters of the run. + FontId fontId; ///< Font id of the run. + bool isDefault; ///< Whether the font is a default font not defined by the user. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_FONT_RUN_H__ diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp new file mode 100644 index 0000000..1a97dd4 --- /dev/null +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -0,0 +1,715 @@ +/* + * Copyright (c) 2015 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 + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace +{ + +const float MAX_FLOAT = std::numeric_limits::max(); + +} //namespace + +/** + * @brief Stores temporary layout info of the line. + */ +struct LineLayout +{ + GlyphIndex glyphIndex; ///< Index of the first glyph to be laid-out. + CharacterIndex characterIndex; ///< Index of the first character to be laid-out. + Length numberOfCharacters; ///< The number of characters which fit in one line. + Length numberOfGlyphs; ///< The number of glyph which fit in one line. + float length; ///< The length of the glyphs which fit in one line. + float widthAdvanceDiff; ///< The difference between the width and the advance of the last glyph. + float wsLengthEndOfLine; ///< The length of the white spaces at the end of the line. + float ascender; ///< The maximum ascender of all fonts in the line. + float descender; ///< The minimum descender of all fonts in the line. +}; + +struct LayoutEngine::Impl +{ + Impl() + : mLayout( LayoutEngine::SINGLE_LINE_BOX ), + mHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ), + mVerticalAlignment( LayoutEngine::VERTICAL_ALIGN_TOP ) + { + mFontClient = TextAbstraction::FontClient::Get(); + } + + /** + * Retrieves the line layout for a given box width. + */ + void GetLineLayoutForBox( const LayoutParameters& parameters, + LineLayout& lineLayout ) + { + // Initializes the line layout. + lineLayout.numberOfCharacters = 0u; + lineLayout.numberOfGlyphs = 0u; + lineLayout.length = 0.f; + lineLayout.wsLengthEndOfLine = 0.f; + lineLayout.ascender = 0.f; + lineLayout.descender = MAX_FLOAT; + + // Get the last glyph index. + const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u; + + FontId lastFontId = 0u; + for( GlyphIndex glyphIndex = lineLayout.glyphIndex; + glyphIndex < parameters.totalNumberOfGlyphs; + ++glyphIndex ) + { + // Get the glyph info. + const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex ); + + // Check whether is a white space. + const Character character = *( parameters.textBuffer + lineLayout.numberOfCharacters ); + const bool isWhiteSpace = TextAbstraction::IsWhiteSpace( character ); + + // Get the character indices for the current glyph. The last character index is needed + // because there are glyphs formed by more than one character but their break info is + // given only for the last character. + const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex ); + + // Increase the number of characters. + lineLayout.numberOfCharacters += charactersPerGlyph; + + // Increase the number of glyphs. + lineLayout.numberOfGlyphs++; + + // Increase the accumulated length. + const float glyphLength = ( glyphIndex == lastGlyphIndex ) ? glyphInfo.width : glyphInfo.advance; + + if( isWhiteSpace ) + { + // Add the length to the length of white spaces at the end of the line. + lineLayout.wsLengthEndOfLine += glyphLength; + } + else + { + // Add as well any previous white space length. + lineLayout.length += lineLayout.wsLengthEndOfLine + glyphLength; + + // Clear the white space length at the end of the line. + lineLayout.wsLengthEndOfLine = 0.f; + } + + if( lastFontId != glyphInfo.fontId ) + { + Text::FontMetrics fontMetrics; + mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics ); + + // Sets the maximum ascender. + if( fontMetrics.ascender > lineLayout.ascender ) + { + lineLayout.ascender = fontMetrics.ascender; + } + + // Sets the minimum descender. + if( fontMetrics.descender < lineLayout.descender ) + { + lineLayout.descender = fontMetrics.descender; + } + + lastFontId = glyphInfo.fontId; + } + } + } + + /** + * Retrieves the line layout for a given box width. + */ + void GetMultiLineLayoutForBox( const LayoutParameters& parameters, + LineLayout& lineLayout ) + { + // Initializes the line layout. + lineLayout.numberOfCharacters = 0u; + lineLayout.numberOfGlyphs = 0u; + lineLayout.length = 0.f; + lineLayout.widthAdvanceDiff = 0.f; + lineLayout.wsLengthEndOfLine = 0.f; + lineLayout.ascender = 0.f; + lineLayout.descender = MAX_FLOAT; + + // Stores temporary line layout which has not been added to the final line layout. + LineLayout tmpLineLayout; + tmpLineLayout.numberOfCharacters = 0u; + tmpLineLayout.numberOfGlyphs = 0u; + tmpLineLayout.length = 0.f; + tmpLineLayout.widthAdvanceDiff = 0.f; + tmpLineLayout.wsLengthEndOfLine = 0.f; + tmpLineLayout.ascender = 0.f; + tmpLineLayout.descender = MAX_FLOAT; + + FontId lastFontId = 0u; + for( GlyphIndex glyphIndex = lineLayout.glyphIndex; + glyphIndex < parameters.totalNumberOfGlyphs; + ++glyphIndex ) + { + // Get the glyph info. + const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex ); + + // Get the character indices for the current glyph. The last character index is needed + // because there are glyphs formed by more than one character but their break info is + // given only for the last character. + const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex ); + const CharacterIndex characterFirstIndex = *( parameters.glyphsToCharactersBuffer + glyphIndex ); + const CharacterIndex characterLastIndex = characterFirstIndex + ( ( 1u > charactersPerGlyph ) ? 0u : charactersPerGlyph - 1u ); + + // Get the line break info for the current character. + const LineBreakInfo lineBreakInfo = *( parameters.lineBreakInfoBuffer + characterLastIndex ); + + // Get the word break info for the current character. + const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex ); + + // Increase the number of characters. + tmpLineLayout.numberOfCharacters += charactersPerGlyph; + + // Increase the number of glyphs. + tmpLineLayout.numberOfGlyphs++; + + // Check whether is a white space. + const Character character = *( parameters.textBuffer + characterFirstIndex ); + const bool isWhiteSpace = TextAbstraction::IsWhiteSpace( character ); + + // Increase the accumulated length. + if( isWhiteSpace ) + { + // Add the length to the length of white spaces at the end of the line. + tmpLineLayout.wsLengthEndOfLine += glyphInfo.advance; // I use the advance as the width is always zero for the white spaces. + tmpLineLayout.widthAdvanceDiff = 0.f; + } + else + { + // Add as well any previous white space length. + tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphInfo.advance; + tmpLineLayout.widthAdvanceDiff = glyphInfo.width - glyphInfo.advance; + + // Clear the white space length at the end of the line. + tmpLineLayout.wsLengthEndOfLine = 0.f; + } + + // Check if the accumulated length fits in the width of the box. + if( lineLayout.length + tmpLineLayout.length + tmpLineLayout.widthAdvanceDiff + ( ( 0.f < tmpLineLayout.length ) ? lineLayout.wsLengthEndOfLine : 0.f ) > parameters.boundingBox.width ) + { + // Current word does not fit in the box's width. + return; + } + + if( TextAbstraction::LINE_MUST_BREAK == lineBreakInfo ) + { + // Must break the line. Update the line layout and return. + lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters; + lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs; + lineLayout.length += tmpLineLayout.length; + lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff; + + if( 0.f < tmpLineLayout.length ) + { + lineLayout.length += lineLayout.wsLengthEndOfLine; + + lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine; + } + else + { + lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine; + } + + if( tmpLineLayout.ascender > lineLayout.ascender ) + { + lineLayout.ascender = tmpLineLayout.ascender; + } + + if( tmpLineLayout.descender < lineLayout.descender ) + { + lineLayout.descender = tmpLineLayout.descender; + } + + tmpLineLayout.numberOfCharacters = 0u; + tmpLineLayout.numberOfGlyphs = 0u; + tmpLineLayout.length = 0u; + tmpLineLayout.widthAdvanceDiff = 0u; + tmpLineLayout.wsLengthEndOfLine = 0u; + tmpLineLayout.ascender = 0.f; + tmpLineLayout.descender = MAX_FLOAT; + return; + } + + if( TextAbstraction::WORD_BREAK == wordBreakInfo ) + { + // Current glyph is the last one of the current word. + // Add the temporal layout to the current one. + lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters; + lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs; + lineLayout.length += tmpLineLayout.length; + lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff; + + if( 0.f < tmpLineLayout.length ) + { + lineLayout.length += lineLayout.wsLengthEndOfLine; + + lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine; + } + else + { + lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine; + } + + if( tmpLineLayout.ascender > lineLayout.ascender ) + { + lineLayout.ascender = tmpLineLayout.ascender; + } + + if( tmpLineLayout.descender < lineLayout.descender ) + { + lineLayout.descender = tmpLineLayout.descender; + } + + tmpLineLayout.numberOfCharacters = 0u; + tmpLineLayout.numberOfGlyphs = 0u; + tmpLineLayout.length = 0u; + tmpLineLayout.widthAdvanceDiff = 0u; + tmpLineLayout.wsLengthEndOfLine = 0u; + tmpLineLayout.ascender = 0.f; + tmpLineLayout.descender = MAX_FLOAT; + } + + if( lastFontId != glyphInfo.fontId ) + { + Text::FontMetrics fontMetrics; + mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics ); + + // Sets the maximum ascender. + if( fontMetrics.ascender > tmpLineLayout.ascender ) + { + tmpLineLayout.ascender = fontMetrics.ascender; + } + + // Sets the minimum descender. + if( -fontMetrics.descender < tmpLineLayout.descender ) + { + tmpLineLayout.descender = fontMetrics.descender; + } + + lastFontId = glyphInfo.fontId; + } + } + } + + bool LayoutText( const LayoutParameters& layoutParameters, + Vector& glyphPositions, + Vector& lines, + Size& actualSize ) + { + // TODO Switch between different layouts + bool update = false; + + switch( mLayout ) + { + case LayoutEngine::SINGLE_LINE_BOX: + { + update = SingleLineLayout( layoutParameters, + glyphPositions, + lines, + actualSize ); + break; + } + case LayoutEngine::MULTI_LINE_BOX: + { + update = MultiLineLayout( layoutParameters, + glyphPositions, + lines, + actualSize ); + break; + } + default: + break; + } + + return update; + } + + void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + Vector& glyphPositions ) + { + // Traverses the paragraphs with right to left characters. + for( LineIndex lineIndex = 0u; lineIndex < layoutParameters.numberOfBidirectionalInfoRuns; ++lineIndex ) + { + const BidirectionalLineInfoRun& bidiLine = *( layoutParameters.lineBidirectionalInfoRunsBuffer + lineIndex ); + + float penX = 0.f; + + Vector2* glyphPositionsBuffer = glyphPositions.Begin(); + + // Traverses the characters of the right to left paragraph. + for( CharacterIndex characterLogicalIndex = 0u; + characterLogicalIndex < bidiLine.characterRun.numberOfCharacters; + ++characterLogicalIndex ) + { + // Convert the character in the logical order into the character in the visual order. + const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *( bidiLine.visualToLogicalMap + characterLogicalIndex ); + + // Get the number of glyphs of the character. + const Length numberOfGlyphs = *( layoutParameters.glyphsPerCharacterBuffer + characterVisualIndex ); + + for( GlyphIndex index = 0u; index < numberOfGlyphs; ++index ) + { + // Convert the character in the visual order into the glyph in the visual order. + const GlyphIndex glyphIndex = *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) + index; + + DALI_ASSERT_DEBUG( 0u <= glyphIndex && glyphIndex < layoutParameters.totalNumberOfGlyphs ); + + const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + glyphIndex ); + Vector2& position = *( glyphPositionsBuffer + glyphIndex ); + + position.x = penX + glyph.xBearing; + penX += glyph.advance; + } + } + } + } + + void Align( const LayoutParameters& layoutParameters, + const Size& layoutSize, + const Vector& lines, + Vector& glyphPositions ) + { + Vector2* glyphPositionsBuffer = glyphPositions.Begin(); + + // Traverse all lines and align the glyphs. + // LayoutParameters contains bidirectional info for those lines with + // right to left text, this info includes the paragraph's direction. + + LineIndex bidiLineIndex = 0u; + for( Vector::ConstIterator it = lines.Begin(), endIt = lines.End(); + it != endIt; + ++it ) + { + const LineRun& line = *it; + + // 1) Get the paragrap's direction. + bool paragraphDirection = false; + + // Check if there is any right to left line. + if( ( NULL != layoutParameters.lineBidirectionalInfoRunsBuffer ) && + ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) ) + { + const BidirectionalLineInfoRun* bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex; + + // Get the right to left line that match with current line. + while( ( line.characterRun.characterIndex > bidiLine->characterRun.characterIndex ) && + ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) ) + { + ++bidiLineIndex; + bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex; + } + + if( line.characterRun.characterIndex == bidiLine->characterRun.characterIndex ) + { + paragraphDirection = bidiLine->direction; + } + } + + // 2) Calculate the alignment offset accordingly with the align option, + // the box width, line length, and the paragraphs direction. + float alignOffset = CalculateHorizontalAlignment( layoutSize.width, + line.width, + line.extraLength, + paragraphDirection ); + + // 3) Traverse all glyphs and update the 'x' position. + for( GlyphIndex index = line.glyphIndex, + endIndex = line.glyphIndex + line.numberOfGlyphs; + index < endIndex; + ++index ) + { + Vector2& position = *( glyphPositionsBuffer + index ); + + position.x += alignOffset; + } + } + } + + bool SingleLineLayout( const LayoutParameters& layoutParameters, + Vector& glyphPositions, + Vector& lines, + Size& actualSize ) + { + LineLayout layout; + layout.glyphIndex = 0u; + GetLineLayoutForBox( layoutParameters, + layout ); + + // Create a line run and add it to the lines. + const GlyphIndex lastGlyphIndex = layoutParameters.totalNumberOfGlyphs - 1u; + + LineRun lineRun; + lineRun.glyphIndex = 0u; + lineRun.numberOfGlyphs = layoutParameters.totalNumberOfGlyphs; + lineRun.characterRun.characterIndex = 0u; + lineRun.characterRun.numberOfCharacters = *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex ); + lineRun.width = layout.length; + lineRun.ascender = layout.ascender; + lineRun.descender = layout.descender; + lineRun.extraLength = layout.wsLengthEndOfLine; + lineRun.direction = false; + + lines.PushBack( lineRun ); + + // Update the actual size. + actualSize.width = layout.length; + actualSize.height = lineRun.ascender + -lineRun.descender; + + float penX = 0.f; + float penY = layout.ascender; + + Vector2* glyphPositionsBuffer = glyphPositions.Begin(); + for( GlyphIndex glyphIndex = 0u; glyphIndex < layout.numberOfGlyphs; ++glyphIndex ) + { + const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + glyphIndex ); + Vector2& position = *( glyphPositionsBuffer + glyphIndex ); + + position.x = penX + glyph.xBearing; + position.y = penY - glyph.yBearing; + + penX += glyph.advance; + } + + return true; + } + + bool MultiLineLayout( const LayoutParameters& layoutParameters, + Vector& glyphPositions, + Vector& lines, + Size& actualSize ) + { + float penY = 0.f; + for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; ) + { + float penX = 0.f; + + // Get the layout for the line. + LineLayout layout; + layout.glyphIndex = index; + GetMultiLineLayoutForBox( layoutParameters, + layout ); + + if( 0u == layout.numberOfGlyphs ) + { + // The width is too small and no characters are laid-out. + return false; + } + + // Create a line run and add it to the lines. + const GlyphIndex lastGlyphIndex = index + layout.numberOfGlyphs - 1u; + + LineRun lineRun; + lineRun.glyphIndex = index; + lineRun.numberOfGlyphs = layout.numberOfGlyphs; + lineRun.characterRun.characterIndex = *( layoutParameters.glyphsToCharactersBuffer + index ); + lineRun.characterRun.numberOfCharacters = ( *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex ) ) - lineRun.characterRun.characterIndex; + lineRun.width = layout.length + ( ( layout.widthAdvanceDiff > 0.f ) ? layout.widthAdvanceDiff : 0.f ); + lineRun.ascender = layout.ascender; + lineRun.descender = layout.descender; + lineRun.extraLength = layout.wsLengthEndOfLine; + lineRun.direction = false; + + lines.PushBack( lineRun ); + + // Update the actual size. + if( layout.length + layout.widthAdvanceDiff > actualSize.width ) + { + actualSize.width = layout.length; + } + + actualSize.height += ( lineRun.ascender + -lineRun.descender ); + + // Traverse the glyphs and set the positions. + + penY += layout.ascender; + + Vector2* glyphPositionsBuffer = glyphPositions.Begin(); + for( GlyphIndex i = index; i < index + layout.numberOfGlyphs; ++i ) + { + const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + i ); + Vector2& position = *( glyphPositionsBuffer + i ); + + position.x = penX + glyph.xBearing; + position.y = penY - glyph.yBearing; + + penX += glyph.advance; + } + + penY += -layout.descender; + + // Increase the glyph index. + index += layout.numberOfGlyphs; + } + + return true; + } + + float CalculateHorizontalAlignment( float boxWidth, + float lineLength, + float extraLength, + bool paragraphDirection ) + { + float offset = 0.f; + + HorizontalAlignment alignment = mHorizontalAlignment; + if( paragraphDirection && + ( HORIZONTAL_ALIGN_CENTER != alignment ) ) + { + if( HORIZONTAL_ALIGN_BEGIN == alignment ) + { + alignment = HORIZONTAL_ALIGN_END; + } + else + { + alignment = HORIZONTAL_ALIGN_BEGIN; + } + } + + switch( alignment ) + { + case HORIZONTAL_ALIGN_BEGIN: + { + offset = 0.f; + break; + } + case HORIZONTAL_ALIGN_CENTER: + { + offset = 0.5f * ( boxWidth - lineLength ); + const int intOffset = static_cast( offset ); // try to avoid pixel alignment. + offset = static_cast( intOffset ); + break; + } + case HORIZONTAL_ALIGN_END: + { + offset = boxWidth - lineLength; + break; + } + } + + if( paragraphDirection ) + { + offset -= extraLength; + } + + return offset; + } + + LayoutEngine::Layout mLayout; + LayoutEngine::HorizontalAlignment mHorizontalAlignment; + LayoutEngine::VerticalAlignment mVerticalAlignment; + + TextAbstraction::FontClient mFontClient; +}; + +LayoutEngine::LayoutEngine() +: mImpl( NULL ) +{ + mImpl = new LayoutEngine::Impl(); +} + +LayoutEngine::~LayoutEngine() +{ + delete mImpl; +} + +void LayoutEngine::SetLayout( Layout layout ) +{ + mImpl->mLayout = layout; +} + +unsigned int LayoutEngine::GetLayout() const +{ + return mImpl->mLayout; +} + +void LayoutEngine::SetHorizontalAlignment( HorizontalAlignment alignment ) +{ + mImpl->mHorizontalAlignment = alignment; +} + +LayoutEngine::HorizontalAlignment LayoutEngine::GetHorizontalAlignment() const +{ + return mImpl->mHorizontalAlignment; +} + +void LayoutEngine::SetVerticalAlignment( VerticalAlignment alignment ) +{ + mImpl->mVerticalAlignment = alignment; +} + +LayoutEngine::VerticalAlignment LayoutEngine::GetVerticalAlignment() const +{ + return mImpl->mVerticalAlignment; +} + +bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters, + Vector& glyphPositions, + Vector& lines, + Size& actualSize ) +{ + return mImpl->LayoutText( layoutParameters, + glyphPositions, + lines, + actualSize ); +} + +void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + Vector& glyphPositions ) +{ + mImpl->ReLayoutRightToLeftLines( layoutParameters, + glyphPositions ); +} + +void LayoutEngine::Align( const LayoutParameters& layoutParameters, + const Size& layoutSize, + const Vector& lines, + Vector& glyphPositions ) +{ + mImpl->Align( layoutParameters, + layoutSize, + lines, + glyphPositions ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/layouts/layout-engine.h b/dali-toolkit/internal/text/layouts/layout-engine.h new file mode 100644 index 0000000..0c17d68 --- /dev/null +++ b/dali-toolkit/internal/text/layouts/layout-engine.h @@ -0,0 +1,178 @@ +#ifndef __DALI_TOOLKIT_TEXT_LAYOUT_ENGINE_H__ +#define __DALI_TOOLKIT_TEXT_LAYOUT_ENGINE_H__ + +/* + * Copyright (c) 2015 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 INCLUDE +#include +#include + +// INTERNAL INCLUDE +#include + +namespace Dali +{ + +struct Vector2; + +namespace Toolkit +{ + +namespace Text +{ + +struct LayoutParameters; + +/** + * @brief LayoutEngine is responsible for calculating the visual position of glyphs in layout. + */ +class LayoutEngine +{ +public: + + enum Layout + { + SINGLE_LINE_BOX, + MULTI_LINE_BOX + }; + + enum HorizontalAlignment + { + HORIZONTAL_ALIGN_BEGIN, + HORIZONTAL_ALIGN_CENTER, + HORIZONTAL_ALIGN_END + }; + + enum VerticalAlignment + { + VERTICAL_ALIGN_TOP, + VERTICAL_ALIGN_CENTER, + VERTICAL_ALIGN_BOTTOM + }; + + /** + * @brief Create a new instance of a LayoutEngine. + */ + LayoutEngine(); + + /** + * @brief Virtual destructor. + */ + ~LayoutEngine(); + + /** + * @brief Choose the required layout. + * + * @param[in] layout The required layout. + */ + void SetLayout( Layout layout ); + + /** + * @brief Query the required layout. + * + * @return The required layout. + */ + unsigned int GetLayout() const; + + /** + * @brief Choose the required text horizontal alignment. + * + * @param[in] alignment The required alignment. + */ + void SetHorizontalAlignment( HorizontalAlignment alignment ); + + /** + * @brief Query the required text horizontal alignment. + * + * @return The required alignment. + */ + HorizontalAlignment GetHorizontalAlignment() const; + + /** + * @brief Choose the required text vertical alignment. + * + * @param[in] alignment The required alignment. + */ + void SetVerticalAlignment( VerticalAlignment alignment ); + + /** + * @brief Query the required text vertical alignment. + * + * @return The required alignment. + */ + VerticalAlignment GetVerticalAlignment() const; + + /** + * @brief Store the visual position of glyphs in the VisualModel. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[out] glyphPositions The positions of all the glyphs. + * @param[out] lines The laid-out lines. + * @param[out] actualSize The size of the text after it has been laid-out. + * + * @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character. + */ + bool LayoutText( const LayoutParameters& layoutParameters, + Vector& glyphPositions, + Vector& lines, + Size& actualSize ); + + /** + * @brief Re-lays out those lines with right to left characters. + * + * It doesn't change the phisical position of the glyphs in the model but sets their new position. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in,out] glyphPositions The positions of all the glyphs. + */ + void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + Vector& glyphPositions ); + + /** + * @brief Aligns the laid out lines. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in] layoutSize The size of the laid out the text. + * @param[in] lines The laid-out lines. + * @param[in,out] glyphPositions The positions of all the glyphs. + */ + void Align( const LayoutParameters& layoutParameters, + const Size& layoutSize, + const Vector& lines, + Vector& glyphPositions ); + +private: + + // Undefined + LayoutEngine( const LayoutEngine& handle ); + + // Undefined + LayoutEngine& operator=( const LayoutEngine& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LAYOUT_ENGINE_H__ diff --git a/dali-toolkit/internal/text/layouts/layout-parameters.h b/dali-toolkit/internal/text/layouts/layout-parameters.h new file mode 100644 index 0000000..a370c02 --- /dev/null +++ b/dali-toolkit/internal/text/layouts/layout-parameters.h @@ -0,0 +1,97 @@ +#ifndef __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_H__ +#define __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_H__ + +/* + * Copyright (c) 2015 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 Toolkit +{ + +namespace Text +{ + +struct BidirectionalLineInfoRun; + +/** + * @brief Struct used to pass parameters. + */ +struct LayoutParameters +{ + /** + * Constructor with the needed parameters to layout the text. + * + * @param[in] boundingBox The size of the box containing the text. + * @param[in] textBuffer The text buffer. + * @param[in] lineBreakInfoBuffer The line break info. + * @param[in] wordBreakInfoBuffer The word break info. + * @param[in] totalNumberOfGlyphs The number of glyphs. + * @param[in] glyphsBuffer A vector with glyphs. + * @param[in] glyphsToCharactersBuffer Vector with indices pointing the first character of each glyph. + * @param[in] charactersPerGlyphBuffer Vector with the number of characters that forms each glyph. + */ + LayoutParameters( const Vector2& boundingBox, + const Character* const textBuffer, + const LineBreakInfo* const lineBreakInfoBuffer, + const WordBreakInfo* const wordBreakInfoBuffer, + Length totalNumberOfGlyphs, + const GlyphInfo* const glyphsBuffer, + const CharacterIndex* const glyphsToCharactersBuffer, + const Length* const charactersPerGlyphBuffer ) + : boundingBox( boundingBox ), + textBuffer( textBuffer ), + lineBreakInfoBuffer( lineBreakInfoBuffer ), + wordBreakInfoBuffer( wordBreakInfoBuffer ), + totalNumberOfGlyphs( totalNumberOfGlyphs ), + glyphsBuffer( glyphsBuffer ), + glyphsToCharactersBuffer( glyphsToCharactersBuffer ), + charactersPerGlyphBuffer( charactersPerGlyphBuffer ), + charactersToGlyphsBuffer( NULL ), + glyphsPerCharacterBuffer( NULL ), + lineBidirectionalInfoRunsBuffer( NULL ), + numberOfBidirectionalInfoRuns( 0u ) + {} + + Vector2 boundingBox; + const Character* const textBuffer; + const LineBreakInfo* const lineBreakInfoBuffer; + const WordBreakInfo* const wordBreakInfoBuffer; + Length totalNumberOfGlyphs; + const GlyphInfo* const glyphsBuffer; + const CharacterIndex* const glyphsToCharactersBuffer; + const Length* const charactersPerGlyphBuffer; + GlyphIndex* charactersToGlyphsBuffer; ///< The character to glyph conversion table. + Length* glyphsPerCharacterBuffer; ///< The number of glyphs per character. + BidirectionalLineInfoRun* lineBidirectionalInfoRunsBuffer; ///< Bidirectional conversion tables per line. + Length numberOfBidirectionalInfoRuns; ///< The number of lines with bidirectional info. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_H__ diff --git a/dali-toolkit/internal/text/line-run.h b/dali-toolkit/internal/text/line-run.h new file mode 100644 index 0000000..a71dc0f --- /dev/null +++ b/dali-toolkit/internal/text/line-run.h @@ -0,0 +1,57 @@ +#ifndef __DALI_TOOLKIT_TEXT_LINE_RUN_H__ +#define __DALI_TOOLKIT_TEXT_LINE_RUN_H__ + +/* + * Copyright (c) 2015 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 Toolkit +{ + +namespace Text +{ + +/** + * @brief LineRun + */ +struct LineRun +{ + GlyphIndex glyphIndex; ///< The initial glyph index. + Length numberOfGlyphs; ///< The number of glyphs of the run. + CharacterRun characterRun; ///< The initial character and the number of characters. + float width; ///< The line's width. + float ascender; ///< The line's ascender. + float descender; ///< The line's descender. + float extraLength; ///< The length of the white spaces at the end of the line. + CharacterDirection direction; ///< Direction of the first character of the paragraph. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LINE_RUN_H__ diff --git a/dali-toolkit/internal/text/logical-model-impl.cpp b/dali-toolkit/internal/text/logical-model-impl.cpp new file mode 100644 index 0000000..5a43e35 --- /dev/null +++ b/dali-toolkit/internal/text/logical-model-impl.cpp @@ -0,0 +1,657 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +LogicalModelPtr LogicalModel::New() +{ + return LogicalModelPtr( new LogicalModel() ); +} + +void LogicalModel::SetText( const Character* const text, + Length numberOfCharacters ) +{ + if( 0u == numberOfCharacters ) + { + mText.Clear(); + } + else + { + mText.Resize( numberOfCharacters ); + memcpy( mText.Begin(), text, numberOfCharacters * sizeof( Character ) ); + } +} + +Length LogicalModel::GetNumberOfCharacters() const +{ + return mText.Count(); +} + +void LogicalModel::GetText( Character* text, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( text, mText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) ); +} + +Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const +{ + return mText[characterIndex]; +} + +void LogicalModel::ReplaceText( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const Character* const text, + Length numberOfCharactersToInsert ) +{ +} + +void LogicalModel::SetScripts( const ScriptRun* const scripts, + Length numberOfRuns ) +{ + if( 0u == numberOfRuns ) + { + mScriptRuns.Clear(); + } + else + { + mScriptRuns.Resize( numberOfRuns ); + memcpy( mScriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) ); + } +} + +void LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + ScriptRunIndex& firstScriptRun, + Length& numberOfScriptRuns ) const +{ + // Initialize the number of scripts and the index to the first script. + firstScriptRun = 0u; + numberOfScriptRuns = 0; + bool firstScriptFound = false; + + const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters; + + // Traverse the scripts and count those scripts within the range of characters. + for( Vector::ConstIterator it = mScriptRuns.Begin(), + endIt = mScriptRuns.End(); + it != endIt; + ++it ) + { + const ScriptRun& script = *it; + + if( ( script.characterRun.characterIndex + script.characterRun.numberOfCharacters > characterIndex ) && + ( lastCharacterIndex > script.characterRun.characterIndex ) ) + { + firstScriptFound = true; + ++numberOfScriptRuns; + } + else if( lastCharacterIndex <= script.characterRun.characterIndex ) + { + // nothing else to do. + break; + } + + if( !firstScriptFound ) + { + ++firstScriptRun; + } + } +} + +void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + ScriptRunIndex firstScriptRun = 0u; + Length numberOfScriptRuns = 0u; + + GetNumberOfScriptRuns( characterIndex, + numberOfCharacters, + firstScriptRun, + numberOfScriptRuns ); + + memcpy( scriptRuns, mScriptRuns.Begin() + firstScriptRun, numberOfScriptRuns * sizeof( ScriptRun ) ); +} + +Script LogicalModel::GetScript( CharacterIndex characterIndex ) const +{ + // If this operation is too slow, consider a binary search. + + for( Length index = 0u, length = mScriptRuns.Count(); index < length; ++index ) + { + const ScriptRun* const scriptRun = mScriptRuns.Begin() + index; + + if( ( scriptRun->characterRun.characterIndex <= characterIndex ) && + ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) ) + { + return scriptRun->script; + } + } + + return TextAbstraction::UNKNOWN; +} + +void LogicalModel::ReplaceScripts( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const ScriptRun* const scriptRuns, + Length numberOfCharactersToInsert ) +{ +} + +void LogicalModel::SetFonts( const FontRun* const fonts, + Length numberOfRuns ) +{ + if( 0u == numberOfRuns ) + { + mFontRuns.Clear(); + } + else + { + mFontRuns.Resize( numberOfRuns ); + memcpy( mFontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) ); + } +} + +void LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + FontRunIndex& firstFontRun, + Length& numberOfFontRuns ) const +{ + // Initialize the number of fonts and the index to the first font. + firstFontRun = 0u; + numberOfFontRuns = 0; + bool firstFontFound = false; + + const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters; + + // Traverse the fonts and count those fonts within the range of characters. + for( Vector::ConstIterator it = mFontRuns.Begin(), + endIt = mFontRuns.End(); + it != endIt; + ++it ) + { + const FontRun& font = *it; + + if( ( font.characterRun.characterIndex + font.characterRun.numberOfCharacters > characterIndex ) && + ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) ) + { + firstFontFound = true; + ++numberOfFontRuns; + } + else if( lastCharacterIndex <= font.characterRun.characterIndex ) + { + // nothing else to do. + break; + } + + if( !firstFontFound ) + { + ++firstFontRun; + } + } +} + +void LogicalModel::GetFontRuns( FontRun* fontRuns, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + FontRunIndex firstFontRun = 0u; + Length numberOfFontRuns = 0u; + + GetNumberOfFontRuns( characterIndex, + numberOfCharacters, + firstFontRun, + numberOfFontRuns ); + + memcpy( fontRuns, mFontRuns.Begin() + firstFontRun, numberOfFontRuns * sizeof( FontRun ) ); +} + +FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const +{ + for( Length index = 0u, length = mFontRuns.Count(); index < length; ++index ) + { + const FontRun* const fontRun = mFontRuns.Begin() + index; + + if( ( fontRun->characterRun.characterIndex <= characterIndex ) && + ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) ) + { + return fontRun->fontId; + } + } + + return 0u; +} + +void LogicalModel::ReplaceFonts( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const FontRun* const fontRuns, + Length numberOfCharactersToInsert ) +{ +} + +void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo, + Length length ) +{ + if( 0u == length ) + { + mLineBreakInfo.Clear(); + } + else + { + mLineBreakInfo.Resize( length ); + memcpy( mLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) ); + } +} + +void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo, + CharacterIndex characterIndex, + Length numberOfItems ) const +{ + memcpy( lineBreakInfo, mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) ); +} + +LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const +{ + return *( mLineBreakInfo.Begin() + characterIndex ); +} + +void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex, + Length numberOfItemsToRemove, + const LineBreakInfo* const lineBreakInfo, + Length numberOfItemsToInsert ) +{ +} + +void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo, + Length length ) +{ + if( 0u == length ) + { + mWordBreakInfo.Clear(); + } + else + { + mWordBreakInfo.Resize( length ); + memcpy( mWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) ); + } +} + +void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo, + CharacterIndex characterIndex, + Length numberOfItems ) const +{ + memcpy( wordBreakInfo, mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) ); +} + +WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const +{ + return *( mWordBreakInfo.Begin() + characterIndex ); +} + +void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex, + Length numberOfItemsToRemove, + const WordBreakInfo* const wordBreakInfo, + Length numberOfItemsToInsert ) +{ +} + +void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo, + Length numberOfRuns ) +{ + if( 0u == numberOfRuns ) + { + mBidirectionalParagraphInfo.Clear(); + } + else + { + mBidirectionalParagraphInfo.Resize( numberOfRuns ); + memcpy( mBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) ); + } +} + +void LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + BidirectionalRunIndex& firstBidirectionalRun, + Length& numberOfFontRuns ) const +{ + // Initialize the number of bidi paragraphs and the index to the first paragraph. + firstBidirectionalRun = 0u; + numberOfFontRuns = 0; + bool firstParagraphFound = false; + + // Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters. + for( Vector::ConstIterator it = mBidirectionalParagraphInfo.Begin(), + endIt = mBidirectionalParagraphInfo.End(); + it != endIt; + ++it ) + { + const BidirectionalParagraphInfoRun& bidi = *it; + + if( ( bidi.characterRun.characterIndex + bidi.characterRun.numberOfCharacters > characterIndex ) && + ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) ) + { + firstParagraphFound = true; + ++numberOfFontRuns; + } + + if( !firstParagraphFound ) + { + ++firstBidirectionalRun; + } + } +} + +void LogicalModel::GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + BidirectionalRunIndex firstBidirectionalRun = 0u; + Length numberOfFontRuns = 0u; + + GetNumberOfBidirectionalInfoRuns( characterIndex, + numberOfCharacters, + firstBidirectionalRun, + numberOfFontRuns ); + + memcpy( bidirectionalInfo, mBidirectionalParagraphInfo.Begin() + firstBidirectionalRun, numberOfFontRuns * sizeof( BidirectionalParagraphInfoRun ) ); +} + +void ReplaceBidirectionalInfo( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const BidirectionalParagraphInfoRun* const bidirectionalInfo, + Length numberOfCharactersToInsert ) +{ +} + +void LogicalModel::SetCharacterDirections( const CharacterDirection* const directions, + Length numberOfCharacters ) +{ + if( 0u == numberOfCharacters ) + { + mCharacterDirections.Clear(); + } + else + { + mCharacterDirections.Resize( numberOfCharacters ); + memcpy( mCharacterDirections.Begin(), directions, numberOfCharacters * sizeof( CharacterDirection ) ); + } +} + +void LogicalModel::GetCharacterDirections( CharacterDirection* directions, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + if( 0u == mCharacterDirections.Count() ) + { + // Nothing to retrieve if the model has no right to left characters. + return; + } + + memcpy( directions, mCharacterDirections.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterDirection ) ); +} + +CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const +{ + if( characterIndex >= mCharacterDirections.Count() ) + { + // The model has no right to left characters, so the vector of directions is void. + return false; + } + + return *( mCharacterDirections.Begin() + characterIndex ); +} + +void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo, + Length numberOfRuns ) +{ + if( 0u == numberOfRuns ) + { + mVisualToLogicalMap.Clear(); + mLogicalToVisualMap.Clear(); + mVisualToLogicalCursorMap.Clear(); + } + else + { + const Length numberOfCharacters = mText.Count(); + mVisualToLogicalMap.Resize( numberOfCharacters ); + mLogicalToVisualMap.Resize( numberOfCharacters ); + + const Length numberOfCharactersPlus = numberOfCharacters + 1u; + mVisualToLogicalCursorMap.Resize( numberOfCharactersPlus ); + + CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin(); + CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin(); + + CharacterIndex* modelVisualToLogicalCursorMap = mVisualToLogicalCursorMap.Begin(); + + CharacterIndex lastIndex = 0u; + for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex ) + { + const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex ); + + if( lastIndex < bidiLineInfo.characterRun.characterIndex ) + { + // Fill with the identity. + for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex ) + { + *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex; + } + } + + // Fill the conversion table of the run. + for( CharacterIndex index = 0u; + index < bidiLineInfo.characterRun.numberOfCharacters; + ++index, ++lastIndex ) + { + *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index ); + } + } + + // Complete with the identity if there are some left to right characters after the last right to left. + for( ; lastIndex < numberOfCharacters; ++lastIndex ) + { + *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex; + } + + // Sets the logical to visual conversion map. + for( CharacterIndex index = 0u; index < numberOfCharacters; ++index ) + { + *( modelLogicalToVisualMapBuffer + *( modelVisualToLogicalMapBuffer + index ) ) = index; + } + + // Sets the visual to logical conversion map for cursor positions. + + const Length numberOfBidirectionalParagraphs = mBidirectionalParagraphInfo.Count(); + BidirectionalParagraphInfoRun* bidirectionalParagraphInfoBuffer = mBidirectionalParagraphInfo.Begin(); + BidirectionalParagraphInfoRun* bidirectionalParagraph = bidirectionalParagraphInfoBuffer; + + const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin(); + + Length bidirectionalParagraphIndex = 0u; + bool isRightToLeftParagraph = false; + for( CharacterIndex index = 0u; index < numberOfCharactersPlus; ++index ) + { + if( bidirectionalParagraph && + ( bidirectionalParagraph->characterRun.characterIndex == index ) ) + { + isRightToLeftParagraph = true; + } + + if( 0u == index ) + { + if( isRightToLeftParagraph ) + { + *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters; + } + else // else logical position is zero. + { + *( modelVisualToLogicalCursorMap + index ) = 0u; + } + } + else if( numberOfCharacters == index ) + { + if( isRightToLeftParagraph ) + { + *( modelVisualToLogicalCursorMap + index ) = 0u; + } + else // else logical position is the number of characters. + { + *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters; + } + } + else + { + // Get the character indexed by index - 1 and index + // and calculate the logical position according the directions of + // both characters and the direction of the paragraph. + + const CharacterIndex previousIndex = index - 1u; + const CharacterIndex logicalPosition0 = *( modelVisualToLogicalMapBuffer + previousIndex ); + const CharacterIndex logicalPosition1 = *( modelVisualToLogicalMapBuffer + index ); + + const CharacterDirection direction0 = *( modelCharacterDirections + logicalPosition0 ); + const CharacterDirection direction1 = *( modelCharacterDirections + logicalPosition1 ); + + if( direction0 == direction1 ) + { + // Both glyphs have the same direction. + if( direction0 ) + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition0; + } + else + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition1; + } + } + else + { + if( isRightToLeftParagraph ) + { + if( direction1 ) + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition1 + 1u; + } + else + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition0; + } + } + else + { + if( direction0 ) + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition1; + } + else + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition0 + 1u; + } + } + } + } + + if( bidirectionalParagraph && + ( bidirectionalParagraph->characterRun.characterIndex + bidirectionalParagraph->characterRun.numberOfCharacters == index ) ) + { + isRightToLeftParagraph = false; + ++bidirectionalParagraphIndex; + if( bidirectionalParagraphIndex < numberOfBidirectionalParagraphs ) + { + bidirectionalParagraph = bidirectionalParagraphInfoBuffer + bidirectionalParagraphIndex; + } + else + { + bidirectionalParagraph = NULL; + } + } + } + } +} + +void LogicalModel::ReplaceVisualToLogicalMap( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const BidirectionalLineInfoRun* const bidirectionalInfo, + Length numberOfCharactersToInsert ) +{ +} + +CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const +{ + if( 0u == mLogicalToVisualMap.Count() ) + { + // If there is no logical to visual info is because the whole text is left to right. + // Return the identity. + return logicalCharacterIndex; + } + + return *( mLogicalToVisualMap.Begin() + logicalCharacterIndex ); +} + +CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const +{ + if( 0u == mVisualToLogicalMap.Count() ) + { + // If there is no visual to logical info is because the whole text is left to right. + // Return the identity. + return visualCharacterIndex; + } + + return *( mVisualToLogicalMap.Begin() + visualCharacterIndex ); +} + +void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( logicalToVisualMap, mLogicalToVisualMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) ); +} + +void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( visualToLogicalMap, mVisualToLogicalMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) ); +} + +LogicalModel::~LogicalModel() +{ +} + +LogicalModel::LogicalModel() +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/logical-model-impl.h b/dali-toolkit/internal/text/logical-model-impl.h new file mode 100644 index 0000000..73d9230 --- /dev/null +++ b/dali-toolkit/internal/text/logical-model-impl.h @@ -0,0 +1,619 @@ +#ifndef __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct BidirectionalLineInfoRun; +struct BidirectionalParagraphInfoRun; +struct FontRun; +class LogicalModel; +typedef IntrusivePtr LogicalModelPtr; +struct ScriptRun; + +/** + * @brief A logical text model contains layout independent information. + * + * This includes: + * - A series of UTF-32 characters in logical order + */ +class LogicalModel : public RefObject +{ +public: + + /** + * @brief Create a new instance of a LogicalModel. + * + * @return A pointer to a new LogicalModel. + */ + static LogicalModelPtr New(); + + // Text interface. + + /** + * @brief Replaces any text previously set. + * + * @note If the number of characters is zero the text buffer is cleared. + * + * @param[in] text An array of UTF-32 characters. + * @param[in] numberOfCharacters The length of the array. + */ + void SetText( const Character* const text, + Length numberOfCharacters ); + + /** + * @brief Retrieves the number of characters of the text. + * + * @return The number of characters. + */ + Length GetNumberOfCharacters() const; + + /** + * @brief Retrieves characters from the text in the given buffer. + * + * @pre The size of the @p text buffer needs to be big enough to copy the @p numberOfCharacters. + * @param[out] text Pointer to a buffer where the text is copied. + * @param[in] characterIndex The index to the first character to copy. + * @param[in] numberOfCharacters The number of characters to be copied. + */ + void GetText( Character* text, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves a character. + * + * @param[in] characterIndex Index to a character. + * + * @return A character. + */ + Character GetCharacter( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces characters from the text. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Where to replace the text. + * @param[in] numberOfCharactersToRemove The number of characters to be removed. + * @param[in] text Pointer to a buffer with the text encoded in utf32. + * @param[in] numberOfCharactersToInsert The number of characters in the buffer. + */ + void ReplaceText( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const Character* const text, + Length numberOfCharactersToInsert ); + + // Language support interface. + + /** + * @brief Sets the script runs. + * + * Replaces any scripts previously set. + * + * A run is a group of consecutive characters. A script run contains the script for a run. + * + * @note If the number of runs is zero the script buffer is cleared. + * + * @param[in] scripts Pointer to a buffer with all the script runs. + * @param[in] numberOfRuns The number of script runs. + */ + void SetScripts( const ScriptRun* const scripts, + Length numberOfRuns ); + + /** + * @brief Retrieves the number of script runs and the index to the first one for the given range of characters. + * + * A run is a group of consecutive characters. A script run contains the script for a run. + * + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + * @param[out] firstScriptRun Index to the script run containing the character index. + * @param[out] numberOfScriptRuns The number of script runs. + */ + void GetNumberOfScriptRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + ScriptRunIndex& firstScriptRun, + Length& numberOfScriptRuns ) const; + + /** + * @brief Retrieves the script runs for the given range of characters. + * + * The @p scriptRuns buffer needs to be big enough to copy the number of script runs. + * Call GetNumberOfScriptRuns() to retrieve the number of script runs. + * + * @param[out] scriptRuns Pointer to a buffer where the script runs are copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetScriptRuns( ScriptRun* scriptRuns, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the script for the given character index. + * + * @param[in] characterIndex Index to the character. + * + * @return The character's script. + */ + Script GetScript( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces script runs for the given range of characters. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Index of the first character where to replace the scripts. + * @param[in] numberOfCharactersToRemove The number of characters to be the script removed. + * @param[in] scriptRuns Pointer to a buffer with the script runs. + * @param[in] numberOfCharactersToInsert The number of characters to be the script inserted. + */ + void ReplaceScripts( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const ScriptRun* const scriptRuns, + Length numberOfCharactersToInsert ); + + /** + * @brief Sets the font runs. + * + * Replaces any fonts previously set. + * + * A run is a group of consecutive characters. A font run contains the font id for a run. + * + * @note If the number of runs is zero the font buffer is cleared. + * + * @param[in] fonts Pointer to a buffer with all the font runs. + * @param[in] numberOfRuns The number of font runs. + */ + void SetFonts( const FontRun* const fonts, + Length numberOfRuns ); + + /** + * @brief Retrieves the number of font runs and the index of the first one for the given range of characters. + * + * A run is a group of consecutive characters. A font run contains the font id for a run. + * + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + * @param[out] firstFontRun Index to the font run containing the character index. + * @param[out] numberOfFontRuns The number of font runs. + */ + void GetNumberOfFontRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + FontRunIndex& firstFontRun, + Length& numberOfFontRuns ) const; + + /** + * @brief Retrieves the font runs for the given range of characters. + * + * The @p fontRuns buffer needs to be big enough to copy the number of font runs. + * Call GetNumberOfFontRuns() to retrieve the number of font runs. + * + * @param[out] fontRuns Pointer to a buffer where the font runs are copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetFontRuns( FontRun* fontRuns, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the font id for the given character index. + * + * @param[in] characterIndex Index to the first character. + * + * @return The font id. + */ + FontId GetFont( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces font runs for the given range of characters. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Index of the first character where to replace the fonts. + * @param[in] numberOfCharactersToRemove The number of characters to be the font removed. + * @param[in] fontRuns Pointer to a buffer with the font runs. + * @param[in] numberOfCharactersToInsert The number of characters to be the font inserted. + */ + void ReplaceFonts( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const FontRun* const fontRuns, + Length numberOfCharactersToInsert ); + + // Break info interface. + + /** + * @brief Sets the line break info. + * + * See GetLineBreakInfo() to get how the line break info is encoded. + * + * Replaces any line break info previously set. + * + * @note If the @length is zero the break info buffer is cleared. + * + * @param[in] lineBreakInfo Pointer to a buffer with the line break info. + * @param[in] length The size of the buffer. + */ + void SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo, + Length length ); + + /** + * @brief Retrieves the line break info in the given buffer. + * + * The size of the @p lineBreakInfo buffer needs to be big enough to copy the @p numberOfItems. + * + * Possible values for LineBreakInfo are: + * + * - 0 is a LINE_MUST_BREAK. Text must be broken into a new line. + * - 1 is a LINE_ALLOW_BREAK. Is possible to break the text into a new line. + * - 2 is a LINE_NO_BREAK. Text can't be broken into a new line. + * + @verbatim + i.e. Hello big\nworld produces: + 2222212220 22220 + @endverbatim + * + * @param[out] lineBreakInfo Pointer to a buffer where the line break info is copied. + * @param[in] characterIndex Index to the first line break info item. + * @param[in] numberOfItems The number of items to be copied. + */ + void GetLineBreakInfo( LineBreakInfo* lineBreakInfo, + CharacterIndex characterIndex, + Length numberOfItems ) const; + + /** + * @brief Retrieves the line break info for the given item index. + * + * @param[in] characterIndex Index to the line break info item. + */ + LineBreakInfo GetLineBreakInfo( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces line break info. + * + * See GetLineBreakInfo() to get how the line break info is encoded. + * + * If the @p numberOfItemsToRemove is zero, this operation is like an insert. + * If the @p numberOfItemsToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Where to replace the line break info. + * @param[in] numberOfItemsToRemove The number of items to be removed. + * @param[in] lineBreakInfo Pointer to a buffer with the line break info. + * @param[in] numberOfItemsToInsert The number of items in the buffer. + */ + void ReplaceLineBreakInfo( CharacterIndex characterIndex, + Length numberOfItemsToRemove, + const LineBreakInfo* const lineBreakInfo, + Length numberOfItemsToInsert ); + + /** + * @brief Sets the word break info. + * + * See GetWordBreakInfo() to get how the word break info is encoded. + * + * Replaces any word break info previously set. + * + * @note If the @length is zero the break info buffer is cleared. + * + * @param[in] wordBreakInfo Pointer to a buffer with the word break info. + * @param[in] length The size of the buffer. + */ + void SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo, + Length length ); + + /** + * @brief Retrieves the word break info in the given buffer. + * + * The size of the @p wordBreakInfo buffer needs to be big enough to copy the @p numberOfItems. + * + * The size of the buffer has to be big enough to store the whole word break info per character. + * Call GetNumberOfCharacters() to get the number of characters. + * + * Possible values for WordBreakInfo are: + * + * - 0 is a WORD_BREAK. Text can be broken into a new word. + * - 1 is a WORD_NO_BREAK. Text can't be broken into a new word. + * + @verbatim + i.e. Hello big\nworld produces: + 1111001100 11110 + @endverbatim + * + * @param[out] wordBreakInfo Pointer to a buffer where the word break info is copied. + * @param[in] characterIndex Index to the first word break info item. + * @param[in] numberOfItems The number of items to be copied. + */ + void GetWordBreakInfo( WordBreakInfo* wordBreakInfo, + CharacterIndex characterIndex, + Length numberOfItems ) const; + + /** + * @brief Retrieves the word break info for the given item index. + * + * @param[in] characterIndex Index to the word break info item. + */ + WordBreakInfo GetWordBreakInfo( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces word break info. + * + * See GetWordBreakInfo() to get how the word break info is encoded. + * + * If the @p numberOfItemsToRemove is zero, this operation is like an insert. + * If the @p numberOfItemsToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Where to replace the word break info. + * @param[in] numberOfItemsToRemove The number of items to be removed. + * @param[in] wordBreakInfo Pointer to a buffer with the word break info. + * @param[in] numberOfItemsToInsert The number of items in the buffer. + */ + void ReplaceWordBreakInfo( CharacterIndex characterIndex, + Length numberOfItemsToRemove, + const WordBreakInfo* const wordBreakInfo, + Length numberOfItemsToInsert ); + + // Bidirectional support interface. + + /** + * @brief Sets the bidirectional info runs. + * + * Replaces any bidirectional info previously set. + * + * Each bidirectional info run stores bidirectional info for a whole 'paragraph' of text which contains right to left scripts. + + * In terms of the bidirectional algorithm, a 'paragraph' is understood as a run of characters between Paragraph Separators or appropriate Newline Functions. + * A 'paragraph' may also be determined by higher-level protocols like a mark-up tag. + * + * @note If the number of runs is zero the bidirectional info buffer is cleared. + * + * @param[in] bidirectionalInfo Pointer to a buffer with all the bidirectional info runs. + * @param[in] numberOfRuns The number of bidirectional info runs. + */ + void SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo, + Length numberOfRuns ); + + /** + * @brief Retrieves the number of bidirectional info runs and the index to the first one for the given range of characters. + * + * It may be zero if there is no right to left scripts. + * + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + * + * @return The number of bidirectional info runs. + */ + void GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + BidirectionalRunIndex& firstBidirectionalRun, + Length& numberOfFontRuns ) const; + + /** + * @brief Retrieves the bidirectional paragraph info runs for the given range of characters. + * + * The @p bidirectionalInfo buffer needs to be big enough to copy the number of bidirectional + * paragraph info runs. + * Call GetNumberOfBidirectionalInfoRuns() to retrieve the number of bidirectional runs. + * + * @param[out] bidirectionalInfo Pointer to a buffer where the bidirectional info runs are copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Replaces bidirectional info runs for the given range of characters. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Index of the first character where to replace the bidirectional info. + * @param[in] numberOfCharactersToRemove The number of characters to be the bidirectional info removed. + * @param[in] bidirectionalInfo Pointer to a buffer with the bidirectional info runs. + * @param[in] numberOfCharactersToInsert The number of characters to be the bidirectional info inserted. + */ + void ReplaceBidirectionalInfo( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const BidirectionalParagraphInfoRun* const bidirectionalInfo, + Length numberOfCharactersToInsert ); + + /** + * @brief Replaces the direction of the characters. + * + * @note If the number of characters is zero the directions buffer is cleared. + * + * @param[in] directions The directions of the characters. + * @param[in] numberOfCharacters The number of characters. + */ + void SetCharacterDirections( const CharacterDirection* const directions, + Length numberOfCharacters ); + + /** + * @brief Retrieves the direction of the characters. + * + * It sets @e true for right to left characters and @e false for left to right. + * For neutral characters it check's the next and previous character's directions: + * - If they are equals set that direction. If they are not, sets the paragraph's direction. + * - If there is no next, sets the paragraph's direction. + * + * See SetBidirectionalInfo() to get an explanation of the 'paragraph' meaning in the bidirectional algorithm. + * + * @pre the @p directions vector should be initialized to @e false (left to right) as this method is not going + * to update it if there is no right to left characters. + * + * @param[out] directions Whether the characters are right to left or left to right. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetCharacterDirections( CharacterDirection* directions, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the direction of a characters. + * + * See GetCharacterDirections(). + * + * @param[in] characterIndex Index to a character. + * + * @return The character's direction. + */ + CharacterDirection GetCharacterDirection( CharacterIndex characterIndex ) const; + + // Visual <--> Logical conversion tables. + + /** + * @brief Sets the visual to logical and the logical to visual map tables. + * + * Replaces any map tables previously set. + * + * @note If the number of runs is zero the bidirectional info buffer is cleared. + * + * @param[in] bidirectionalInfo Pointer to a buffer with all the bidirectional info runs. + * @param[in] numberOfRuns The number of bidirectional info runs. + */ + void SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo, + Length numberOfRuns ); + + /** + * @brief Replaces the visual to logical and logical to visual map tables for the given range of characters. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Index of the first character where to replace the map tables. + * @param[in] numberOfCharactersToRemove The number of characters to be removed. + * @param[in] bidirectionalInfo Pointer to a buffer with the bidirectional info runs. + * @param[in] numberOfCharactersToInsert The number of characters to be inserted. + */ + void ReplaceVisualToLogicalMap( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const BidirectionalLineInfoRun* const bidirectionalInfo, + Length numberOfCharactersToInsert ); + + /** + * @brief Retrieves the visual character index for the given logical character index. + * + * @param[in] logicalCharacterIndex The logical character index. + * + * @return The visual character index. + */ + CharacterIndex GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const; + + /** + * @brief Retrieves the logical character index for the given visual character index. + * + * @param[in] visualCharacterIndex The visual character index. + * + * @return The logical character index. + */ + CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const; + + /** + * @brief Retrieves the whole or part of the logical to visual conversion map. + * + * The size of the buffer needs to be big enough to copy the @p numberOfCharacters. + * + * @param[out] logicalToVisualMap Pointer to a buffer where the conversion map is copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the whole or part of the visual to logical conversion map. + * + * The size of the buffer needs to be big enough to copy the @p numberOfCharacters. + * + * @param[out] visualToLogicalMap Pointer to a buffer where the conversion map is copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + +protected: + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~LogicalModel(); + +private: + + /** + * @brief Private constructor. + */ + LogicalModel(); + + // Undefined + LogicalModel( const LogicalModel& handle ); + + // Undefined + LogicalModel& operator=( const LogicalModel& handle ); + +public: + + Vector mText; + Vector mScriptRuns; + Vector mFontRuns; + Vector mLineBreakInfo; + Vector mWordBreakInfo; + Vector mBidirectionalParagraphInfo; + Vector mCharacterDirections; ///< For each character, whether is right to left. ( @e flase is left to right, @e true right to left ). + Vector mBidirectionalLineInfo; + Vector mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table. + Vector mVisualToLogicalMap; ///< Bidirectional visual to logical conversion table. + Vector mVisualToLogicalCursorMap; ///< Bidirectional visual to logical cursor conversion table. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__ diff --git a/dali-toolkit/internal/text/multi-language-support-impl.cpp b/dali-toolkit/internal/text/multi-language-support-impl.cpp new file mode 100644 index 0000000..6553c51 --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2015 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 + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace +{ +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_MULTI_LANGUAGE_SUPPORT"); +#endif + +const Dali::Toolkit::Text::Character UTF32_A = 0x0041; +} + +namespace Text +{ + +namespace Internal +{ + +/** + * @brief Retrieves the font Id from the font run for a given character's @p index. + * + * If the character's index exceeds the current font run it increases the iterator to get the next one. + * + * @param[in] index The character's index. + * @param[in,out] fontRunIt Iterator to the current font run. + * @param[in] fontRunEndIt Iterator to one after the last font run. + * + * @return The font id. + */ +FontId GetFontId( Length index, + Vector::ConstIterator& fontRunIt, + const Vector::ConstIterator& fontRunEndIt ) +{ + FontId fontId = 0u; + + if( fontRunIt != fontRunEndIt ) + { + const FontRun& fontRun = *fontRunIt; + + if( ( index >= fontRun.characterRun.characterIndex ) && + ( index < fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) ) + { + fontId = fontRun.fontId; + } + + if( index + 1u == fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) + { + // All the characters of the current run have been traversed. Get the next one for the next iteration. + ++fontRunIt; + } + } + + return fontId; +} + +/** + * @brief Retrieves the script Id from the script run for a given character's @p index. + * + * If the character's index exceeds the current script run it increases the iterator to get the next one. + * + * @param[in] index The character's index. + * @param[in,out] scriptRunIt Iterator to the current font run. + * @param[in] scriptRunEndIt Iterator to one after the last script run. + * + * @return The script. + */ +Script GetScript( Length index, + Vector::ConstIterator& scriptRunIt, + const Vector::ConstIterator& scriptRunEndIt ) +{ + Script script = TextAbstraction::UNKNOWN; + + if( scriptRunIt != scriptRunEndIt ) + { + const ScriptRun& scriptRun = *scriptRunIt; + + if( ( index >= scriptRun.characterRun.characterIndex ) && + ( index < scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ) ) + { + script = scriptRun.script; + } + + if( index + 1u == scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ) + { + // All the characters of the current run have been traversed. Get the next one for the next iteration. + ++scriptRunIt; + } + } + + return script; +} + +/** + * @brief Whether the character is valid for all scripts. i.e. the white space. + * + * @param[in] character The character. + * + * @return @e true if the character is valid for all scripts. + */ +bool IsValidForAllScripts( Character character ) +{ + return ( TextAbstraction::IsWhiteSpace( character ) || + TextAbstraction::IsZeroWidthNonJoiner( character ) || + TextAbstraction::IsZeroWidthJoiner( character ) || + TextAbstraction::IsZeroWidthSpace( character ) || + TextAbstraction::IsLeftToRightMark( character ) || + TextAbstraction::IsRightToLeftMark( character ) || + TextAbstraction::IsThinSpace( character ) ); +} + +bool ValidateFontsPerScript::FindValidFont( FontId fontId ) const +{ + for( Vector::ConstIterator it = mValidFonts.Begin(), + endIt = mValidFonts.End(); + it != endIt; + ++it ) + { + if( fontId == *it ) + { + return true; + } + } + + return false; +} + +MultilanguageSupport::MultilanguageSupport() +: mDefaultFontPerScriptCache(), + mValidFontsPerScriptCache() +{ + // Initializes the default font cache to zero (invalid font). + // Reserves space to cache the default fonts and access them with the script as an index. + mDefaultFontPerScriptCache.Resize( TextAbstraction::UNKNOWN, 0u ); + + // Initializes the valid fonts cache to NULL (no valid fonts). + // Reserves space to cache the valid fonts and access them with the script as an index. + mValidFontsPerScriptCache.Resize( TextAbstraction::UNKNOWN, NULL ); +} + +MultilanguageSupport::~MultilanguageSupport() +{ + // Destroy the valid fonts per script cache. + + for( Vector::Iterator it = mValidFontsPerScriptCache.Begin(), + endIt = mValidFontsPerScriptCache.End(); + it != endIt; + ++it ) + { + delete *it; + } +} + +Text::MultilanguageSupport MultilanguageSupport::Get() +{ + Text::MultilanguageSupport multilanguageSupportHandle; + + SingletonService service( SingletonService::Get() ); + if( service ) + { + // Check whether the singleton is already created + Dali::BaseHandle handle = service.GetSingleton( typeid( Text::MultilanguageSupport ) ); + if( handle ) + { + // If so, downcast the handle + MultilanguageSupport* impl = dynamic_cast< Internal::MultilanguageSupport* >( handle.GetObjectPtr() ); + multilanguageSupportHandle = Text::MultilanguageSupport( impl ); + } + else // create and register the object + { + multilanguageSupportHandle = Text::MultilanguageSupport( new MultilanguageSupport ); + service.Register( typeid( multilanguageSupportHandle ), multilanguageSupportHandle ); + } + } + + return multilanguageSupportHandle; +} + +void MultilanguageSupport::SetScripts( const Vector& text, + const Vector& lineBreakInfo, + Vector& scripts ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + // Stores the current script run. + ScriptRun currentScriptRun; + currentScriptRun.characterRun.characterIndex = 0u; + currentScriptRun.characterRun.numberOfCharacters = 0u; + currentScriptRun.script = TextAbstraction::UNKNOWN; + + // Reserve some space to reduce the number of reallocations. + scripts.Reserve( numberOfCharacters << 2u ); + + // Whether the first valid script need to be set. + bool firstValidScript = true; + + // Whether the first valid script is a right to left script. + bool isParagraphRTL = false; + + // Count the number of characters which are valid for all scripts. i.e. white spaces or '\n'. + Length numberOfAllScriptCharacters = 0u; + + // Pointers to the text and break info buffers. + const Character* textBuffer = text.Begin(); + const LineBreakInfo* breakInfoBuffer = lineBreakInfo.Begin(); + + // Traverse all characters and set the scripts. + for( Length index = 0u; index < numberOfCharacters; ++index ) + { + Character character = *( textBuffer + index ); + LineBreakInfo breakInfo = *( breakInfoBuffer + index ); + + // Some characters (like white spaces) are valid for many scripts. The rules to set a script + // for them are: + // - If they are at the begining of a paragraph they get the script of the first character with + // a defined script. If they are at the end, they get the script of the last one. + // - If they are between two scripts with the same direction, they get the script of the previous + // character with a defined script. If the two scripts have different directions, they get the + // script of the first character of the paragraph with a defined script. + + // Skip those characters valid for many scripts like white spaces or '\n'. + bool endOfText = index == numberOfCharacters; + while( !endOfText && + IsValidForAllScripts( character ) ) + { + // Count all these characters to be added into a script. + ++numberOfAllScriptCharacters; + + if( TextAbstraction::LINE_MUST_BREAK == breakInfo ) + { + // The next character is a new paragraph. + // Know when there is a new paragraph is needed because if there is a white space + // between two scripts with different directions, it is added to the script with + // the same direction than the first script of the paragraph. + firstValidScript = true; + isParagraphRTL = false; + } + + // Get the next character. + ++index; + endOfText = index == numberOfCharacters; + if( !endOfText ) + { + character = *( textBuffer + index ); + breakInfo = *( breakInfoBuffer + index ); + } + } + + if( endOfText ) + { + // Last characters of the text are 'white spaces'. + // There is nothing else to do. Just add the remaining characters to the last script after this bucle. + break; + } + + // Get the script of the character. + Script script = TextAbstraction::GetCharacterScript( character ); + + // Check if it is the first character of a paragraph. + if( firstValidScript && + ( TextAbstraction::UNKNOWN != script ) ) + { + // Sets the direction of the first valid script. + isParagraphRTL = TextAbstraction::IsRightToLeftScript( script ); + firstValidScript = false; + } + + if( script != currentScriptRun.script ) + { + // Current run needs to be stored and a new one initialized. + + if( isParagraphRTL != TextAbstraction::IsRightToLeftScript( script ) ) + { + // Current script has different direction than the first script of the paragraph. + // All the previously skipped characters need to be added to the previous script before it's stored. + currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; + numberOfAllScriptCharacters = 0u; + } + + if( 0u != currentScriptRun.characterRun.numberOfCharacters ) + { + // Store the script run. + scripts.PushBack( currentScriptRun ); + } + + // Initialize the new one. + currentScriptRun.characterRun.characterIndex = currentScriptRun.characterRun.characterIndex + currentScriptRun.characterRun.numberOfCharacters; + currentScriptRun.characterRun.numberOfCharacters = numberOfAllScriptCharacters; // Adds the white spaces which are at the begining of the script. + currentScriptRun.script = script; + numberOfAllScriptCharacters = 0u; + } + else + { + // Adds white spaces between characters. + currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; + numberOfAllScriptCharacters = 0u; + } + + if( TextAbstraction::LINE_MUST_BREAK == breakInfo ) + { + // The next character is a new paragraph. + firstValidScript = true; + isParagraphRTL = false; + } + + // Add one more character to the run. + ++currentScriptRun.characterRun.numberOfCharacters; + } + + // Add remaining characters into the last script. + currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; + if( 0u != currentScriptRun.characterRun.numberOfCharacters ) + { + if( TextAbstraction::UNKNOWN == currentScriptRun.script ) + { + // There are only white spaces in the last script. Set the latin script. + currentScriptRun.script = TextAbstraction::LATIN; + } + + // Store the last run. + scripts.PushBack( currentScriptRun ); + } +} + +void MultilanguageSupport::ReplaceScripts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +void MultilanguageSupport::ValidateFonts( const Vector& text, + const Vector& scripts, + Vector& fonts ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + // Copy the fonts set by application developers. + const Length numberOfFontRuns = fonts.Count(); + const Vector definedFonts = fonts; + fonts.Clear(); + + // Traverse the characters and validate/set the fonts. + + // Get the caches. + FontId* defaultFontPerScriptCacheBuffer = mDefaultFontPerScriptCache.Begin(); + ValidateFontsPerScript** validFontsPerScriptCacheBuffer = mValidFontsPerScriptCache.Begin(); + + // Stores the validated font runs. + fonts.Reserve( numberOfFontRuns ); + + // Initializes a validated font run. + FontRun currentFontRun; + currentFontRun.characterRun.characterIndex = 0u; + currentFontRun.characterRun.numberOfCharacters = 0u; + currentFontRun.fontId = 0u; + currentFontRun.isDefault = false; + + // Get the font client. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + + // Iterators of the font and script runs. + Vector::ConstIterator fontRunIt = definedFonts.Begin(); + Vector::ConstIterator fontRunEndIt = definedFonts.End(); + Vector::ConstIterator scriptRunIt = scripts.Begin(); + Vector::ConstIterator scriptRunEndIt = scripts.End(); + + for( Length index = 0u; index < numberOfCharacters; ++index ) + { + // Get the character. + const Character character = *( text.Begin() + index ); + + // Get the font for the character. + FontId fontId = GetFontId( index, + fontRunIt, + fontRunEndIt ); + + // Get the script for the character. + Script script = GetScript( index, + scriptRunIt, + scriptRunEndIt ); + + if( TextAbstraction::UNKNOWN == script ) + { + DALI_LOG_WARNING( "MultilanguageSupport::ValidateFonts. Unknown script!" ); + script = TextAbstraction::LATIN; + } + + // Whether the font being validated is a default one not set by the user. + const bool isDefault = ( 0u == fontId ); + + // The default font point size. + PointSize26Dot6 pointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE; + + if( !isDefault ) + { + // Validate if the font set by the user supports the character. + + // Check first in the caches. + + // The user may have set the default font. Check it. Otherwise check in the valid fonts cache. + if( fontId != *( defaultFontPerScriptCacheBuffer + script ) ) + { + // Check in the valid fonts cache. + ValidateFontsPerScript* validateFontsPerScript = *( validFontsPerScriptCacheBuffer + script ); + + if( NULL == validateFontsPerScript ) + { + validateFontsPerScript = new ValidateFontsPerScript(); + } + + if( NULL != validateFontsPerScript ) + { + if( !validateFontsPerScript->FindValidFont( fontId ) ) + { + // Use the font client to validate the font. + GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character ); + + // Emojis are present in many monochrome fonts; prefer color by default. + if( TextAbstraction::EMOJI == script && + 0u != glyphIndex ) + { + BufferImage bitmap = fontClient.CreateBitmap( fontId, glyphIndex ); + if( bitmap && + Pixel::BGRA8888 != bitmap.GetPixelFormat() ) + { + glyphIndex = 0; + } + } + + if( 0u == glyphIndex ) + { + // Get the point size of the current font. It will be used to get a default font id. + pointSize = fontClient.GetPointSize( fontId ); + + // The font is not valid. Set to zero and a default one will be set. + fontId = 0u; + } + else + { + // Add the font to the valid font cache. + validateFontsPerScript->mValidFonts.PushBack( fontId ); + } + } + } + } + } // !isDefault + + // The font has not been validated. Find a default one. + if( 0u == fontId ) + { + // The character has no font assigned. Get a default one from the cache + fontId = *( defaultFontPerScriptCacheBuffer + script ); + + // If the cache has not a default font, get one from the font client. + if( 0u == fontId ) + { + // Emojis are present in many monochrome fonts; prefer color by default. + bool preferColor = ( TextAbstraction::EMOJI == script ); + + // Find a default font. + fontId = fontClient.FindDefaultFont( character, pointSize, preferColor ); + + // If the system does not support a suitable font, fallback to Latin + if( 0u == fontId ) + { + fontId = *( defaultFontPerScriptCacheBuffer + TextAbstraction::LATIN ); + } + if( 0u == fontId ) + { + fontId = fontClient.FindDefaultFont( UTF32_A, pointSize ); + } + +#ifdef DEBUG_ENABLED + Dali::TextAbstraction::FontDescription description; + fontClient.GetDescription( fontId, description ); + DALI_LOG_INFO( gLogFilter, Debug::Concise, "Script: %s; Selected font: %s\n", Dali::TextAbstraction::ScriptName[script], description.path.c_str() ); +#endif + // Cache the font. + *( defaultFontPerScriptCacheBuffer + script ) = fontId; + } + } + + // The font is now validated. + + if( ( fontId != currentFontRun.fontId ) || + ( isDefault != currentFontRun.isDefault ) ) + { + // Current run needs to be stored and a new one initialized. + + if( 0u != currentFontRun.characterRun.numberOfCharacters ) + { + // Store the font run. + fonts.PushBack( currentFontRun ); + } + + // Initialize the new one. + currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters; + currentFontRun.characterRun.numberOfCharacters = 0u; + currentFontRun.fontId = fontId; + currentFontRun.isDefault = isDefault; + } + + // Add one more character to the run. + ++currentFontRun.characterRun.numberOfCharacters; + } + + if( 0u != currentFontRun.characterRun.numberOfCharacters ) + { + // Store the last run. + fonts.PushBack( currentFontRun ); + } +} + +void MultilanguageSupport::ValidateFonts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +} // namespace Internal + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/multi-language-support-impl.h b/dali-toolkit/internal/text/multi-language-support-impl.h new file mode 100644 index 0000000..0f7e177 --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-support-impl.h @@ -0,0 +1,149 @@ +#ifndef __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__ + +/* + * Copyright (c) 2015 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 Toolkit +{ + +namespace Text +{ + +namespace Internal +{ + +/** + * @brief Stores valid font ids per script. + */ +struct ValidateFontsPerScript +{ + /** + * Default constructor. + */ + ValidateFontsPerScript() + : mValidFonts() + {} + + /** + * Default destructor. + */ + ~ValidateFontsPerScript() + {} + + /** + * @brief Whether the given @p fontId is in the vector of valid fonts. + * + * @param[in] fontId The font id. + * + * @return @e true if the font is in the vector of valid fonts. + */ + bool FindValidFont( FontId fontId ) const; + + Vector mValidFonts; +}; + +/** + * @brief Multi-language support implementation. @see Text::MultilanguageSupport. + */ +class MultilanguageSupport : public BaseObject +{ +public: + + /** + * Constructor + */ + MultilanguageSupport(); + + /** + * Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~MultilanguageSupport(); + + /** + * @copydoc Dali::MultilanguageSupport::Get() + */ + static Text::MultilanguageSupport Get(); + + /** + * @copydoc Dali::MultilanguageSupport::SetScripts() + */ + void SetScripts( const Vector& text, + const Vector& lineBreakInfo, + Vector& scripts ); + + /** + * @copydoc Dali::MultilanguageSupport::ReplaceScripts() + */ + void ReplaceScripts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + + /** + * @copydoc Dali::MultilanguageSupport::ValidateFonts( const Vector& text, const Vector& scripts, Vector& fonts ) + */ + void ValidateFonts( const Vector& text, + const Vector& scripts, + Vector& fonts ); + + /** + * @copydoc Dali::MultilanguageSupport::ValidateFonts( LogicalModel& model, CharacterIndex characterIndex, Length numberOfCharactersToRemove, Length numberOfCharactersToInsert ) + */ + void ValidateFonts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); +private: + Vector mDefaultFontPerScriptCache; ///< Caches the default font for a script. + Vector mValidFontsPerScriptCache; ///< Caches valid fonts for a script. +}; + +} // namespace Internal + +inline static Internal::MultilanguageSupport& GetImplementation( MultilanguageSupport& multilanguageSupport ) +{ + DALI_ASSERT_ALWAYS( multilanguageSupport && "multi-language handle is empty" ); + BaseObject& handle = multilanguageSupport.GetBaseObject(); + return static_cast( handle ); +} + +inline static const Internal::MultilanguageSupport& GetImplementation( const MultilanguageSupport& multilanguageSupport ) +{ + DALI_ASSERT_ALWAYS( multilanguageSupport && "multi-language handle is empty" ); + const BaseObject& handle = multilanguageSupport.GetBaseObject(); + return static_cast( handle ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__ diff --git a/dali-toolkit/internal/text/multi-language-support.cpp b/dali-toolkit/internal/text/multi-language-support.cpp new file mode 100644 index 0000000..4416dba --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-support.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015 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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +MultilanguageSupport::MultilanguageSupport() +{ +} + +MultilanguageSupport::~MultilanguageSupport() +{ +} + +MultilanguageSupport::MultilanguageSupport( Internal::MultilanguageSupport* implementation ) +: BaseHandle( implementation ) +{ +} + +MultilanguageSupport MultilanguageSupport::Get() +{ + return Internal::MultilanguageSupport::Get(); +} + +void MultilanguageSupport::SetScripts( const Vector& text, + const Vector& lineBreakInfo, + Vector& scripts ) +{ + GetImplementation( *this ).SetScripts( text, + lineBreakInfo, + scripts ); +} + +void MultilanguageSupport::ReplaceScripts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ + GetImplementation( *this ).ReplaceScripts( model, + characterIndex, + numberOfCharactersToRemove, + numberOfCharactersToInsert ); +} + +void MultilanguageSupport::ValidateFonts( const Vector& text, + const Vector& scripts, + Vector& fonts ) +{ + GetImplementation( *this ).ValidateFonts( text, + scripts, + fonts ); +} + +void MultilanguageSupport::ValidateFonts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ + GetImplementation( *this ).ValidateFonts( model, + characterIndex, + numberOfCharactersToRemove, + numberOfCharactersToInsert ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/multi-language-support.h b/dali-toolkit/internal/text/multi-language-support.h new file mode 100644 index 0000000..b70f672 --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-support.h @@ -0,0 +1,169 @@ +#ifndef __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_H__ +#define __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal DALI_INTERNAL +{ + +class MultilanguageSupport; + +} // Internal + +class LogicalModel; + +/** + * @brief Sets the character's scripts to the model and validates the fonts set by the user or assigns default ones. + */ +class MultilanguageSupport : public BaseHandle +{ +public: + + /** + * @brief Create an uninitialized MultilanguageSupport handle. + */ + MultilanguageSupport(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~MultilanguageSupport(); + + /** + * @brief This constructor is used by MultilanguageSupport::Get(). + * + * @param[in] implementation A pointer to the internal multi-language support object. + */ + explicit DALI_INTERNAL MultilanguageSupport( Internal::MultilanguageSupport* implementation ); + + /** + * @brief Retrieve a handle to the MultilanguageSupport instance. + * + * @return A handle to the MultilanguageSupport. + */ + static MultilanguageSupport Get(); + + /** + * @brief Sets the scripts of the whole text. + * + * Scripts are used to validate and set default fonts and to shape the text in further steps. + * + * Some characters (like white spaces) are valid for many scripts. The rules to set a script + * for them are: + * - If they are at the begining of a paragraph they get the script of the first character with + * a defined script. If they are at the end, they get the script of the last one. + * - If they are between two scripts with the same direction, they get the script of the previous + * character with a defined script. If the two scripts have different directions, they get the + * script of the first character of the paragraph with a defined script. + * + * @param[in] text Vector of UTF-32 characters. + * @param[in] lineBreakInfo Vector with the line break info. + * @param[out] scripts Vector containing the script runs for the whole text. + */ + void SetScripts( const Vector& text, + const Vector& lineBreakInfo, + Vector& scripts ); + + /** + * Replaces the scrips of the given range of characters. + * + * @pre The @p model needs to have a text set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ + void ReplaceScripts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + + /** + * @brief Validates the character's font of the whole text. + * + * It may update fonts set by application developers. + * + * This method ensures all characters are going to be rendered using an appropriate font. Provided a valid font + * exists in the platform. + * + * For those characters with no font set, it sets a default one. + * + * If a font has been set by the application developer, this method checks if the font supports the character. + * If it doesn't, this method replaces it by a default one. + * + * @param[in] text Vector of UTF-32 characters. + * @param[in] scripts Vector containing the script runs for the whole text. + * @param[in,out] fonts Initially contains the fonts set by the application developers. Returns the validated fonts. + */ + void ValidateFonts( const Vector& text, + const Vector& scripts, + Vector& fonts ); + + /** + * Validates the character's font of the given range of characters. + * + * It may update fonts set by the mark-up processor. + * It sets default fonts based on the script to those characters without a font set. + * + * @pre The @p model needs to have a text set. + * @pre The @p model needs to have the scripts set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ + void ValidateFonts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_H__ diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp new file mode 100644 index 0000000..16fdc8a --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp @@ -0,0 +1,153 @@ + /* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +//#define DISPLAY_ATLAS + +AtlasGlyphManager::AtlasGlyphManager() +: mCount( 0 ) +{ + mAtlasManager = Dali::Toolkit::AtlasManager::New(); +} + +AtlasGlyphManager::~AtlasGlyphManager() +{ +} + +AtlasGlyphManagerPtr AtlasGlyphManager::New() +{ + AtlasGlyphManagerPtr internal = new AtlasGlyphManager(); + return internal; +} + +void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph, + const BufferImage& bitmap, + Dali::Toolkit::AtlasManager::AtlasSlot& slot ) +{ + GlyphRecord record; + record.mFontId = glyph.fontId; + record.mIndex = glyph.index; + + mAtlasManager.Add( bitmap, slot ); + record.mImageId = slot.mImageId; + mGlyphRecords.PushBack( record ); + +#ifdef DISPLAY_ATLAS + { + uint32_t atlasCount = mAtlasManager.GetAtlasCount(); + if ( atlasCount > mCount ) + { + for ( uint32_t i = 0; i < atlasCount; ++i ) + { + ImageActor actor = ImageActor::New( mAtlasManager.GetAtlasContainer( i + 1u ) ); + actor.SetParentOrigin( Vector3( 0.5f, 0.25f + ( static_cast< float >( i ) * 0.25f ), 0.5f ) ); + actor.SetAnchorPoint( AnchorPoint::CENTER ); + actor.SetSize( 256.0f, 256.0f ); + Stage::GetCurrent().Add( actor ); + } + } + mCount = atlasCount; + } +#endif +} + +void AtlasGlyphManager::GenerateMeshData( uint32_t imageId, + const Vector2& position, + MeshData& meshData ) +{ + mAtlasManager.GenerateMeshData( imageId, position, meshData ); +} + +void AtlasGlyphManager::StitchMesh( MeshData& first, + const MeshData& second ) +{ + mAtlasManager.StitchMesh( first, second ); +} + +void AtlasGlyphManager::Cached( Text::FontId fontId, + uint32_t index, + Dali::Toolkit::AtlasManager::AtlasSlot& slot ) +{ + for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i ) + { + if ( fontId == mGlyphRecords[ i ].mFontId && index == mGlyphRecords[ i ].mIndex ) + { + slot.mImageId = mGlyphRecords[ i ].mImageId; + slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId ); + return; + } + } + slot.mImageId = 0; +} + +Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId ) +{ + return mAtlasManager.GetAtlasSize( atlasId ); +} + +void AtlasGlyphManager::SetNewAtlasSize( const Vector2& size, + const Vector2& blockSize ) +{ + mAtlasManager.SetNewAtlasSize( size, blockSize ); +} + +void AtlasGlyphManager::Remove( uint32_t imageId ) +{ + if ( mAtlasManager.Remove( imageId ) ) + { + for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i ) + { + if ( mGlyphRecords[ i ].mImageId == imageId ) + { + mGlyphRecords.Remove( mGlyphRecords.Begin() + i ); + return; + } + } + } +} + +Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId ) +{ + return mAtlasManager.GetPixelFormat( atlasId ); +} + +const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics() +{ + mMetrics.mGlyphCount = mGlyphRecords.Size(); + mAtlasManager.GetMetrics( mMetrics.mAtlasMetrics ); + return mMetrics; +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h new file mode 100644 index 0000000..5068426 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h @@ -0,0 +1,154 @@ + +#ifndef __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__ +#define __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +class AtlasGlyphManager; + +} // namespace Toolkit + +namespace Toolkit +{ + +namespace Internal +{ + +class AtlasGlyphManager; +typedef IntrusivePtr AtlasGlyphManagerPtr; + +class AtlasGlyphManager : public Dali::BaseObject +{ +public: + + struct GlyphRecord + { + Text::FontId mFontId; + Text::GlyphIndex mIndex; + uint32_t mImageId; + }; + + AtlasGlyphManager(); + + virtual ~AtlasGlyphManager(); + +/** + * Create a new AtlasGlyphManager + */ + static AtlasGlyphManagerPtr New(); + + /** + * @copydoc Toolkit::AtlasGlyphManager::Add + */ + void Add( const Text::GlyphInfo& glyph, + const BufferImage& bitmap, + Dali::Toolkit::AtlasManager::AtlasSlot& slot ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::GenerateMeshData + */ + void GenerateMeshData( uint32_t imageId, + const Vector2& position, + MeshData& meshData ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::StitchMesh + */ + void StitchMesh( MeshData& first, + const MeshData& second ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::Cached + */ + void Cached( Text::FontId fontId, + Text::GlyphIndex index, + Dali::Toolkit::AtlasManager::AtlasSlot& slot ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::GetAtlasSize + */ + Vector2 GetAtlasSize( uint32_t atlasId ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::SetNewAtlasSize + */ + void SetNewAtlasSize( const Vector2& size, + const Vector2& blockSize ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::Remove + */ + void Remove( uint32_t imageId ); + + /** + * @copydoc toolkit::AtlasGlyphManager::GetPixelFormat + */ + Pixel::Format GetPixelFormat( uint32_t atlasId ); + + /** + * @copydoc toolkit::AtlasGlyphManager::GetMetrics + */ + const Toolkit::AtlasGlyphManager::Metrics& GetMetrics(); + +private: + + Dali::Toolkit::AtlasManager mAtlasManager; + Vector< GlyphRecord > mGlyphRecords; + uint32_t mCount; + Toolkit::AtlasGlyphManager::Metrics mMetrics; +}; + +} // namespace Internal + +inline const Internal::AtlasGlyphManager& GetImplementation(const Toolkit::AtlasGlyphManager& manager) +{ + DALI_ASSERT_ALWAYS( manager && "AtlasGlyphManager handle is empty" ); + + const BaseObject& handle = manager.GetBaseObject(); + + return static_cast(handle); +} + +inline Internal::AtlasGlyphManager& GetImplementation(Toolkit::AtlasGlyphManager& manager) +{ + DALI_ASSERT_ALWAYS( manager && "AtlasGlyphManager handle is empty" ); + + BaseObject& handle = manager.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + + + #endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__ \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp new file mode 100644 index 0000000..d46ef18 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp @@ -0,0 +1,129 @@ + /* + * Copyright (c) 2015 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 +#include + +namespace Dali +{ + +namespace Toolkit +{ + +AtlasGlyphManager::AtlasGlyphManager() +{ +} + +AtlasGlyphManager::~AtlasGlyphManager() +{ +} + +AtlasGlyphManager AtlasGlyphManager::Get() +{ + AtlasGlyphManager manager; + + // Check whether the AtlasGlyphManager is already created + SingletonService singletonService( SingletonService::Get() ); + if ( singletonService ) + { + Dali::BaseHandle handle = singletonService.GetSingleton(typeid(AtlasGlyphManager)); + if(handle) + { + // If so, downcast the handle of singleton to AtlasGlyphManager + manager = AtlasGlyphManager(dynamic_cast(handle.GetObjectPtr())); + } + + if(!manager) + { + // If not, create the AtlasGlyphManager and register it as a singleton + manager = AtlasGlyphManager(new Internal::AtlasGlyphManager()); + singletonService.Register(typeid(manager), manager); + } + } + return manager; +} + +AtlasGlyphManager::AtlasGlyphManager(Internal::AtlasGlyphManager *impl) + : BaseHandle(impl) +{ +} + +void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph, + const BufferImage& bitmap, + AtlasManager::AtlasSlot& slot ) +{ + GetImplementation(*this).Add( glyph, bitmap, slot ); +} + +void AtlasGlyphManager::GenerateMeshData( uint32_t imageId, + const Vector2& position, + MeshData& meshData ) +{ + GetImplementation(*this).GenerateMeshData( imageId, + position, + meshData ); +} + +void AtlasGlyphManager::StitchMesh( MeshData& first, + const MeshData& second ) +{ + GetImplementation(*this).StitchMesh( first, second ); +} + +void AtlasGlyphManager::Cached( Text::FontId fontId, + Text::GlyphIndex index, + AtlasManager::AtlasSlot& slot ) +{ + GetImplementation(*this).Cached( fontId, index, slot ); +} + +void AtlasGlyphManager::SetNewAtlasSize( const Vector2& size, + const Vector2& blockSize ) +{ + GetImplementation(*this).SetNewAtlasSize( size, blockSize ); +} + +Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId ) +{ + return GetImplementation(*this).GetAtlasSize( atlasId ); +} + +void AtlasGlyphManager::Remove( uint32_t imageId ) +{ + GetImplementation(*this).Remove( imageId ); +} + +Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId ) +{ + return GetImplementation(*this).GetPixelFormat( atlasId ); +} + +const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics() +{ + return GetImplementation(*this).GetMetrics(); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h new file mode 100644 index 0000000..cbfa754 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h @@ -0,0 +1,164 @@ +#ifndef __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__ +#define __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__ + +/* + * Copyright (c) 2015 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 AtlasGlyphManager; +} + + +class DALI_IMPORT_API AtlasGlyphManager : public BaseHandle +{ +public: + + /** + * Description of GlyphManager state + */ + struct Metrics + { + uint32_t mGlyphCount; // number of glyphs being managed + AtlasManager::Metrics mAtlasMetrics; // metrics from the Atlas Manager + }; + + /** + * @brief Create a AtlasGlyphManager handle. + * + * Calling member functions with an uninitialised handle is not allowed. + */ + AtlasGlyphManager(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~AtlasGlyphManager(); + + /** + * @brief Create or retrieve AtlasGlyphManager singleton. + * + * @return A handle to the AtlasGlyphManager control. + */ + static AtlasGlyphManager Get(); + + /** + * @brief Ask Atlas Manager to add a glyph + * + * @param[in] glyph glyph to add to an atlas + * @param[in] bitmap bitmap to use for glyph addition + * @param[out] slot information returned by atlas manager for addition + */ + void Add( const Text::GlyphInfo& glyph, + const BufferImage& bitmap, + AtlasManager::AtlasSlot& slot ); + + /** + * @brief Generate mesh data for an image contained in an atlas + * + * @param[in] imageId ID of image to generate geometry for + * @param[in] position top left of image + * @param[out] meshData generated MeshData + */ + void GenerateMeshData( uint32_t imageId, + const Vector2& position, + MeshData& meshData ); + + /** + * @brief Stitch Two Meshes together + * + * @param[in] first first mesh + * @param[in] second second mesh + */ + void StitchMesh( MeshData& first, + const MeshData& second ); + + /** + * @brief Check to see if a glyph is being cached + * + * @param[in] fontId The font that this glyph comes from + * @param[in] index The GlyphIndex of this glyph + * @param[out] slot container holding information about the glyph( mImage = 0 indicates not being cached ) + */ + void Cached( Text::FontId fontId, + Text::GlyphIndex index, + AtlasManager::AtlasSlot& slot ); + + /** + * @brief Retrieve the size of an atlas + * + * @param[in] atlasId Id of the atlas to interrogate + * + * @return The pixel size of the atlas + */ + Vector2 GetAtlasSize( uint32_t atlasId ); + + /** + * @brief Set the Atlas size and block size for subsequent atlas generation + * + * @param[in] size size of the atlas in pixels + * @param[in] blockSize size of a block in this atlas in pixels + */ + void SetNewAtlasSize( const Vector2& size, + const Vector2& blockSize ); + + /** + * @brief Unreference an image from the atlas and remove from cache if no longer needed + * + * @param[in] imageId ID of the image + */ + void Remove( uint32_t imageId ); + + /** + * @brief Get the Pixel Format used by an atlas + * + * @param[in] atlasId Id of atlas to check + * + * @return The pixel format of the atlas + */ + Pixel::Format GetPixelFormat( uint32_t atlasId ); + + /** + * @brief Get Glyph Manager metrics + * + * @return const reference to glyph manager metrics + */ + const Metrics& GetMetrics(); + +private: + + explicit DALI_INTERNAL AtlasGlyphManager(Internal::AtlasGlyphManager *impl); + +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__ diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp new file mode 100644 index 0000000..fda82f4 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -0,0 +1,693 @@ +/* + * Copyright (c) 2015 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 + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_ATLAS_RENDERER"); +#endif + +using namespace Dali; +using namespace Dali::Toolkit; +using namespace Dali::Toolkit::Text; + +namespace +{ + const Vector2 DEFAULT_ATLAS_SIZE( 512.0f, 512.0f ); + const Vector2 DEFAULT_BLOCK_SIZE( 16.0f, 16.0f ); + const Vector2 PADDING( 4.0f, 4.0f ); // Allow for variation in font glyphs +} + +struct AtlasRenderer::Impl : public ConnectionTracker +{ + + enum Style + { + STYLE_NORMAL, + STYLE_DROP_SHADOW + }; + + struct MeshRecord + { + Vector4 mColor; + uint32_t mAtlasId; + MeshData mMeshData; + FrameBufferImage mBuffer; + bool mIsUnderline; + }; + + struct Extent + { + float mBaseLine; + float mLeft; + float mRight; + float mUnderlinePosition; + float mUnderlineThickness; + uint32_t mMeshRecordIndex; + }; + + struct AtlasRecord + { + uint32_t mImageId; + Text::GlyphIndex mIndex; + }; + + struct MaxBlockSize + { + FontId mFontId; + Vector2 mNeededBlockSize; + }; + + Impl() + { + mGlyphManager = AtlasGlyphManager::Get(); + mFontClient = TextAbstraction::FontClient::Get(); + mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_SIZE, DEFAULT_BLOCK_SIZE ); + mBasicShader = BasicShader::New(); + mBgraShader = BgraShader::New(); + mBasicShadowShader = BasicShadowShader::New(); + + mFace.reserve( 6u ); + mFace.push_back( 0 ); mFace.push_back( 2u ); mFace.push_back( 1u ); + mFace.push_back( 1u ); mFace.push_back( 2u ); mFace.push_back( 3u ); + } + + void AddGlyphs( const std::vector& positions, + const Vector& glyphs, + const Vector4& textColor, + const Vector2& shadowOffset, + const Vector4& shadowColor, + float underlineEnabled, + const Vector4& underlineColor ) + { + AtlasManager::AtlasSlot slot; + std::vector< MeshRecord > meshContainer; + Vector< Extent > extents; + + float currentUnderlinePosition = 0.0f; + float currentUnderlineThickness = 0.0f; + FontId lastFontId = 0; + Style style = STYLE_NORMAL; + + if ( shadowOffset.x != 0.0f || shadowOffset.y != 0.0f ) + { + style = STYLE_DROP_SHADOW; + } + + if ( mImageIds.Size() ) + { + // Unreference any currently used glyphs + RemoveText(); + } + + CalculateBlocksSize( glyphs ); + + for ( uint32_t i = 0; i < glyphs.Size(); ++i ) + { + GlyphInfo glyph = glyphs[ i ]; + + // No operation for white space + if ( glyph.width && glyph.height ) + { + // Are we still using the same fontId as previous + if ( glyph.fontId != lastFontId ) + { + // We need to fetch fresh font underline metrics + FontMetrics fontMetrics; + mFontClient.GetFontMetrics( glyph.fontId, fontMetrics ); + currentUnderlinePosition = fontMetrics.underlinePosition; + currentUnderlineThickness = fontMetrics.underlineThickness; + + // Ensure that an underline is at least 1 pixel high + if ( currentUnderlineThickness < 1.0f ) + { + currentUnderlineThickness = 1.0f; + } + } + + Vector2 position = positions[ i ]; + MeshData newMeshData; + mGlyphManager.Cached( glyph.fontId, glyph.index, slot ); + + if ( slot.mImageId ) + { + // This glyph already exists so generate mesh data plugging in our supplied position + mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData ); + mImageIds.PushBack( slot.mImageId ); + } + else + { + + // Select correct size for new atlas if needed....? + if ( lastFontId != glyph.fontId ) + { + for ( uint32_t j = 0; j < mBlockSizes.size(); ++j ) + { + if ( mBlockSizes[ j ].mFontId == glyph.fontId ) + { + mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_SIZE, mBlockSizes[ j ].mNeededBlockSize ); + } + } + lastFontId = glyph.fontId; + } + + // Glyph doesn't currently exist in atlas so upload + BufferImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index ); + + // Locate a new slot for our glyph + mGlyphManager.Add( glyph, bitmap, slot ); + + // Generate mesh data for this quad, plugging in our supplied position + if ( slot.mImageId ) + { + mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData ); + mImageIds.PushBack( slot.mImageId ); + } + } + // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas) + StitchTextMesh( meshContainer, + newMeshData, + extents, + textColor, + position.y + glyph.yBearing, + currentUnderlinePosition, + currentUnderlineThickness, + slot ); + } + } + + if ( underlineEnabled ) + { + // Check to see if any of the text needs an underline + GenerateUnderlines( meshContainer, extents, underlineColor, textColor ); + } + + // For each MeshData object, create a mesh actor and add to the renderable actor + if ( meshContainer.size() ) + { + for ( std::vector< MeshRecord >::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt ) + { + MeshActor actor = MeshActor::New( Mesh::New( mIt->mMeshData ) ); + actor.SetColor( mIt->mColor ); + if ( mIt->mIsUnderline ) + { + actor.SetColorMode( USE_OWN_COLOR ); + } + else + { + actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + } + + // Check to see what pixel format the shader should be + if ( mGlyphManager.GetPixelFormat( mIt->mAtlasId ) == Pixel::L8 ) + { + // Create an effect if necessary + if ( style == STYLE_DROP_SHADOW ) + { + actor.Add( GenerateShadow( *mIt, shadowOffset, shadowColor ) ); + } + actor.SetShaderEffect( mBasicShader ); + } + else + { + actor.SetShaderEffect( mBgraShader ); + } + + if ( mActor ) + { + mActor.Add( actor ); + } + else + { + mActor = actor; + } + } + mActor.OffStageSignal().Connect( this, &AtlasRenderer::Impl::OffStageDisconnect ); + } +#if defined(DEBUG_ENABLED) + Toolkit::AtlasGlyphManager::Metrics metrics = mGlyphManager.GetMetrics(); + DALI_LOG_INFO( gLogFilter, Debug::Concise, "TextAtlasRenderer::GlyphManager::GlyphCount: %i, AtlasCount: %i, TextureMemoryUse: %iK\n", + metrics.mGlyphCount, + metrics.mAtlasMetrics.mAtlasCount, + metrics.mAtlasMetrics.mTextureMemoryUsed / 1024 ); + for ( uint32_t i = 0; i < metrics.mAtlasMetrics.mAtlasCount; ++i ) + { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Atlas [%i] %sPixels: %s Size: %ix%i, BlockSize: %ix%i, BlocksUsed: %i/%i\n", + i + 1, i > 8 ? "" : " ", + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mPixelFormat == Pixel::L8 ? "L8 " : "BGRA", + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mWidth, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mHeight, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mBlockWidth, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mBlockHeight, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mBlocksUsed, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mTotalBlocks ); + } +#endif + } + + void StitchTextMesh( std::vector< MeshRecord >& meshContainer, + MeshData& newMeshData, + Vector< Extent >& extents, + const Vector4& color, + float baseLine, + float underlinePosition, + float underlineThickness, + AtlasManager::AtlasSlot& slot ) + { + if ( slot.mImageId ) + { + MeshData::VertexContainer verts = newMeshData.GetVertices(); + float left = verts[ 0 ].x; + float right = verts[ 1 ].x; + + // Check to see if there's a mesh data object that references the same atlas ? + uint32_t index = 0; + for ( std::vector< MeshRecord >::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt, ++index ) + { + if ( slot.mAtlasId == mIt->mAtlasId ) + { + // Stitch the mesh to the existing mesh and adjust any extents + mGlyphManager.StitchMesh( mIt->mMeshData, newMeshData ); + AdjustExtents( extents, + meshContainer, + index, + color, + left, + right, + baseLine, + underlinePosition, + underlineThickness ); + return; + } + } + + // No mesh data object currently exists that references this atlas, so create a new one + MeshRecord meshRecord; + meshRecord.mAtlasId = slot.mAtlasId; + meshRecord.mMeshData = newMeshData; + meshRecord.mColor = color; + meshRecord.mIsUnderline = false; + meshContainer.push_back( meshRecord ); + + // Adjust extents for this new meshrecord + AdjustExtents( extents, + meshContainer, + meshContainer.size() - 1u, + color, + left, + right, + baseLine, + underlinePosition, + underlineThickness ); + + } + } + + void AdjustExtents( Vector< Extent >& extents, + std::vector< MeshRecord>& meshRecords, + uint32_t index, + const Vector4& color, + float left, + float right, + float baseLine, + float underlinePosition, + float underlineThickness ) + { + bool foundExtent = false; + for ( Vector< Extent >::Iterator eIt = extents.Begin(); eIt != extents.End(); ++eIt ) + { + if ( Equals( baseLine, eIt->mBaseLine ) ) + { + // If we've found an extent with the same color then we don't need to create a new extent + if ( color == meshRecords[ index ].mColor ) + { + foundExtent = true; + if ( left < eIt->mLeft ) + { + eIt->mLeft = left; + } + if ( right > eIt->mRight ) + { + eIt->mRight = right; + } + } + // Font metrics use negative values for lower underline positions + if ( underlinePosition < eIt->mUnderlinePosition ) + { + eIt->mUnderlinePosition = underlinePosition; + } + if ( underlineThickness > eIt->mUnderlineThickness ) + { + eIt->mUnderlineThickness = underlineThickness; + } + } + } + if ( !foundExtent ) + { + Extent extent; + extent.mLeft = left; + extent.mRight = right; + extent.mBaseLine = baseLine; + extent.mUnderlinePosition = underlinePosition; + extent.mUnderlineThickness = underlineThickness; + extent.mMeshRecordIndex = index; + extents.PushBack( extent ); + } + } + + // Unreference any glyphs that were used with this actor + void OffStageDisconnect( Dali::Actor actor ) + { + RemoveText(); + } + + void RemoveText() + { + for ( uint32_t i = 0; i < mImageIds.Size(); ++i ) + { + mGlyphManager.Remove( mImageIds[ i ] ); + } + mImageIds.Resize( 0 ); + } + + void CalculateBlocksSize( const Vector& glyphs ) + { + MaxBlockSize maxBlockSize; + for ( uint32_t i = 0; i < glyphs.Size(); ++i ) + { + // Get the fontId of this glyph and check to see if a max size exists? + FontId fontId = glyphs[ i ].fontId; + float paddedWidth = glyphs[ i ].width + PADDING.x; + float paddedHeight = glyphs[ i ].height + PADDING.y; + bool foundFont = false; + + for ( uint32_t j = 0; j < mBlockSizes.size(); ++j ) + { + if ( mBlockSizes[ j ].mFontId == fontId ) + { + foundFont = true; + if ( mBlockSizes[ j ].mNeededBlockSize.x < paddedWidth ) + { + mBlockSizes[ j ].mNeededBlockSize.x = paddedWidth; + } + if ( mBlockSizes[ j ].mNeededBlockSize.y < paddedHeight ) + { + mBlockSizes[ j ].mNeededBlockSize.y = paddedHeight; + } + } + } + + if ( !foundFont ) + { + maxBlockSize.mNeededBlockSize = Vector2( paddedWidth, paddedHeight ); + maxBlockSize.mFontId = fontId; + mBlockSizes.push_back( maxBlockSize ); + } + } + } + + void GenerateUnderlines( std::vector< MeshRecord>& meshRecords, + Vector< Extent >& extents, + const Vector4& underlineColor, + const Vector4& textColor ) + { + MeshData newMeshData; + const float zero = 0.0f; + const float half = 0.5f; + + for ( Vector< Extent >::ConstIterator eIt = extents.Begin(); eIt != extents.End(); ++eIt ) + { + MeshData::VertexContainer newVerts; + newVerts.reserve( 4u ); + uint32_t index = eIt->mMeshRecordIndex; + Vector2 uv = mGlyphManager.GetAtlasSize( meshRecords[ index ].mAtlasId ); + + // Make sure we don't hit texture edge for single pixel texture ( filled pixel is in top left of every atlas ) + float u = half / uv.x; + float v = half / uv.y; + float thickness = eIt->mUnderlineThickness; + float baseLine = eIt->mBaseLine - eIt->mUnderlinePosition - ( thickness * 0.5f ); + float tlx = eIt->mLeft; + float brx = eIt->mRight; + + newVerts.push_back( MeshData::Vertex( Vector3( tlx, baseLine, zero ), + Vector2( zero, zero ), + Vector3( zero, zero, zero ) ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( brx, baseLine, zero ), + Vector2( u, zero ), + Vector3( zero, zero, zero ) ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( tlx, baseLine + thickness, zero ), + Vector2( zero, v ), + Vector3( zero, zero, zero ) ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( brx, baseLine + thickness, zero ), + Vector2( u, v ), + Vector3( zero, zero, zero ) ) ); + + newMeshData.SetVertices( newVerts ); + newMeshData.SetFaceIndices( mFace ); + + if ( underlineColor == textColor ) + { + mGlyphManager.StitchMesh( meshRecords[ index ].mMeshData, newMeshData ); + } + else + { + MeshRecord record; + newMeshData.SetMaterial( meshRecords[ index ].mMeshData.GetMaterial() ); + newMeshData.SetHasNormals( true ); + newMeshData.SetHasColor( false ); + newMeshData.SetHasTextureCoords( true ); + record.mMeshData = newMeshData; + record.mAtlasId = meshRecords[ index ].mAtlasId; + record.mColor = underlineColor; + record.mIsUnderline = true; + meshRecords.push_back( record ); + } + } + } + + MeshActor GenerateShadow( MeshRecord& meshRecord, + const Vector2& shadowOffset, + const Vector4& shadowColor ) + { + // Scan vertex buffer to determine width and height of effect buffer needed + MeshData::VertexContainer verts = meshRecord.mMeshData.GetVertices(); + const float one = 1.0f; + const float zero = 0.0f; + float tlx = verts[ 0 ].x; + float tly = verts[ 0 ].y; + float brx = zero; + float bry = zero; + + for ( uint32_t i = 0; i < verts.size(); ++i ) + { + if ( verts[ i ].x < tlx ) + { + tlx = verts[ i ].x; + } + if ( verts[ i ].y < tly ) + { + tly = verts[ i ].y; + } + if ( verts[ i ].x > brx ) + { + brx = verts[ i ].x; + } + if ( verts[ i ].y > bry ) + { + bry = verts[ i ].y; + } + } + + float width = brx - tlx; + float height = bry - tly; + float divWidth = 2.0f / width; + float divHeight = 2.0f / height; + + // Create a buffer to render to + meshRecord.mBuffer = FrameBufferImage::New( width, height ); + + // Create a mesh actor to contain the post-effect render + MeshData::VertexContainer vertices; + MeshData::FaceIndices face; + + vertices.push_back( MeshData::Vertex( Vector3( tlx + shadowOffset.x, tly + shadowOffset.y, zero ), + Vector2( zero, zero ), + Vector3( zero, zero, zero ) ) ); + + vertices.push_back( MeshData::Vertex( Vector3( brx + shadowOffset.x, tly + shadowOffset.y, zero ), + Vector2( one, zero ), + Vector3( zero, zero, zero ) ) ); + + vertices.push_back( MeshData::Vertex( Vector3( tlx + shadowOffset.x, bry + shadowOffset.y, zero ), + Vector2( zero, one ), + Vector3( zero, zero, zero ) ) ); + + vertices.push_back( MeshData::Vertex( Vector3( brx + shadowOffset.x, bry + shadowOffset.y, zero ), + Vector2( one, one ), + Vector3( zero, zero, zero ) ) ); + + MeshData meshData; + Material newMaterial = Material::New("effect buffer"); + newMaterial.SetDiffuseTexture( meshRecord.mBuffer ); + meshData.SetMaterial( newMaterial ); + meshData.SetVertices( vertices ); + meshData.SetFaceIndices( mFace ); + meshData.SetHasNormals( true ); + meshData.SetHasColor( false ); + meshData.SetHasTextureCoords( true ); + MeshActor actor = MeshActor::New( Mesh::New( meshData ) ); + actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + actor.SetShaderEffect( mBgraShader ); + actor.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); + actor.SetSortModifier( 0.1f ); // force behind main text + + // Create a sub actor to render once with normalized vertex positions + MeshData newMeshData; + MeshData::VertexContainer newVerts; + MeshData::FaceIndices newFaces; + MeshData::FaceIndices faces = meshRecord.mMeshData.GetFaces(); + for ( uint32_t i = 0; i < verts.size(); ++i ) + { + MeshData::Vertex vertex = verts[ i ]; + vertex.x = ( ( vertex.x - tlx ) * divWidth ) - one; + vertex.y = ( ( vertex.y - tly ) * divHeight ) - one; + newVerts.push_back( vertex ); + } + + // Reverse triangle winding order + uint32_t faceCount = faces.size() / 3; + for ( uint32_t i = 0; i < faceCount; ++i ) + { + uint32_t index = i * 3; + newFaces.push_back( faces[ index + 2 ] ); + newFaces.push_back( faces[ index + 1 ] ); + newFaces.push_back( faces[ index ] ); + } + + newMeshData.SetMaterial( meshRecord.mMeshData.GetMaterial() ); + newMeshData.SetVertices( newVerts ); + newMeshData.SetFaceIndices( newFaces ); + newMeshData.SetHasNormals( true ); + newMeshData.SetHasColor( false ); + newMeshData.SetHasTextureCoords( true ); + + MeshActor subActor = MeshActor::New( Mesh::New( newMeshData ) ); + subActor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + subActor.SetColor( shadowColor ); + subActor.SetShaderEffect( mBasicShadowShader ); + subActor.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); + + // Create a render task to render the effect + RenderTask task = Stage::GetCurrent().GetRenderTaskList().CreateTask(); + task.SetTargetFrameBuffer( meshRecord.mBuffer ); + task.SetSourceActor( subActor ); + task.SetClearEnabled( true ); + task.SetClearColor( Vector4::ZERO ); + task.SetExclusive( true ); + task.SetRefreshRate( RenderTask::REFRESH_ONCE ); + task.FinishedSignal().Connect( this, &AtlasRenderer::Impl::RenderComplete ); + actor.Add( subActor ); + return actor; + } + + void RenderComplete( RenderTask& renderTask ) + { + // Disconnect and remove this single shot render task + renderTask.FinishedSignal().Disconnect( this, &AtlasRenderer::Impl::RenderComplete ); + Stage::GetCurrent().GetRenderTaskList().RemoveTask( renderTask ); + + // Get the actor used for render to buffer and remove it from the parent + Actor renderActor = renderTask.GetSourceActor(); + if ( renderActor ) + { + Actor parent = renderActor.GetParent(); + if ( parent ) + { + parent.Remove( renderActor ); + } + } + } + + RenderableActor mActor; ///< The actor parent which renders the text + AtlasGlyphManager mGlyphManager; ///< Glyph Manager to handle upload and caching + Vector< uint32_t > mImageIds; ///< A list of imageIDs used by the renderer + TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information + ShaderEffect mBasicShader; ///> Shader used to render L8 glyphs + ShaderEffect mBgraShader; ///> Shader used to render BGRA glyphs + ShaderEffect mBasicShadowShader; ///> Shader used to render drop shadow into buffer + std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas + std::vector< MeshData::FaceIndex > mFace; ///> Face indices for a quad +}; + +Text::RendererPtr AtlasRenderer::New() +{ + return Text::RendererPtr( new AtlasRenderer() ); +} + +RenderableActor AtlasRenderer::Render( Text::ViewInterface& view ) +{ + + UnparentAndReset( mImpl->mActor ); + + Text::Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + if( numberOfGlyphs > 0 ) + { + Vector glyphs; + glyphs.Resize( numberOfGlyphs ); + + view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs ); + + std::vector positions; + positions.resize( numberOfGlyphs ); + view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs ); + mImpl->AddGlyphs( positions, + glyphs, + view.GetTextColor(), + view.GetShadowOffset(), + view.GetShadowColor(), + view.IsUnderlineEnabled(), + view.GetUnderlineColor() ); + } + return mImpl->mActor; +} + +AtlasRenderer::AtlasRenderer() +{ + mImpl = new Impl(); + +} + +AtlasRenderer::~AtlasRenderer() +{ + delete mImpl; +} \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.h b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.h new file mode 100644 index 0000000..e259621 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.h @@ -0,0 +1,87 @@ +#ifndef __DALI_TOOLKIT_TEXT_ATLAS_RENDERER_H__ +#define __DALI_TOOLKIT_TEXT_ATLAS_RENDERER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief Implementation of a text renderer based on dynamic atlases. + * + */ +class AtlasRenderer : public Renderer +{ +public: + + /** + * @brief Create the renderer. + */ + static RendererPtr New(); + + /** + * @brief Render the glyphs from a ViewInterface. + * + * @param[in] view The interface to a view. + * @return The Renderable actor used to position the text. + */ + virtual RenderableActor Render( ViewInterface& view ); + +protected: + + /** + * @brief Constructor. + */ + AtlasRenderer(); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~AtlasRenderer(); + +private: + + // Undefined + AtlasRenderer( const AtlasRenderer& handle ); + + // Undefined + AtlasRenderer& operator=( const AtlasRenderer& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_ATLAS_RENDERER_H__ diff --git a/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp new file mode 100644 index 0000000..dc6ec3e --- /dev/null +++ b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2015 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 +#include +#include +#include +#include +#include +#include + + +using namespace Dali; +using namespace Dali::Toolkit; +using namespace Dali::Toolkit::Text; + +namespace +{ + +const std::size_t PADDING = 2; //< To avoid GL filtering artefacts + +struct TextureCoordinates +{ + TextureCoordinates() + : topLeft( 0.0f, 0.0f ), + topRight( 1.0f, 0.0f ), + bottomLeft( 0.0f, 1.0f ), + bottomRight( 1.0f, 1.0f ) + { + } + + Vector2 topLeft; + Vector2 topRight; + Vector2 bottomLeft; + Vector2 bottomRight; +}; + +struct AtlasGlyph +{ + AtlasGlyph() + : fontId( 0 ), + index( 0 ), + xOffset( 0 ), + width( 0 ), + height( 0 ) + { + } + + AtlasGlyph( FontId id, + GlyphIndex glyphIndex, + std::size_t offset, + std::size_t widthPixels, + std::size_t heightPixels, + BufferImage bitmap ) + : fontId( id ), + index( glyphIndex ), + xOffset( offset ), + width( widthPixels ), + height( heightPixels ), + mBitmap( bitmap ) + { + } + + FontId fontId; + GlyphIndex index; + std::size_t xOffset; + std::size_t width; + std::size_t height; + BufferImage mBitmap; + TextureCoordinates coords; +}; + +} // unnamed namespace + +struct BasicRenderer::Impl +{ + /** + * @brief Create the renderer implementation. + */ + Impl() + : mWidthL8( 0.0f ), + mHeightL8( 0.0f ), + mWidthBGRA8888( 0.0f ), + mHeightBGRA8888( 0.0f ) + { + mFontClient = TextAbstraction::FontClient::Get(); + } + + /** + * @brief Reset the previous glyph calculations. + * + * @param[in] size The glyph space to reserve. + */ + void Reset( std::size_t size ) + { + mWidthL8 = 0.0f; + mHeightL8 = 0.0f; + mWidthBGRA8888 = 0.0f; + mHeightBGRA8888 = 0.0f; + mGlyphs.clear(); + mGlyphs.reserve( size ); + mAtlasL8.Reset(); + mAtlasBGRA8888.Reset(); + } + + /** + * @brief Ccreate an Atlas, uploading the necessary glyph bitmaps + * + * @param[in] glyphs The glyphs to upload. + */ + void CreateAtlases( const Vector& glyphs ) + { + // Clear previous atlas + Reset( glyphs.Count() ); + + for( unsigned int i=0; i 0 && + height > 0 ) // skip whitespace + { + if( !GlyphFound( glyphs[i].fontId, glyphs[i].index ) ) + { + AddGlyph( glyphs[i] ); + } + } + } + + mAtlasL8 = CreateAtlas( mWidthL8, mHeightL8, Pixel::L8 ); + mAtlasBGRA8888 = CreateAtlas( mWidthBGRA8888, mHeightBGRA8888, Pixel::BGRA8888 ); + } + + Atlas CreateAtlas( unsigned int width, unsigned int height, Pixel::Format format ) + { + Atlas atlas; + + if( width > 0 && height > 0 ) + { + atlas = Atlas::New( width, height, format ); + + for( unsigned int i=0; i(glyph.xOffset) / static_cast(width); + coords.topLeft.y = 0.0f; + coords.topRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(width); + coords.topRight.y = 0.0f; + coords.bottomLeft.x = static_cast(glyph.xOffset) / static_cast(width); + coords.bottomLeft.y = static_cast(glyph.height) / static_cast(height); + coords.bottomRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(width); + coords.bottomRight.y = static_cast(glyph.height) / static_cast(height); + } + } + } + + return atlas; + } + + /** + * @brief Check whether we already have the glyph. + */ + bool GlyphFound( FontId fontId, GlyphIndex index ) const + { + for( unsigned int i=0; i& glyphs, const std::vector& positions, Pixel::Format format, Image image ) + { + MeshData::VertexContainer vertices( 4 * glyphs.Count() ); // 1 quad per glyph + + MeshData::FaceIndices faces; + faces.reserve( 6 * glyphs.Count() ); // 2 triangles per quad + + for( unsigned int i=0; i 0 && + height > 0 ) // skip whitespace + { + const Vector2& position = positions[i]; + + TextureCoordinates coords; + if( GetTextureCoordinates( format, glyphs[i].fontId, glyphs[i].index, coords ) ) + { + vertices[ i*4 + 0 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 0.0f*height, 0.0f ), coords.topLeft, Vector3( 1.0f, 0.0f, 0.0f ) ); + vertices[ i*4 + 1 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 0.0f*height, 0.0f ), coords.topRight, Vector3( 1.0f, 1.0f, 0.0f ) ); + vertices[ i*4 + 2 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomLeft, Vector3( 0.0f, 1.0f, 0.0f ) ); + vertices[ i*4 + 3 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomRight, Vector3( 0.0f, 0.0f, 1.0f ) ); + + faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 3 ); faces.push_back( i*4 + 1 ); + faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 2 ); faces.push_back( i*4 + 3 ); + } + } + } + + Material material = Material::New( "Material" ); + material.SetDiffuseTexture( image ); + + // Create the mesh data from the vertices and faces + MeshData meshData; + meshData.SetHasColor( false ); + meshData.SetMaterial( material ); + meshData.SetVertices( vertices ); + meshData.SetFaceIndices( faces ); + + // Create a mesh from the data + Dali::Mesh mesh = Mesh::New( meshData ); + return mesh; + } + + RenderableActor mActor; ///< The actor which renders the text + + Atlas mAtlasL8; + unsigned int mWidthL8; + unsigned int mHeightL8; + + // A separate Atlas is used for color Emojis + Atlas mAtlasBGRA8888; + unsigned int mWidthBGRA8888; + unsigned int mHeightBGRA8888; + + std::vector mGlyphs; + + TextAbstraction::FontClient mFontClient; +}; + +Text::RendererPtr BasicRenderer::New() +{ + return Text::RendererPtr( new BasicRenderer() ); +} + +RenderableActor BasicRenderer::Render( Text::ViewInterface& view ) +{ + // Remove the previous text + UnparentAndReset( mImpl->mActor ); + + Text::Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + if( numberOfGlyphs > 0 ) + { + Vector glyphs; + glyphs.Resize( numberOfGlyphs ); + + view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs ); + + std::vector positions; + positions.resize( numberOfGlyphs ); + view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs ); + + mImpl->CreateAtlases( glyphs ); + + MeshActor actorL8; + if( mImpl->mAtlasL8 ) + { + actorL8 = MeshActor::New( mImpl->CreateMesh( glyphs, positions, Pixel::L8, mImpl->mAtlasL8 ) ); + actorL8.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + + ShaderEffect shader = BasicShader::New(); + actorL8.SetShaderEffect( shader ); + } + + MeshActor actorBGRA8888; + if( mImpl->mAtlasBGRA8888 ) + { + actorBGRA8888 = MeshActor::New( mImpl->CreateMesh( glyphs, positions, Pixel::BGRA8888, mImpl->mAtlasBGRA8888 ) ); + actorBGRA8888.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + + ShaderEffect shader = BgraShader::New(); + actorBGRA8888.SetShaderEffect( shader ); + } + + // If we have both monochrome & color glyphs, two mesh actors are returned in a container + if( actorL8 && actorBGRA8888 ) + { + mImpl->mActor = ImageActor::New(); + mImpl->mActor.Add( actorL8 ); + mImpl->mActor.Add( actorBGRA8888 ); + } + else + { + if( actorL8 ) + { + mImpl->mActor = actorL8; + } + else if( actorBGRA8888 ) + { + mImpl->mActor = actorBGRA8888; + } + } + } + + return mImpl->mActor; +} + +BasicRenderer::BasicRenderer() +{ + mImpl = new Impl(); +} + +BasicRenderer::~BasicRenderer() +{ + delete mImpl; +} diff --git a/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.h b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.h new file mode 100644 index 0000000..1cf8469 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.h @@ -0,0 +1,90 @@ +#ifndef __DALI_TOOLKIT_TEXT_BASIC_RENDERER_H__ +#define __DALI_TOOLKIT_TEXT_BASIC_RENDERER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A reference implementation of Text::Renderer. + * + * This is intended for testing & performance comparisons with more complex solutions. + * Each basic renderer creates its own texture atlas, and uses a simple packing algorithm, + * in which glyphs are stored in a single row. + */ +class BasicRenderer : public Renderer +{ +public: + + /** + * @brief Create the renderer. + */ + static RendererPtr New(); + + /** + * @brief Render the glyphs from a ViewInterface. + * + * @param[in] view The interface to a view. + * @return The Renderable actor used to position the text. + */ + virtual RenderableActor Render( ViewInterface& view ); + +protected: + + /** + * @brief Constructor. + */ + BasicRenderer(); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~BasicRenderer(); + +private: + + // Undefined + BasicRenderer( const BasicRenderer& handle ); + + // Undefined + BasicRenderer& operator=( const BasicRenderer& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BASIC_RENDERER_H__ diff --git a/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.cpp b/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.cpp new file mode 100644 index 0000000..0afddbb --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace BasicShader +{ + +Dali::ShaderEffect New() +{ + std::string vertexShader = DALI_COMPOSE_SHADER( + uniform mediump vec4 uTextureRect;\n + void main()\n + {\n + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + }\n + ); + + std::string fragmentShader = DALI_COMPOSE_SHADER( + void main()\n + {\n + mediump vec4 color = texture2D( sTexture, vTexCoord ); + gl_FragColor = vec4(uColor.rgb, uColor.a*color.r); + }\n + ); + + Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( vertexShader, fragmentShader, + Dali::GeometryType( Dali::GEOMETRY_TYPE_TEXTURED_MESH ), + Dali::ShaderEffect::GeometryHints( Dali::ShaderEffect::HINT_NONE ) ); + return shaderEffect; +} + +} // namespace BasicShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h b/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h new file mode 100644 index 0000000..cc97d1b --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h @@ -0,0 +1,53 @@ +#ifndef __DALI_TOOLKIT_TEXT_BASIC_SHADER_H__ +#define __DALI_TOOLKIT_TEXT_BASIC_SHADER_H__ + +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A basic shader for rendering glyphs in Pixel::L8 format. + */ +namespace BasicShader +{ + +/** + * Create a basic text shader. + * @return A handle to a newly allocated ShaderEffect + */ +Dali::ShaderEffect New(); + +} // namespace BasicShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BASIC_SHADER_H__ diff --git a/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.cpp b/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.cpp new file mode 100644 index 0000000..f7789f1 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace BasicShadowShader +{ + +Dali::ShaderEffect New() +{ + std::string vertexShader = DALI_COMPOSE_SHADER( + void main()\n + {\n + gl_Position = vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + }\n + ); + + std::string fragmentShader = DALI_COMPOSE_SHADER( + void main()\n + {\n + mediump vec4 color = texture2D( sTexture, vTexCoord ); + gl_FragColor = vec4(uColor.rgb, uColor.a*color.r); + }\n + ); + + Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( vertexShader, fragmentShader, + Dali::GeometryType( Dali::GEOMETRY_TYPE_TEXTURED_MESH ), + Dali::ShaderEffect::GeometryHints( Dali::ShaderEffect::HINT_NONE ) ); + return shaderEffect; +} + +} // namespace BasicShadowShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.h b/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.h new file mode 100644 index 0000000..93bd0a3 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.h @@ -0,0 +1,53 @@ +#ifndef __DALI_TOOLKIT_TEXT_BASIC_SHADOW_SHADER_H__ +#define __DALI_TOOLKIT_TEXT_BASIC_SHADOW_SHADER_H__ + +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A basic shader for rendering glyphs in Pixel::L8 format. + */ +namespace BasicShadowShader +{ + +/** + * Create a basic text shadow shader. + * @return A handle to a newly allocated ShaderEffect + */ +Dali::ShaderEffect New(); + +} // namespace BasicShadowShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BASIC_SHADOW_SHADER_H__ diff --git a/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.cpp b/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.cpp new file mode 100644 index 0000000..7f2f2a5 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 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 HEADERS +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace BgraShader +{ + +Dali::ShaderEffect New() +{ + std::string vertexShader = DALI_COMPOSE_SHADER( + uniform mediump vec4 uTextureRect;\n + void main()\n + {\n + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + }\n + ); + + std::string fragmentShader = DALI_COMPOSE_SHADER( + void main()\n + {\n + gl_FragColor = texture2D( sTexture, vTexCoord ); + }\n + ); + + Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( vertexShader, fragmentShader, + Dali::GeometryType( Dali::GEOMETRY_TYPE_TEXTURED_MESH ), + Dali::ShaderEffect::GeometryHints( Dali::ShaderEffect::HINT_NONE ) ); + return shaderEffect; +} + +} // namespace BGRAShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + diff --git a/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h b/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h new file mode 100644 index 0000000..16293c6 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h @@ -0,0 +1,54 @@ + +#ifndef __DALI_TOOLKIT_TEXT_BGRA_SHADER_H__ +#define __DALI_TOOLKIT_TEXT_BGRA_SHADER_H__ + +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A BGRA shader for rendering glyphs. + */ +namespace BgraShader +{ + +/** + * Create a basic text shader. + * @return A handle to a newly allocated ShaderEffect + */ +Dali::ShaderEffect New(); + +} // namespace BGRAShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BGRA_SHADER_H__ diff --git a/dali-toolkit/internal/text/rendering/text-backend-impl.cpp b/dali-toolkit/internal/text/rendering/text-backend-impl.cpp new file mode 100644 index 0000000..5653ebf --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-backend-impl.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015 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 + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal +{ + +struct Backend::Impl +{ + int temp; // placeholder for future backend implemenations +}; + +Backend::Backend() +: mImpl( NULL ) +{ + mImpl = new Impl(); +} + +Backend::~Backend() +{ + delete mImpl; +} + +Dali::Toolkit::Text::Backend Backend::Get() +{ + Dali::Toolkit::Text::Backend backendHandle; + + Dali::SingletonService service( SingletonService::Get() ); + if ( service ) + { + // Check whether the singleton is already created + Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::Toolkit::Text::Backend ) ); + if(handle) + { + // If so, downcast the handle + Backend* impl = dynamic_cast< Dali::Toolkit::Text::Internal::Backend* >( handle.GetObjectPtr() ); + backendHandle = Dali::Toolkit::Text::Backend( impl ); + } + else // create and register the object + { + backendHandle = Dali::Toolkit::Text::Backend( new Backend ); + service.Register( typeid( backendHandle ), backendHandle ); + } + } + + return backendHandle; +} + +RendererPtr Backend::NewRenderer( unsigned int renderingType ) +{ + RendererPtr renderer; + + switch( renderingType ) + { + case Dali::Toolkit::Text::RENDERING_BASIC: + { + renderer = Dali::Toolkit::Text::BasicRenderer::New(); + } + break; + + case Dali::Toolkit::Text::RENDERING_SHARED_ATLAS: + { + renderer = Dali::Toolkit::Text::AtlasRenderer::New(); + } + break; + + default: + { + DALI_LOG_WARNING( "Unknown renderer type: %d", renderingType ); + break; + } + } + + return renderer; +} + +} // namespace Internal + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/text-backend-impl.h b/dali-toolkit/internal/text/rendering/text-backend-impl.h new file mode 100644 index 0000000..a185ee2 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-backend-impl.h @@ -0,0 +1,103 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_BACKEND_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_BACKEND_H__ + +/* + * Copyright (c) 2015 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 Toolkit +{ + +namespace Text +{ + +namespace Internal +{ + +/** + * Implementation of the text rendering backend + */ +class Backend : public BaseObject +{ +public: + + /** + * Constructor + */ + Backend(); + + /** + * Destructor + */ + ~Backend(); + + /** + * @copydoc Dali::Toolkit::Text::Backend::Get() + */ + static Dali::Toolkit::Text::Backend Get(); + + /** + * @copydoc Dali::Toolkit::Text::Backend::NewRenderer() + */ + RendererPtr NewRenderer( unsigned int renderingType ); + +private: + + // Undefined copy constructor. + Backend( const Backend& ); + + // Undefined assignment constructor. + Backend& operator=( Backend& ); + +private: + + struct Impl; + Impl* mImpl; + +}; // class Backend + +} // namespace Internal + +inline static Internal::Backend& GetImplementation(Backend& backend) +{ + DALI_ASSERT_ALWAYS( backend && "backend handle is empty" ); + BaseObject& handle = backend.GetBaseObject(); + return static_cast(handle); +} + +inline static const Internal::Backend& GetImplementation(const Backend& backend) +{ + DALI_ASSERT_ALWAYS( backend && "backend handle is empty" ); + const BaseObject& handle = backend.GetBaseObject(); + return static_cast(handle); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_BACKEND_H__ diff --git a/dali-toolkit/internal/text/rendering/text-backend.cpp b/dali-toolkit/internal/text/rendering/text-backend.cpp new file mode 100644 index 0000000..ee48026 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-backend.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 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 +{ + +namespace Text +{ + +Backend Backend::Get() +{ + return Internal::Backend::Get(); +} + +RendererPtr Backend::NewRenderer( unsigned int renderingType ) +{ + return GetImplementation(*this).NewRenderer( renderingType ); +} + +Backend::Backend() +{ +} + +Backend::~Backend() +{ +} + +Backend::Backend( const Backend& handle ) +: BaseHandle( handle ) +{ +} + +Backend& Backend::operator=( const Backend& handle ) +{ + BaseHandle::operator=( handle ); + return *this; +} + +Backend::Backend( Internal::Backend* internal ) +: BaseHandle( internal ) +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/text-backend.h b/dali-toolkit/internal/text/rendering/text-backend.h new file mode 100644 index 0000000..df7bfa2 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-backend.h @@ -0,0 +1,106 @@ +#ifndef __DALI_TOOLKIT_TEXT_BACKEND_H__ +#define __DALI_TOOLKIT_TEXT_BACKEND_H__ + +/* + * Copyright (c) 2015 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 Toolkit +{ + +namespace Text +{ + +namespace Internal DALI_INTERNAL +{ +class Backend; +} + +/** + * @brief Provides access to different text rendering backends. + */ +class DALI_IMPORT_API Backend : public BaseHandle +{ +public: + + /** + * @brief Retrieve a handle to the Backend instance. + * + * @return A handle to the Backend + */ + static Backend Get(); + + /** + * @brief Create a renderer from a particluar rendering type. + * + * @param[in] renderingType The type of rendering required. + * @return A handle to the newly created renderer. + */ + RendererPtr NewRenderer( unsigned int renderingType ); + + /** + * @brief Create an uninitialized TextAbstraction handle. + */ + Backend(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~Backend(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @param[in] handle A reference to the copied handle. + */ + Backend( const Backend& handle ); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @param [in] handle A reference to the copied handle. + * @return A reference to this. + */ + Backend& operator=( const Backend& handle ); + +public: // Not intended for application developers + + /** + * @brief This constructor is used by Backend::Get(). + * + * @param[in] backend A pointer to the internal backend object. + */ + explicit DALI_INTERNAL Backend( Internal::Backend* backend ); +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BACKEND_H__ diff --git a/plugins/dali-script-v8/src/actors/text-actor-api.h b/dali-toolkit/internal/text/rendering/text-renderer.cpp similarity index 59% rename from plugins/dali-script-v8/src/actors/text-actor-api.h rename to dali-toolkit/internal/text/rendering/text-renderer.cpp index f074703..4d74934 100644 --- a/plugins/dali-script-v8/src/actors/text-actor-api.h +++ b/dali-toolkit/internal/text/rendering/text-renderer.cpp @@ -1,6 +1,3 @@ -#ifndef __DALI_V8PLUGIN_TEXT_ACTOR_API_H__ -#define __DALI_V8PLUGIN_TEXT_ACTOR_API_H__ - /* * Copyright (c) 2015 Samsung Electronics Co., Ltd. * @@ -18,26 +15,28 @@ * */ - -// EXTERNAL INCLUDES -#include -#include +// CLASS HEADER +#include namespace Dali { -namespace V8Plugin +namespace Toolkit { -namespace TextActorApi +namespace Text { - Actor New( const v8::FunctionCallbackInfo< v8::Value >& args ); - void SetToNaturalSize( const v8::FunctionCallbackInfo< v8::Value >& args ); -}; // namespace TextActorApi +Renderer::Renderer() +{ +} -} // namespace V8Plugin +Renderer::~Renderer() +{ +} -} // namespace Dali +} // namespace Text + +} // namespace Toolkit -#endif // header __DALI_V8PLUGIN_TEXT_ACTOR_API_H__ +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/text-renderer.h b/dali-toolkit/internal/text/rendering/text-renderer.h new file mode 100644 index 0000000..3485f16 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-renderer.h @@ -0,0 +1,86 @@ +#ifndef __DALI_TOOLKIT_TEXT_RENDERER_H__ +#define __DALI_TOOLKIT_TEXT_RENDERER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class Renderer; +typedef IntrusivePtr RendererPtr; + +/** + * @brief Abstract base class for Text renderers. + * + * This is reponsible for rendering the glyphs from a ViewInterface in the specified positions. + * It is implemented by returning a RenderableActor intended as the child of a UI control. + */ +class Renderer : public RefObject +{ +public: + + /** + * @brief Render the glyphs from a ViewInterface. + * + * @param[in] view The interface to a view. + * @return The Renderable actor used to position the text. + */ + virtual RenderableActor Render( ViewInterface& view ) = 0; + +protected: + + /** + * @brief Constructor. + */ + Renderer(); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~Renderer(); + +private: + + // Undefined + Renderer( const Renderer& handle ); + + // Undefined + Renderer& operator=( const Renderer& handle ); +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_RENDERER_H__ diff --git a/dali-toolkit/internal/text/script-run.h b/dali-toolkit/internal/text/script-run.h new file mode 100644 index 0000000..3533df6 --- /dev/null +++ b/dali-toolkit/internal/text/script-run.h @@ -0,0 +1,48 @@ +#ifndef __DALI_TOOLKIT_TEXT_SCRIPT_RUN_H__ +#define __DALI_TOOLKIT_TEXT_SCRIPT_RUN_H__ + +/* + * Copyright (c) 2015 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 Run of characters with the same script. + */ +struct ScriptRun +{ + CharacterRun characterRun; ///< The initial character index and the number of characters of the run. + Script script; ///< Script of the run. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_SCRIPT_RUN_H__ diff --git a/dali-toolkit/internal/text/segmentation.cpp b/dali-toolkit/internal/text/segmentation.cpp new file mode 100644 index 0000000..efac834 --- /dev/null +++ b/dali-toolkit/internal/text/segmentation.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +void SetLineBreakInfo( const Vector& text, + Vector& lineBreakInfo ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + // Retrieve the line break info. + lineBreakInfo.Resize( numberOfCharacters ); + TextAbstraction::Segmentation::Get().GetLineBreakPositions( text.Begin(), + numberOfCharacters, + lineBreakInfo.Begin() ); +} + +void ReplaceLineBreakInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +void SetWordBreakInfo( const Vector& text, + Vector& wordBreakInfo ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + // Retrieve the word break info. + wordBreakInfo.Resize( numberOfCharacters ); + TextAbstraction::Segmentation::Get().GetWordBreakPositions( text.Begin(), + numberOfCharacters, + wordBreakInfo.Begin() ); +} + +void ReplaceWordBreakInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/segmentation.h b/dali-toolkit/internal/text/segmentation.h new file mode 100644 index 0000000..949b1c9 --- /dev/null +++ b/dali-toolkit/internal/text/segmentation.h @@ -0,0 +1,107 @@ +#ifndef __DALI_TOOLKIT_TEXT_SEGMENTATION_H__ +#define __DALI_TOOLKIT_TEXT_SEGMENTATION_H__ + +/* + * Copyright (c) 2015 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 Toolkit +{ + +namespace Text +{ + +class LogicalModel; + +/** + * Sets line break info. + * + * Possible values for LineBreakInfo are: + * + * - 0 is a LINE_MUST_BREAK. Text must be broken into a new line. + * - 1 is a LINE_ALLOW_BREAK. Is possible to break the text into a new line. + * - 2 is a LINE_NO_BREAK. Text can't be broken into a new line. + * + * @param[in] text Vector of UTF-32 characters. + * @param[out] lineBreakInfo The line break info + */ +void SetLineBreakInfo( const Vector& text, + Vector& lineBreakInfo ); + +/** + * Replaces line break info. + * + * @pre The @p model needs to have a text set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ReplaceLineBreakInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +/** + * Sets word break info. + * + * - 0 is a WORD_BREAK. Text can be broken into a new word. + * - 1 is a WORD_NO_BREAK. Text can't be broken into a new word. + * + * @param[in] text Vector of UTF-32 characters. + * @param[out] wordBreakInfo The word break info. + */ +void SetWordBreakInfo( const Vector& text, + Vector& wordBreakInfo ); + +/** + * Replaces word break info. + * + * @pre The @p model needs to have a text set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ReplaceWordBreakInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_SEGMENTATION_H__ diff --git a/dali-toolkit/internal/text/shaper.cpp b/dali-toolkit/internal/text/shaper.cpp new file mode 100644 index 0000000..8e2eed1 --- /dev/null +++ b/dali-toolkit/internal/text/shaper.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015 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 + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +CharacterIndex min( CharacterIndex index0, + CharacterIndex index1 ) +{ + return ( index0 < index1 ) ? index0 : index1; +} + +void ShapeText( const Vector& text, + const Vector& lineBreakInfo, + const Vector& scripts, + const Vector& fonts, + Vector& glyphs, + Vector& glyphToCharacterMap, + Vector& charactersPerGlyph ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + +#ifdef DEBUG_ENABLED + const Length numberOfFontRuns = fonts.Count(); + const Length numberOfScriptRuns = scripts.Count(); +#endif + + DALI_ASSERT_DEBUG( ( 0u != numberOfFontRuns ) && + ( numberOfCharacters == fonts[numberOfFontRuns - 1u].characterRun.characterIndex + fonts[numberOfFontRuns - 1u].characterRun.numberOfCharacters ) && + "Toolkit::Text::ShapeText. All characters must have a font set." ); + + DALI_ASSERT_DEBUG( ( 0u != numberOfScriptRuns ) && + ( numberOfCharacters == scripts[numberOfScriptRuns - 1u].characterRun.characterIndex + scripts[numberOfScriptRuns - 1u].characterRun.numberOfCharacters ) && + "Toolkit::Text::ShapeText. All characters must have a script set." ); + + // The text needs to be split in chunks of consecutive characters. + // Each chunk must contain characters with the same font id and script set. + // A chunk of consecutive characters must not contain a LINE_MUST_BREAK, if there is one a new chunk have to be created. + + TextAbstraction::Shaping shaping = TextAbstraction::Shaping::Get(); + + // To shape the text a font and an script is needed. + Vector::ConstIterator fontRunIt = fonts.Begin(); + Vector::ConstIterator scriptRunIt = scripts.Begin(); + + // Index to the the next one to be shaped. Is pointing the character after the last one it was shaped. + CharacterIndex previousIndex = 0u; + + // The current font id and script used to shape the text. + FontId currentFontId = 0u; + Script currentScript = TextAbstraction::UNKNOWN; + + // Reserve some space to allocate the glyphs and the glyph to character map. + // There is no way to know the number of glyphs before shaping the text. + // To avoid reallocations it's reserved space for a slightly biger number of glyphs than the number of characters. + + Length numberOfGlyphsReserved = static_cast( numberOfCharacters * 1.3f ); + glyphs.Resize( numberOfGlyphsReserved ); + glyphToCharacterMap.Resize( numberOfGlyphsReserved ); + + // The actual number of glyphs. + Length totalNumberOfGlyphs = 0u; + + const Character* textBuffer = text.Begin(); + const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + GlyphInfo* glyphsBuffer = glyphs.Begin(); + CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + + // Traverse the characters and shape the text. + for( previousIndex = 0; previousIndex < numberOfCharacters; ) + { + // Get the font id and the script. + const FontRun& fontRun = *fontRunIt; + const ScriptRun& scriptRun = *scriptRunIt; + + currentFontId = fontRun.fontId; + currentScript = scriptRun.script; + + // Get the min index to the last character of both runs. + CharacterIndex currentIndex = min( fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters, + scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ); + + // Check if there is a line must break. + bool mustBreak = false; + for( CharacterIndex index = previousIndex; index < currentIndex; ++index ) + { + mustBreak = TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ); + if( mustBreak ) + { + currentIndex = index; + break; + } + } + + // Check if the current index is a new paragraph character. + // A \n is going to be shaped in order to not to mess the conversion tables. + // After the \n character is shaped, the glyph is going to be reset to its + // default in order to not to get any metric or font index for it. + const bool isNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + currentIndex ) ); + + // The last character is always a must-break even if it's not a \n. + Length numberOfCharactersToShape = currentIndex - previousIndex; + if( mustBreak ) + { + // Add one more character to shape. + ++numberOfCharactersToShape; + } + + // Shape the text for the current chunk. + const Length numberOfGlyphs = shaping.Shape( textBuffer + previousIndex, + numberOfCharactersToShape, + currentFontId, + currentScript ); + + const Length glyphIndex = totalNumberOfGlyphs; + totalNumberOfGlyphs += numberOfGlyphs; + + if( totalNumberOfGlyphs > numberOfGlyphsReserved ) + { + // Resize the vectors to get enough space. + numberOfGlyphsReserved = static_cast( totalNumberOfGlyphs * 1.3f ); + glyphs.Resize( numberOfGlyphsReserved ); + glyphToCharacterMap.Resize( numberOfGlyphsReserved ); + + // Iterators are not valid anymore, set them again. + glyphsBuffer = glyphs.Begin(); + glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + } + + // Retrieve the glyphs and the glyph to character conversion map. + shaping.GetGlyphs( glyphsBuffer + glyphIndex, + glyphToCharacterMapBuffer + glyphIndex ); + + if( isNewParagraph ) + { + // TODO : This is a work around to avoid drawing a square in the + // place of a new line character. + + // If the last character is a \n, it resets the glyph to the default + // to avoid getting any metric for it. + GlyphInfo& glyph = *( glyphsBuffer + glyphIndex + ( numberOfGlyphs - 1u ) ); + + glyph = GlyphInfo(); + } + + // Update indices. + if( 0u != glyphIndex ) + { + for( Length index = glyphIndex; index < glyphIndex + numberOfGlyphs; ++index ) + { + CharacterIndex& characterIndex = *( glyphToCharacterMapBuffer + index ); + characterIndex += previousIndex; + } + } + + // Update the iterators to get the next font or script run. + if( currentIndex == fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) + { + ++fontRunIt; + } + if( currentIndex == scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ) + { + ++scriptRunIt; + } + + // Update the previous index. Jumps the \n if needed. + previousIndex = mustBreak ? currentIndex + 1u : currentIndex; + } + + // Add the number of characters per glyph. + charactersPerGlyph.Reserve( totalNumberOfGlyphs ); + previousIndex = 0u; + for( Length index = 1u; index < totalNumberOfGlyphs; ++index ) + { + const CharacterIndex characterIndex = *( glyphToCharacterMapBuffer + index ); + + charactersPerGlyph.PushBack( characterIndex - previousIndex ); + + previousIndex = characterIndex; + } + + charactersPerGlyph.PushBack( numberOfCharacters - previousIndex ); + + // Resize the vectors to set the right number of items. + glyphs.Resize( totalNumberOfGlyphs ); + glyphToCharacterMap.Resize( totalNumberOfGlyphs ); +} + +void ShapeText( const LogicalModel& logicalModel, + VisualModel& visualModel, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/shaper.h b/dali-toolkit/internal/text/shaper.h new file mode 100644 index 0000000..d423cc5 --- /dev/null +++ b/dali-toolkit/internal/text/shaper.h @@ -0,0 +1,88 @@ +#ifndef __DALI_TOOLKIT_TEXT_SHAPER_H__ +#define __DALI_TOOLKIT_TEXT_SHAPER_H__ + +/* + * Copyright (c) 2015 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 +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class LogicalModel; +class VisualModel; + +/** + * Shapes the whole text. + * + * @param[in] text Vector of UTF-32 characters. + * @param[in] lineBreakInfo The line break info. + * @param[in] scripts Vector containing the script runs for the whole text. + * @param[in] fonts Vector with validated fonts. + * @param[out] glyphs Vector of glyphs in the visual order. + * @param[out] glyphToCharacterMap Vector containing the first character in the logical model that each glyph relates to. + * @param[out] charactersPerGlyph Vector containing the number of characters per glyph. + */ +void ShapeText( const Vector& text, + const Vector& lineBreakInfo, + const Vector& scripts, + const Vector& fonts, + Vector& glyphs, + Vector& glyphToCharacterMap, + Vector& charactersPerGlyph ); + +/** + * Replaces the shape info of the given range of characters. + * + * @pre The @p model needs to have a text set. + * @pre The @p model needs to have the scripts set. + * @pre The @p model needs to have the fonts set. + * @pre The @p model needs to have the bidirectional info set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] logicalModel The text's logical model. + * @param[in,out] visualModel The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ShapeText( const LogicalModel& logicalModel, + VisualModel& visualModel, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_SHAPER_H__ diff --git a/dali-toolkit/internal/text/text-control-interface.cpp b/dali-toolkit/internal/text/text-control-interface.cpp new file mode 100644 index 0000000..8ac77d1 --- /dev/null +++ b/dali-toolkit/internal/text/text-control-interface.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +ControlInterface::ControlInterface() +{ +} + +ControlInterface::~ControlInterface() +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-control-interface.h b/dali-toolkit/internal/text/text-control-interface.h new file mode 100644 index 0000000..3eb26b6 --- /dev/null +++ b/dali-toolkit/internal/text/text-control-interface.h @@ -0,0 +1,59 @@ +#ifndef __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__ +#define __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__ + +/* + * Copyright (c) 2015 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 +{ + +/** + * @brief An interface that the Text::Controller uses to request a text relayout. + */ +class ControlInterface +{ +public: + + /** + * @brief Constructor. + */ + ControlInterface(); + + /** + * @brief Virtual destructor. + */ + virtual ~ControlInterface(); + + /** + * @brief Called to request a text relayout. + */ + virtual void RequestTextRelayout() = 0; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__ diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp new file mode 100644 index 0000000..7d05f52 --- /dev/null +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -0,0 +1,2133 @@ +/* + * Copyright (c) 2015 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 + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; + +namespace +{ + +const float MAX_FLOAT = std::numeric_limits::max(); + +enum ModifyType +{ + REPLACE_TEXT, ///< Replace the entire text + INSERT_TEXT, ///< Insert characters at the current cursor position + DELETE_TEXT ///< Delete a character at the current cursor position +}; + +struct ModifyEvent +{ + ModifyType type; + std::string text; +}; + +} // namespace + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct Controller::FontDefaults +{ + FontDefaults() + : mDefaultPointSize(0.0f), + mFontId(0u) + { + } + + FontId GetFontId( TextAbstraction::FontClient& fontClient ) + { + if( !mFontId ) + { + Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64; + mFontId = fontClient.GetFontId( mDefaultFontFamily, mDefaultFontStyle, pointSize ); + } + + return mFontId; + } + + std::string mDefaultFontFamily; + std::string mDefaultFontStyle; + float mDefaultPointSize; + FontId mFontId; +}; + +struct Controller::TextInput +{ + // Used to queue input events until DoRelayout() + enum EventType + { + KEYBOARD_FOCUS_GAIN_EVENT, + KEYBOARD_FOCUS_LOST_EVENT, + CURSOR_KEY_EVENT, + TAP_EVENT, + PAN_EVENT, + GRAB_HANDLE_EVENT + }; + + union Param + { + int mInt; + unsigned int mUint; + float mFloat; + }; + + struct Event + { + Event( EventType eventType ) + : type( eventType ) + { + p1.mInt = 0; + p2.mInt = 0; + } + + EventType type; + Param p1; + Param p2; + Param p3; + }; + + struct CursorInfo + { + CursorInfo() + : primaryPosition(), + secondaryPosition(), + lineHeight( 0.f ), + primaryCursorHeight( 0.f ), + secondaryCursorHeight( 0.f ), + isSecondaryCursor( false ) + {} + + ~CursorInfo() + {} + + Vector2 primaryPosition; ///< The primary cursor's position. + Vector2 secondaryPosition; ///< The secondary cursor's position. + float lineHeight; ///< The height of the line where the cursor is placed. + float primaryCursorHeight; ///< The primary cursor's height. + float secondaryCursorHeight; ///< The secondary cursor's height. + bool isSecondaryCursor; ///< Whether the secondary cursor is valid. + }; + + /** + * @brief Some characters can be shaped in more than one glyph. + * This struct is used to retrieve metrics from these group of glyphs. + */ + struct GlyphMetrics + { + GlyphMetrics() + : fontHeight( 0.f ), + advance( 0.f ), + ascender( 0.f ), + xBearing( 0.f ) + {} + + ~GlyphMetrics() + {} + + float fontHeight; ///< The font's height of that glyphs. + float advance; ///< The sum of all the advances of all the glyphs. + float ascender; ///< The font's ascender. + float xBearing; ///< The x bearing of the first glyph. + }; + + enum State + { + INACTIVE, + SELECTING, + EDITING, + EDITING_WITH_POPUP + }; + + TextInput( LogicalModelPtr logicalModel, + VisualModelPtr visualModel, + DecoratorPtr decorator, + FontDefaults* fontDefaults, + TextAbstraction::FontClient& fontClient ) + : mLogicalModel( logicalModel ), + mVisualModel( visualModel ), + mDecorator( decorator ), + mFontDefaults( fontDefaults ), + mFontClient( fontClient ), + mState( INACTIVE ), + mPrimaryCursorPosition( 0u ), + mSecondaryCursorPosition( 0u ), + mDecoratorUpdated( false ), + mCursorBlinkEnabled( true ), + mGrabHandleEnabled( true ), + mGrabHandlePopupEnabled( true ), + mSelectionEnabled( true ), + mHorizontalScrollingEnabled( true ), + mVerticalScrollingEnabled( false ), + mUpdateCursorPosition( false ) + {} + + /** + * @brief Helper to move the cursor, grab handle etc. + */ + bool ProcessInputEvents( const Vector2& controlSize, + const Vector2& alignmentOffset ) + { + mDecoratorUpdated = false; + + if( mDecorator ) + { + for( vector::iterator iter = mEventQueue.begin(); iter != mEventQueue.end(); ++iter ) + { + switch( iter->type ) + { + case KEYBOARD_FOCUS_GAIN_EVENT: + { + OnKeyboardFocus( true ); + break; + } + case KEYBOARD_FOCUS_LOST_EVENT: + { + OnKeyboardFocus( false ); + break; + } + case CURSOR_KEY_EVENT: + { + OnCursorKeyEvent( *iter ); + break; + } + case TAP_EVENT: + { + OnTapEvent( *iter, alignmentOffset ); + break; + } + case PAN_EVENT: + { + OnPanEvent( *iter, controlSize, alignmentOffset ); + break; + } + case GRAB_HANDLE_EVENT: + { + OnGrabHandleEvent( *iter ); + break; + } + } + } + } + + // The cursor must also be repositioned after inserts into the model + if( mUpdateCursorPosition ) + { + UpdateCursorPosition(); + mUpdateCursorPosition = false; + } + + mEventQueue.clear(); + + return mDecoratorUpdated; + } + + void OnKeyboardFocus( bool hasFocus ) + { + if( !hasFocus ) + { + ChangeState( INACTIVE ); + } + else + { + ChangeState( EDITING ); + } + } + + void OnCursorKeyEvent( const Event& event ) + { + int keyCode = event.p1.mInt; + + if( Dali::DALI_KEY_CURSOR_LEFT == keyCode ) + { + if( mPrimaryCursorPosition > 0u ) + { + mPrimaryCursorPosition = CalculateNewCursorIndex( mPrimaryCursorPosition - 1u ); + } + } + else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode ) + { + if( mLogicalModel->GetNumberOfCharacters() > mPrimaryCursorPosition ) + { + mPrimaryCursorPosition = CalculateNewCursorIndex( mPrimaryCursorPosition ); + } + } + else if( Dali::DALI_KEY_CURSOR_UP == keyCode ) + { + // TODO + } + else if( Dali::DALI_KEY_CURSOR_DOWN == keyCode ) + { + // TODO + } + + UpdateCursorPosition(); + } + + void HandleCursorKey( int keyCode ) + { + // TODO + } + + void OnTapEvent( const Event& event, + const Vector2& alignmentOffset ) + { + unsigned int tapCount = event.p1.mUint; + + if( 1u == tapCount ) + { + ChangeState( EDITING ); + + float xPosition = event.p2.mFloat - alignmentOffset.x; + float yPosition = event.p3.mFloat - alignmentOffset.y; + + mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, + yPosition ); + + UpdateCursorPosition(); + } + else if( mSelectionEnabled && + 2u == tapCount ) + { + ChangeState( SELECTING ); + + RepositionSelectionHandles( event.p2.mFloat, event.p3.mFloat ); + } + } + + void OnPanEvent( const Event& event, + const Vector2& controlSize, + const Vector2& alignmentOffset ) + { + int state = event.p1.mInt; + + if( Gesture::Started == state || + Gesture::Continuing == state ) + { + const Vector2& actualSize = mVisualModel->GetActualSize(); + + if( mHorizontalScrollingEnabled ) + { + const float displacementX = event.p2.mFloat; + mScrollPosition.x += displacementX; + + // Clamp between -space & 0 (and the text alignment). + const float contentWidth = actualSize.width; + if( contentWidth > controlSize.width ) + { + const float space = ( contentWidth - controlSize.width ) + alignmentOffset.x; + mScrollPosition.x = ( mScrollPosition.x < -space ) ? -space : mScrollPosition.x; + mScrollPosition.x = ( mScrollPosition.x > -alignmentOffset.x ) ? -alignmentOffset.x : mScrollPosition.x; + + mDecoratorUpdated = true; + } + else + { + mScrollPosition.x = 0.f; + } + } + + if( mVerticalScrollingEnabled ) + { + const float displacementY = event.p3.mFloat; + mScrollPosition.y += displacementY; + + // Clamp between -space & 0 (and the text alignment). + if( actualSize.height > controlSize.height ) + { + const float space = ( actualSize.height - controlSize.height ) + alignmentOffset.y; + mScrollPosition.y = ( mScrollPosition.y < -space ) ? -space : mScrollPosition.y; + mScrollPosition.y = ( mScrollPosition.y > -alignmentOffset.y ) ? -alignmentOffset.y : mScrollPosition.y; + + mDecoratorUpdated = true; + } + else + { + mScrollPosition.y = 0.f; + } + } + } + } + + void OnGrabHandleEvent( const Event& event ) + { + unsigned int state = event.p1.mUint; + + if( GRAB_HANDLE_PRESSED == state ) + { + float xPosition = event.p2.mFloat + mScrollPosition.x; + float yPosition = event.p3.mFloat + mScrollPosition.y; + + mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, + yPosition ); + + UpdateCursorPosition(); + + //mDecorator->HidePopup(); + ChangeState ( EDITING ); + } + else if ( mGrabHandlePopupEnabled && + GRAB_HANDLE_RELEASED == state ) + { + //mDecorator->ShowPopup(); + ChangeState ( EDITING_WITH_POPUP ); + mDecoratorUpdated = true; + } + } + + void RepositionSelectionHandles( float visualX, float visualY ) + { + // TODO - Find which word was selected + + const Vector& glyphs = mVisualModel->mGlyphs; + const Vector::SizeType glyphCount = glyphs.Count(); + + const Vector& positions = mVisualModel->mGlyphPositions; + const Vector::SizeType positionCount = positions.Count(); + + // Guard against glyphs which did not fit inside the layout + const Vector::SizeType count = (positionCount < glyphCount) ? positionCount : glyphCount; + + if( count ) + { + float primaryX = positions[0].x; + float secondaryX = positions[count-1].x + glyphs[count-1].width; + + // TODO - multi-line selection + const Vector& lines = mVisualModel->mLines; + float height = lines.Count() ? lines[0].ascender + -lines[0].descender : 0.0f; + + mDecorator->SetPosition( PRIMARY_SELECTION_HANDLE, primaryX, 0.0f, height ); + mDecorator->SetPosition( SECONDARY_SELECTION_HANDLE, secondaryX, 0.0f, height ); + + mDecorator->ClearHighlights(); + mDecorator->AddHighlight( primaryX, 0.0f, secondaryX, height ); + } + } + + void ChangeState( State newState ) + { + if( mState != newState ) + { + mState = newState; + + if( INACTIVE == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); + mDecorator->StopCursorBlink(); + mDecorator->SetGrabHandleActive( false ); + mDecorator->SetSelectionActive( false ); + mDecorator->SetPopupActive( false ); + mDecoratorUpdated = true; + } + else if ( SELECTING == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); + mDecorator->StopCursorBlink(); + mDecorator->SetGrabHandleActive( false ); + mDecorator->SetSelectionActive( true ); + mDecoratorUpdated = true; + } + else if( EDITING == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + if( mCursorBlinkEnabled ) + { + mDecorator->StartCursorBlink(); + } + if( mGrabHandleEnabled ) + { + mDecorator->SetGrabHandleActive( true ); + } + if( mGrabHandlePopupEnabled ) + { + mDecorator->SetPopupActive( false ); + } + mDecorator->SetSelectionActive( false ); + mDecoratorUpdated = true; + } + else if( EDITING_WITH_POPUP == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + if( mCursorBlinkEnabled ) + { + mDecorator->StartCursorBlink(); + } + if( mGrabHandleEnabled ) + { + mDecorator->SetGrabHandleActive( true ); + } + if( mGrabHandlePopupEnabled ) + { + mDecorator->SetPopupActive( true ); + } + mDecorator->SetSelectionActive( false ); + mDecoratorUpdated = true; + } + } + } + + LineIndex GetClosestLine( float y ) const + { + float totalHeight = 0.f; + LineIndex lineIndex = 0u; + + const Vector& lines = mVisualModel->mLines; + for( LineIndex endLine = lines.Count(); + lineIndex < endLine; + ++lineIndex ) + { + const LineRun& lineRun = lines[lineIndex]; + totalHeight += lineRun.ascender + -lineRun.descender; + if( y < totalHeight ) + { + return lineIndex; + } + } + + return lineIndex-1; + } + + /** + * @brief Retrieves the cursor's logical position for a given touch point x,y + * + * @param[in] visualX The touch point x. + * @param[in] visualY The touch point y. + * + * @return The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character. + */ + CharacterIndex GetClosestCursorIndex( float visualX, + float visualY ) const + { + CharacterIndex logicalIndex = 0u; + + const Length numberOfGlyphs = mVisualModel->mGlyphs.Count(); + const Length numberOfLines = mVisualModel->mLines.Count(); + if( 0 == numberOfGlyphs || + 0 == numberOfLines ) + { + return logicalIndex; + } + + // Transform to visual model coords + visualX -= mScrollPosition.x; + visualY -= mScrollPosition.y; + + // Find which line is closest + const LineIndex lineIndex = GetClosestLine( visualY ); + const LineRun& line = mVisualModel->mLines[lineIndex]; + + // Get the positions of the glyphs. + const Vector& positions = mVisualModel->mGlyphPositions; + const Vector2* const positionsBuffer = positions.Begin(); + + // Get the visual to logical conversion tables. + const CharacterIndex* const visualToLogicalBuffer = ( 0u != mLogicalModel->mVisualToLogicalMap.Count() ) ? mLogicalModel->mVisualToLogicalMap.Begin() : NULL; + const CharacterIndex* const visualToLogicalCursorBuffer = mLogicalModel->mVisualToLogicalCursorMap.Begin(); + + // Get the character to glyph conversion table. + const GlyphIndex* const charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin(); + + // Get the glyphs per character table. + const Length* const glyphsPerCharacterBuffer = mVisualModel->mGlyphsPerCharacter.Begin(); + + // If the vector is void, there is no right to left characters. + const bool hasRightToLeftCharacters = NULL != visualToLogicalBuffer; + + const CharacterIndex startCharacter = line.characterRun.characterIndex; + const CharacterIndex endCharacter = line.characterRun.characterIndex + line.characterRun.numberOfCharacters; + DALI_ASSERT_DEBUG( endCharacter <= mLogicalModel->mText.Count() && "Invalid line info" ); + + // Whether there is a hit on a glyph. + bool matched = false; + + // Traverses glyphs in visual order. To do that use the visual to logical conversion table. + CharacterIndex visualIndex = startCharacter; + for( ; !matched && ( visualIndex < endCharacter ); ++visualIndex ) + { + // The character in logical order. + const CharacterIndex characterLogicalOrderIndex = hasRightToLeftCharacters ? *( visualToLogicalBuffer + visualIndex ) : visualIndex; + + // The first glyph for that character in logical order. + const GlyphIndex glyphLogicalOrderIndex = *( charactersToGlyphBuffer + characterLogicalOrderIndex ); + + // The number of glyphs for that character + const Length numberOfGlyphs = *( glyphsPerCharacterBuffer + characterLogicalOrderIndex ); + + // Get the metrics for the group of glyphs. + GlyphMetrics glyphMetrics; + GetGlyphsMetrics( glyphLogicalOrderIndex, + numberOfGlyphs, + glyphMetrics ); + + const Vector2& position = *( positionsBuffer + glyphLogicalOrderIndex ); + + const float glyphX = -glyphMetrics.xBearing + position.x + 0.5f * glyphMetrics.advance; + + if( visualX < glyphX ) + { + matched = true; + break; + } + } + + // Return the logical position of the cursor in characters. + + if( !matched ) + { + visualIndex = endCharacter; + } + + return hasRightToLeftCharacters ? *( visualToLogicalCursorBuffer + visualIndex ) : visualIndex; + } + + /** + * @brief Calculates the cursor's position for a given character index in the logical order. + * + * It retrieves as well the line's height and the cursor's height and + * if there is a valid alternative cursor, its position and height. + * + * @param[in] logical The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character. + * @param[out] cursorInfo The line's height, the cursor's height, the cursor's position and whether there is an alternative cursor. + */ + void GetCursorPosition( CharacterIndex logical, + CursorInfo& cursorInfo ) const + { + // TODO: Check for multiline with \n, etc... + + // Check if the logical position is the first or the last one of the text. + const bool isFirstPosition = 0u == logical; + const bool isLastPosition = mLogicalModel->GetNumberOfCharacters() == logical; + + if( isFirstPosition && isLastPosition ) + { + // There is zero characters. Get the default font. + + FontId defaultFontId = 0u; + if( NULL == mFontDefaults ) + { + defaultFontId = mFontClient.GetFontId( String::EMPTY, + String::EMPTY ); + } + else + { + defaultFontId = mFontDefaults->GetFontId( mFontClient ); + } + + Text::FontMetrics fontMetrics; + mFontClient.GetFontMetrics( defaultFontId, fontMetrics ); + + cursorInfo.lineHeight = fontMetrics.ascender - fontMetrics.descender; + cursorInfo.primaryCursorHeight = cursorInfo.lineHeight; + + cursorInfo.primaryPosition.x = 0.f; + cursorInfo.primaryPosition.y = 0.f; + + // Nothing else to do. + return; + } + + // Get the previous logical index. + const CharacterIndex previousLogical = isFirstPosition ? 0u : logical - 1u; + + // Decrease the logical index if it's the last one. + if( isLastPosition ) + { + --logical; + } + + // Get the direction of the character and the previous one. + const CharacterDirection* const modelCharacterDirectionsBuffer = ( 0u != mLogicalModel->mCharacterDirections.Count() ) ? mLogicalModel->mCharacterDirections.Begin() : NULL; + + CharacterDirection isCurrentRightToLeft = false; + CharacterDirection isPreviousRightToLeft = false; + if( NULL != modelCharacterDirectionsBuffer ) // If modelCharacterDirectionsBuffer is NULL, it means the whole text is left to right. + { + isCurrentRightToLeft = *( modelCharacterDirectionsBuffer + logical ); + isPreviousRightToLeft = *( modelCharacterDirectionsBuffer + previousLogical ); + } + + // Get the line where the character is laid-out. + const LineRun* modelLines = mVisualModel->mLines.Begin(); + + const LineIndex lineIndex = mVisualModel->GetLineOfCharacter( logical ); + const LineRun& line = *( modelLines + lineIndex ); + + // Get the paragraph's direction. + const CharacterDirection isRightToLeftParagraph = line.direction; + + // Check whether there is an alternative position: + + cursorInfo.isSecondaryCursor = ( isCurrentRightToLeft != isPreviousRightToLeft ) || + ( isLastPosition && ( isRightToLeftParagraph != isCurrentRightToLeft ) ); + + // Set the line height. + cursorInfo.lineHeight = line.ascender + -line.descender; + + // Convert the cursor position into the glyph position. + CharacterIndex characterIndex = logical; + if( cursorInfo.isSecondaryCursor && + ( isRightToLeftParagraph != isCurrentRightToLeft ) ) + { + characterIndex = previousLogical; + } + + const GlyphIndex currentGlyphIndex = *( mVisualModel->mCharactersToGlyph.Begin() + characterIndex ); + const Length numberOfGlyphs = *( mVisualModel->mGlyphsPerCharacter.Begin() + characterIndex ); + const Length numberOfCharacters = *( mVisualModel->mCharactersPerGlyph.Begin() +currentGlyphIndex ); + + // Get the metrics for the group of glyphs. + GlyphMetrics glyphMetrics; + GetGlyphsMetrics( currentGlyphIndex, + numberOfGlyphs, + glyphMetrics ); + + float interGlyphAdvance = 0.f; + if( !isLastPosition && + ( numberOfCharacters > 1u ) ) + { + const CharacterIndex firstIndex = *( mVisualModel->mGlyphsToCharacters.Begin() + currentGlyphIndex ); + interGlyphAdvance = static_cast( characterIndex - firstIndex ) * glyphMetrics.advance / static_cast( numberOfCharacters ); + } + + // Get the glyph position and x bearing. + const Vector2& currentPosition = *( mVisualModel->mGlyphPositions.Begin() + currentGlyphIndex ); + + // Set the cursor's height. + cursorInfo.primaryCursorHeight = glyphMetrics.fontHeight; + + // Set the position. + cursorInfo.primaryPosition.x = -glyphMetrics.xBearing + currentPosition.x + ( isCurrentRightToLeft ? glyphMetrics.advance : interGlyphAdvance ); + cursorInfo.primaryPosition.y = line.ascender - glyphMetrics.ascender; + + if( isLastPosition ) + { + // The position of the cursor after the last character needs special + // care depending on its direction and the direction of the paragraph. + + if( cursorInfo.isSecondaryCursor ) + { + // Need to find the first character after the last character with the paragraph's direction. + // i.e l0 l1 l2 r0 r1 should find r0. + + // TODO: check for more than one line! + characterIndex = isRightToLeftParagraph ? line.characterRun.characterIndex : line.characterRun.characterIndex + line.characterRun.numberOfCharacters - 1u; + characterIndex = mLogicalModel->GetLogicalCharacterIndex( characterIndex ); + + const GlyphIndex glyphIndex = *( mVisualModel->mCharactersToGlyph.Begin() + characterIndex ); + const Length numberOfGlyphs = *( mVisualModel->mGlyphsPerCharacter.Begin() + characterIndex ); + + const Vector2& position = *( mVisualModel->mGlyphPositions.Begin() + glyphIndex ); + + // Get the metrics for the group of glyphs. + GlyphMetrics glyphMetrics; + GetGlyphsMetrics( glyphIndex, + numberOfGlyphs, + glyphMetrics ); + + cursorInfo.primaryPosition.x = -glyphMetrics.xBearing + position.x + ( isRightToLeftParagraph ? 0.f : glyphMetrics.advance ); + + cursorInfo.primaryPosition.y = line.ascender - glyphMetrics.ascender; + } + else + { + if( !isCurrentRightToLeft ) + { + cursorInfo.primaryPosition.x += glyphMetrics.advance; + } + else + { + cursorInfo.primaryPosition.x -= glyphMetrics.advance; + } + } + } + + // Set the alternative cursor position. + if( cursorInfo.isSecondaryCursor ) + { + // Convert the cursor position into the glyph position. + const CharacterIndex previousCharacterIndex = ( ( isRightToLeftParagraph != isCurrentRightToLeft ) ? logical : previousLogical ); + const GlyphIndex previousGlyphIndex = *( mVisualModel->mCharactersToGlyph.Begin() + previousCharacterIndex ); + const Length numberOfGlyphs = *( mVisualModel->mGlyphsPerCharacter.Begin() + previousCharacterIndex ); + + // Get the glyph position. + const Vector2& previousPosition = *( mVisualModel->mGlyphPositions.Begin() + previousGlyphIndex ); + + // Get the metrics for the group of glyphs. + GlyphMetrics glyphMetrics; + GetGlyphsMetrics( previousGlyphIndex, + numberOfGlyphs, + glyphMetrics ); + + // Set the cursor position and height. + cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + previousPosition.x + ( ( ( isLastPosition && !isCurrentRightToLeft ) || + ( !isLastPosition && isCurrentRightToLeft ) ) ? glyphMetrics.advance : 0.f ); + + cursorInfo.secondaryCursorHeight = 0.5f * glyphMetrics.fontHeight; + + cursorInfo.secondaryPosition.y = cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight - line.descender - ( glyphMetrics.fontHeight - glyphMetrics.ascender ); + + // Update the primary cursor height as well. + cursorInfo.primaryCursorHeight *= 0.5f; + } + } + + /** + * @brief Get some glyph's metrics of a group of glyphs formed as a result of shaping one character. + * + * @param[in] glyphIndex The index to the first glyph. + * @param[in] numberOfGlyphs The number of glyphs. + * @param[out] glyphMetrics Some glyph metrics (font height, advance, ascender and x bearing). + */ + void GetGlyphsMetrics( GlyphIndex glyphIndex, + Length numberOfGlyphs, + GlyphMetrics& glyphMetrics ) const + { + const GlyphInfo* glyphsBuffer = mVisualModel->mGlyphs.Begin(); + + const GlyphInfo& firstGlyph = *( glyphsBuffer + glyphIndex ); + + Text::FontMetrics fontMetrics; + mFontClient.GetFontMetrics( firstGlyph.fontId, fontMetrics ); + + glyphMetrics.fontHeight = fontMetrics.height; + glyphMetrics.advance = firstGlyph.advance; + glyphMetrics.ascender = fontMetrics.ascender; + glyphMetrics.xBearing = firstGlyph.xBearing; + + for( unsigned int i = 1u; i < numberOfGlyphs; ++i ) + { + const GlyphInfo& glyphInfo = *( glyphsBuffer + glyphIndex + i ); + + glyphMetrics.advance += glyphInfo.advance; + } + } + + /** + * @brief Calculates the new cursor index. + * + * It takes into account that in some scripts multiple characters can form a glyph and all of them + * need to be jumped with one key event. + * + * @param[in] index The initial new index. + * + * @return The new cursor index. + */ + CharacterIndex CalculateNewCursorIndex( CharacterIndex index ) const + { + CharacterIndex cursorIndex = mPrimaryCursorPosition; + + const Script script = mLogicalModel->GetScript( index ); + const GlyphIndex* charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin(); + const Length* charactersPerGlyphBuffer = mVisualModel->mCharactersPerGlyph.Begin(); + + Length numberOfCharacters = 0u; + if( TextAbstraction::LATIN == script ) + { + // Prevents to jump the whole Latin ligatures like fi, ff, ... + numberOfCharacters = 1u; + } + else + { + GlyphIndex glyphIndex = *( charactersToGlyphBuffer + index ); + numberOfCharacters = *( charactersPerGlyphBuffer + glyphIndex ); + + while( 0u == numberOfCharacters ) + { + numberOfCharacters = *( charactersPerGlyphBuffer + glyphIndex ); + ++glyphIndex; + } + } + + if( index < mPrimaryCursorPosition ) + { + cursorIndex -= numberOfCharacters; + } + else + { + cursorIndex += numberOfCharacters; + } + + return cursorIndex; + } + + void UpdateCursorPosition() + { + CursorInfo cursorInfo; + + GetCursorPosition( mPrimaryCursorPosition, + cursorInfo ); + + mDecorator->SetPosition( PRIMARY_CURSOR, + cursorInfo.primaryPosition.x, + cursorInfo.primaryPosition.y, + cursorInfo.primaryCursorHeight, + cursorInfo.lineHeight ); + + if( cursorInfo.isSecondaryCursor ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_BOTH ); + mDecorator->SetPosition( SECONDARY_CURSOR, + cursorInfo.secondaryPosition.x, + cursorInfo.secondaryPosition.y, + cursorInfo.secondaryCursorHeight, + cursorInfo.lineHeight ); + } + else + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + } + + mUpdateCursorPosition = false; + mDecoratorUpdated = true; + } + + LogicalModelPtr mLogicalModel; + VisualModelPtr mVisualModel; + DecoratorPtr mDecorator; + FontDefaults* mFontDefaults; + TextAbstraction::FontClient& mFontClient; + std::string mPlaceholderText; + + /** + * This is used to delay handling events until after the model has been updated. + * The number of updates to the model is minimized to improve performance. + */ + vector mEventQueue; ///< The queue of touch events etc. + + State mState; ///< Selection mode, edit mode etc. + + CharacterIndex mPrimaryCursorPosition; ///< Index into logical model for primary cursor + CharacterIndex mSecondaryCursorPosition; ///< Index into logical model for secondary cursor + + /** + * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control. + * Typically this will have a negative value with scrolling occurs. + */ + Vector2 mScrollPosition; ///< The text is offset by this position when scrolling. + + bool mDecoratorUpdated : 1; ///< True if the decorator was updated during event processing + bool mCursorBlinkEnabled : 1; ///< True if cursor should blink when active + bool mGrabHandleEnabled : 1; ///< True if grab handle is enabled + bool mGrabHandlePopupEnabled : 1; ///< True if the grab handle popu-up should be shown + bool mSelectionEnabled : 1; ///< True if selection handles, highlight etc. are enabled + bool mHorizontalScrollingEnabled : 1; ///< True if horizontal scrolling is enabled + bool mVerticalScrollingEnabled : 1; ///< True if vertical scrolling is enabled + bool mUpdateCursorPosition : 1; ///< True if the visual position of the cursor must be recalculated +}; + +struct Controller::Impl +{ + Impl( ControlInterface& controlInterface ) + : mControlInterface( controlInterface ), + mLogicalModel(), + mVisualModel(), + mFontDefaults( NULL ), + mTextInput( NULL ), + mFontClient(), + mView(), + mLayoutEngine(), + mModifyEvents(), + mControlSize(), + mAlignmentOffset(), + mOperationsPending( NO_OPERATION ), + mRecalculateNaturalSize( true ) + { + mLogicalModel = LogicalModel::New(); + mVisualModel = VisualModel::New(); + + mFontClient = TextAbstraction::FontClient::Get(); + + mView.SetVisualModel( mVisualModel ); + + // Set the text properties to default + mVisualModel->SetTextColor( Color::WHITE ); + mVisualModel->SetShadowOffset( Vector2::ZERO ); + mVisualModel->SetShadowColor( Vector4::ZERO ); + mVisualModel->SetUnderlineEnabled( false ); + } + + ~Impl() + { + delete mTextInput; + } + + ControlInterface& mControlInterface; ///< Reference to the text controller. + LogicalModelPtr mLogicalModel; ///< Pointer to the logical model. + VisualModelPtr mVisualModel; ///< Pointer to the visual model. + FontDefaults* mFontDefaults; ///< Avoid allocating this when the user does not specify a font. + Controller::TextInput* mTextInput; ///< Avoid allocating everything for text input until EnableTextInput(). + TextAbstraction::FontClient mFontClient; ///< Handle to the font client. + View mView; ///< The view interface to the rendering back-end. + LayoutEngine mLayoutEngine; ///< The layout engine. + std::vector mModifyEvents; ///< Temporary stores the text set until the next relayout. + Size mControlSize; ///< The size of the control. + Vector2 mAlignmentOffset; ///< Vertical and horizontal offset of the whole text inside the control due to alignment. + OperationsMask mOperationsPending; ///< Operations pending to be done to layout the text. + bool mRecalculateNaturalSize:1; ///< Whether the natural size needs to be recalculated. +}; + +ControllerPtr Controller::New( ControlInterface& controlInterface ) +{ + return ControllerPtr( new Controller( controlInterface ) ); +} + +void Controller::SetText( const std::string& text ) +{ + // Cancel previously queued inserts etc. + mImpl->mModifyEvents.clear(); + + // Keep until size negotiation + ModifyEvent event; + event.type = REPLACE_TEXT; + event.text = text; + mImpl->mModifyEvents.push_back( event ); + + if( mImpl->mTextInput ) + { + // Cancel previously queued events + mImpl->mTextInput->mEventQueue.clear(); + + // TODO - Hide selection decorations + } +} + +void Controller::GetText( std::string& text ) const +{ + if( !mImpl->mModifyEvents.empty() && + REPLACE_TEXT == mImpl->mModifyEvents[0].type ) + { + text = mImpl->mModifyEvents[0].text; + } + else + { + // TODO - Convert from UTF-32 + } +} + +void Controller::SetPlaceholderText( const std::string& text ) +{ + if( !mImpl->mTextInput ) + { + mImpl->mTextInput->mPlaceholderText = text; + } +} + +void Controller::GetPlaceholderText( std::string& text ) const +{ + if( !mImpl->mTextInput ) + { + text = mImpl->mTextInput->mPlaceholderText; + } +} + +void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily ) +{ + if( !mImpl->mFontDefaults ) + { + mImpl->mFontDefaults = new Controller::FontDefaults(); + } + + mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily; + mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + RequestRelayout(); +} + +const std::string& Controller::GetDefaultFontFamily() const +{ + if( mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->mDefaultFontFamily; + } + + return String::EMPTY;; +} + +void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle ) +{ + if( !mImpl->mFontDefaults ) + { + mImpl->mFontDefaults = new Controller::FontDefaults(); + } + + mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle; + mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + RequestRelayout(); +} + +const std::string& Controller::GetDefaultFontStyle() const +{ + if( mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->mDefaultFontStyle; + } + + return String::EMPTY; +} + +void Controller::SetDefaultPointSize( float pointSize ) +{ + if( !mImpl->mFontDefaults ) + { + mImpl->mFontDefaults = new Controller::FontDefaults(); + } + + mImpl->mFontDefaults->mDefaultPointSize = pointSize; + mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + RequestRelayout(); +} + +float Controller::GetDefaultPointSize() const +{ + if( mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->mDefaultPointSize; + } + + return 0.0f; +} + +void Controller::GetDefaultFonts( Vector& fonts, Length numberOfCharacters ) const +{ + if( mImpl->mFontDefaults ) + { + FontRun fontRun; + fontRun.characterRun.characterIndex = 0; + fontRun.characterRun.numberOfCharacters = numberOfCharacters; + fontRun.fontId = mImpl->mFontDefaults->GetFontId( mImpl->mFontClient ); + fontRun.isDefault = true; + + fonts.PushBack( fontRun ); + } +} + +const Vector4& Controller::GetTextColor() const +{ + return mImpl->mVisualModel->GetTextColor(); +} + +const Vector2& Controller::GetShadowOffset() const +{ + return mImpl->mVisualModel->GetShadowOffset(); +} + +const Vector4& Controller::GetShadowColor() const +{ + return mImpl->mVisualModel->GetShadowColor(); +} + +const Vector4& Controller::GetUnderlineColor() const +{ + return mImpl->mVisualModel->GetUnderlineColor(); +} + +bool Controller::IsUnderlineEnabled() const +{ + return mImpl->mVisualModel->IsUnderlineEnabled(); +} + +void Controller::SetTextColor( const Vector4& textColor ) +{ + mImpl->mVisualModel->SetTextColor( textColor ); +} + +void Controller::SetShadowOffset( const Vector2& shadowOffset ) +{ + mImpl->mVisualModel->SetShadowOffset( shadowOffset ); +} + +void Controller::SetShadowColor( const Vector4& shadowColor ) +{ + mImpl->mVisualModel->SetShadowColor( shadowColor ); +} + +void Controller::SetUnderlineColor( const Vector4& color ) +{ + mImpl->mVisualModel->SetUnderlineColor( color ); +} + +void Controller::SetUnderlineEnabled( bool enabled ) +{ + mImpl->mVisualModel->SetUnderlineEnabled( enabled ); +} + +void Controller::EnableTextInput( DecoratorPtr decorator ) +{ + if( !mImpl->mTextInput ) + { + mImpl->mTextInput = new TextInput( mImpl->mLogicalModel, + mImpl->mVisualModel, + decorator, + mImpl->mFontDefaults, + mImpl->mFontClient ); + } +} + +void Controller::SetEnableCursorBlink( bool enable ) +{ + DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "TextInput disabled" ); + + if( mImpl->mTextInput ) + { + mImpl->mTextInput->mCursorBlinkEnabled = enable; + + if( !enable && + mImpl->mTextInput->mDecorator ) + { + mImpl->mTextInput->mDecorator->StopCursorBlink(); + } + } +} + +bool Controller::GetEnableCursorBlink() const +{ + if( mImpl->mTextInput ) + { + return mImpl->mTextInput->mCursorBlinkEnabled; + } + + return false; +} + +const Vector2& Controller::GetScrollPosition() const +{ + if( mImpl->mTextInput ) + { + return mImpl->mTextInput->mScrollPosition; + } + + return Vector2::ZERO; +} + +const Vector2& Controller::GetAlignmentOffset() const +{ + return mImpl->mAlignmentOffset; +} + +Vector3 Controller::GetNaturalSize() +{ + Vector3 naturalSize; + + // Make sure the model is up-to-date before layouting + ProcessModifyEvents(); + + if( mImpl->mRecalculateNaturalSize ) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + GET_WORD_BREAKS | + BIDI_INFO | + SHAPE_TEXT | + GET_GLYPH_METRICS ); + // Make sure the model is up-to-date before layouting + UpdateModel( onlyOnceOperations ); + + // Operations that need to be done if the size changes. + const OperationsMask sizeOperations = static_cast( LAYOUT | + ALIGN | + REORDER ); + + DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ), + static_cast( onlyOnceOperations | + sizeOperations ), + naturalSize.GetVectorXY() ); + + // Do not do again the only once operations. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); + + // Do the size related operations again. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); + + // Stores the natural size to avoid recalculate it again + // unless the text/style changes. + mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() ); + + mImpl->mRecalculateNaturalSize = false; + } + else + { + naturalSize = mImpl->mVisualModel->GetNaturalSize(); + } + + return naturalSize; +} + +float Controller::GetHeightForWidth( float width ) +{ + // Make sure the model is up-to-date before layouting + ProcessModifyEvents(); + + Size layoutSize; + if( width != mImpl->mControlSize.width ) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + GET_WORD_BREAKS | + BIDI_INFO | + SHAPE_TEXT | + GET_GLYPH_METRICS ); + // Make sure the model is up-to-date before layouting + UpdateModel( onlyOnceOperations ); + + // Operations that need to be done if the size changes. + const OperationsMask sizeOperations = static_cast( LAYOUT | + ALIGN | + REORDER ); + + DoRelayout( Size( width, MAX_FLOAT ), + static_cast( onlyOnceOperations | + sizeOperations ), + layoutSize ); + + // Do not do again the only once operations. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); + + // Do the size related operations again. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); + } + else + { + layoutSize = mImpl->mVisualModel->GetActualSize(); + } + + return layoutSize.height; +} + +bool Controller::Relayout( const Size& size ) +{ + if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) + { + bool glyphsRemoved( false ); + if( 0u != mImpl->mVisualModel->GetNumberOfGlyphPositions() ) + { + mImpl->mVisualModel->SetGlyphPositions( NULL, 0u ); + glyphsRemoved = true; + } + + // Not worth to relayout if width or height is equal to zero. + return glyphsRemoved; + } + + if( size != mImpl->mControlSize ) + { + // Operations that need to be done if the size changes. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | + LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); + + mImpl->mControlSize = size; + } + + // Make sure the model is up-to-date before layouting + ProcessModifyEvents(); + UpdateModel( mImpl->mOperationsPending ); + + Size layoutSize; + bool updated = DoRelayout( mImpl->mControlSize, + mImpl->mOperationsPending, + layoutSize ); + + // Do not re-do any operation until something changes. + mImpl->mOperationsPending = NO_OPERATION; + + // After doing the text layout, the alignment offset to place the actor in the desired position can be calculated. + CalculateTextAlignment( size ); + + if( mImpl->mTextInput ) + { + // Move the cursor, grab handle etc. + updated = mImpl->mTextInput->ProcessInputEvents( mImpl->mControlSize, mImpl->mAlignmentOffset ) || updated; + } + + return updated; +} + +void Controller::ProcessModifyEvents() +{ + std::vector& events = mImpl->mModifyEvents; + + for( unsigned int i=0; imLogicalModel->mText.Clear(); + mImpl->mLogicalModel->mScriptRuns.Clear(); + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mLogicalModel->mLineBreakInfo.Clear(); + mImpl->mLogicalModel->mWordBreakInfo.Clear(); + mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear(); + mImpl->mLogicalModel->mCharacterDirections.Clear(); + mImpl->mLogicalModel->mBidirectionalLineInfo.Clear(); + mImpl->mLogicalModel->mLogicalToVisualMap.Clear(); + mImpl->mLogicalModel->mVisualToLogicalMap.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + // Convert text into UTF-32 + Vector& utf32Characters = mImpl->mLogicalModel->mText; + utf32Characters.Resize( text.size() ); + + // This is a bit horrible but std::string returns a (signed) char* + const uint8_t* utf8 = reinterpret_cast( text.c_str() ); + + // Transform a text array encoded in utf8 into an array encoded in utf32. + // It returns the actual number of characters. + Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() ); + utf32Characters.Resize( characterCount ); + + // Reset the cursor position + if( mImpl->mTextInput ) + { + mImpl->mTextInput->mPrimaryCursorPosition = characterCount; + // TODO - handle secondary cursor + } + + // The natural size needs to be re-calculated. + mImpl->mRecalculateNaturalSize = true; + + // Apply modifications to the model + mImpl->mOperationsPending = ALL_OPERATIONS; + UpdateModel( ALL_OPERATIONS ); + mImpl->mOperationsPending = static_cast( LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); +} + +void Controller::InsertTextEvent( const std::string& text ) +{ + DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "Unexpected InsertTextEvent" ); + + // TODO - Optimize this + mImpl->mLogicalModel->mScriptRuns.Clear(); + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mLogicalModel->mLineBreakInfo.Clear(); + mImpl->mLogicalModel->mWordBreakInfo.Clear(); + mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear(); + mImpl->mLogicalModel->mCharacterDirections.Clear(); + mImpl->mLogicalModel->mBidirectionalLineInfo.Clear(); + mImpl->mLogicalModel->mLogicalToVisualMap.Clear(); + mImpl->mLogicalModel->mVisualToLogicalMap.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + // Convert text into UTF-32 + Vector utf32Characters; + utf32Characters.Resize( text.size() ); + + // This is a bit horrible but std::string returns a (signed) char* + const uint8_t* utf8 = reinterpret_cast( text.c_str() ); + + // Transform a text array encoded in utf8 into an array encoded in utf32. + // It returns the actual number of characters. + Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() ); + utf32Characters.Resize( characterCount ); + + // Insert at current cursor position + Vector& modifyText = mImpl->mLogicalModel->mText; + CharacterIndex& cursorIndex = mImpl->mTextInput->mPrimaryCursorPosition; + + if( cursorIndex < modifyText.Count() ) + { + modifyText.Insert( modifyText.Begin() + cursorIndex, utf32Characters.Begin(), utf32Characters.End() ); + } + else + { + modifyText.Insert( modifyText.End(), utf32Characters.Begin(), utf32Characters.End() ); + } + + // Advance the cursor position + ++cursorIndex; + + // The natural size needs to be re-calculated. + mImpl->mRecalculateNaturalSize = true; + + // Apply modifications to the model; TODO - Optimize this + mImpl->mOperationsPending = ALL_OPERATIONS; + UpdateModel( ALL_OPERATIONS ); + mImpl->mOperationsPending = static_cast( LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); + + // Queue a cursor reposition event; this must wait until after DoRelayout() + mImpl->mTextInput->mUpdateCursorPosition = true; +} + +void Controller::DeleteTextEvent() +{ + DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "Unexpected InsertTextEvent" ); + + // TODO - Optimize this + mImpl->mLogicalModel->mScriptRuns.Clear(); + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mLogicalModel->mLineBreakInfo.Clear(); + mImpl->mLogicalModel->mWordBreakInfo.Clear(); + mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear(); + mImpl->mLogicalModel->mCharacterDirections.Clear(); + mImpl->mLogicalModel->mBidirectionalLineInfo.Clear(); + mImpl->mLogicalModel->mLogicalToVisualMap.Clear(); + mImpl->mLogicalModel->mVisualToLogicalMap.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + // Delte at current cursor position + Vector& modifyText = mImpl->mLogicalModel->mText; + CharacterIndex& cursorIndex = mImpl->mTextInput->mPrimaryCursorPosition; + + if( cursorIndex > 0 && + cursorIndex-1 < modifyText.Count() ) + { + modifyText.Remove( modifyText.Begin() + cursorIndex - 1 ); + + // Cursor position retreat + --cursorIndex; + } + + // The natural size needs to be re-calculated. + mImpl->mRecalculateNaturalSize = true; + + // Apply modifications to the model; TODO - Optimize this + mImpl->mOperationsPending = ALL_OPERATIONS; + UpdateModel( ALL_OPERATIONS ); + mImpl->mOperationsPending = static_cast( LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); + + // Queue a cursor reposition event; this must wait until after DoRelayout() + mImpl->mTextInput->mUpdateCursorPosition = true; +} + +void Controller::UpdateModel( OperationsMask operationsRequired ) +{ + // Calculate the operations to be done. + const OperationsMask operations = static_cast( mImpl->mOperationsPending & operationsRequired ); + + Vector& utf32Characters = mImpl->mLogicalModel->mText; + + const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters(); + + Vector& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo; + if( GET_LINE_BREAKS & operations ) + { + // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to + // calculate the bidirectional info for each 'paragraph'. + // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines + // is not shaped together). + lineBreakInfo.Resize( numberOfCharacters, TextAbstraction::LINE_NO_BREAK ); + + SetLineBreakInfo( utf32Characters, + lineBreakInfo ); + } + + Vector& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo; + if( GET_WORD_BREAKS & operations ) + { + // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines). + wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK ); + + SetWordBreakInfo( utf32Characters, + wordBreakInfo ); + } + + const bool getScripts = GET_SCRIPTS & operations; + const bool validateFonts = VALIDATE_FONTS & operations; + + Vector& scripts = mImpl->mLogicalModel->mScriptRuns; + Vector& validFonts = mImpl->mLogicalModel->mFontRuns; + + if( getScripts || validateFonts ) + { + // Validates the fonts assigned by the application or assigns default ones. + // It makes sure all the characters are going to be rendered by the correct font. + MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get(); + + if( getScripts ) + { + // Retrieves the scripts used in the text. + multilanguageSupport.SetScripts( utf32Characters, + lineBreakInfo, + scripts ); + } + + if( validateFonts ) + { + if( 0u == validFonts.Count() ) + { + // Copy the requested font defaults received via the property system. + // These may not be valid i.e. may not contain glyphs for the necessary scripts. + GetDefaultFonts( validFonts, numberOfCharacters ); + } + + // Validates the fonts. If there is a character with no assigned font it sets a default one. + // After this call, fonts are validated. + multilanguageSupport.ValidateFonts( utf32Characters, + scripts, + validFonts ); + } + } + + Vector mirroredUtf32Characters; + bool textMirrored = false; + if( BIDI_INFO & operations ) + { + // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's + // bidirectional info. + + Length numberOfParagraphs = 0u; + + const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + for( Length index = 0u; index < numberOfCharacters; ++index ) + { + if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) ) + { + ++numberOfParagraphs; + } + } + + Vector& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo; + bidirectionalInfo.Reserve( numberOfParagraphs ); + + // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts. + SetBidirectionalInfo( utf32Characters, + scripts, + lineBreakInfo, + bidirectionalInfo ); + + if( 0u != bidirectionalInfo.Count() ) + { + // This paragraph has right to left text. Some characters may need to be mirrored. + // TODO: consider if the mirrored string can be stored as well. + + textMirrored = GetMirroredText( utf32Characters, mirroredUtf32Characters ); + + // Only set the character directions if there is right to left characters. + Vector& directions = mImpl->mLogicalModel->mCharacterDirections; + directions.Resize( numberOfCharacters ); + + GetCharactersDirection( bidirectionalInfo, + directions ); + } + else + { + // There is no right to left characters. Clear the directions vector. + mImpl->mLogicalModel->mCharacterDirections.Clear(); + } + + } + + Vector& glyphs = mImpl->mVisualModel->mGlyphs; + Vector& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters; + Vector& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph; + if( SHAPE_TEXT & operations ) + { + const Vector& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters; + // Shapes the text. + ShapeText( textToShape, + lineBreakInfo, + scripts, + validFonts, + glyphs, + glyphsToCharactersMap, + charactersPerGlyph ); + + // Create the 'number of glyphs' per character and the glyph to character conversion tables. + mImpl->mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters ); + mImpl->mVisualModel->CreateCharacterToGlyphTable( numberOfCharacters ); + } + + const Length numberOfGlyphs = glyphs.Count(); + + if( GET_GLYPH_METRICS & operations ) + { + mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), numberOfGlyphs ); + } +} + +bool Controller::DoRelayout( const Size& size, + OperationsMask operationsRequired, + Size& layoutSize ) +{ + bool viewUpdated( false ); + + // Calculate the operations to be done. + const OperationsMask operations = static_cast( mImpl->mOperationsPending & operationsRequired ); + + if( LAYOUT & operations ) + { + // Some vectors with data needed to layout and reorder may be void + // after the first time the text has been laid out. + // Fill the vectors again. + + Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs(); + + if( 0u == numberOfGlyphs ) + { + // Nothing else to do if there is no glyphs. + return true; + } + + Vector& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo; + Vector& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo; + Vector& glyphs = mImpl->mVisualModel->mGlyphs; + Vector& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters; + Vector& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph; + + // Set the layout parameters. + LayoutParameters layoutParameters( size, + mImpl->mLogicalModel->mText.Begin(), + lineBreakInfo.Begin(), + wordBreakInfo.Begin(), + numberOfGlyphs, + glyphs.Begin(), + glyphsToCharactersMap.Begin(), + charactersPerGlyph.Begin() ); + + // The laid-out lines. + // It's not possible to know in how many lines the text is going to be laid-out, + // but it can be resized at least with the number of 'paragraphs' to avoid + // some re-allocations. + Vector& lines = mImpl->mVisualModel->mLines; + + // Delete any previous laid out lines before setting the new ones. + lines.Clear(); + + // The capacity of the bidirectional paragraph info is the number of paragraphs. + lines.Reserve( mImpl->mLogicalModel->mBidirectionalParagraphInfo.Capacity() ); + + // Resize the vector of positions to have the same size than the vector of glyphs. + Vector& glyphPositions = mImpl->mVisualModel->mGlyphPositions; + glyphPositions.Resize( numberOfGlyphs ); + + // Update the visual model. + viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters, + glyphPositions, + lines, + layoutSize ); + + if( viewUpdated ) + { + // Reorder the lines + if( REORDER & operations ) + { + Vector& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo; + + // Check first if there are paragraphs with bidirectional info. + if( 0u != bidirectionalInfo.Count() ) + { + // Get the lines + const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines(); + + // Reorder the lines. + Vector lineBidirectionalInfoRuns; + lineBidirectionalInfoRuns.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters. + ReorderLines( bidirectionalInfo, + lines, + lineBidirectionalInfoRuns ); + + // Set the bidirectional info into the model. + const Length numberOfBidirectionalInfoRuns = lineBidirectionalInfoRuns.Count(); + mImpl->mLogicalModel->SetVisualToLogicalMap( lineBidirectionalInfoRuns.Begin(), + numberOfBidirectionalInfoRuns ); + + // Set the bidirectional info per line into the layout parameters. + layoutParameters.lineBidirectionalInfoRunsBuffer = lineBidirectionalInfoRuns.Begin(); + layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns; + + // Get the character to glyph conversion table and set into the layout. + layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin(); + + // Get the glyphs per character table and set into the layout. + layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin(); + + // Re-layout the text. Reorder those lines with right to left characters. + mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters, + glyphPositions ); + + // Free the allocated memory used to store the conversion table in the bidirectional line info run. + for( Vector::Iterator it = lineBidirectionalInfoRuns.Begin(), + endIt = lineBidirectionalInfoRuns.End(); + it != endIt; + ++it ) + { + BidirectionalLineInfoRun& bidiLineInfo = *it; + + free( bidiLineInfo.visualToLogicalMap ); + } + } + } // REORDER + + if( ALIGN & operations ) + { + mImpl->mLayoutEngine.Align( layoutParameters, + layoutSize, + lines, + glyphPositions ); + } + + // Sets the actual size. + if( UPDATE_ACTUAL_SIZE & operations ) + { + mImpl->mVisualModel->SetActualSize( layoutSize ); + } + } // view updated + } + else + { + layoutSize = mImpl->mVisualModel->GetActualSize(); + } + + return viewUpdated; +} + +void Controller::CalculateTextAlignment( const Size& size ) +{ + // Get the direction of the first character. + const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u ); + + const Size& actualSize = mImpl->mVisualModel->GetActualSize(); + + // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END; + LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment(); + if( firstParagraphDirection && + ( LayoutEngine::HORIZONTAL_ALIGN_CENTER != horizontalAlignment ) ) + { + if( LayoutEngine::HORIZONTAL_ALIGN_BEGIN == horizontalAlignment ) + { + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END; + } + else + { + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN; + } + } + + switch( horizontalAlignment ) + { + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + { + mImpl->mAlignmentOffset.x = 0.f; + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + { + const int intOffset = static_cast( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment. + mImpl->mAlignmentOffset.x = static_cast( intOffset ); + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_END: + { + mImpl->mAlignmentOffset.x = size.width - actualSize.width; + break; + } + } + + const LayoutEngine::VerticalAlignment verticalAlignment = mImpl->mLayoutEngine.GetVerticalAlignment(); + switch( verticalAlignment ) + { + case LayoutEngine::VERTICAL_ALIGN_TOP: + { + mImpl->mAlignmentOffset.y = 0.f; + break; + } + case LayoutEngine::VERTICAL_ALIGN_CENTER: + { + const int intOffset = static_cast( 0.5f * ( size.height - actualSize.height ) ); // try to avoid pixel alignment. + mImpl->mAlignmentOffset.y = static_cast( intOffset ); + break; + } + case LayoutEngine::VERTICAL_ALIGN_BOTTOM: + { + mImpl->mAlignmentOffset.y = size.height - actualSize.height; + break; + } + } +} + +View& Controller::GetView() +{ + return mImpl->mView; +} + +LayoutEngine& Controller::GetLayoutEngine() +{ + return mImpl->mLayoutEngine; +} + +void Controller::RequestRelayout() +{ + mImpl->mControlInterface.RequestTextRelayout(); +} + +void Controller::KeyboardFocusGainEvent() +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusGainEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::KEYBOARD_FOCUS_GAIN_EVENT ); + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +void Controller::KeyboardFocusLostEvent() +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusLostEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::KEYBOARD_FOCUS_LOST_EVENT ); + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyEvent" ); + + if( mImpl->mTextInput && + keyEvent.state == KeyEvent::Down ) + { + int keyCode = keyEvent.keyCode; + const std::string& keyString = keyEvent.keyPressed; + + // Pre-process to separate modifying events from non-modifying input events. + if( Dali::DALI_KEY_ESCAPE == keyCode ) + { + // Escape key is a special case which causes focus loss + KeyboardFocusLostEvent(); + } + else if( Dali::DALI_KEY_CURSOR_LEFT == keyCode || + Dali::DALI_KEY_CURSOR_RIGHT == keyCode || + Dali::DALI_KEY_CURSOR_UP == keyCode || + Dali::DALI_KEY_CURSOR_DOWN == keyCode ) + { + TextInput::Event event( TextInput::CURSOR_KEY_EVENT ); + event.p1.mInt = keyCode; + mImpl->mTextInput->mEventQueue.push_back( event ); + } + else if( Dali::DALI_KEY_BACKSPACE == keyCode ) + { + // Queue a delete event + ModifyEvent event; + event.type = DELETE_TEXT; + mImpl->mModifyEvents.push_back( event ); + } + else if( !keyString.empty() ) + { + // Queue an insert event + ModifyEvent event; + event.type = INSERT_TEXT; + event.text = keyString; + mImpl->mModifyEvents.push_back( event ); + } + + mImpl->mTextInput->ChangeState( TextInput::EDITING ); // todo Confirm this is the best place to change the state of + + RequestRelayout(); + } + + return false; +} + +void Controller::TapEvent( unsigned int tapCount, float x, float y ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected TapEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::TAP_EVENT ); + event.p1.mUint = tapCount; + event.p2.mFloat = x; + event.p3.mFloat = y; + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +void Controller::PanEvent( Gesture::State state, const Vector2& displacement ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected PanEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::PAN_EVENT ); + event.p1.mInt = state; + event.p2.mFloat = displacement.x; + event.p3.mFloat = displacement.y; + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +void Controller::GrabHandleEvent( GrabHandleState state, float x, float y ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected GrabHandleEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::GRAB_HANDLE_EVENT ); + event.p1.mUint = state; + event.p2.mFloat = x; + event.p3.mFloat = y; + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +Controller::~Controller() +{ + delete mImpl; +} + +Controller::Controller( ControlInterface& controlInterface ) +: mImpl( NULL ) +{ + mImpl = new Controller::Impl( controlInterface ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h new file mode 100644 index 0000000..0234e7c --- /dev/null +++ b/dali-toolkit/internal/text/text-controller.h @@ -0,0 +1,449 @@ +#ifndef __DALI_TOOLKIT_TEXT_CONTROLLER_H__ +#define __DALI_TOOLKIT_TEXT_CONTROLLER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class Controller; +class LayoutEngine; + +typedef IntrusivePtr ControllerPtr; +typedef Dali::Toolkit::Text::ControlInterface ControlInterface; + +/** + * @brief A Text Controller is used by UI Controls which display text. + * + * It manipulates the Logical & Visual text models on behalf of the UI Controls. + * It provides a view of the text that can be used by rendering back-ends. + * + * For selectable/editable UI controls, the controller handles input events from the UI control + * and decorations (grab handles etc) via an observer interface. + */ +class Controller : public RefObject, public Decorator::Observer +{ +private: + + /** + * @brief Text related operations to be done in the relayout process. + */ + enum OperationsMask + { + NO_OPERATION = 0x0000, + CONVERT_TO_UTF32 = 0x0001, + GET_SCRIPTS = 0x0002, + VALIDATE_FONTS = 0x0004, + GET_LINE_BREAKS = 0x0008, + GET_WORD_BREAKS = 0x0010, + BIDI_INFO = 0x0020, + SHAPE_TEXT = 0x0040, + GET_GLYPH_METRICS = 0x0080, + LAYOUT = 0x0100, + UPDATE_ACTUAL_SIZE = 0x0200, + REORDER = 0x0400, + ALIGN = 0x0800, + ALL_OPERATIONS = 0xFFFF + }; + +public: + + /** + * @brief Create a new instance of a Controller. + * + * @param[in] controlInterface An interface used to request a text relayout. + * @return A pointer to a new Controller. + */ + static ControllerPtr New( ControlInterface& controlInterface ); + + /** + * @brief Replaces any text previously set. + * + * @note This will be converted into UTF-32 when stored in the text model. + * @param[in] text A string of UTF-8 characters. + */ + void SetText( const std::string& text ); + + /** + * @brief Retrieve any text previously set. + * + * @return A string of UTF-8 characters. + */ + void GetText( std::string& text ) const; + + /** + * @brief Replaces any placeholder text previously set. + * + * @param[in] text A string of UTF-8 characters. + */ + void SetPlaceholderText( const std::string& text ); + + /** + * @brief Retrieve any placeholder text previously set. + * + * @return A string of UTF-8 characters. + */ + void GetPlaceholderText( std::string& text ) const; + + /** + * @brief Set the default font family. + * + * @param[in] defaultFontFamily The default font family. + */ + void SetDefaultFontFamily( const std::string& defaultFontFamily ); + + /** + * @brief Retrieve the default font family. + * + * @return The default font family. + */ + const std::string& GetDefaultFontFamily() const; + + /** + * @brief Set the default font style. + * + * @param[in] defaultFontStyle The default font style. + */ + void SetDefaultFontStyle( const std::string& defaultFontStyle ); + + /** + * @brief Retrieve the default font style. + * + * @return The default font style. + */ + const std::string& GetDefaultFontStyle() const; + + /** + * @brief Set the default point size. + * + * @param[in] defaultFontStyle The default point size. + */ + void SetDefaultPointSize( float pointSize ); + + /** + * @brief Retrieve the default point size. + * + * @return The default point size. + */ + float GetDefaultPointSize() const; + + /** + * @brief Retrieve the default fonts. + * + * @param[out] fonts The default font family, style and point sizes. + * @param[in] numberOfCharacters The number of characters in the logical model. + */ + void GetDefaultFonts( Dali::Vector& fonts, Length numberOfCharacters ) const; + + /** + * @brief Set the text color + * + * @param textColor The text color + */ + void SetTextColor( const Vector4& textColor ); + + /** + * @brief Retrieve the text color + * + * @return The text color + */ + const Vector4& GetTextColor() const; + + /** + * @brief Set the shadow offset. + * + * @param[in] shadowOffset The shadow offset, 0,0 indicates no shadow. + */ + void SetShadowOffset( const Vector2& shadowOffset ); + + /** + * @brief Retrieve the shadow offset. + * + * @return The shadow offset. + */ + const Vector2& GetShadowOffset() const; + + /** + * @brief Set the shadow color. + * + * @param[in] shadowColor The shadow color. + */ + void SetShadowColor( const Vector4& shadowColor ); + + /** + * @brief Retrieve the shadow color. + * + * @return The shadow color. + */ + const Vector4& GetShadowColor() const; + + /** + * @brief Set the underline color. + * + * @param[in] color color of underline. + */ + void SetUnderlineColor( const Vector4& color ); + + /** + * @brief Retrieve the underline color. + * + * @return The underline color. + */ + const Vector4& GetUnderlineColor() const; + + /** + * @brief Set the underline enabled flag. + * + * @param[in] enabled The underline enabled flag. + */ + void SetUnderlineEnabled( bool enabled ); + + /** + * @brief Returns whether the text is underlined or not. + * + * @return The underline state. + */ + bool IsUnderlineEnabled() const; + + /** + * @brief Called to enable text input. + * + * @note Only selectable or editable controls should calls this. + * @param[in] decorator Used to create cursor, selection handle decorations etc. + */ + void EnableTextInput( DecoratorPtr decorator ); + + /** + * @brief Called to enable/disable cursor blink. + * + * @note Only editable controls should calls this. + * @param[in] enabled Whether the cursor should blink or not. + */ + void SetEnableCursorBlink( bool enable ); + + /** + * @brief Query whether cursor blink is enabled. + * + * @return Whether the cursor should blink or not. + */ + bool GetEnableCursorBlink() const; + + /** + * @brief Query the current scroll position; the UI control is responsible for moving actors to this position. + * + * @return The scroll position. + */ + const Vector2& GetScrollPosition() const; + + /** + * @brief Query the alignment offset. + * + * @return The alignmnet offset. + */ + const Vector2& GetAlignmentOffset() const; + + /** + * @copydoc Control::GetNaturalSize() + */ + Vector3 GetNaturalSize(); + + /** + * @copydoc Control::GetHeightForWidth() + */ + float GetHeightForWidth( float width ); + + /** + * @brief Triggers a relayout which updates View (if necessary). + * + * @note UI Controls are expected to minimize calls to this method e.g. call once after size negotiation. + * @param[in] size A the size of a bounding box to layout text within. + * @return True if the text model or decorations were updated. + */ + bool Relayout( const Size& size ); + + /** + * @brief Process queued events which modify the model. + */ + void ProcessModifyEvents(); + + /** + * @brief Used to process an event queued from SetText() + * + * @param[in] newText The new text to store in the logical model. + */ + void ReplaceTextEvent( const std::string& newText ); + + /** + * @brief Used to process an event queued from key events etc. + * + * @param[in] text The text to insert into the logical model. + */ + void InsertTextEvent( const std::string& text ); + + /** + * @brief Used to process an event queued from backspace key etc. + */ + void DeleteTextEvent(); + + /** + * @brief Update the model following text replace/insert etc. + * + * @param[in] operationsRequired The layout operations which need to be done. + */ + void UpdateModel( OperationsMask operationsRequired ); + + /** + * @brief Lays-out the text. + * + * GetNaturalSize(), GetHeightForWidth() and Relayout() calls this method. + * + * @param[in] size A the size of a bounding box to layout text within. + * @param[in] operations The layout operations which need to be done. + * @param[out] layoutSize The size of the laid-out text. + */ + bool DoRelayout( const Size& size, + OperationsMask operations, + Size& layoutSize ); + + /** + * @brief Calulates the alignment of the whole text inside the bounding box. + * + * @param[in] size The size of the bounding box. + */ + void CalculateTextAlignment( const Size& size ); + + /** + * @brief Return the layout engine. + * + * @return A reference to the layout engine. + */ + LayoutEngine& GetLayoutEngine(); + + /** + * @brief Return a view of the text. + * + * @return A reference to the view. + */ + View& GetView(); + + // Text-input Event Queuing + + /** + * @brief Caller by editable UI controls when keyboard focus is gained. + */ + void KeyboardFocusGainEvent(); + + /** + * @brief Caller by editable UI controls when focus is lost. + */ + void KeyboardFocusLostEvent(); + + /** + * @brief Caller by editable UI controls when key events are received. + * + * @param[in] event The key event. + */ + bool KeyEvent( const Dali::KeyEvent& event ); + + /** + * @brief Caller by editable UI controls when a tap gesture occurs. + * @param[in] tapCount The number of taps. + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + */ + void TapEvent( unsigned int tapCount, float x, float y ); + + /** + * @brief Caller by editable UI controls when a pan gesture occurs. + * + * @param[in] state The state of the gesture. + * @param[in] displacement This distance panned since the last pan gesture. + */ + void PanEvent( Gesture::State state, const Vector2& displacement ); + + /** + * @copydoc Dali::Toolkit::Text::Decorator::Observer::GrabHandleEvent() + */ + virtual void GrabHandleEvent( GrabHandleState state, float x, float y ); + +protected: + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~Controller(); + +private: + + /** + * @brief Request a relayout using the ControlInterface. + */ + void RequestRelayout(); + + /** + * @brief Private constructor. + */ + Controller( ControlInterface& controlInterface ); + + // Undefined + Controller( const Controller& handle ); + + // Undefined + Controller& operator=( const Controller& handle ); + +private: + + struct Impl; + Impl* mImpl; + + // Avoid allocating this when the user does not specify a font + struct FontDefaults; + + // Avoid allocating this for non-editable controls + struct TextInput; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_CONTROLLER_H__ diff --git a/dali-toolkit/internal/text/text-definitions.h b/dali-toolkit/internal/text/text-definitions.h new file mode 100644 index 0000000..17bca2d --- /dev/null +++ b/dali-toolkit/internal/text/text-definitions.h @@ -0,0 +1,63 @@ +#ifndef __DALI_TEXT_ABSTRACTION_TEXT_TYPE_DEFINITIONS_H__ +#define __DALI_TEXT_ABSTRACTION_TEXT_TYPE_DEFINITIONS_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +typedef TextAbstraction::FontId FontId; ///< The unique identifier for a font face (generated by FontClient). +typedef TextAbstraction::FontMetrics FontMetrics; ///< The metrics for a Font expressed in 26.6 fractional pixel format. +typedef TextAbstraction::PointSize26Dot6 PointSize26Dot6; ///< The point size in 26.6 fractional points. +typedef TextAbstraction::FaceIndex FaceIndex; ///< Used with fonts which allow several font faces. +typedef TextAbstraction::GlyphIndex GlyphIndex; ///< Uniquely identifies a glyph within a particular font. +typedef TextAbstraction::Character Character; ///< A UTF-32 representation of a character. +typedef TextAbstraction::GlyphInfo GlyphInfo; ///< The information describing a glyph (font ID, index, metrics). +typedef TextAbstraction::CharacterIndex CharacterIndex; ///< An index into an array of characters. +typedef TextAbstraction::Length Length; ///< The length of an array. +typedef TextAbstraction::BidiInfoIndex BidiInfoIndex; ///< Index to the bidirectional info for a paragraph. +typedef TextAbstraction::Script Script; ///< The character's script. +typedef TextAbstraction::LineBreakInfo LineBreakInfo; ///< Line break info (must break, allow break, no break). Possible values are: @e LINE_MUST_BREAK, @e LINE_ALLOW_BREAK and @e LINE_NO_BREAK (in the TextAbstraction namespace). +typedef TextAbstraction::WordBreakInfo WordBreakInfo; ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace). +typedef TextAbstraction::CharacterDirection CharacterDirection; ///< The character's direction: @e false is left to right, @e true is right to left. + +typedef uint32_t GlyphIndex; ///< An index into an array of glyphs. +typedef uint32_t ScriptRunIndex; ///< An index into an array of script runs. +typedef uint32_t FontRunIndex; ///< An index into an array of font runs. +typedef uint32_t BidirectionalRunIndex; ///< An index into an array of font runs. +typedef uint32_t LineIndex; ///< An index into an array of lines. + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TEXT_ABSTRACTION_TEXT_TYPE_DEFINITIONS_H__ diff --git a/dali-toolkit/internal/text/text-io.cpp b/dali-toolkit/internal/text/text-io.cpp new file mode 100644 index 0000000..3bc1761 --- /dev/null +++ b/dali-toolkit/internal/text/text-io.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +std::ostream& operator<< (std::ostream& o, const Vector& text) +{ + o << std::hex; + + for( unsigned int i=0; i& scriptRun) +{ + for( unsigned int i=0; i9: LATIN" for a ten character run staring from beginning of the model + o << scriptRun[i].characterRun.characterIndex << "->" << (scriptRun[i].characterRun.characterIndex + scriptRun[i].characterRun.numberOfCharacters ) << ": "; + o << TextAbstraction::ScriptName[scriptRun[i].script]; + + if( i+1 < scriptRun.Count() ) + { + o << ", "; + } + } + + return o << std::dec; +} + +std::ostream& operator<< (std::ostream& o, const Vector& fontRun) +{ + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + + for( unsigned int i=0; i9: ID:1 TizenSansKorean style:Regular size:10.0" for a ten character run staring from beginning of the model + o << fontRun[i].characterRun.characterIndex << "->" << (fontRun[i].characterRun.characterIndex + fontRun[i].characterRun.numberOfCharacters ) << ": "; + + FontId id = fontRun[i].fontId; + TextAbstraction::FontDescription fontDescription; + fontClient.GetDescription( id, fontDescription ); + o << "ID:" << id << ", " << fontDescription.family << " style:" << fontDescription.style << " size:" << (fontClient.GetPointSize(id) / 64); + + if( i+1 < fontRun.Count() ) + { + o << ", "; + } + } + + return o << std::dec; +} + +std::ostream& operator<< (std::ostream& o, const Vector& lineRuns) +{ + for( unsigned int i=0; i9 Characters: 0->9 (10)" for a ten character run staring from beginning of the model + o << "Line " << i << " Glyphs: " << lineRuns[i].glyphIndex << "->" << (lineRuns[i].glyphIndex + lineRuns[i].numberOfGlyphs ); + o << " Characters: " << lineRuns[i].characterRun.characterIndex << "->" << (lineRuns[i].characterRun.characterIndex + lineRuns[i].characterRun.numberOfCharacters ); + o << " Width: " << lineRuns[i].width; + o << " Ascender: " << lineRuns[i].ascender; + o << " Descender: " << lineRuns[i].descender; + + if( i+1 < lineRuns.Count() ) + { + o << ", "; + } + } + + return o << std::dec; +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-io.h b/dali-toolkit/internal/text/text-io.h new file mode 100644 index 0000000..25620e0 --- /dev/null +++ b/dali-toolkit/internal/text/text-io.h @@ -0,0 +1,82 @@ +#ifndef __DALI_TEXT_ABSTRACTION_TEXT_IO_H__ +#define __DALI_TEXT_ABSTRACTION_TEXT_IO_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief Print a vector of characters. + * + * @param [in] o The output stream operator. + * @param [in] text The text to print. + * @return The output stream operator. + */ +std::ostream& operator<< (std::ostream& o, const Vector& text); + +/** + * @brief Print a vector of script runs. + * + * @param [in] o The output stream operator. + * @param [in] scriptRuns The script runs to print. + * @return The output stream operator. + */ +std::ostream& operator<< (std::ostream& o, const Vector& scriptRuns); + +/** + * @brief Print a vector of font runs. + * + * @param [in] o The output stream operator. + * @param [in] fontRuns The font runs to print. + * @return The output stream operator. + */ +std::ostream& operator<< (std::ostream& o, const Vector& fontRuns); + +/** + * @brief Print a vector of line runs. + * + * @param [in] o The output stream operator. + * @param [in] lineRuns The line runs to print. + * @return The output stream operator. + */ +std::ostream& operator<< (std::ostream& o, const Vector& lineRuns); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TEXT_ABSTRACTION_TEXT_IO_H__ diff --git a/dali-toolkit/internal/text/text-view-interface.cpp b/dali-toolkit/internal/text/text-view-interface.cpp new file mode 100644 index 0000000..54d1589 --- /dev/null +++ b/dali-toolkit/internal/text/text-view-interface.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +ViewInterface::ViewInterface() +{ +} + +ViewInterface::~ViewInterface() +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h new file mode 100644 index 0000000..116ad50 --- /dev/null +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -0,0 +1,134 @@ +#ifndef __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__ +#define __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__ + +/* + * Copyright (c) 2015 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 +{ + +struct Vector2; + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief Abstract interface to provide the information necessary displaying text. + * + * This includes: + * - The font & glyph IDs needed to get bitmaps etc. from TextAbstraction + * - The visual position of each glyph within the layout + * - A window into the text layout e.g. which page of a document to view + */ +class ViewInterface +{ +public: + + /** + * @brief Constructor. + */ + ViewInterface(); + + /** + * @brief Virtual destructor + */ + virtual ~ViewInterface(); + + /** + * Retrieves the number of glyphs. + * + * @return The number of glyphs. + */ + virtual Length GetNumberOfGlyphs() const = 0; + + /** + * @brief Retrieves glyphs in the given buffer. + * + * The size of the @p glyphs buffer needs to be big enough to copy the @p numberOfGlyphs. + * @param[out] glyphs Pointer to a buffer where the glyphs are copied. + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs Number of glyphs to be copied. + */ + virtual void GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const = 0; + + /** + * @brief Retrieves the glyph positions. + * + * @pre The size of the @p positions buffer needs to be big enough to copy the @p numberOfGlyphs positions. + * @param[out] glyphPositions Pointer to a buffer where the glyph positions are copied. + * @param[in] glyphIndex Index to the first glyph position. + * @param[in] numberOfGlyphs The number of positions to be copied. + */ + virtual void GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const = 0; + + /** + * @brief Retrieves the text color + * + * @return The text color + */ + virtual const Vector4& GetTextColor() const = 0; + + /** + * @brief Retrieves the shadow offset, 0 indicates no shadow. + * + * @return The shadow offset. + */ + virtual const Vector2& GetShadowOffset() const = 0; + + /** + * @brief Retrieves the shadow color. + * + * @return The shadow color. + */ + virtual const Vector4& GetShadowColor() const = 0; + + /** + * @brief Retrieves the underline color. + * + * @return The underline color. + */ + virtual const Vector4& GetUnderlineColor() const = 0; + + /** + * @brief Returns whether is underline is enabled or not. + * + * @return The underline state. + */ + virtual bool IsUnderlineEnabled() const = 0; + +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__ diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp new file mode 100644 index 0000000..b0825f6 --- /dev/null +++ b/dali-toolkit/internal/text/text-view.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct View::Impl +{ + VisualModelPtr mVisualModel; +}; + +View::View() +: mImpl( NULL ) +{ + mImpl = new View::Impl(); +} + +View::~View() +{ + delete mImpl; +} + +void View::SetVisualModel( VisualModelPtr visualModel ) +{ + mImpl->mVisualModel = visualModel; +} + +const Vector4& View::GetTextColor() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetTextColor(); + } + return Vector4::ZERO; +} + +const Vector2& View::GetShadowOffset() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetShadowOffset(); + } + return Vector2::ZERO; +} + +const Vector4& View::GetShadowColor() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetShadowColor(); + } + return Vector4::ZERO; +} + +const Vector4& View::GetUnderlineColor() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetUnderlineColor(); + } + return Vector4::ZERO; +} + +bool View::IsUnderlineEnabled() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.IsUnderlineEnabled(); + } + return false; +} + +Length View::GetNumberOfGlyphs() const +{ + if( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + + Length glyphCount = model.GetNumberOfGlyphs(); + Length positionCount = model.GetNumberOfGlyphPositions(); + + DALI_ASSERT_DEBUG( positionCount <= glyphCount && "Invalid glyph positions in Model" ); + + return (positionCount < glyphCount) ? positionCount : glyphCount; + } + + return 0; +} + +void View::GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + if( mImpl->mVisualModel ) + { + mImpl->mVisualModel->GetGlyphs( glyphs, glyphIndex, numberOfGlyphs ); + } +} + +void View::GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + if( mImpl->mVisualModel ) + { + mImpl->mVisualModel->GetGlyphPositions( glyphPositions, glyphIndex, numberOfGlyphs ); + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h new file mode 100644 index 0000000..b9bd7fc --- /dev/null +++ b/dali-toolkit/internal/text/text-view.h @@ -0,0 +1,123 @@ +#ifndef __DALI_TOOLKIT_TEXT_VIEW_H__ +#define __DALI_TOOLKIT_TEXT_VIEW_H__ + +/* + * Copyright (c) 2015 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 +{ + +struct Vector2; + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief View provides an interface between the Text layout engine and rendering back-end. + */ +class View : public ViewInterface +{ +public: + + /** + * @brief Create a new instance of a View. + */ + View(); + + /** + * @brief Virtual destructor. + */ + virtual ~View(); + + /** + * @brief Set the visual model. + * + * @param[in] visualModel The visual model used by the View. + */ + void SetVisualModel( VisualModelPtr visualModel ); + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfGlyphs() + */ + virtual Length GetNumberOfGlyphs() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetGlyphs() + */ + virtual void GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetGlyphPositions() + */ + virtual void GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetTextColor() + */ + virtual const Vector4& GetTextColor() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetShadowOffset() + */ + virtual const Vector2& GetShadowOffset() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetShadowColor() + */ + virtual const Vector4& GetShadowColor() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetUnderlineColor() + */ + virtual const Vector4& GetUnderlineColor() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::IsUnderlineEnabled() + */ + virtual bool IsUnderlineEnabled() const; + +private: + + // Undefined + View( const View& handle ); + + // Undefined + View& operator=( const View& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_VIEW_H__ diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp new file mode 100644 index 0000000..c070179 --- /dev/null +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2015 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +VisualModelPtr VisualModel::New() +{ + return VisualModelPtr( new VisualModel() ); +} + +void VisualModel::SetGlyphs( const GlyphInfo* glyphs, + const CharacterIndex* characterIndices, + const Length* charactersPerGlyph, + Length numberOfGlyphs ) +{ + if( 0u == numberOfGlyphs ) + { + mGlyphs.Clear(); + mGlyphsToCharacters.Clear(); + mCharactersToGlyph.Clear(); + mCharactersPerGlyph.Clear(); + mGlyphsPerCharacter.Clear(); + } + else + { + if( NULL != glyphs ) + { + mGlyphs.Resize( numberOfGlyphs ); + memcpy( mGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) ); + } + + if( NULL != characterIndices ) + { + mGlyphsToCharacters.Resize( numberOfGlyphs ); + memcpy( mGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) ); + } + + if( NULL != charactersPerGlyph ) + { + mCharactersPerGlyph.Resize( numberOfGlyphs ); + memcpy( mCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) ); + + // Build the glyphs per character table. + CreateGlyphsPerCharacterTable(); + + // Build the characters to glyph conversion table. + CreateCharacterToGlyphTable(); + } + } +} + +void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters ) +{ + // 1) Reserve some space for the characters to avoid reallocations. + if( 0u == numberOfCharacters ) + { + // If no number of characters is given, just set something sensible to avoid reallocations. + numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f ); + } + mCharactersToGlyph.Reserve( numberOfCharacters ); + + DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u || + ( 0u == numberOfCharacters ) ); + + const Length* const glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin(); + + // 2) Traverse the glyphs and set the glyph indices per character. + + // Index to the glyph. + GlyphIndex glyphIndex = 0u; + CharacterIndex characterIndex = 0u; + for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(), + endIt = mCharactersPerGlyph.End(); + it != endIt; + ++it ) + { + const Length numberOfCharactersPerGlyph = *it; + + Length numberOfGlyphs = 0u; + // Set the glyph indices. + for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex ) + { + mCharactersToGlyph.PushBack( glyphIndex ); + numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex ); + } + glyphIndex += numberOfGlyphs; + } +} + +void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters ) +{ + // 1) Reserve some space for the characters to avoid reallocations. + if( 0u == numberOfCharacters ) + { + // If no number of characters is given, just set something sensible to avoid reallocations. + numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f ); + } + mGlyphsPerCharacter.Reserve( numberOfCharacters ); + + // 2) Traverse the glyphs and set the number of glyphs per character. + + // The number of 'characters per glyph' equal to zero. + Length zeroCharactersPerGlyph = 0u; + + for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(), + endIt = mCharactersPerGlyph.End(); + it != endIt; + ++it ) + { + const Length numberOfCharactersPerGlyph = *it; + + // Set the glyphs per character. + if( 0u == numberOfCharactersPerGlyph ) + { + ++zeroCharactersPerGlyph; + } + else + { + const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u ); + for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex ) + { + mGlyphsPerCharacter.PushBack( 0u ); + } + + mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph ); + + zeroCharactersPerGlyph = 0u; + } + } +} + +Length VisualModel::GetNumberOfGlyphs() const +{ + return mGlyphs.Count(); +} + +void VisualModel::GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) ); +} + +const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const +{ + return mGlyphs[glyphIndex]; +} + +void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const GlyphInfo* const glyphs, + const Length* const numberOfCharacters, + Length numberOfGlyphsToInsert ) +{ +} + +CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const +{ + return mGlyphsToCharacters[glyphIndex]; +} + +Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const +{ + return mCharactersPerGlyph[glyphIndex]; +} + +GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const +{ + return mCharactersToGlyph[characterIndex]; +} + +void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( characterToGlyphMap, mCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) ); +} + +void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphToCharacter, mGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) ); +} + +void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( charactersPerGlyph, mCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) ); +} + +void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) ); +} + +void VisualModel::SetGlyphPositions( const Vector2* glyphPositions, + Length numberOfGlyphs ) +{ + if( 0u == numberOfGlyphs ) + { + mGlyphPositions.Clear(); + } + else + { + mGlyphPositions.Resize( numberOfGlyphs ); + memcpy( mGlyphPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) ); + } +} + +Length VisualModel::GetNumberOfGlyphPositions() const +{ + return mGlyphPositions.Count(); +} + +void VisualModel::GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) ); +} + +const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const +{ + return *( mGlyphPositions.Begin() + glyphIndex ); +} + +void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const Vector2* const positions, + Length numberOfGlyphsToInsert ) +{ +} + +void VisualModel::SetLines( const LineRun* const lines, + Length numberOfLines ) +{ + if( 0u == numberOfLines ) + { + mLines.Clear(); + } + else + { + mLines.Resize( numberOfLines ); + memcpy( mLines.Begin(), lines, numberOfLines * sizeof( LineRun ) ); + } +} + +Length VisualModel::GetNumberOfLines() const +{ + return mLines.Count(); +} + +void VisualModel::GetLines( LineRun* lines, + LineIndex lineIndex, + Length numberOfLines ) const +{ + memcpy( lines, mLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) ); +} + +void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex, + Length numberOfGlyphs, + LineIndex& firstLine, + Length& numberOfLines ) const +{ + // Initialize the number of lines and the first line. + firstLine = 0u; + numberOfLines = 0u; + bool firstLineFound = false; + + const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs; + + // Traverse the lines and count those lines within the range of glyphs. + for( Vector::ConstIterator it = mLines.Begin(), + endIt = mLines.End(); + it != endIt; + ++it ) + { + const LineRun& line = *it; + + if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) && + ( lastGlyphIndex > line.glyphIndex ) ) + { + firstLineFound = true; + ++numberOfLines; + } + else if( lastGlyphIndex <= line.glyphIndex ) + { + // nothing else to do. + break; + } + + if( !firstLineFound ) + { + ++firstLine; + } + } +} + +void VisualModel::GetLinesOfGlyphRange( LineRun* lines, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + LineIndex firstLine = 0u; + Length numberOfLines = 0u; + + GetNumberOfLines( glyphIndex, + numberOfGlyphs, + firstLine, + numberOfLines ); + + memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) ); +} + +LineIndex VisualModel::GetLineOfGlyph( GlyphIndex glyphIndex ) +{ + const CharacterIndex characterIndex = *( mGlyphsToCharacters.Begin() + glyphIndex ); + + return GetLineOfCharacter( characterIndex ); +} + +LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex ) +{ + // 1) Check first in the cached line. + + const LineRun& lineRun = *( mLines.Begin() + mCachedLineIndex ); + + if( ( lineRun.characterRun.characterIndex <= characterIndex ) && + ( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) ) + { + return mCachedLineIndex; + } + + // 2) Is not in the cached line. Check in the other lines. + + LineIndex index = characterIndex < lineRun.characterRun.characterIndex ? 0u : mCachedLineIndex + 1u; + + for( Vector::ConstIterator it = mLines.Begin() + index, + endIt = mLines.End(); + it != endIt; + ++it, ++index ) + { + const LineRun& lineRun = *it; + + if( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) + { + mCachedLineIndex = index; + break; + } + } + + return index; +} + +void VisualModel::ReplaceLines( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const LineRun* const lines, + Length numberOfGlyphsToInsert ) +{ +} + +void VisualModel::SetNaturalSize( const Vector2& size ) +{ + mNaturalSize = size; +} + +const Vector2& VisualModel::GetNaturalSize() const +{ + return mNaturalSize; +} + +void VisualModel::SetActualSize( const Vector2& size ) +{ + mActualSize = size; +} + +const Vector2& VisualModel::GetActualSize() const +{ + return mActualSize; +} + +void VisualModel::SetTextColor( const Vector4& textColor ) +{ + mTextColor = textColor; + + if ( !mUnderlineColorSet ) + { + mUnderlineColor = textColor; + } +} + +void VisualModel::SetShadowOffset( const Vector2& shadowOffset ) +{ + mShadowOffset = shadowOffset; +} + +void VisualModel::SetShadowColor( const Vector4& shadowColor ) +{ + mShadowColor = shadowColor; +} + +void VisualModel::SetUnderlineColor( const Vector4& color ) +{ + mUnderlineColor = color; + mUnderlineColorSet = true; +} + +void VisualModel::SetUnderlineEnabled( bool enabled ) +{ + mUnderlineEnabled = enabled; +} + +const Vector4& VisualModel::GetTextColor() const +{ + return mTextColor; +} + +const Vector2& VisualModel::GetShadowOffset() const +{ + return mShadowOffset; +} + +const Vector4& VisualModel::GetShadowColor() const +{ + return mShadowColor; +} + +const Vector4& VisualModel::GetUnderlineColor() const +{ + return mUnderlineColor; +} + +bool VisualModel::IsUnderlineEnabled() const +{ + return mUnderlineEnabled; +} + +void VisualModel::ClearCaches() +{ + mCachedLineIndex = 0u; +} + +VisualModel::~VisualModel() +{ +} + +VisualModel::VisualModel() +: mGlyphs(), + mGlyphsToCharacters(), + mCharactersToGlyph(), + mCharactersPerGlyph(), + mGlyphsPerCharacter(), + mGlyphPositions(), + mLines(), + mTextColor(), + mShadowColor(), + mUnderlineColor(), + mShadowOffset(), + mNaturalSize(), + mActualSize(), + mCachedLineIndex( 0u ), + mUnderlineEnabled( false ), + mUnderlineColorSet( false ) +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h new file mode 100644 index 0000000..aa8a75f --- /dev/null +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -0,0 +1,534 @@ +#ifndef __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +struct Vector2; + +namespace Toolkit +{ + +namespace Text +{ + +struct LineRun; +class VisualModel; +typedef IntrusivePtr VisualModelPtr; + +/** + * @brief A visual text model contains layout specific information. + * + * This includes: + * - A series of glyphs in visual order i.e. after the bidirectional reordering. + * - The position of each glyph within a 2D bounding box. + */ +class VisualModel : public RefObject +{ +public: + + /** + * @brief Create a new instance of a VisualModel. + * + * @return A pointer to a new VisualModel. + */ + static VisualModelPtr New(); + + // Glyph interface. + + /** + * @brief Replaces any glyphs previously set. + * + * @note If the number of glyphs is zero, all buffers are cleared. + * @note If one pointer is NULL and the number of glyphs is not zero, the buffer is not touched. + * + * @param[in] glyphs An array of glyphs in the visual order. + * @param[in] characterIndices An array containing the first character in the logical model that each glyph relates to. + * @param[in] charactersPerGlyph An array containing the number of characters per glyph. + * @param[in] numberOfGlyphs The number of glyphs. + */ + void SetGlyphs( const GlyphInfo* glyphs, + const CharacterIndex* characterIndices, + const Length* charactersPerGlyph, + Length numberOfGlyphs ); + + /** + * @brief Creates the character to glyph conversion table. + * + * @pre The glyphs per character table needs to be created first. + * + * @param[in] numberOfCharacters The number of characters. + */ + void CreateCharacterToGlyphTable( Length numberOfCharacters = 0u ); + + /** + * @brief Creates an array containing the number of glyphs per character. + * + * @param[in] numberOfCharacters The number of characters. + */ + void CreateGlyphsPerCharacterTable( Length numberOfCharacters = 0u ); + + /** + * @brief Retrieves the number of glyphs. + * + * @return The number of glyphs. + */ + Length GetNumberOfGlyphs() const; + + /** + * @brief Retrieves glyphs in the given buffer. + * + * The size of the @p glyphs buffer needs to be big enough to copy the @p numberOfGlyphs. + * @param[out] glyphs Pointer to a buffer where the glyphs are copied. + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs Number of glyphs to be copied. + */ + void GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieves a glyph. + * + * @param[in] glyphIndex Index to a glyph. + * + * @return A glyph. + */ + const GlyphInfo& GetGlyphInfo( GlyphIndex glyphIndex ) const; + + /** + * @brief Replaces glyphs. + * + * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert. + * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove. + * + * @param[in] glyphIndex Where to replace the glyphs. + * @param[in] numberOfGlyphsToRemove The number of glyphs to be removed. + * @param[in] glyphs Pointer to a buffer with the new glyphs. + * @param[in] numberOfCharacters Pointer to a buffer with the number of characters per glyph. + * @param[in] numberOfGlyphsToInsert The number of new glyphs in the buffer. + */ + void ReplaceGlyphs( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const GlyphInfo* const glyphs, + const Length* const numberOfCharacters, + Length numberOfGlyphsToInsert ); + + // Character <--> Glyph conversion + + /** + * @brief Retrieves the first character in the logical model which a glyph represents. + * + * @note After shaping several characters may be represented by the same glyph. + * Alternatively several glyphs may be required to display a character. + * @param[in] glyphIndex The glyph index. + * @return The character index. + */ + CharacterIndex GetCharacterIndex( GlyphIndex glyphIndex ) const; + + /** + * @brief Query the number of characters the glyph represents. + * + * @param[in] glyphIndex The glyph index. + * @return The number of characters represented by the glyph. + */ + Length GetCharactersPerGlyph( GlyphIndex glyphIndex ) const; + + /** + * @brief Retrieves the first glyph in the visual model which represents a given character. + * + * @note After shaping several characters may be represented by the same glyph. + * Alternatively several glyphs may be required to display a character. + * @param[in] characterIndex The character index. + * @return The glyph index. + */ + GlyphIndex GetGlyphIndex( CharacterIndex characterIndex ) const; + + /** + * @brief Retrieves the whole or part of the character to glyph conversion map. + * + * The size of the buffer needs to be big enough to copy the @p numberOfCharacters. + * + * @param[out] characterToGlyphMap Pointer to a buffer where the conversion map is copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the whole or part of the glyph to character conversion map. + * + * The size of the buffer needs to be big enough to copy the @p numberOfGlyphs. + * + * @param[out] glyphToCharacter Pointer to a buffer where the conversion map is copied. + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs The number of glyphs. + */ + void GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieves for each glyph the number of characters the glyph represents. + * + * @param[out] charactersPerGlyph Pointer to a buffer where the number of characters for each glyph are copied. + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs The number of glyphs. + */ + void GetCharactersPerGlyphMap( Length* charactersPerGlyph, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieves for each character the number of glyphs the character is shaped. + * + * @param[out] glyphsPerCharacter Pointer to a buffer where the number of glyphs for each character are copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetGlyphsPerCharacterMap( Length* glyphsPerCharacter, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + // Position interface + + /** + * @brief Replaces any glyph positions previously set. + * + * @note If the number of glyphs is zero the position buffer is cleared. + * + * @param[in] glyphPositions An array of visual positions for each glyph. + * @param[in] numberOfGlyphs The number of positions. + */ + void SetGlyphPositions( const Vector2* glyphPositions, + Length numberOfGlyphs ); + + /** + * @brief Retrieves the number of glyph positions set. + * + * @note This may be less than the number of glyphs in the model. + * @return The number of glyphs. + */ + Length GetNumberOfGlyphPositions() const; + + /** + * @brief Retrieves the glyph positions. + * + * @pre The size of the @p positions buffer needs to be big enough to copy the @p numberOfGlyphs positions. + * @param[out] glyphPositions Pointer to a buffer where the glyph positions are copied. + * @param[in] glyphIndex Index to the first glyph position. + * @param[in] numberOfGlyphs The number of positions to be copied. + */ + void GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieve the glyph's position of the given glyph. + * + * @param[in] glyphIndex Index to the glyph. + * + * @return The glyph's position. + */ + const Vector2& GetGlyphPosition( GlyphIndex glyphIndex ) const; + + /** + * @brief Replaces glyph's positions. + * + * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert. + * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove. + * + * @param[in] glyphIndex Where to replace the glyph's positions. + * @param[in] numberOfGlyphsToRemove The number of glyph's positions to be removed. + * @param[in] positions Pointer to a buffer with the new glyph's positions. + * @param[in] numberOfGlyphsToInsert The number of new glyph's positions in the buffer. + */ + void ReplaceGlyphPositions( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const Vector2* const positions, + Length numberOfGlyphsToInsert ); + + // Line interface. + + /** + * @brief Sets the lines. + * + * Replaces any lines previously set. + * + * Every line is an item run containing the index to the first glyph of the line and the number of glyphs. + * + * @note If the number of lines is zero or the pointer is NULL, the lines buffer is cleared. + * + * @param[in] lines Pointer to a buffer containing all the line runs. + * @param[in] numberOfLines The number of lines in the buffer. + */ + void SetLines( const LineRun* const lines, + Length numberOfLines ); + + /** + * @brief Retrieves the number of lines of the whole text. + * + * @return The number of lines. + */ + Length GetNumberOfLines() const; + + /** + * @brief Retrieves lines. + * + * The size of the @p lines buffer needs to be big enough to copy the @p numberOfLines. + * + * @param[out] lines Pointer to a buffer where the lines are copied. + * @param[in] lineIndex Index to the first line. + * @param[in] numberOfLines Number of lines to be copied. + */ + void GetLines( LineRun* lines, + LineIndex lineIndex, + Length numberOfLines ) 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. + * @param[in] numberOfGlyphs The number of glyph. + * @param[out] firstLine Index to the line containing the glyph index. + * @param[out] numberOfLines The number of lines. + */ + void GetNumberOfLines( GlyphIndex glyphIndex, + Length numberOfGlyphs, + LineIndex& firstLine, + Length& numberOfLines ) const; + /** + * @brief Retrieves the lines where the given range of glyphs is laid out. + * + * The size of the @p lines buffer needs to be big enough to copy the @p numberOfLines. + * + * @param[out] lines Pointer to a buffer where the lines are copied. + * @param[in] glyphIndex Index to the first glyphs of the range. + * @param[in] numberOfGlyphs Number of glyphs in the range. + */ + void GetLinesOfGlyphRange( LineRun* lines, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieves the line index where the glyph is laid-out. + * + * @param[in] glyphIndex The glyph's index. + * + * @return The line index. + */ + LineIndex GetLineOfGlyph( GlyphIndex glyphIndex ); + + /** + * @brief Retrieves the line index where the character is laid-out. + * + * @param[in] characterIndex The character's index. + * + * @return The line index. + */ + LineIndex GetLineOfCharacter( CharacterIndex characterIndex ); + + /** + * @brief Replaces lines for the given range of glyphs. + * + * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert. + * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove. + * + * @param[in] glyphIndex Index of the first glyph where to replace the line info. + * @param[in] numberOfGlyphsToRemove The number of glyphs to be the line info removed. + * @param[in] lines Pointer to a buffer with the lines. + * @param[in] numberOfGlyphsToInsert The number of characters to be the line info inserted. + */ + void ReplaceLines( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const LineRun* const lines, + Length numberOfGlyphsToInsert ); + + // Size interface + + /** + * @brief Sets the natural size. + * + * @param[in] size The text's natural size. + */ + void SetNaturalSize( const Vector2& size ); + + /** + * @brief Retrieves the natural size. + * + * @return The text's natural size. + */ + const Vector2& GetNaturalSize() const; + + /** + * @brief Sets the text's actual size after it has been laid out. + * + * @param[in] size The text's size. + */ + void SetActualSize( const Vector2& size ); + + /** + * @brief Retrieves the text's actual size after it has been laid out. + * + * @return The text's size. + */ + const Vector2& GetActualSize() const; + + /** + * @brief Set the text's color + * + * @param[in] textColor The text's color + */ + void SetTextColor( const Vector4& textColor ); + + /** + * @brief Retrieve the text's color + * + * @return The text's color + */ + const Vector4& GetTextColor() const; + + /** + * @brief Sets the text's shadow offset. + * + * @param[in] shadowOffset The shadow offset, 0,0 indicates no shadow. + */ + void SetShadowOffset( const Vector2& shadowOffset ); + + /** + * @brief Retrieves the text's shadow offset. + * + * @return The text's shadow offset, 0,0 indicates no shadow. + */ + const Vector2& GetShadowOffset() const; + + /** + * @brief Sets the text's shadow color. + * + * @param[in] shadowColor The shadow color. + */ + void SetShadowColor( const Vector4& shadowColor ); + + /** + * @brief Retrieves the text's shadow color. + * + * @return The text's shadow color. + */ + const Vector4& GetShadowColor() const; + + /** + * @brief Sets the text's underline color. + * + * @param[in] color The text's underline color. + */ + void SetUnderlineColor( const Vector4& color ); + + /** + * @brief Retrieves the text's underline color. + * + * @return The text's underline color. + */ + const Vector4& GetUnderlineColor() const; + + /** + * @brief Sets the text underline flag. + * + * @param[in] enabled true if underlined. + */ + void SetUnderlineEnabled( bool enabled ); + + /** + * @brief Returns whether the text is underlined or not. + * + * @return underline state. + */ + bool IsUnderlineEnabled() const; + + /** + * @brief Clear the caches. + */ + void ClearCaches(); + +protected: + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~VisualModel(); + +private: + + /** + * @brief Private constructor. + */ + VisualModel(); + + // Undefined + VisualModel( const VisualModel& handle ); + + // Undefined + VisualModel& operator=( const VisualModel& handle ); + +public: + + Vector mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics. + Vector mGlyphsToCharacters; ///< For each glyph, the index of the first character. + Vector mCharactersToGlyph; ///< For each character, the index of the first glyph. + Vector mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph. + Vector mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped. + Vector mGlyphPositions; ///< For each glyph, the position. + Vector mLines; ///< The laid out lines. + + Vector4 mTextColor; ///< The text color + Vector4 mShadowColor; ///< Color of drop shadow + Vector4 mUnderlineColor; ///< Color of underline + Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow + +private: + + Size mNaturalSize; ///< Size of the text with no line wrapping. + Size mActualSize; ///< Size of the laid-out text considering the layout properties set. + + // Caches to increase performance in some consecutive operations. + LineIndex mCachedLineIndex; ///< Used to increase performance in consecutive calls to GetLineOfGlyph() or GetLineOfCharacter() with consecutive glyphs or characters. + +public: + bool mUnderlineEnabled:1; ///< Underline enabled flag + bool mUnderlineColorSet:1; ///< Has the underline color been explicitly set? +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__ diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index 4cea531..f8eded1 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -168,6 +168,7 @@ public: // Construction & Destruction Impl(Control& controlImpl) : mControlImpl( controlImpl ), + mStyleName(""), mBackground( NULL ), mStartingPinchScale( NULL ), mKeyEventSignal(), @@ -246,6 +247,12 @@ public: switch ( index ) { + case Toolkit::Control::Property::STYLE_NAME: + { + controlImpl.SetStyleName( value.Get< std::string >() ); + break; + } + case Toolkit::Control::Property::BACKGROUND_COLOR: { controlImpl.SetBackgroundColor( value.Get< Vector4 >() ); @@ -306,6 +313,12 @@ public: switch ( index ) { + case Toolkit::Control::Property::STYLE_NAME: + { + value = controlImpl.GetStyleName(); + break; + } + case Toolkit::Control::Property::BACKGROUND_COLOR: { value = controlImpl.GetBackgroundColor(); @@ -347,6 +360,7 @@ public: // Data Control& mControlImpl; + std::string mStyleName; Background* mBackground; ///< Only create the background if we use it Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this Toolkit::Control::KeyEventSignalType mKeyEventSignal; @@ -369,12 +383,14 @@ public: static PropertyRegistration PROPERTY_1; static PropertyRegistration PROPERTY_2; static PropertyRegistration PROPERTY_3; + static PropertyRegistration PROPERTY_4; }; // Properties registered without macro to use specific member variables. -PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "background-color", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); -PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "background-image", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); -PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "key-input-focus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "style-name", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "background-color", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "background-image", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "key-input-focus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); Toolkit::Control Control::New() { @@ -491,6 +507,23 @@ LongPressGestureDetector Control::GetLongPressGestureDetector() const return mImpl->mLongPressGestureDetector; } +void Control::SetStyleName( const std::string& styleName ) +{ + if( styleName != mImpl->mStyleName ) + { + mImpl->mStyleName = styleName; + + // Apply new style + Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); + GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); + } +} + +const std::string& Control::GetStyleName() const +{ + return mImpl->mStyleName; +} + void Control::SetBackgroundColor( const Vector4& color ) { Background& background( mImpl->GetBackground() ); @@ -730,7 +763,7 @@ void Control::Initialize() Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); // Register for style changes - styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange ); + styleManager.StyleChangeSignal().Connect( this, &Control::OnStyleChange ); // SetTheme GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); @@ -808,13 +841,13 @@ void Control::OnActivated() { } -void Control::OnThemeChange( Toolkit::StyleManager styleManager ) -{ - GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); -} - -void Control::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange ) +void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) { + // By default the control is only interested in theme (not font) changes + if( change.themeChange ) + { + GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); + } } void Control::OnPinch(const PinchGesture& pinch) @@ -984,18 +1017,6 @@ void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* call mImpl->SignalDisconnected( slotObserver, callback ); } -void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) -{ - if( change.themeChange ) - { - OnThemeChange( styleManager ); - } - else if( change.defaultFontChange || change.defaultFontSizeChange ) - { - OnFontChange( change.defaultFontChange, change.defaultFontSizeChange ); - } -} - } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/public-api/controls/control-impl.h b/dali-toolkit/public-api/controls/control-impl.h index 2583450..a816989 100644 --- a/dali-toolkit/public-api/controls/control-impl.h +++ b/dali-toolkit/public-api/controls/control-impl.h @@ -170,6 +170,16 @@ public: // Background /** + * @copydoc Dali::Toolkit::Control::SetStyleName + */ + void SetStyleName( const std::string& styleName ); + + /** + * @copydoc Dali::Toolkit::Control::GetStyleName + */ + const std::string& GetStyleName() const; + + /** * @copydoc Dali::Toolkit::Control::SetBackgroundColor */ void SetBackgroundColor( const Vector4& color ); @@ -395,21 +405,12 @@ private: virtual void OnActivated(); /** - * @brief This method should be overridden by deriving classes when - * they wish to be notified when the style manager changes the theme. + * @brief This method should be overridden by deriving classes requiring notifications when the style changes. * * @param[in] styleManager The StyleManager object. + * @param[in] change Information denoting what has changed. */ - virtual void OnThemeChange( Toolkit::StyleManager styleManager ); - - /** - * @brief This method should be overridden by deriving classes when - * they wish to be notified when the style changes the default font. - * - * @param[in] defaultFontChange Information denoting whether the default font has changed. - * @param[in] defaultFontSizeChange Information denoting whether the default font size has changed. - */ - virtual void OnFontChange( bool defaultFontChange, bool defaultFontSizeChange ); + virtual void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); /** * @brief Called whenever a pinch gesture is detected on this control. @@ -646,16 +647,6 @@ private: */ virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback ); - // Style - - /** - * @brief This method is the callback for the StyleChangeSignal from StyleManager - * - * @param[in] styleManager The StyleManager Object - * @param[in] change Information denoting what has changed. - */ - DALI_INTERNAL void DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); - private: // Undefined diff --git a/dali-toolkit/public-api/controls/control.cpp b/dali-toolkit/public-api/controls/control.cpp index a66f2ae..4ceae4f 100644 --- a/dali-toolkit/public-api/controls/control.cpp +++ b/dali-toolkit/public-api/controls/control.cpp @@ -104,6 +104,16 @@ LongPressGestureDetector Control::GetLongPressGestureDetector() const return GetImplementation().GetLongPressGestureDetector(); } +void Control::SetStyleName( const std::string& styleName ) +{ + GetImplementation().SetStyleName( styleName ); +} + +const std::string& Control::GetStyleName() const +{ + return GetImplementation().GetStyleName(); +} + void Control::SetBackgroundColor( const Vector4& color ) { GetImplementation().SetBackgroundColor( color ); diff --git a/dali-toolkit/public-api/controls/control.h b/dali-toolkit/public-api/controls/control.h index 1e6f8d9..b4373c7 100644 --- a/dali-toolkit/public-api/controls/control.h +++ b/dali-toolkit/public-api/controls/control.h @@ -82,7 +82,8 @@ public: { enum { - BACKGROUND_COLOR = PROPERTY_START_INDEX, ///< name "background-color", @see SetBackgroundColor, type Vector4 + STYLE_NAME = PROPERTY_START_INDEX, ///< name "style-name", @see SetStyleName, type std::string + BACKGROUND_COLOR, ///< name "background-color", @see SetBackgroundColor, type Vector4 BACKGROUND_IMAGE, ///< name "background-image", @see SetBackgroundImage, type Map KEY_INPUT_FOCUS, ///< name "key-input-focus", @see SetKeyInputFocus, type bool }; @@ -245,6 +246,22 @@ public: // Background /** + * @brief Sets the name of the style to be applied to the control. + * + * @param[in] styleName A string matching a style described in a stylesheet. + */ + void SetStyleName( const std::string& styleName ); + + /** + * @brief Retrieves the name of the style to be applied to the control (if any). + * + * @return A string matching a style or an empty string. + */ + const std::string& GetStyleName() const; + + // Background + + /** * @brief Sets the background color of the control. * * @param[in] color The required background color of the control diff --git a/dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp b/dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp index 1474151..5a6ae0e 100644 --- a/dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp +++ b/dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp @@ -83,7 +83,6 @@ ImageActor CreateSolidColorActor( const Vector4& color, bool border, const Vecto imageData.Update(); image = ImageActor::New( imageData ); - image.SetAnchorPoint( AnchorPoint::CENTER ); image.SetParentOrigin( ParentOrigin::CENTER ); if( border ) diff --git a/dali-toolkit/public-api/controls/navigation-frame/navigation-bar-style.h b/dali-toolkit/public-api/controls/navigation-frame/navigation-bar-style.h index 9df024c..4a06591 100644 --- a/dali-toolkit/public-api/controls/navigation-frame/navigation-bar-style.h +++ b/dali-toolkit/public-api/controls/navigation-frame/navigation-bar-style.h @@ -105,8 +105,6 @@ namespace Toolkit * Constructor */ NaviTitleBarStyle( Actor background, - TextStyle titleTextStyle, - TextStyle subtitleTextStyle, int referenceWidth, int height, int titleHeightWithoutSubtitle, @@ -120,7 +118,6 @@ namespace Toolkit int buttonBottomMargin, int gapBetweenButtons ) : BasicNaviBarStyle( background, referenceWidth, height), - titleTextStyle( titleTextStyle ), subtitleTextStyle( subtitleTextStyle ), titleHeightWithoutSubtitle( titleHeightWithoutSubtitle ), titleHeightWithSubtitle( titleHeightWithSubtitle ), subtitleHeight( subtitleHeight ), titleLeftMargin( titleLeftMargin ), titleBottomMargin( titleBottomMargin ), @@ -130,8 +127,6 @@ namespace Toolkit { } - TextStyle titleTextStyle; ///< the text style of the tile text - TextStyle subtitleTextStyle; ///< the text style of the subtitle text int titleHeightWithoutSubtitle; ///< the height of the title when no subtitle exists int titleHeightWithSubtitle; ///< the height of the title when there is subtitle below int subtitleHeight; ///< the height of the subtitle diff --git a/dali-toolkit/public-api/controls/popup/popup.cpp b/dali-toolkit/public-api/controls/popup/popup.cpp index df8e42d..b557f01 100644 --- a/dali-toolkit/public-api/controls/popup/popup.cpp +++ b/dali-toolkit/public-api/controls/popup/popup.cpp @@ -87,12 +87,7 @@ void Popup::SetTitle( const std::string& text ) GetImpl(*this).SetTitle( text ); } -void Popup::SetTitle( TextView titleActor ) -{ - GetImpl(*this).SetTitle( titleActor ); -} - -TextView Popup::GetTitle() const +std::string Popup::GetTitle() const { return GetImpl(*this).GetTitle(); } diff --git a/dali-toolkit/public-api/controls/popup/popup.h b/dali-toolkit/public-api/controls/popup/popup.h index fc14389..1ab708b 100644 --- a/dali-toolkit/public-api/controls/popup/popup.h +++ b/dali-toolkit/public-api/controls/popup/popup.h @@ -20,7 +20,6 @@ // INTERNAL INCLUDES #include -#include namespace Dali { @@ -167,18 +166,11 @@ public: void SetTitle( const std::string& text ); /** - * @brief Sets a title for this Popup. - * - * @param[in] titleActor The TextView to appear as the heading for this Popup - */ - void SetTitle( TextView titleActor ); - - /** * @brief Gets the text (TextView) for this Popup. * - * @return The TextView representing this popup is returned. + * @return The text to appear as the heading for this Popup */ - TextView GetTitle() const; + std::string GetTitle() const; /** * @brief Adds a button to this Popup. diff --git a/dali-toolkit/public-api/controls/text-controls/text-field.cpp b/dali-toolkit/public-api/controls/text-controls/text-field.cpp new file mode 100644 index 0000000..7935752 --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-field.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015 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 +{ + +TextField TextField::New() +{ + return Internal::TextField::New(); +} + +TextField::TextField() +{ +} + +TextField::TextField( const TextField& handle ) +: Control( handle ) +{ +} + +TextField& TextField::operator=( const TextField& handle ) +{ + if( &handle != this ) + { + Control::operator=( handle ); + } + return *this; +} + +TextField::~TextField() +{ +} + +TextField TextField::DownCast( BaseHandle handle ) +{ + return Control::DownCast(handle); +} + +TextField::TextField( Internal::TextField& implementation ) +: Control(implementation) +{ +} + +TextField::TextField( Dali::Internal::CustomActor* internal ) +: Control( internal ) +{ + VerifyCustomActorPointer( internal ); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-controls/text-field.h b/dali-toolkit/public-api/controls/text-controls/text-field.h new file mode 100644 index 0000000..3736a2f --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-field.h @@ -0,0 +1,153 @@ +#ifndef __DALI_TOOLKIT_TEXT_FIELD_H__ +#define __DALI_TOOLKIT_TEXT_FIELD_H__ + +/* + * Copyright (c) 2015 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 Internal DALI_INTERNAL +{ +class TextField; +} + +/** + * @brief A control which provides a single-line editable text field. + */ +class DALI_IMPORT_API TextField : public Control +{ +public: + + /** + * @brief The start and end property ranges for this control. + */ + enum PropertyRange + { + PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, + PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices + }; + + /** + * @brief An enumeration of properties belonging to the TextLabel class. + */ + struct Property + { + enum + { + RENDERING_BACKEND = PROPERTY_START_INDEX, ///< name "rendering-backend", The type or rendering e.g. bitmap-based, type INT + PLACEHOLDER_TEXT, ///< name "placeholder-text", The text to display when the TextField is empty, type STRING + TEXT, ///< name "text", The text to display in UTF-8 format, type STRING + FONT_FAMILY, ///< name "font-family", The requested font family, type STRING + FONT_STYLE, ///< name "font-style", The requested font style e.g. Regular/Italic, type STRING + POINT_SIZE, ///< name "point-size", The size of font in points, type FLOAT + EXCEED_POLICY, ///< name "exceed-policy" Specifies how the text is truncated when it does not fit, type INT + PRIMARY_CURSOR_COLOR, ///< name "primary-cursor-color", The color to apply to the primary cursor, type VECTOR4 + SECONDARY_CURSOR_COLOR, ///< name "secondary-cursor-color", The color to apply to the secondary cursor, type VECTOR4 + ENABLE_CURSOR_BLINK, ///< name "enable-cursor-blink", Whether the cursor should blink or not, type BOOLEAN + CURSOR_BLINK_INTERVAL, ///< name "cursor-blink-interval", The time interval between cursor on/off states, type FLOAT + CURSOR_BLINK_DURATION, ///< name "cursor-blink-duration", The cursor will stop blinking after this duration (if non-zero), type FLOAT + GRAB_HANDLE_IMAGE, ///< name "grab-handle-image", The image to display for grab handle, type STRING + DECORATION_BOUNDING_BOX, ///< name "decoration-bounding-box", The decorations (handles etc) will positioned within this area on-screen, type RECTANGLE + HORIZONTAL_ALIGNMENT, ///< name "horizontal-alignment", The line horizontal alignment, type STRING, values "BEGIN", "CENTER", "END" + VERTICAL_ALIGNMENT ///< name "vertical-alignment", The line vertical alignment, type STRING, values "TOP", "CENTER", "BOTTOM" + }; + }; + + /** + * @brief Specifies how the text is truncated when it does not fit + * + * The default value is \e EXCEED_POLICY_CLIP. + */ + enum ExceedPolicy + { + EXCEED_POLICY_ORIGINAL, ///< The text will be display at original size, and may exceed the TextField boundary. + EXCEED_POLICY_CLIP ///< The end of text will be clipped to fit within the TextField. + }; + + /** + * Create the TextField control. + * @return A handle to the TextField control. + */ + static TextField New(); + + /** + * @brief Creates an empty handle. + */ + TextField(); + + /** + * @brief Copy constructor. + * + * @param[in] handle The handle to copy from. + */ + TextField( const TextField& handle ); + + /** + * @brief Assignment operator. + * + * @param[in] handle The handle to copy from. + * @return A reference to this. + */ + TextField& operator=( const TextField& handle ); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~TextField(); + + /** + * @brief Downcast a handle to TextField. + * + * If the BaseHandle points is a TextField the downcast returns a valid handle. + * If not the returned handle is left empty. + * + * @param[in] handle Handle to an object + * @return handle to a TextField or an empty handle + */ + static TextField DownCast( BaseHandle handle ); + +public: // Not intended for application developers + + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The Control implementation. + */ + DALI_INTERNAL TextField( Internal::TextField& implementation ); + + /** + * @brief Allows the creation of this Control from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor. + */ + explicit DALI_INTERNAL TextField( Dali::Internal::CustomActor* internal ); +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_FIELD_H__ diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.cpp b/dali-toolkit/public-api/controls/text-controls/text-label.cpp new file mode 100644 index 0000000..7a61615 --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-label.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015 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 +{ + +TextLabel TextLabel::New() +{ + return Internal::TextLabel::New(); +} + +TextLabel TextLabel::New( const std::string& text ) +{ + TextLabel label = Internal::TextLabel::New(); + label.SetProperty( TextLabel::Property::TEXT, text ); + + return label; +} + +TextLabel::TextLabel() +{ +} + +TextLabel::TextLabel( const TextLabel& handle ) +: Control( handle ) +{ +} + +TextLabel& TextLabel::operator=( const TextLabel& handle ) +{ + if( &handle != this ) + { + Control::operator=( handle ); + } + return *this; +} + +TextLabel::~TextLabel() +{ +} + +TextLabel TextLabel::DownCast( BaseHandle handle ) +{ + return Control::DownCast(handle); +} + +TextLabel::TextLabel( Internal::TextLabel& implementation ) +: Control(implementation) +{ +} + +TextLabel::TextLabel( Dali::Internal::CustomActor* internal ) +: Control( internal ) +{ + VerifyCustomActorPointer( internal ); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.h b/dali-toolkit/public-api/controls/text-controls/text-label.h new file mode 100644 index 0000000..7ecb200 --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-label.h @@ -0,0 +1,150 @@ +#ifndef __DALI_TOOLKIT_TEXT_LABEL_H__ +#define __DALI_TOOLKIT_TEXT_LABEL_H__ + +/* + * Copyright (c) 2015 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 Internal DALI_INTERNAL +{ +class TextLabel; +} + +/** + * @brief A control which renders a short text string. + * + * Text labels are lightweight, non-editable and do not respond to user input. + */ +class DALI_IMPORT_API TextLabel : public Control +{ +public: + + /** + * @brief The start and end property ranges for this control. + */ + enum PropertyRange + { + PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, + PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices + }; + + /** + * @brief An enumeration of properties belonging to the TextLabel class. + */ + struct Property + { + enum + { + RENDERING_BACKEND = PROPERTY_START_INDEX, ///< name "rendering-backend", The type or rendering e.g. bitmap-based, type INT + TEXT, ///< name "text", The text to display in UTF-8 format, type STRING + FONT_FAMILY, ///< name "font-family", The requested font family, type STRING + FONT_STYLE, ///< name "font-style", The requested font style e.g. Regular/Italic, type STRING + POINT_SIZE, ///< name "point-size", The size of font in points, type FLOAT + MULTI_LINE, ///< name "multi-line", The single-line or multi-line layout option, type BOOLEAN + HORIZONTAL_ALIGNMENT, ///< name "horizontal-alignment", The line horizontal alignment, type STRING, values "BEGIN", "CENTER", "END" + VERTICAL_ALIGNMENT, ///< name "vertical-alignment", The line vertical alignment, type STRING, values "TOP", "CENTER", "BOTTOM" + TEXT_COLOR, ///< name "text-color", The text color, type VECTOR4 + SHADOW_OFFSET, ///< name "shadow-offset", The drop shadow offset 0 indicates no shadow, type VECTOR2 + SHADOW_COLOR, ///< name "shadow-color", The color of a drop shadow, type VECTOR4 + UNDERLINE_ENABLED, ///< name "underline-enabled", The underline enabled flag type BOOLEAN + UNDERLINE_COLOR, ///< name "underline-color", The color of the underline type VECTOR4 + }; + }; + + /** + * @brief Create the TextLabel control. + * + * @return A handle to the TextLabel control. + */ + static TextLabel New(); + + /** + * @brief Create the TextLabel control. + * + * @param[in] text The text to display. + * @return A handle to the TextLabel control. + */ + static TextLabel New( const std::string& text ); + + /** + * @brief Creates an empty handle. + */ + TextLabel(); + + /** + * @brief Copy constructor. + * + * @param[in] handle The handle to copy from. + */ + TextLabel( const TextLabel& handle ); + + /** + * @brief Assignment operator. + * + * @param[in] handle The handle to copy from. + * @return A reference to this. + */ + TextLabel& operator=( const TextLabel& handle ); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~TextLabel(); + + /** + * @brief Downcast a handle to TextLabel. + * + * If the BaseHandle points is a TextLabel the downcast returns a valid handle. + * If not the returned handle is left empty. + * + * @param[in] handle Handle to an object + * @return handle to a TextLabel or an empty handle + */ + static TextLabel DownCast( BaseHandle handle ); + +public: // Not intended for application developers + + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The Control implementation. + */ + DALI_INTERNAL TextLabel( Internal::TextLabel& implementation ); + + /** + * @brief Allows the creation of this Control from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor. + */ + explicit DALI_INTERNAL TextLabel( Dali::Internal::CustomActor* internal ); +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LABEL_H__ diff --git a/dali-toolkit/public-api/controls/text-controls/text-selection-popup.cpp b/dali-toolkit/public-api/controls/text-controls/text-selection-popup.cpp new file mode 100644 index 0000000..4c55375 --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-selection-popup.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015 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 + +using namespace Dali; + +namespace Dali +{ + +namespace Toolkit +{ + +TextSelectionPopup TextSelectionPopup::New() +{ + return Internal::TextSelectionPopup::New(); +} + +TextSelectionPopup::TextSelectionPopup() +{ +} + +TextSelectionPopup::TextSelectionPopup( const TextSelectionPopup& handle ) +: Control( handle ) +{ +} + +TextSelectionPopup& TextSelectionPopup::operator=( const TextSelectionPopup& handle ) +{ + if( &handle != this ) + { + Control::operator=( handle ); + } + return *this; +} + +TextSelectionPopup::~TextSelectionPopup() +{ +} + +TextSelectionPopup TextSelectionPopup::DownCast( BaseHandle handle ) +{ + return Control::DownCast(handle); +} + +TextSelectionPopup::TextSelectionPopup( Internal::TextSelectionPopup& implementation ) +: Control(implementation) +{ +} + +TextSelectionPopup::TextSelectionPopup( Dali::Internal::CustomActor* internal ) +: Control( internal ) +{ + VerifyCustomActorPointer( internal ); +} + + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-controls/text-selection-popup.h b/dali-toolkit/public-api/controls/text-controls/text-selection-popup.h new file mode 100644 index 0000000..2243f2d --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-selection-popup.h @@ -0,0 +1,143 @@ +#ifndef __DALI_TOOLKIT_TEXT_SELECTION_POPUP_H__ +#define __DALI_TOOLKIT_TEXT_SELECTION_POPUP_H__ + +/* + * Copyright (c) 2015 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 Internal DALI_INTERNAL +{ +class TextSelectionPopup; +} + +/** + * @brief A control which provides a Popup with a number of buttons + * + * The style of the pop can be set through style sheets, this includes the images for the buttons + * A Show and Hide API is provided. + * + * If the buttons exceed the size constraints of the popup then it will offer scrolling. + * + * + */ +class DALI_IMPORT_API TextSelectionPopup : public Control +{ +public: + + /** + * @brief The start and end property ranges for this control. + */ + enum PropertyRange + { + PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, + PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices + }; + + /** + * @brief An enumeration of properties belonging to the TextLabel class. + */ + struct Property + { + enum + { + + POPUP_MAX_SIZE, ///< name "popup-max-size", The max size the Popup can be, type VECTOR2 + POPUP_BACKGROUND_IMAGE, ///< name "popup-background-image", The image to display for popup background type STRING + POPUP_CLIPBOARD_BUTTON_ICON_IMAGE, ///< name "popup-clipboard-button-image", The image to use as the popup clipboard icon, type STRING + POPUP_CUT_BUTTON_ICON_IMAGE, ///< name "popup-cut-button-image", The image to use as the popup cut icon, type STRING + POPUP_COPY_BUTTON_ICON_IMAGE, ///< name "popup-copy-button-image", The image to use as the popup copy icon, type STRING + POPUP_PASTE_BUTTON_ICON_IMAGE, ///< name "popup-paste-button-image", The image to use as the popup paste icon, type STRING + POPUP_SELECT_BUTTON_ICON_IMAGE, ///< name "popup-select-button-image", The image to use as the popup select icon, type STRING + POPUP_SELECT_ALL_BUTTON_ICON_IMAGE, ///< name "popup-select-all-button-image", The image to use as the popup select all icon, type STRING + }; + }; + + /** + * Create the TextSelectionPopup control. + * @return A handle to the TextSelectionPopup control. + */ + static TextSelectionPopup New(); + + /** + * @brief Creates an empty handle. + */ + TextSelectionPopup(); + + /** + * @brief Copy constructor. + * + * @param[in] handle The handle to copy from. + */ + TextSelectionPopup( const TextSelectionPopup& handle ); + + /** + * @brief Assignment operator. + * + * @param[in] handle The handle to copy from. + * @return A reference to this. + */ + TextSelectionPopup& operator=( const TextSelectionPopup& handle ); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~TextSelectionPopup(); + + /** + * @brief Downcast a handle to TextSelectionPopup. + * + * If the BaseHandle points is a TextSelectionPopup the downcast returns a valid handle. + * If not the returned handle is left empty. + * + * @param[in] handle Handle to an object + * @return handle to a TextSelectionPopup or an empty handle + */ + static TextSelectionPopup DownCast( BaseHandle handle ); + +public: // Not intended for application developers + + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The Control implementation. + */ + DALI_INTERNAL TextSelectionPopup( Internal::TextSelectionPopup& implementation ); + + /** + * @brief Allows the creation of this Control from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor. + */ + explicit DALI_INTERNAL TextSelectionPopup( Dali::Internal::CustomActor* internal ); + +}; // Class TextSelectionPopup + +} // namespace Toolkit + +} // namepsace Dali + +#endif // __DALI_TOOLKIT_TEXT_SELECTION_POPUP_H__ diff --git a/dali-toolkit/public-api/controls/text-input/text-input.cpp b/dali-toolkit/public-api/controls/text-input/text-input.cpp deleted file mode 100644 index f0a43e3..0000000 --- a/dali-toolkit/public-api/controls/text-input/text-input.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -TextInput::TextInput() -{ -} - -TextInput::TextInput(Internal::TextInput& implementation) -: Control(implementation) -{ -} - -TextInput::TextInput( const TextInput& textInput ) -: Control( textInput ) -{ -} - -TextInput& TextInput::operator=( const TextInput& textInput ) -{ - if( &textInput != this ) - { - Control::operator=( textInput ); - } - - return *this; -} - -TextInput TextInput::New() -{ - return Internal::TextInput::New(); -} - -TextInput TextInput::DownCast( BaseHandle actor ) -{ - return Control::DownCast(actor); -} - -TextInput::~TextInput() -{ -} - -std::string TextInput::GetText() const -{ - return GetImpl(*this).GetText(); -} - -std::string TextInput::GetMarkupText() const -{ - return GetImpl(*this).GetMarkupText(); -} - -void TextInput::SetMaxCharacterLength(std::size_t maxChars) -{ - GetImpl(*this).SetMaxCharacterLength(maxChars); -} - -void TextInput::SetNumberOfLinesLimit(std::size_t maxLines) -{ - GetImpl(*this).SetNumberOfLinesLimit( maxLines ); -} - -std::size_t TextInput::GetNumberOfLinesLimit() const -{ - return GetImpl(*this).GetNumberOfLinesLimit(); -} - -std::size_t TextInput::GetNumberOfCharacters() const -{ - return GetImpl(*this).GetNumberOfCharacters(); -} - -void TextInput::SetPlaceholderText( const std::string& placeHolderText ) -{ - GetImpl(*this).SetPlaceholderText( placeHolderText ); -} - -std::string TextInput::GetPlaceholderText() -{ - return GetImpl(*this).GetPlaceholderText(); -} - -void TextInput::SetInitialText(const std::string& initialText) -{ - GetImpl(*this).SetInitialText(initialText); -} - -void TextInput::SetEditable(bool editMode) -{ - GetImpl(*this).SetEditable(editMode, false); -} - -void TextInput::SetEditable(bool editMode, const Vector2& touchPoint) -{ - GetImpl(*this).SetEditable(editMode, true, touchPoint); -} - -bool TextInput::IsEditable() const -{ - return GetImpl(*this).IsEditable(); -} - -void TextInput::SetEditOnTouch( bool editOnTouch ) -{ - GetImpl(*this).SetEditOnTouch( editOnTouch ); -} - -bool TextInput::IsEditOnTouch() const -{ - return GetImpl(*this).IsEditOnTouch(); -} - -void TextInput::SetTextSelectable( bool textSelectable ) -{ - GetImpl(*this).SetTextSelectable( textSelectable ); -} - -bool TextInput::IsTextSelectable() const -{ - return GetImpl(*this).IsTextSelectable(); -} - -bool TextInput::IsTextSelected() const -{ - return GetImpl(*this).IsTextSelected(); -} - -void TextInput::SelectText(std::size_t start, std::size_t end) -{ - GetImpl(*this).SelectText( start, end ); -} - -void TextInput::DeSelectText() -{ - GetImpl(*this).DeSelectText(); -} - -void TextInput::SetGrabHandleImage( Image image ) -{ - GetImpl(*this).SetGrabHandleImage(image); -} - -void TextInput::SetCursorImage(Dali::Image image, const Vector4& border ) -{ - GetImpl(*this).SetCursorImage(image, border ); -} - -Vector3 TextInput::GetSelectionHandleSize() -{ - return GetImpl(*this).GetSelectionHandleSize(); -} - -void TextInput::SetRTLCursorImage(Dali::Image image, const Vector4& border ) -{ - GetImpl(*this).SetRTLCursorImage(image, border ); -} - -void TextInput::EnableGrabHandle(bool toggle) -{ - GetImpl(*this).EnableGrabHandle( toggle ); -} - -bool TextInput::IsGrabHandleEnabled() -{ - return GetImpl(*this).IsGrabHandleEnabled(); -} - -void TextInput::SetBoundingRectangle( const Rect& boundingOriginAndSize ) -{ - GetImpl(*this).SetBoundingRectangle( boundingOriginAndSize ); -} - -const Rect TextInput::GetBoundingRectangle() const -{ - return GetImpl(*this).GetBoundingRectangle(); -} - -void TextInput::SetActiveStyle( const TextStyle& style, const TextStyle::Mask mask ) -{ - GetImpl(*this).SetActiveStyle(style,mask); -} - -void TextInput::ApplyStyle( const TextStyle& style, const TextStyle::Mask mask ) -{ - GetImpl(*this).ApplyStyle( style, mask ); -} - -void TextInput::ApplyStyleToAll( const TextStyle& style, const TextStyle::Mask mask ) -{ - GetImpl(*this).ApplyStyleToAll( style, mask ); -} - -TextStyle TextInput::GetStyleAtCursor() const -{ - return GetImpl(*this).GetStyleAtCursor(); -} - -void TextInput::SetTextAlignment( Toolkit::Alignment::Type align ) -{ - GetImpl(*this).SetTextAlignment(align); -} - -void TextInput::SetTextLineJustification( Toolkit::TextView::LineJustification justification ) -{ - GetImpl(*this).SetTextLineJustification(justification); -} - -void TextInput::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ) -{ - GetImpl(*this).SetFadeBoundary( fadeBoundary ); -} - -const Toolkit::TextView::FadeBoundary& TextInput::GetFadeBoundary() const -{ - return GetImpl(*this).GetFadeBoundary(); -} - -Alignment::Type TextInput::GetTextAlignment() const -{ - return GetImpl(*this).GetTextAlignment(); -} - -void TextInput::SetMultilinePolicy( TextView::MultilinePolicy policy ) -{ - GetImpl(*this).SetMultilinePolicy(policy); -} - -TextView::MultilinePolicy TextInput::GetMultilinePolicy() const -{ - return GetImpl(*this).GetMultilinePolicy(); -} - -void TextInput::SetWidthExceedPolicy( TextView::ExceedPolicy policy ) -{ - GetImpl(*this).SetWidthExceedPolicy(policy); -} - -TextView::ExceedPolicy TextInput::GetWidthExceedPolicy() const -{ - return GetImpl(*this).GetWidthExceedPolicy(); -} - -void TextInput::SetHeightExceedPolicy( TextView::ExceedPolicy policy ) -{ - GetImpl(*this).SetHeightExceedPolicy(policy); -} - -TextView::ExceedPolicy TextInput::GetHeightExceedPolicy() const -{ - return GetImpl(*this).GetHeightExceedPolicy(); -} - -void TextInput::SetExceedEnabled( bool enable ) -{ - GetImpl(*this).SetExceedEnabled( enable ); -} - -bool TextInput::GetExceedEnabled() const -{ - return GetImpl(*this).GetExceedEnabled(); -} - -void TextInput::SetSortModifier( float depthOffset ) -{ - GetImpl( *this ).SetSortModifier( depthOffset ); -} - -void TextInput::SetSnapshotModeEnabled( bool enable ) -{ - GetImpl( *this ).SetSnapshotModeEnabled( enable ); -} - -bool TextInput::IsSnapshotModeEnabled() const -{ - return GetImpl( *this ).IsSnapshotModeEnabled(); -} - -void TextInput::SetScrollEnabled( bool enable ) -{ - GetImpl( *this ).SetScrollEnabled( enable ); -} - -bool TextInput::IsScrollEnabled() const -{ - return GetImpl( *this ).IsScrollEnabled(); -} - -void TextInput::SetScrollPosition( const Vector2& position ) -{ - GetImpl( *this ).SetScrollPosition( position ); -} - -Vector2 TextInput::GetScrollPosition() const -{ - return GetImpl( *this ).GetScrollPosition(); -} - -TextInput::InputSignalType& TextInput::InputStartedSignal() -{ - return GetImpl(*this).InputStartedSignal(); -} - -TextInput::InputSignalType& TextInput::InputFinishedSignal() -{ - return GetImpl(*this).InputFinishedSignal(); -} - -TextInput::InputSignalType& TextInput::CutAndPasteToolBarDisplayedSignal() -{ - return GetImpl(*this).CutAndPasteToolBarDisplayedSignal(); -} - -TextInput::StyleChangedSignalType& TextInput::StyleChangedSignal() -{ - return GetImpl(*this).StyleChangedSignal(); -} - -TextInput::TextModifiedSignalType& TextInput::TextModifiedSignal() -{ - return GetImpl(*this).TextModifiedSignal(); -} - -TextInput::MaxInputCharactersReachedSignalType& TextInput::MaxInputCharactersReachedSignal() -{ - return GetImpl(*this).MaxInputCharactersReachedSignal(); -} - -TextInput::InputTextExceedBoundariesSignalType& TextInput::InputTextExceedBoundariesSignal() -{ - return GetImpl(*this).InputTextExceedBoundariesSignal(); -} - -void TextInput::SetMarkupProcessingEnabled( bool enable ) -{ - return GetImpl( *this ).SetMarkupProcessingEnabled( enable ); -} - -bool TextInput::IsMarkupProcessingEnabled() const -{ - return GetImpl( *this ).IsMarkupProcessingEnabled(); -} - - -TextInput::TextInput( Dali::Internal::CustomActor* internal ) -: Control( internal ) -{ - VerifyCustomActorPointer(internal); -} - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-input/text-input.h b/dali-toolkit/public-api/controls/text-input/text-input.h deleted file mode 100644 index 0598988..0000000 --- a/dali-toolkit/public-api/controls/text-input/text-input.h +++ /dev/null @@ -1,654 +0,0 @@ -#ifndef __DALI_TOOLKIT_TEXT_INPUT_H__ -#define __DALI_TOOLKIT_TEXT_INPUT_H__ - -/* - * 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal DALI_INTERNAL -{ -class TextInput; -} - -/** - * @brief TextInput Actor takes input one character at a time and displays it as a string within an input box. - * Characters can be removed from the end of the string until it is empty. A maximum length of displayed string - * can be set. - */ -class DALI_IMPORT_API TextInput : public Control -{ - -public: - - /** - * @brief The start and end property ranges for this control. - */ - enum PropertyRange - { - PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, - PROPERTY_END_INDEX = PROPERTY_START_INDEX + 512 ///< Reserve property indices - }; - - /** - * @brief An enumeration of properties belonging to the TextInput class. - */ - struct Property - { - enum - { - HIGHLIGHT_COLOR = PROPERTY_START_INDEX, // Property, name "highlight-color", type Vector4 - CUT_AND_PASTE_COLOR, // Property, name "cut-and-paste-bg-color", type Vector4 - CUT_AND_PASTE_PRESSED_COLOR, // Property, name "cut-and-paste-pressed-color", type Vector4 - CUT_AND_PASTE_BORDER_COLOR, // Property, name "cut-and-paste-border-color", type Vector4 - CUT_AND_PASTE_ICON_COLOR, // Property, name "cut-and-paste-icon-color", type Vector4 - CUT_AND_PASTE_ICON_PRESSED_COLOR, // Property, name "cut-and-paste-icon-pressed-color", type Vector4 - CUT_AND_PASTE_TEXT_COLOR, // Property, name "cut-and-paste-text-color", type Vector4 - CUT_AND_PASTE_TEXT_PRESSED_COLOR, // Property, name "cut-and-paste-text-pressed-color", type Vector4 - CUT_BUTTON_POSITION_PRIORITY, // Property, name "cut-button-position-priority", type unsigned int - COPY_BUTTON_POSITION_PRIORITY, // Property, name "copy-button-position-priority", type unsigned int - PASTE_BUTTON_POSITION_PRIORITY, // Property, name "paste-button-position-priority", type unsigned int - SELECT_BUTTON_POSITION_PRIORITY, // Property, name "select-button-position-priority", type unsigned int - SELECT_ALL_BUTTON_POSITION_PRIORITY, // Property, name "select-all-button-position-priority", type unsigned int - CLIPBOARD_BUTTON_POSITION_PRIORITY, // Property, name "clipboard-button-position-priority", type unsigned int - POP_UP_OFFSET_FROM_TEXT, // Property, name "popup-offset-from-text", type Vector4 - CURSOR_COLOR, // Property, name "cursor-color", type Vector4 - }; - }; - -public: - - /** - * @brief Create an uninitialized TextInput; this can be initialized with TextView::New(). - * - * Calling member functions with an uninitialized Dali::Object is not allowed. - */ - TextInput(); - - /** - * @brief Copy constructor. - * - * @param handle to be copied - */ - TextInput( const TextInput& handle ); - - /** - * @brief Assignment operator. - * - * @param handle to object we want to point to - * @return handle to the TextInput - */ - TextInput& operator=( const TextInput& handle ); - - /** - * @brief Create an initialised TextInput. - * - * @return A handle to a newly allocated Dali resource. - */ - static TextInput New(); - - /** - * @brief Downcast an Object handle to TextInput. - * - * If handle points to a TextInput the downcast produces valid - * handle. If not the returned handle is left uninitialized. - * - * @param[in] handle Handle to an object - * @return handle to a TextInput or an uninitialized handle - */ - static TextInput DownCast( BaseHandle handle ); - - /** - * @brief Destructor - * - * This is non-virtual since derived Handle types must not contain data or virtual methods. - */ - ~TextInput(); - - /** - * @brief Get the inputed text currently being displayed. - * - * @return string, the currently displayed string. - */ - std::string GetText() const; - - /** - * @brief Get the inputed text currently being displayed together with mark-up tags. - * - * @return string, the currently displayed string with mark-up. - */ - std::string GetMarkupText() const; - - /** - * @brief Set the maximum number of characters for the Text Input. - * - * @param [in] maxChars the max number of characters - */ - void SetMaxCharacterLength(std::size_t maxChars); - - /** - * @brief Limits the number of lines of text Text Input will display. - * - * @param [in] maxLines the max number of lines to display, must be greater than 0. - * Currently the only valid limit is 1. Which turns TextInput into Single line mode. Any number higher than 1 results in no limit. - */ - void SetNumberOfLinesLimit(std::size_t maxLines); - - /** - * @brief Returns the limit of lines Text Input is allowed to display. - * - * @return max line number limit - */ - std::size_t GetNumberOfLinesLimit() const; - - /** - * @brief Returns the number of characters TextInput is displaying. - * - * @return number of characters - */ - std::size_t GetNumberOfCharacters() const; - - /** - * @brief Sets a place holder text to be displayed when the text-input is empty. - * - * If not set or set to an empty string then no place holder will be shown. - * @param [in] placeHolderText text to be used as place holder. - */ - void SetPlaceholderText( const std::string& placeHolderText ); - - /** - * @return the current set place holder text, empty string returned if not set. - */ - std::string GetPlaceholderText(); - - /** - * @brief set initial text to be displayed in text-input. - * - * Can be used to edit a pre-existing string. - * @param [in] initialText text to be initially displayed - */ - void SetInitialText(const std::string& initialText); - - /** - * @brief Manual method to set the focus on the TextInput so it starts or stops edit state. - * - * @pre The text input actor has been initialised. - * @param[in] editMode true or false to indicate editMode on or off - */ - void SetEditable(bool editMode); - - /** - * @see SetEditable(bool editMode). - * - * It sets the cursor in the closest character to the given touch point. - * - * @param[in] editMode true or false to indicate editMode on or off - * @param[in] touchPoint A position in actor coordinates within the text-input. - */ - void SetEditable(bool editMode, const Vector2& touchPoint); - - /** - * @brief Check if TextInput is in edit state. - * - * @pre The text input actor has been initialised. - * @return True or False to indicate editMode on or off - */ - bool IsEditable() const; - - /** - * @brief Method to enable or disable edit on touch/tap. - * - * If not enabled (set to false) then SetEditable(true) will be used to start edit mode. - * @pre The text input actor has been initialised. - * @param[in] editOnTouch true or false to indicate if editing should start on touch - * default is for editing to start on touching textinput - */ - void SetEditOnTouch(bool editOnTouch = true); - - /** - * @brief Check if TextInput starts edit mode on touch. - * - * @pre The text input actor has been initialised. - * @return True or False to indicate editOnTouch on or off - */ - bool IsEditOnTouch() const; - - /** - * @brief Check if Text Selection is enabled so required text can be highlighted. - * - * @pre The text input actor has been initialised. - * @param[in] textSelectable true or false to indicate if text can be selected or not - * default is for text to be select-able when in edit mode - */ - void SetTextSelectable(bool textSelectable = true); - - /** - * @brief Check if Text can be selected. - * - * @pre The text input actor has been initialised. - * @return True or False to indicate if text can be selected or not - */ - bool IsTextSelectable() const; - - /** - * @brief Check if any text is currently selected, can be used to determine if ApplyStyle or SetActiveStyle should be used. - * - * @pre The text input actor has been initialised. - * @return True if text selected else False - */ - bool IsTextSelected() const; - - /** - * @brief Selects text between the given positions. - * - * @pre TextInput should be in edit mode. - * @param start position to start selection - * @param end position to end selection, inclusive of this character. - * Providing 0 and result from GetNumberOfCharacters() will select all text. - */ - void SelectText(std::size_t start, std::size_t end); - - /** - * @brief If any text is selected then de-select it and hide highlight. - * - * @pre The text input actor has been initialised. - */ - void DeSelectText(); - - /** - * @brief Set the image to be used as the cursor grab hander. - * - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - */ - void SetGrabHandleImage( Image image ); - - /** - * Depreciated API. - * @brief Set the image to be used for the regular left to right cursor. - * - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - * @param[in] border The nine patch border for the image. - */ - void SetCursorImage(Dali::Image image, const Vector4& border ); - - /** - * @brief Retrieve the selection handle size. - * - * Both handles have same size. - * @return Vector3 the selection handle size. - */ - Vector3 GetSelectionHandleSize(); - - /** - * @brief Set the image to be used for the Right to Left cursor. - * - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - * @param[in] border The nine patch border for the image. - */ - void SetRTLCursorImage(Dali::Image image, const Vector4& border ); - - /** - * @brief Toggle to enable the grab handle, used to position cursor when magnifier not being used. - * - * Default behaviour is to use the magnifier to position the cursor, enabling this prevents the magnifier from being shown. - * @param[in] toggle true to enable, false to disable grab handle - */ - void EnableGrabHandle(bool toggle); - - /** - * @brief Method to check if grab handle is enabled, if false then the magnifier will be used to position cursor. - * - * @return bool returns true is grab handle enabled. - */ - bool IsGrabHandleEnabled(); - - /** - * @brief Set the bounding rectangle which handles, popup and similar decorations will not exceed. - * - * The default value is the width and height of the stage from the top left origin. - * If a title bar for example is on the top of the screen then the y should be the title's height and - * the boundary height the stage height minus the title's height. - * Restrictions - The boundary box should be set up with a fixed z position for the text-input and the default camera. - * @param[in] boundingOriginAndSize Rect( x coordinate, y coordinate, width, height ) - * @code - * +----------------------------------------+ - * |(x,y) | - * |+--------------------------------------+| - * || || - * || Bounding Box || boundary height - * || || - * |+--------------------------------------+| - * +----------------------------------------+ - * boundary width - * @endcode - */ - void SetBoundingRectangle( const Rect& boundingOriginAndSize ); - - /** - * @brief Retrieve the bounding box origin and dimensions. - * - * default is set once control is added to stage, before this the return vector will be Vector4:ZERO - * @return Rect the bounding rectangle - */ - const Rect GetBoundingRectangle() const; - - /** - * @brief Sets the style for new text being typed. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @pre The text input actor has been initialised. - * @param[in] style The style for the new text. - * @param[in] mask The bit mask. - */ - void SetActiveStyle( const TextStyle& style, const TextStyle::Mask mask = TextStyle::ALL ); - - /** - * @brief Applies the given style to the selected text. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * Introduced text after this call uses the new style. - * @param[in] style The given style. - * @param[in] mask The bit mask. - */ - void ApplyStyle( const TextStyle& style, const TextStyle::Mask mask = TextStyle::ALL ); - - /** - * @brief Applies the given style to all text, selected or not selected. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @param[in] style The given style. - * @param[in] mask The bit mask. - */ - void ApplyStyleToAll( const TextStyle& style, const TextStyle::Mask mask = TextStyle::ALL ); - - /** - * @brief Get the style of the Text character before the cursor. - * - * If no character before then return the InputStyle. - * @return TextStyle, the style of the character before the cursor - */ - TextStyle GetStyleAtCursor() const; - - /** - * @brief Set the current text alignment (overrides default setting). - * - * The default alignment is dependent on the current text in the text field. - * If the text begins using LTR characters (e.g. European text) then the - * alignment is HorizontalLeft. If the text begins using RTL characters - * (e.g. Hebrew/Arabic text) then the alignment is HorizontalRight. - * If there is no text, then the alignment defaults to: - * (HorizontalLeft | VerticalCenter) - * @param[in] align The new alignment option. - */ - void SetTextAlignment( Toolkit::Alignment::Type align ); - - /** - * @brief Set the current line justification. (overrides default setting). - * - * The default justification is dependent on the current text in the text field. - * If the text begins using LTR characters (e.g. European text) then the - * justification is HorizontalLeft. If the text begins using RTL characters - * (e.g. Hebrew/Arabic text) then the justification is HorizontalRight. - * If there is no text, then the justification defaults to: - * (HorizontalLeft | VerticalCenter) - * @param[in] justification The new line justification. - */ - void SetTextLineJustification( Toolkit::TextView::LineJustification justification ); - - /** - * @brief Sets a fade boundary. - * - * @see TextView::FadeBoundary. - * - * @param[in] fadeBoundary The given fade boundary. - */ - void SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ); - - /** - * @brief Retrieves the fade boundary. - * - * @see TextView::FadeBoundary. - * - * @return The fade boundary. - */ - const Toolkit::TextView::FadeBoundary& GetFadeBoundary() const; - - /** - * @brief Get the current text alignment combined into a single value. - * - * The values can be tested by using the & operator - * and the desired flag. e.g. if (GetTextAlignment() & HorizontalCentre) ... - * @return The combined text alignment - */ - Toolkit::Alignment::Type GetTextAlignment() const; - - /** - * @brief Sets how to split the text in lines policy. - * - * @param policy The multi-line policy. - */ - void SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ); - - /** - * @brief Gets the split in lines policy. - * - * @return The multi-line policy. - */ - Toolkit::TextView::MultilinePolicy GetMultilinePolicy() const; - - /** - * @brief Sets how to display the text inside the TextView when it exceeds the text-view's width. - * - * @param policy The exceed policy. - */ - void SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @brief Gets the width exceed policy. - * - * @return The exceed policy. - */ - TextView::ExceedPolicy GetWidthExceedPolicy() const; - - /** - * @brief Sets how to display the text inside the TextView when it exceeds the text-view's height. - * - * @param policy The exceed policy. - */ - void SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @brief Gets the height exceed policy. - * - * @return The exceed policy. - */ - TextView::ExceedPolicy GetHeightExceedPolicy() const; - - /** - * @brief Sets if the inputed text can exceed the text-input boundary. - * - * By default is enabled. - * - * @param[in] enable Whether the inputed text can exceed its boundary. - */ - void SetExceedEnabled( bool enable ); - - /** - * @brief Retrieves whether inputed text can exceed the text-input boundary. - * - * @return \e true if text inputed can exceed the boundary, otherwise \e false. - */ - bool GetExceedEnabled() const; - - /** - * @brief Allows modification of text-actor's position in the depth sort algorithm. - * - * @see Dali::RenderableActor::SetSortModifier() - * @param [in] depthOffset the offset to be given to the internal text-actors. Positive values pushing it further back. - */ - void SetSortModifier( float depthOffset ); - - /** - * @brief Sets whether text-view renders text using a previously generated snapshot. - * - * @see TextView::SetSnapshotModeEnabled() - * - * @param[in] enable Whether text-view is using or not a snapshot to render text. - */ - void SetSnapshotModeEnabled( bool enable ); - - /** - * @brief Retrieves whether text-view is using a snapshot to render text. - * - * @see TextView::IsSnapshotModeEnabled() - * - * @return \e true if text-view is using a snapshot to render text, otherwhise it returns \e false. - */ - bool IsSnapshotModeEnabled() const; - - /** - * @copydoc TextView::SetScrollEnabled() - */ - void SetScrollEnabled( bool enable ); - - /** - * @copydoc TextView::IsScrollEnabled() - */ - bool IsScrollEnabled() const; - - /** - * @copydoc TextView::SetScrollPosition() - */ - void SetScrollPosition( const Vector2& position ); - - /** - * @copydoc TextView::GetScrollPosition() - */ - Vector2 GetScrollPosition() const; - - /** - * @brief Sets whether markup processing should be carried out. - * - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ); - - /** - * @brief Returns whether markup processing is enabled or not - * - * @return true is markup processing is enabled - */ - bool IsMarkupProcessingEnabled() const; - - -public: /* Signals */ - - /// @brief Input Signal. - typedef Signal< void ( TextInput textInput ) > InputSignalType; - - /// @brief Input style changed signal. - typedef Signal< void ( TextInput textInput, const TextStyle& style ) > StyleChangedSignalType; - - /// @brief Text modified signal. - typedef Signal< void ( TextInput textInput ) > TextModifiedSignalType; - - /// @brief Max input characters reached signal. - typedef Signal< void ( TextInput textInput ) > MaxInputCharactersReachedSignalType; - - /// @brief Input text exceeds boundaries signal. - typedef Signal< void ( TextInput textInput ) > InputTextExceedBoundariesSignalType; - - /** - * @brief Signal emitted when the Text-Input starts receiving input. - */ - InputSignalType& InputStartedSignal(); - - /** - * @brief Signal emitted when the Text-Input is finished receiving input. - * - * TextInput::GetText() can be called to get current text string. - * @return The signal to connect to - */ - InputSignalType& InputFinishedSignal(); - - /** - * @brief Signal emitted when the cut and paste toolbar is displayed. - * - * @return The signal to connect to - */ - InputSignalType& CutAndPasteToolBarDisplayedSignal(); - - /** - * @brief Signal emitted when style changes. - * - * @return The signal to connect to - */ - StyleChangedSignalType& StyleChangedSignal(); - - /** - * @brief Signal emitted when text changes. - * - * @return The signal to connect to. - */ - TextModifiedSignalType& TextModifiedSignal(); - - /** - * @brief Signal emitted when max input characters are reached during text input. - * - * @return The signal to connect to - */ - MaxInputCharactersReachedSignalType& MaxInputCharactersReachedSignal(); - - /** - * @brief Signal emitted when input text exceeds the boundaries of the text-input. - * - * @return The signal to connect to - */ - InputTextExceedBoundariesSignalType& InputTextExceedBoundariesSignal(); - -public: // Not intended for application developers - - /** - * @brief Creates a handle using the Toolkit::Internal implementation. - * - * @param[in] implementation The Control implementation. - */ - DALI_INTERNAL TextInput(Internal::TextInput& implementation); - - /** - * @brief Allows the creation of this Control from an Internal::CustomActor pointer. - * - * @param[in] internal A pointer to the internal CustomActor. - */ - explicit DALI_INTERNAL TextInput(Dali::Internal::CustomActor* internal ); -}; - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_TEXT_INPUT_H__ diff --git a/dali-toolkit/public-api/controls/text-view/text-view.cpp b/dali-toolkit/public-api/controls/text-view/text-view.cpp deleted file mode 100644 index 85620de..0000000 --- a/dali-toolkit/public-api/controls/text-view/text-view.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -TextView::CharacterLayoutInfo::CharacterLayoutInfo() -: mSize(), - mPosition(), - mIsNewLineChar( false ), - mIsNewParagraphChar( false ), - mIsRightToLeftCharacter( false ), - mIsVisible( true ), - mDescender() -{ -} - -TextView::CharacterLayoutInfo::~CharacterLayoutInfo() -{ -} - -TextView::CharacterLayoutInfo::CharacterLayoutInfo( const TextView::CharacterLayoutInfo& characterLayoutInfo ) -: mSize( characterLayoutInfo.mSize ), - mPosition( characterLayoutInfo.mPosition ), - mIsNewLineChar( characterLayoutInfo.mIsNewParagraphChar ), - mIsNewParagraphChar( characterLayoutInfo.mIsNewParagraphChar ), - mIsRightToLeftCharacter( characterLayoutInfo.mIsRightToLeftCharacter ), - mIsVisible( characterLayoutInfo.mIsVisible ), - mDescender( characterLayoutInfo.mDescender ) -{ -} - -TextView::CharacterLayoutInfo& TextView::CharacterLayoutInfo::operator=( const TextView::CharacterLayoutInfo& characterLayoutInfo ) -{ - mSize = characterLayoutInfo.mSize; - mPosition = characterLayoutInfo.mPosition; - mIsNewLineChar = characterLayoutInfo.mIsNewParagraphChar; - mIsNewParagraphChar = characterLayoutInfo.mIsNewParagraphChar; - mIsRightToLeftCharacter = characterLayoutInfo.mIsRightToLeftCharacter; - mIsVisible = characterLayoutInfo.mIsVisible; - mDescender = characterLayoutInfo.mDescender; - - return *this; -} - -TextView::CharacterLayoutInfo::CharacterLayoutInfo( const Size& size, - const Vector3& position, - bool isNewParagraphChar, - bool isRightToLeftCharacter, - bool isVisible, - float descender ) -: mSize( size ), - mPosition( position ), - mIsNewLineChar( isNewParagraphChar ), - mIsNewParagraphChar( isNewParagraphChar ), - mIsRightToLeftCharacter( isRightToLeftCharacter ), - mIsVisible( isVisible ), - mDescender( descender ) -{ -} - -TextView::TextLayoutInfo::TextLayoutInfo() -: mCharacterLayoutInfoTable(), - mLines(), - mCharacterLogicalToVisualMap(), - mCharacterVisualToLogicalMap(), - mTextSize(), - mScrollOffset() -{ -} - -TextView::TextLayoutInfo::~TextLayoutInfo() -{ -} - -TextView::TextLayoutInfo::TextLayoutInfo( const TextView::TextLayoutInfo& textLayoutInfo ) -: mCharacterLayoutInfoTable( textLayoutInfo.mCharacterLayoutInfoTable ), - mLines( textLayoutInfo.mLines ), - mCharacterLogicalToVisualMap( textLayoutInfo.mCharacterLogicalToVisualMap ), - mCharacterVisualToLogicalMap( textLayoutInfo.mCharacterVisualToLogicalMap ), - mTextSize( textLayoutInfo.mTextSize ), - mScrollOffset( textLayoutInfo.mScrollOffset ) -{ -} - -TextView::TextLayoutInfo& TextView::TextLayoutInfo::operator=( const TextView::TextLayoutInfo& textLayoutInfo ) -{ - mCharacterLayoutInfoTable = textLayoutInfo.mCharacterLayoutInfoTable; - mLines = textLayoutInfo.mLines; - mCharacterLogicalToVisualMap = textLayoutInfo.mCharacterLogicalToVisualMap; - mCharacterVisualToLogicalMap = textLayoutInfo.mCharacterVisualToLogicalMap; - mTextSize = textLayoutInfo.mTextSize; - mScrollOffset = textLayoutInfo.mScrollOffset; - - return *this; -} - -TextView::FadeBoundary::FadeBoundary() -: mLeft( 0 ), - mRight( 0 ), - mTop( 0 ), - mBottom( 0 ) -{ -} - -TextView::FadeBoundary::FadeBoundary( PixelSize left, PixelSize right, PixelSize top, PixelSize bottom ) -: mLeft( left ), - mRight( right ), - mTop( top ), - mBottom( bottom ) -{ -} - -TextView::TextView() -{ -} - -TextView::TextView( const TextView& handle ) -: Control( handle ) -{ -} - -TextView::TextView( Dali::Internal::CustomActor* internal ) -: Control( internal ) -{ - VerifyCustomActorPointer(internal); -} - -TextView& TextView::operator=( const TextView& handle ) -{ - if( &handle != this ) - { - Control::operator=( handle ); - } - return *this; -} - -TextView TextView::New() -{ - return Internal::TextView::New(); -} - -TextView TextView::New( const std::string& text ) -{ - TextView textView = Internal::TextView::New(); - textView.SetText( text ); - return textView; -} - -TextView TextView::New( const MarkupProcessor::StyledTextArray& text ) -{ - TextView textView = Internal::TextView::New(); - textView.SetText( text ); - return textView; -} - -TextView TextView::DownCast( BaseHandle handle ) -{ - return Control::DownCast(handle); -} - -TextView::~TextView() -{ -} - -void TextView::SetText( const std::string& text ) -{ - GetImpl( *this ).SetText( text ); -} - -void TextView::SetText( const MarkupProcessor::StyledTextArray& text ) -{ - GetImpl( *this ).SetText( text ); -} - -void TextView::InsertTextAt( std::size_t position, const std::string& text ) -{ - GetImpl( *this ).InsertTextAt( position, text ); -} - -void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text ) -{ - GetImpl( *this ).InsertTextAt( position, text ); -} - -void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ) -{ - GetImpl( *this ).ReplaceTextFromTo( position, numberOfCharacters, text ); -} - -void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text ) -{ - GetImpl( *this ).ReplaceTextFromTo( position, numberOfCharacters, text ); -} - -void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ) -{ - GetImpl( *this ).RemoveTextFrom( position, numberOfCharacters ); -} - -std::string TextView::GetText() const -{ - return GetImpl( *this ).GetText(); -} - -void TextView::SetLineHeightOffset( PointSize offset ) -{ - GetImpl( *this ).SetLineHeightOffset( offset ); -} - -PointSize TextView::GetLineHeightOffset() const -{ - return GetImpl( *this ).GetLineHeightOffset(); -} - -void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask ) -{ - GetImpl( *this ).SetStyleToCurrentText( style, mask ); -} - -void TextView::SetTextAlignment( Alignment::Type align ) -{ - GetImpl( *this ).SetTextAlignment( align ); -} - -Alignment::Type TextView::GetTextAlignment() const -{ - return GetImpl( *this ).GetTextAlignment(); -} - -void TextView::SetMultilinePolicy( TextView::MultilinePolicy policy ) -{ - GetImpl( *this ).SetMultilinePolicy( policy ); -} - -TextView::MultilinePolicy TextView::GetMultilinePolicy() const -{ - return GetImpl( *this ).GetMultilinePolicy(); -} - -void TextView::SetWidthExceedPolicy( TextView::ExceedPolicy policy ) -{ - GetImpl( *this ).SetWidthExceedPolicy( policy ); -} - -TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const -{ - return GetImpl( *this ).GetWidthExceedPolicy(); -} - -void TextView::SetHeightExceedPolicy( ExceedPolicy policy ) -{ - GetImpl( *this ).SetHeightExceedPolicy( policy ); -} - -TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const -{ - return GetImpl( *this ).GetHeightExceedPolicy(); -} - -void TextView::SetLineJustification( TextView::LineJustification justification ) -{ - GetImpl( *this ).SetLineJustification( justification ); -} - -TextView::LineJustification TextView::GetLineJustification() const -{ - return GetImpl( *this ).GetLineJustification(); -} - -void TextView::SetFadeBoundary( const TextView::FadeBoundary& fadeBoundary ) -{ - GetImpl( *this ).SetFadeBoundary( fadeBoundary ); -} - -const TextView::FadeBoundary& TextView::GetFadeBoundary() const -{ - return GetImpl( *this ).GetFadeBoundary(); -} - -void TextView::SetEllipsizeText( const std::string& ellipsizeText ) -{ - GetImpl( *this ).SetEllipsizeText( ellipsizeText ); -} - -void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText ) -{ - GetImpl( *this ).SetEllipsizeText( ellipsizeText ); -} - -std::string TextView::GetEllipsizeText() const -{ - return GetImpl( *this ).GetEllipsizeText(); -} - -void TextView::GetTextLayoutInfo( TextLayoutInfo& textLayoutInfo ) -{ - GetImpl( *this ).GetTextLayoutInfo( textLayoutInfo ); -} - -void TextView::SetSortModifier( float depthOffset ) -{ - GetImpl( *this ).SetSortModifier( depthOffset ); -} - -void TextView::SetSnapshotModeEnabled( bool enable ) -{ - GetImpl( *this ).SetSnapshotModeEnabled( enable ); -} - -bool TextView::IsSnapshotModeEnabled() const -{ - return GetImpl( *this ).IsSnapshotModeEnabled(); -} - -void TextView::SetScrollEnabled( bool enable ) -{ - GetImpl( *this ).SetScrollEnabled( enable ); -} - -bool TextView::IsScrollEnabled() const -{ - return GetImpl( *this ).IsScrollEnabled(); -} - -void TextView::SetScrollPosition( const Vector2& position ) -{ - GetImpl( *this ).SetScrollPosition( position ); -} - -const Vector2& TextView::GetScrollPosition() const -{ - return GetImpl( *this ).GetScrollPosition(); -} - -bool TextView::IsScrollPositionTrimmed() const -{ - return GetImpl( *this ).IsScrollPositionTrimmed(); -} - -TextView::ScrolledSignalType& TextView::ScrolledSignal() -{ - return GetImpl( *this ).ScrolledSignal(); -} - -void TextView::SetMarkupProcessingEnabled( bool enable ) -{ - return GetImpl( *this ).SetMarkupProcessingEnabled( enable ); -} - -bool TextView::IsMarkupProcessingEnabled() const -{ - return GetImpl( *this ).IsMarkupProcessingEnabled(); -} - -TextView::TextView( Internal::TextView& implementation ) -: Control( implementation ) -{ -} - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-view/text-view.h b/dali-toolkit/public-api/controls/text-view/text-view.h deleted file mode 100644 index 0eb8024..0000000 --- a/dali-toolkit/public-api/controls/text-view/text-view.h +++ /dev/null @@ -1,674 +0,0 @@ -#ifndef __DALI_TOOLKIT_TEXT_VIEW_H__ -#define __DALI_TOOLKIT_TEXT_VIEW_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal DALI_INTERNAL -{ -class TextView; -} - -/** - * @brief The TextView class is a UI Dali::Toolkit::Control designed to extend the capabilities of the basic Dali::TextActor. - * - * It provides support for multi-line wrapping, multi-language font detection, text alignment, scrolling and styling. - * - * See the \link text-view Text View \endlink page of the Programming Guide for more details and examples. - * - * Signals - * | %Signal Name | Method | - * |-------------------|---------------------------| - * | scrolled | @ref ScrolledSignal() | - */ -class DALI_IMPORT_API TextView : public Control -{ -public: - - /** - * @brief The start and end property ranges for this control. - */ - enum PropertyRange - { - PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, - PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices - }; - - /** - * @brief An enumeration of properties belonging to the TextView class. - */ - struct Property - { - enum - { - MARKUP_ENABLED = PROPERTY_START_INDEX, ///< name "markup-enabled", @see SetMarkupProcessingEnabled(), type bool - TEXT, ///< name "text", @see SetText(), type std::string - MULTILINE_POLICY, ///< name "multiline-policy", @see SetMultilinePolicy(), type std::string - WIDTH_EXCEED_POLICY, ///< name "width-exceed-policy", @see SetWidthExceedPolicy(), type std::string - HEIGHT_EXCEED_POLICY, ///< name "height-exceed-policy", @see SetHeightExceedPolicy(), type std::string - LINE_JUSTIFICATION, ///< name "line-justification", @see SetLineJustification(), type std::string - FADE_BOUNDARY, ///< name "fade-boundary", @see SetFadeBoundary(), type Vector4 - LINE_HEIGHT_OFFSET, ///< name "line-height-offset", @see SetLineHeightOffset(), type float - HORIZONTAL_ALIGNMENT, ///< name "horizontal-alignment", @see SetTextAlignment(), type std::string - VERTICAL_ALIGNMENT, ///< name "vertical-alignment", @see SetTextAlignment(), type std::string - }; - }; - - /** - * @brief Structure used to retrieve Layout info per character. - */ - struct CharacterLayoutInfo - { - /** - * @brief Default constructor. - * - * Initializes all members to their default values. - */ - CharacterLayoutInfo(); - - /** - * @brief Empty destructor. - * - * @note Added to increase coverage. - */ - ~CharacterLayoutInfo(); - - /** - * @brief Copy constructor. - */ - CharacterLayoutInfo( const CharacterLayoutInfo& characterLayoutInfo ); - - /** - * @brief Assignment operator. - */ - CharacterLayoutInfo& operator=( const CharacterLayoutInfo& character ); - - /** - * @brief Constructor. - * - * @param[in] size of the character. - * @param[in] position of the character. - * @param[in] isNewParagraphChar Whether the character is a new paragraph character. - * @param[in] isRightToLeftCharacter Whether is a right to left character. - * @param[in] visible Whether is visible. - * @param[in] descender of the character (distance from the base line to the bottom of the character.) - */ - CharacterLayoutInfo( const Size& size, - const Vector3& position, - bool isNewParagraphChar, - bool isRightToLeftCharacter, - bool visible, - float descender ); - - Size mSize; ///< Size of the character. - Vector3 mPosition; ///< Position of the character within the text view. - bool mIsNewLineChar:1; ///< @deprecated. Use mIsNewParagraphChar instead. - bool mIsNewParagraphChar:1; ///< Whether this character represent a new paragraph. - bool mIsRightToLeftCharacter:1; ///< Whether it's a right-to-left character. - bool mIsVisible:1; ///< Whether this character is visible or not. - float mDescender; ///< The character's descender which is the distance from the baseline to the bottom of the character - }; - - typedef std::vector CharacterLayoutInfoContainer; ///< Container of layout info per character. - - /** - * @brief Stores some info about a line. - */ - struct LineLayoutInfo - { - std::size_t mCharacterGlobalIndex; ///< Global index within the whole text of the first character of current line. - Size mSize; ///< Size of the current line. - float mAscender; ///< The max ascender of the current line. - }; - - typedef std::vector LineLayoutInfoContainer; ///< Container of layout info per line. - - /** - * @brief How text is laid out. - */ - struct TextLayoutInfo - { - /** - * @brief Default constructor. - */ - TextLayoutInfo(); - - /** - * @brief Empty destructor. - * - * @note Added to increase coverage. - */ - ~TextLayoutInfo(); - - /** - * @brief Copy constructor. - */ - TextLayoutInfo( const TextLayoutInfo& textLayoutInfo ); - - /** - * @brief Assignment operator. - */ - TextLayoutInfo& operator=( const TextLayoutInfo& textLayoutInfo ); - - CharacterLayoutInfoContainer mCharacterLayoutInfoTable; ///< The table of character's positions and sizes sorted by the character's visual index. - LineLayoutInfoContainer mLines; ///< For each line, it stores an index to the first character of the line. - std::vector mCharacterLogicalToVisualMap; ///< The map to store the character's logical (input) index according to its visual (reordered) index. - std::vector mCharacterVisualToLogicalMap; ///< The map to store the character's visual (reordered) index according to its logical (input) index. - Size mTextSize; ///< Text size after relayout. - Vector2 mScrollOffset; ///< Scroll's position. - }; - - /** - * @brief This structure represents a fade boundary. - * - * If the Exceed policy is set to Fade all text which does not fit within the text-view fade boundary is faded out. Text which exceeds the text-view boundary becomes invisible. - * The \e left, \e right, \e top and \e bottom values are positive, in pixels and set the distances between the text-view and fade boundaries. - */ - struct FadeBoundary - { - /** - * @brief Default constructor. - * - * Initializes all values to 0. It means no fade boundary. - */ - FadeBoundary(); - - /** - * @brief Constructor. - * - * Initializes the fade boundary with the given values. - * - * @param[in] left value in pixels. - * @param[in] right value in pixels. - * @param[in] top value in pixels. - * @param[in] bottom value in pixels. - */ - FadeBoundary( PixelSize left, PixelSize right, PixelSize top, PixelSize bottom ); - - PixelSize mLeft; ///< The left fade boundary - PixelSize mRight; ///< The right fade boundary - PixelSize mTop; ///< The top fade boundary - PixelSize mBottom; ///< The bottom fade bounday - }; - - /** - * @brief Define how to wrap the text's paragraphs in lines. - * - * \e SplitByNewLineChar will wrap the text's paragraphs in lines when a '\\n' character or a \
is found. - * \e SplitByWord has effect only when TextView size is assigned. - * It will wrap the text's paragraphs in lines when a '\\n' character or a \
is found or if a paragraph exceeds the TextView's boundary. This option won't split a word in two. - * \e SplitByChar has effect only when TextView size is assigned. - * It will wrap the text's paragraphs in lines when a '\\n' character or a \
is found or if a paragraph exceeds the TextView's boundary. This option might split a word in two. - * The default value is \e SplitByNewLineChar. - */ - enum MultilinePolicy - { - SplitByNewLineChar, ///< Text's paragraphs will wrap in lines when '\\n' character is found. - SplitByWord, ///< Text's paragraphs will wrap in lines by word or if '\\n' character is found. It has effect only when TextView size is assigned. - SplitByChar ///< Text's paragraphs will wrap in lines by char or if '\\n' character is found. It has effect only when TextView size is assigned. - }; - - /** - * @brief Define how to display the lines when they doesn't fit inside the TextView after the text's paragraphs are wrapped in lines. - * - * The default value is \e Original. - */ - enum ExceedPolicy - { - Original, ///< Will display the lines in their original size. If a line, a word or a character is bigger than the TextView size it may exceed its boundary. - Fade, ///< Will display the lines in their original size. It won't display the part of the line which exceeds the TextView boundary. It fades the text out. - Split, ///< Will split the lines in a new line(s). - ShrinkToFit, ///< Will shrink the lines to fit the TextView boundary. - EllipsizeEnd ///< Will ellipsize the lines by the end. - }; - - /** - * @brief Define how to justify lines inside the text's boundary. - * - * The default value is \e Left. - */ - enum LineJustification - { - Left, ///< Justify to the left. - Center, ///< Centered. - Right, ///< Justify to the right. - Justified ///< Line justified. - }; - -public: - /** - * @brief Create a TextView handle; this can be initialised with TextView::New(). - * - * Calling member functions with an uninitialised Dali::Object handle is not allowed. - */ - TextView(); - - /** - * @brief Copy constructor. - * - * Creates another handle that points to the same real object - * @param[in] handle The handle to copy from - */ - TextView( const TextView& handle ); - - /** - * @brief Assignment operator. - * - * Changes this handle to point to another real object - * @param[in] handle The handle to copy from - * @return a reference to this - */ - TextView& operator=( const TextView& handle ); - - /** - * @brief Create a TextView control with no text. - * - * @return A handle the TextView control. - */ - static TextView New(); - - /** - * @brief Create a TextView control. - * - * @param[in] text to display. - * @return A handle the TextView control. - */ - static TextView New( const std::string& text ); - - /** - * @brief Create a TextView control with styled text. - * - * @param[in] text The text with style to display. - * @return A handle the TextView control. - */ - static TextView New( const MarkupProcessor::StyledTextArray& text ); - - /** - * @brief Downcast an Object handle to TextView. - * - * If handle points to a TextView the - * downcast produces valid handle. If not the returned handle is left uninitialized. - * @param[in] handle Handle to an object - * @return handle to a TextView or an uninitialized handle - */ - static TextView DownCast( BaseHandle handle ); - - /** - * @brief Destructor - * - * This is non-virtual since derived Handle types must not contain data or virtual methods. - */ - ~TextView(); - - /** - * @brief Replace the current text with a new text string. - * - * @param[in] text to display. The string may contain style tags. - */ - void SetText( const std::string& text ); - - /** - * @brief Replace the current text with a new text string with style. - * - * @param[in] text The text with style to display. - */ - void SetText( const MarkupProcessor::StyledTextArray& text ); - - /** - * @brief Inserts the given text in the specified position. - * - * @param[in] position Where the given text is going to be added. - * @param[in] text The text to be added. - */ - void InsertTextAt( std::size_t position, const std::string& text ); - - /** - * @brief Inserts the given text with style in the specified position. - * - * @param[in] position Where the given text is going to be added. - * @param[in] text The text with style to be added. - */ - void InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text ); - - /** - * @brief Replaces part of the text. - * - * It removes the specified number of characters from the given position and inserts the given text in the same specified position. - * - * @param[in] position of the first character to be removed and Where the given text is going to be added. - * @param[in] numberOfCharacters number of characters to be removed. - * @param[in] text The text to be added. - */ - void ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ); - - /** - * @brief Replaces part of the text. - * - * It removes the specified number of characters from the given position and inserts the given text with style in the same specified position. - * - * @param[in] position of the first character to be removed and Where the given text is going to be added. - * @param[in] numberOfCharacters number of characters to be removed. - * @param[in] text The text with style to be added. - */ - void ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text ); - - /** - * @brief Removes the specified number of characters from the given position. - * - * @param[in] position of the first character to be removed. - * @param[in] numberOfCharacters number of characters to be removed. - */ - void RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ); - - /** - * @brief Get the currently displayed text. - * - * @return The currently displayed text. - */ - std::string GetText() const; - - /** - * @brief Sets a line height offset. - * - * The line height offset will be added to the font line height. - * @param [in] offset The height offset in PointSize units. - */ - void SetLineHeightOffset( PointSize offset ); - - /** - * @brief Retrieves the line height offset. - * - * @return The line height offset in PointSize units. - */ - PointSize GetLineHeightOffset() const; - - /** - * @brief Sets the given style to the current text. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @note TextView doesn't store a copy of the given style, it applies the given style to the current text only. - * Subsequent calls to SetText() will override any style set by this method. - * @param[in] style The given style - * @param[in] mask The bit mask. - */ - void SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask = TextStyle::ALL ); - - /** - * @brief Set the current text alignment. - * - * Default alignment is (HorizontalCenter | VerticalCenter) - * @param[in] align The new alignment option. - */ - void SetTextAlignment( Alignment::Type align ); - - /** - * @brief Get the current text alignment combined into a single value. - * - * The values can be tested by using the & operator - * and the desired flag. e.g. if (GetTextAlignment() & HorizontalCentre) ... - * @return the combined alignment - */ - Alignment::Type GetTextAlignment() const; - - /** - * @brief Sets how to split the paragraphs into lines. - * - * @param policy The multi-line policy. \e SplitByNewLineChar is set by default. - */ - void SetMultilinePolicy( MultilinePolicy policy ); - - /** - * @brief Gets the wrap in lines policy. - * - * @return The multi-line policy. - */ - MultilinePolicy GetMultilinePolicy() const; - - /** - * @brief Sets how to display the text inside the TextView when it exceeds the text-view's width. - * - * @param policy The exceed policy. Original is set by default. - */ - void SetWidthExceedPolicy( ExceedPolicy policy ); - - /** - * @brief Gets the width exceed policy. - * - * @return The exceed policy. - */ - ExceedPolicy GetWidthExceedPolicy() const; - - /** - * @brief Sets how to display the text inside the TextView when it exceeds the text-view's height. - * - * @param policy The exceed policy. Original is set by default. - */ - void SetHeightExceedPolicy( ExceedPolicy policy ); - - /** - * @brief Gets the height exceed policy. - * - * @return The exceed policy. - */ - ExceedPolicy GetHeightExceedPolicy() const; - - /** - * @brief Sets how to justify lines inside the text's boundary. - * - * @param justification The line justification. Left is set by default. - */ - void SetLineJustification( LineJustification justification ); - - /** - * @brief Gets the line justification. - * - * @return The line justification. - */ - LineJustification GetLineJustification() const; - - /** - * @brief Sets a fade boundary. - * - * @see FadeBoundary. - * - * @param[in] fadeBoundary The given fade boundary. - */ - void SetFadeBoundary( const FadeBoundary& fadeBoundary ); - - /** - * @brief Retrieves the fade boundary. - * - * @see FadeBoundary. - * - * @return The fade boundary. - */ - const FadeBoundary& GetFadeBoundary() const; - - /** - * @brief Sets the ellipsize text. - * - * @param[in] ellipsizeText The new text. The string may contain style tags. By default the ellipsize text is '...' - */ - void SetEllipsizeText( const std::string& ellipsizeText ); - - /** - * @brief Sets the ellipsize text with style. - * - * @param[in] ellipsizeText The new text with its style. - */ - void SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText ); - - /** - * @brief Retrieves the ellipsize text. - * - * @return The ellipsize text. - */ - std::string GetEllipsizeText() const; - - /** - * @brief A mechanism to retrieve layout information from the TextView. - * - * It produces a vector of CharcterLayoutInfo structures which describe the size and position of each character, - * two vectors which maps the logical and visual positions of the characters in a bidirectional text, the size - * of the whole laid-out text and the scroll offset value. - * - * @see TextLayoutInfo. - * - * @param[out] textLayoutInfo A structure with text layout information. - */ - void GetTextLayoutInfo( TextLayoutInfo& textLayoutInfo ); - - /** - * @brief Allows modification of text-actor's position in the depth sort algorithm. - * - * @see Dali::RenderableActor::SetSortModifier() - * @param [in] depthOffset the offset to be given to the internal text-actors. Positive values pushing it further back. - */ - void SetSortModifier( float depthOffset ); - - /** - * @brief Sets whether text-view renders text using a previously generated snapshot. - * - * Rendering long text using a snapshot may increase performance. The default value is \e false (render without using a snapshot). - * - * @param[in] enable Whether text-view is using a snapshot to render text. - */ - void SetSnapshotModeEnabled( bool enable ); - - /** - * @brief Retrieves whether text-view is using a snapshot to render text. - * - * @return \e true if text-view is using a snapshot to render text, otherwhise it returns \e false. - */ - bool IsSnapshotModeEnabled() const; - - /** - * @brief Sets whether markup processing should be carried out. - * - * To use markup, applications need to SetMarkupProcessingEnabled first, then SetText(). - * - * @see SetText() - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ); - - /** - * @brief Retrieves whether text-view is processing markup text - * - * @return \e true if text-view markup processing is enabled, otherwhise it returns \e false. - */ - bool IsMarkupProcessingEnabled() const; - - /** - * @brief Enables or disables the text scroll. - * - * When scroll is enabled, snapshot mode will be enabled automatically. Equally, if scroll is disabled - * the snapshot mode is restored to the previous value. - * - * @param[in] enable Whether to enable the text scroll. - */ - void SetScrollEnabled( bool enable ); - - /** - * @brief Retrieves whether the text scroll is enabled. - * - * @return \e true if the scroll is enabled. - */ - bool IsScrollEnabled() const; - - /** - * @brief Sets a new scroll position. - * - * The new scroll position set could be trimmed if the text doesn't cover the whole text-view. - * i.e. If a text-view is 100x100 and a text is 200x100 a scroll position beyond 50x0 will be trimmed to 50x0. - * - * Call IsScrollPositionTrimmed() to know if the last scroll position set has been trimmed. - * - * A signal is emitted. @see ScrolledSignal(). - * - * @param[in] position The new scroll position. - */ - void SetScrollPosition( const Vector2& position ); - - /** - * @brief Recrieves current scroll position. - * - * @return The scroll position. - */ - const Vector2& GetScrollPosition() const; - - /** - * @brief Whether the last scroll position set was trimmed. - * - * @return \e true if the last scroll position set was trimmed, otherwise \e false. - */ - bool IsScrollPositionTrimmed() const; - -public: - /// @brief Signal types - typedef Signal< void ( TextView textView, Vector2 scrollDelta ) > ScrolledSignalType; - - /** - * @brief Signal emitted when the text is scrolled inside the text-view. - * - * A callback with the following prototype can be connected to this signal. - * - * Callback(TextView textView, Vector2 scrollDelta) - * - * \e textView is the handle of the text-view emitting the signal. - * \e scrollDelta is the differente of the current scroll position with the previous one. - * @return The signal to connect to - */ - ScrolledSignalType& ScrolledSignal(); - -public: // Not intended for application developers - - /** - * @brief Creates a handle using the Toolkit::Internal implementation. - * @note Not intended for application developers - * - * @param[in] implementation The Control implementation. - */ - DALI_INTERNAL TextView( Internal::TextView& implementation ); - - /** - * @brief Allows the creation of this Control from an Internal::CustomActor pointer. - * @note Not intended for application developers - * - * @param[in] internal A pointer to the internal CustomActor. - */ - explicit DALI_INTERNAL TextView( Dali::Internal::CustomActor* internal ); -}; - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_ITEM_VIEW_H__ diff --git a/dali-toolkit/public-api/file.list b/dali-toolkit/public-api/file.list index 0f06f3d..41c390a 100755 --- a/dali-toolkit/public-api/file.list +++ b/dali-toolkit/public-api/file.list @@ -48,8 +48,9 @@ public_api_src_files = \ $(public_api_src_dir)/controls/slider/slider.cpp \ $(public_api_src_dir)/controls/super-blur-view/super-blur-view.cpp \ $(public_api_src_dir)/controls/table-view/table-view.cpp \ - $(public_api_src_dir)/controls/text-input/text-input.cpp \ - $(public_api_src_dir)/controls/text-view/text-view.cpp \ + $(public_api_src_dir)/controls/text-controls/text-label.cpp \ + $(public_api_src_dir)/controls/text-controls/text-field.cpp \ + $(public_api_src_dir)/controls/text-controls/text-selection-popup.cpp \ $(public_api_src_dir)/controls/tool-bar/tool-bar.cpp \ $(public_api_src_dir)/controls/bloom-view/bloom-view.cpp \ $(public_api_src_dir)/controls/cluster/cluster-style.cpp \ @@ -61,7 +62,6 @@ public_api_src_files = \ $(public_api_src_dir)/focus-manager/focus-manager.cpp \ $(public_api_src_dir)/focus-manager/keyboard-focus-manager.cpp \ $(public_api_src_dir)/focus-manager/keyinput-focus-manager.cpp \ - $(public_api_src_dir)/markup-processor/markup-processor.cpp \ $(public_api_src_dir)/shader-effects/bubble-effect/bubble-effect.cpp \ $(public_api_src_dir)/shader-effects/bubble-effect/color-adjuster.cpp \ $(public_api_src_dir)/shader-effects/alpha-discard-effect.cpp \ @@ -203,11 +203,10 @@ public_api_super_blur_view_header_files = \ public_api_table_view_header_files = \ $(public_api_src_dir)/controls/table-view/table-view.h -public_api_text_input_header_files = \ - $(public_api_src_dir)/controls/text-input/text-input.h - -public_api_text_view_header_files = \ - $(public_api_src_dir)/controls/text-view/text-view.h +public_api_text_controls_header_files = \ + $(public_api_src_dir)/controls/text-controls/text-label.h \ + $(public_api_src_dir)/controls/text-controls/text-field.h \ + $(public_api_src_dir)/controls/text-controls/text-selection-popup.h public_api_tool_bar_header_files = \ $(public_api_src_dir)/controls/tool-bar/tool-bar.h @@ -225,9 +224,6 @@ public_api_focus_manager_header_files = \ $(public_api_src_dir)/focus-manager/keyboard-focus-manager.h \ $(public_api_src_dir)/focus-manager/keyinput-focus-manager.h -public_api_markup_processor_header_files = \ - $(public_api_src_dir)/markup-processor/markup-processor.h - public_api_shader_effects_header_files = \ $(public_api_src_dir)/shader-effects/alpha-discard-effect.h \ $(public_api_src_dir)/shader-effects/bendy-effect.h \ @@ -275,3 +271,5 @@ public_api_scripting_header_files = \ $(public_api_src_dir)/scripting/script.h \ $(public_api_src_dir)/scripting/script-plugin.h +public_api_rendering_backend_header_files = \ + $(public_api_src_dir)/text/rendering-backend.h diff --git a/dali-toolkit/public-api/markup-processor/markup-processor.cpp b/dali-toolkit/public-api/markup-processor/markup-processor.cpp deleted file mode 100644 index 83359fd..0000000 --- a/dali-toolkit/public-api/markup-processor/markup-processor.cpp +++ /dev/null @@ -1,1121 +0,0 @@ -/* - * 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. - * - */ - -// HEADER INCLUDE -#include - -// EXTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace MarkupProcessor -{ - -namespace -{ -const std::string WEB_COLOR_TOKEN( "#" ); -const std::string HEX_COLOR_TOKEN( "0x" ); -const std::string ALPHA_ONE( "FF" ); - -const std::string BLACK_COLOR( "black" ); -const std::string WHITE_COLOR( "white" ); -const std::string RED_COLOR( "red" ); -const std::string GREEN_COLOR( "green" ); -const std::string BLUE_COLOR( "blue" ); -const std::string YELLOW_COLOR( "yellow" ); -const std::string MAGENTA_COLOR( "magenta" ); -const std::string CYAN_COLOR( "cyan" ); -const std::string TRANSPARENT_COLOR( "transparent" ); - -const std::string XHTML_B_TAG("b"); -const std::string XHTML_I_TAG("i"); -const std::string XHTML_U_TAG("u"); -const std::string XHTML_BR_TAG("br"); -const std::string XHTML_FONT_TAG("font"); -const std::string XHTML_SHADOW_TAG("shadow"); -const std::string XHTML_GLOW_TAG("glow"); -const std::string XHTML_OUTLINE_TAG("outline"); -const std::string XHTML_SMOOTH_EDGE_TAG("smooth"); -const std::string XHTML_SIZE_PROPERTY("size"); -const std::string XHTML_COLOR_PROPERTY("color"); -const std::string XHTML_FACE_PROPERTY("face"); -const std::string XHTML_STYLE_PROPERTY("style"); -const std::string XHTML_PARAM_PROPERTY("param"); -const std::string XHTML_PARAM_X_PROPERTY("paramx"); -const std::string XHTML_PARAM_Y_PROPERTY("paramy"); - -const char LESS_THAN( '<' ); -const char GREATER_THAN( '>' ); -const char EQUAL( '=' ); -const char QUOTATION_MARK( '\''); -const char LINE_SEPARATOR_CR( 0x0D ); // Carriage return character CR -const char LINE_SEPARATOR_LF( 0x0A ); // New line character LF -const char SLASH( '/' ); -const char BACK_SLASH( '\\' ); - -const std::string LINE_SEPARATOR_LF_STRING(1 , LINE_SEPARATOR_LF); ///< a string with 1 line separator character -/** - * Stores a property pair: name, value. - */ -struct Property -{ - Property( const std::string& n, const std::string& v ) - : name( n ), - value( v ) - {} - - std::string name; - std::string value; -}; - - -/** - * Compare if two strings are equal. - * - * The comparison is case insensitive. - * - * @param[in] string1 First of the two strings to be compared. - * @param[in] string2 Second of the strings to be compared. - * - * @return \e true if both strings are equal (case insensitive). - */ -bool CaseInsensitiveComparison( const std::string& string1, const std::string& string2 ) -{ - const std::size_t stringSize = string1.size(); - if( stringSize != string2.size() ) - { - // Early return. Strings have different sizes. - return false; - } - - bool equal = true; - for( std::size_t index = 0; equal && ( index < stringSize ); ++index ) - { - if( std::toupper( *( string1.begin() + index ) ) != std::toupper( *( string2.begin() + index ) ) ) - { - equal = false; - } - } - - return equal; -} - -/** - * Converts a string into a float value. - * @param[in] floatStr A float packed inside a string. - * @return The float value. - */ -float StringToFloat( const std::string& floatStr ) -{ - float ret = 0.f; - - std::istringstream( floatStr ) >> ret; - - return ret; -} - -/** - * Converts a float into a string. - * @param[in] value. A float. - * @return The float packed into a string. - */ -std::string FloatToString( float value ) -{ - std::ostringstream stream; - stream << value; - - return stream.str(); -} - -/** - * Converts a string into an hexadecimal unsigned int. - * @param[in] uintStr An hexadecimal unsigned int packed inside a string. - * @return The hexadecimal value. - */ -unsigned int StringToHex( const std::string& uintStr ) -{ - unsigned int ret = 0; - - std::string str( uintStr ); - if( uintStr.size() <= 8 ) - { - str.insert( 2, std::string( "ff" ) ); - } - - std::istringstream( str ) >> std::hex >> ret; - - return ret; -} - -/** - * Converts an hexadecimal value into a string. - * @param[in] value. An hexadecimal value. - * @return The hexadecimal value packed inside a string. - */ -std::string HexToString( unsigned int value ) -{ - std::ostringstream stream; - stream << std::hex << value; - return stream.str(); -} - -/** - * Converts an ARGB color packed in 4 byte unsigned int into a Vector4 color used in Dali. - * @param[in] color An ARGB color packed in an unsigned int. - * @param[out] retColor A Vector4 with the converted color. - */ -void UintColorToVector4( unsigned int color, Vector4& retColor ) -{ - retColor.a = static_cast( ( color & 0xFF000000 ) >> 24 ) / 255.f; - retColor.r = static_cast( ( color & 0x00FF0000 ) >> 16 ) / 255.f; - retColor.g = static_cast( ( color & 0x0000FF00 ) >> 8 ) / 255.f; - retColor.b = static_cast( color & 0x000000FF ) / 255.f; -} - -/** - * Converts an ARGB Vector4 color into a 4 byte packed inside an unsigned int. - * @param[in] color A Vector4 with an ARGB color. - * @return An unsigned int with the converted color. - */ -unsigned int Vector4ColorToUint( const Vector4& color ) -{ - unsigned int retColor = 0; - - retColor = static_cast( color.a * 255.f ) << 24; - retColor += static_cast( color.r * 255.f ) << 16; - retColor += static_cast( color.g * 255.f ) << 8; - retColor += static_cast( color.b * 255.f ); - - return retColor; -} - -/** - * Converts a color packed inside a string into an ARGB Vector4 color. - * The string color could be in hexadecimal ( 0xFF0000FF ), webcolor ( #0000FF or #00F ) or some constant values: - * black, white, red, green, blue, yellow, magenta, cyan, transparent. - * @param[in] colorStr A color packed inside a string.. - * @param[out] retColor A color packed inside a Vector4. - */ -void ColorStringToVector4( const std::string& colorStr, Vector4& retColor ) -{ - std::string subStr1 = colorStr.substr( 0, 1 ); - std::string subStr2 = colorStr.substr( 0, 2 ); - - if( WEB_COLOR_TOKEN == subStr1 ) - { - std::string webColor( colorStr.begin() + 1, colorStr.end() ); - if( 3 == webColor.size() ) // 3 component web color #F00 (red) - { - webColor.insert( 2, &( webColor[2] ), 1 ); - webColor.insert( 1, &( webColor[1] ), 1 ); - webColor.insert( 0, &( webColor[0] ), 1 ); - webColor.insert( 0, ALPHA_ONE ); - } - else if( 6 == webColor.size() ) // 6 component web color #FF0000 (red) - { - webColor.insert( 0, ALPHA_ONE ); - } - webColor.insert( 0, HEX_COLOR_TOKEN ); - - UintColorToVector4( StringToHex( webColor ), retColor ); - } - else if( CaseInsensitiveComparison( HEX_COLOR_TOKEN, subStr2 ) ) - { - UintColorToVector4( StringToHex( colorStr ), retColor ); - } - else if( CaseInsensitiveComparison( BLACK_COLOR, colorStr ) ) - { - retColor = Color::BLACK; - } - else if( CaseInsensitiveComparison( WHITE_COLOR, colorStr ) ) - { - retColor = Color::WHITE; - } - else if( CaseInsensitiveComparison( RED_COLOR, colorStr ) ) - { - retColor = Color::RED; - } - else if( CaseInsensitiveComparison( GREEN_COLOR, colorStr ) ) - { - retColor = Color::GREEN; - } - else if( CaseInsensitiveComparison( BLUE_COLOR, colorStr ) ) - { - retColor = Color::BLUE; - } - else if( CaseInsensitiveComparison( YELLOW_COLOR, colorStr ) ) - { - retColor = Color::YELLOW; - } - else if( CaseInsensitiveComparison( MAGENTA_COLOR, colorStr ) ) - { - retColor = Color::MAGENTA; - } - else if( CaseInsensitiveComparison( CYAN_COLOR, colorStr ) ) - { - retColor = Color::CYAN; - } - else if( CaseInsensitiveComparison( TRANSPARENT_COLOR, colorStr ) ) - { - retColor = Color::TRANSPARENT; - } -} - -/** - * Converts a color packed inside a Vector4 into a string. - * The string color could be in hexadecimal ( 0xFF0000FF ), webcolor ( #0000FF or #00F ) or some constant values: - * black, white, red, green, blue, yellow, magenta, cyan, transparent. - * @param[in] color A color packed inside a Vector4 - * @return The color packed inside a string. - */ -std::string Vector4ToColorString( const Vector4& color ) -{ - std::string colorStr; - - if( Color::BLACK == color ) - { - colorStr = BLACK_COLOR; - } - else if( Color::WHITE == color ) - { - colorStr = WHITE_COLOR; - } - else if( Color::RED == color ) - { - colorStr = RED_COLOR; - } - else if( Color::GREEN == color ) - { - colorStr = GREEN_COLOR; - } - else if( Color::BLUE == color ) - { - colorStr = BLUE_COLOR; - } - else if( Color::YELLOW == color ) - { - colorStr = YELLOW_COLOR; - } - else if( Color::MAGENTA == color ) - { - colorStr = MAGENTA_COLOR; - } - else if( Color::CYAN == color ) - { - colorStr = CYAN_COLOR; - } - else if( Color::TRANSPARENT == color ) - { - colorStr = TRANSPARENT_COLOR; - } - else - { - colorStr = HEX_COLOR_TOKEN + HexToString( Vector4ColorToUint( color ) ); - } - - return colorStr; -} - -/** - * Skips any unnecessary white space. - * @param[in,out] it Iterator pointing to the current character of the markup string which is being parsed. - * @param[in] endIt Iterator pointing to the end of the markup string. - */ -void SkipWhiteSpace( std::string::const_iterator& it, const std::string::const_iterator& endIt ) -{ - bool found = false; - for( ; ( !found ) && ( it != endIt ); ++it ) - { - if( !isspace( *it ) ) - { - found = true; - --it; - } - } -} - -/** - * Adds a line separator 'LF' character to the given styled text array. - * @param[in] style The current style. - * @param[in,out] styledTextArray The given styled text array. - */ -void AddNewLineChar( const TextStyle& style, StyledTextArray& styledTextArray ) -{ - const Text text( LINE_SEPARATOR_LF_STRING ); - styledTextArray.push_back( StyledText( text, style ) ); -} - -/** - * Adds text to the given styled text array. - * It splits the text in characters. - * @param[in] textToBeStored The text to be stored. - * @param[in] styleToBeStored The current style. - * @param[in,out] styledTextArray The given styled text array. - */ -void AddText( const std::string& textToBeStored, const TextStyle& styleToBeStored, StyledTextArray& styledTextArray ) -{ - const Text text( textToBeStored ); - for( size_t i = 0, length = text.GetLength(); i < length; ++i ) - { - styledTextArray.push_back( StyledText( Text( text[i] ), styleToBeStored ) ); - } -} - -/** - * Splits the tag string into the tag name and its properties. - * @param[in] tag The tag string with its pairs property, value. - * @param[out] tagName The name of the tag. - * @param[out] properties Vector of properties. - */ -void ParseProperties( const std::string& tag, std::string& tagName, std::vector& properties ) -{ - // Find first the tag name. - bool found = false; - bool isQuotationOpen = false; - std::string::const_iterator it, endIt; - for( it = tag.begin(), endIt = tag.end(); ( !found ) && ( it != endIt ); ++it ) - { - const char character( *it ); - if( !isspace( character ) ) - { - tagName += character; - } - else - { - found = true; - } - } - SkipWhiteSpace( it, endIt ); - - // Find the properties. - std::string name; - std::string value; - bool addToNameValue = true; - for( ; it != endIt; ++it ) - { - const char character( *it ); - if( isspace( character ) && !isQuotationOpen ) - { - if( !name.empty() && !value.empty() ) - { - // Every time a white space is found, a new property is created and stored in the properties vector. - properties.push_back( Property( name, value ) ); - name .clear(); - value.clear(); - addToNameValue = true; // next read characters will be added to the name. - } - } - else if( EQUAL == character ) // '=' - { - addToNameValue = false; // next read characters will be added to the value. - SkipWhiteSpace( it, endIt ); - } - else if( QUOTATION_MARK == character ) // '\'' - { - // Do not add quotation marks to neither name nor value. - isQuotationOpen = !isQuotationOpen; - } - else - { - // Adds characters to the name or the value. - if( addToNameValue ) - { - name += character; - } - else - { - value += character; - } - } - } - if( !name.empty() && !value.empty() ) - { - // Checks if the last property needs to be added. - properties.push_back( Property( name, value ) ); - } -} - -/** - * It parses a tag and its properties if the given iterator \e it is pointing at a tag beginning. - * @param[in,out] it Iterator pointing to the current character of the markup string which is being parsed. - * @param[in] endIt Iterator pointing to the end of the markup string. - * @param[out] tag Name of the tag. - * @param[out] isEndTag Whether the tag is and end tag i.e or not. - * @param[out] properties The vector with tag properties. - * @return \e true if the iterator \e it is pointing a markup tag. Otherwise \e false. - */ -bool IsTag( std::string::const_iterator& it, const std::string::const_iterator& endIt, std::string& tag, bool& isEndTag, std::vector& properties ) -{ - bool isTag = false; - bool isQuotationOpen = false; - bool propertiesFound = false; - std::string tagString; - - const char character( *it ); - if( LESS_THAN == character ) // '<' - { - // if the iterator is pointing to a '<' character, then check if it's a markup tag is needed. - ++it; - if( it != endIt ) - { - SkipWhiteSpace( it, endIt ); - - for( ; ( !isTag ) && ( it != endIt ); ++it ) - { - const char character( *it ); - - if( SLASH == character ) // '/' - { - // if the tag has a '/' then it's an end or empty tag. - isEndTag = true; - - if( ( it + 1 != endIt ) && ( isspace( *( it + 1 ) ) ) && ( !isQuotationOpen ) ) - { - ++it; - SkipWhiteSpace( it, endIt ); - --it; - } - } - else if( GREATER_THAN == character ) // '>' - { - isTag = true; - } - else if(QUOTATION_MARK == character) - { - isQuotationOpen = !isQuotationOpen; - tagString += character; - } - else if( isspace( character ) ) // ' ' - { - // If the tag contains white spaces then it may have properties. - if ( !isQuotationOpen ) - { - propertiesFound = true; - } - tagString += character; - } - else - { - // If it's not any of the 'special' characters then just add it to the tag string. - tagString += character; - } - } - --it; - } - } - - // If the tag string has white spaces, then parse the properties is needed. - if( propertiesFound ) - { - ParseProperties( tagString, tag, properties ); - } - else - { - tag = tagString; - } - - return isTag; -} - -} // namespace - -void GetStyledTextArray( const std::string& markupString, StyledTextArray& styledTextArray, bool scanForMarkup ) -{ - styledTextArray.clear(); - - if ( !scanForMarkup ) - { - const Text text( markupString ); - const std::size_t size = text.GetLength(); - - styledTextArray.resize( size, StyledText( Text(), TextStyle() ) ); - - std::size_t index = 0; - for( StyledTextArray::iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it, ++index ) - { - StyledText& styledText( *it ); - - styledText.mText.Append( text[index] ); - } - return; - } - - TextStyle defaultStyle; - std::stack styleStack; - - styleStack.push( defaultStyle ); - TextStyle currentStyle = styleStack.top(); - std::string textToBeStored; - TextStyle styleToBeStored( currentStyle ); - for( std::string::const_iterator it = markupString.begin(), endIt = markupString.end(); it != endIt; ++it ) - { - std::string tag; - bool isEndTag = false; - std::vector tagProperties; - if( IsTag( it, endIt, tag, isEndTag, tagProperties ) ) - { - if( CaseInsensitiveComparison( XHTML_I_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - newStyle.SetItalics( true ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_U_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - newStyle.SetUnderline( true ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_B_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - newStyle.SetWeight( TextStyle::BOLD ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_BR_TAG, tag ) ) - { - if( isEndTag ) - { - AddText( textToBeStored, styleToBeStored, styledTextArray ); - AddNewLineChar( currentStyle, styledTextArray ); - textToBeStored.clear(); - } - } //
- else if( CaseInsensitiveComparison( XHTML_FONT_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_FACE_PROPERTY, property.name ) ) - { - newStyle.SetFontName( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_STYLE_PROPERTY, property.name ) ) - { - newStyle.SetFontStyle( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_COLOR_PROPERTY, property.name ) ) - { - Vector4 color; - ColorStringToVector4( property.value, color ); - newStyle.SetTextColor( color ); - } - else if( CaseInsensitiveComparison( XHTML_SIZE_PROPERTY, property.name ) ) - { - newStyle.SetFontPointSize( PointSize( StringToFloat( property.value ) ) ); - } - } - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_SHADOW_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - Vector4 color( TextStyle::DEFAULT_SHADOW_COLOR ); - Vector2 offset( TextStyle::DEFAULT_SHADOW_OFFSET ); - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_PARAM_X_PROPERTY, property.name ) ) - { - offset.x = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_PARAM_Y_PROPERTY, property.name ) ) - { - offset.y = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_COLOR_PROPERTY, property.name ) ) - { - ColorStringToVector4( property.value, color ); - } - } - newStyle.SetShadow( true, color, offset ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_GLOW_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - Vector4 color( TextStyle::DEFAULT_GLOW_COLOR ); - float intensity = TextStyle::DEFAULT_GLOW_INTENSITY; - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_PARAM_PROPERTY, property.name ) ) - { - intensity = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_COLOR_PROPERTY, property.name ) ) - { - ColorStringToVector4( property.value, color ); - } - } - newStyle.SetGlow( true, color, intensity ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_OUTLINE_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - Vector4 color( TextStyle::DEFAULT_OUTLINE_COLOR ); - Vector2 thickness( TextStyle::DEFAULT_OUTLINE_THICKNESS ); - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_PARAM_X_PROPERTY, property.name ) ) - { - thickness.x = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_PARAM_Y_PROPERTY, property.name ) ) - { - thickness.y = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_COLOR_PROPERTY, property.name ) ) - { - ColorStringToVector4( property.value, color ); - } - } - newStyle.SetOutline( true, color, thickness ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_SMOOTH_EDGE_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_PARAM_PROPERTY, property.name ) ) - { - newStyle.SetSmoothEdge( StringToFloat( property.value ) ); - } - } - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - } // end if( IsTag() ) - else - { - char character( *it ); - - // Adding < or > special character. - if( ( BACK_SLASH == character ) && ( it + 1 != endIt ) ) - { - const char nextChar( *( it + 1 ) ); - if( ( LESS_THAN == nextChar ) || ( GREATER_THAN == nextChar ) ) - { - character = nextChar; - ++it; - } - } - else if( ( LINE_SEPARATOR_CR == character ) && ( it + 1 != endIt ) ) - { - if( LINE_SEPARATOR_LF == *( it + 1 ) ) - { - character = LINE_SEPARATOR_LF; - ++it; - } - } - - if( styleToBeStored != currentStyle ) - { - if( !textToBeStored.empty() ) - { - AddText( textToBeStored, styleToBeStored, styledTextArray ); - textToBeStored.clear(); - } - styleToBeStored = currentStyle; - } - textToBeStored.insert( textToBeStored.end(), character ); - } - } - if( !textToBeStored.empty() ) - { - AddText( textToBeStored, styleToBeStored, styledTextArray ); - textToBeStored.clear(); - } -} - -void GetPlainString( const StyledTextArray& styledTextArray, std::string& plainString ) -{ - // First step is put all simultaneous characters with same style together. - for( StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it ) - { - const StyledText& styledText( *it ); - plainString += styledText.mText.GetText(); - } -} - -void GetMarkupString( const StyledTextArray& styledTextArray, std::string& markupString ) -{ - const std::string WHITE_SPACE( " " ); - - TextStyle previousStyle; - StyledText newStyledText; - StyledTextArray compressedStyledTextArray; - - markupString.clear(); - - // First step is put all simultaneous characters with same style together. - for( StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it ) - { - const StyledText& styledText( *it ); - - if( previousStyle != styledText.mStyle ) - { - if( !newStyledText.mText.IsEmpty() ) - { - compressedStyledTextArray.push_back( newStyledText ); - } - newStyledText = StyledText(); - newStyledText.mStyle = styledText.mStyle; - } - - if( !styledText.mText.IsEmpty() ) - { - const char character = styledText.mText.GetText()[0]; - if( ( character == LESS_THAN ) || ( character == GREATER_THAN ) ) - { - newStyledText.mText.Append( Text( std::string( &BACK_SLASH, 1 ) ) ); - } - } - - newStyledText.mText.Append( styledText.mText ); - - previousStyle = newStyledText.mStyle; - } - - //Add the last characters. - if( !newStyledText.mText.IsEmpty() ) - { - compressedStyledTextArray.push_back( newStyledText ); - } - - // Write markup string. - const std::string lineSeparatorStr( &LINE_SEPARATOR_LF ); - const Text lineSeparator( lineSeparatorStr ); - - const TextStyle defaultStyle; - for( StyledTextArray::const_iterator it = compressedStyledTextArray.begin(), endIt = compressedStyledTextArray.end(); it != endIt; ++it ) - { - const StyledText& styledText( *it ); - - bool isItalics = styledText.mStyle.IsItalicsEnabled(); - bool isBold = defaultStyle.GetWeight() != styledText.mStyle.GetWeight(); - bool isUnderline = styledText.mStyle.IsUnderlineEnabled(); - bool hasFontFace = defaultStyle.GetFontName() != styledText.mStyle.GetFontName(); - bool hasFontStyle = defaultStyle.GetFontStyle() != styledText.mStyle.GetFontStyle(); - bool hasFontSize = fabsf( defaultStyle.GetFontPointSize() - styledText.mStyle.GetFontPointSize() ) > GetRangedEpsilon( defaultStyle.GetFontPointSize(), styledText.mStyle.GetFontPointSize() ); - bool hasFontColor = defaultStyle.GetTextColor() != styledText.mStyle.GetTextColor(); - - bool hasSmooth = fabsf( defaultStyle.GetSmoothEdge() - styledText.mStyle.GetSmoothEdge() ) > GetRangedEpsilon( defaultStyle.GetSmoothEdge(), styledText.mStyle.GetSmoothEdge() ); - bool hasShadowColor = defaultStyle.GetShadowColor() != styledText.mStyle.GetShadowColor(); - bool hasShadowParams = defaultStyle.GetShadowOffset() != styledText.mStyle.GetShadowOffset(); - bool hasGlowColor = defaultStyle.GetGlowColor() != styledText.mStyle.GetGlowColor(); - bool hasGlowParams = fabsf( defaultStyle.GetGlowIntensity() - styledText.mStyle.GetGlowIntensity() ) > GetRangedEpsilon( defaultStyle.GetGlowIntensity(), styledText.mStyle.GetGlowIntensity() ); - bool hasOutlineColor = defaultStyle.GetOutlineColor() != styledText.mStyle.GetOutlineColor(); - bool hasOutlineParams = defaultStyle.GetOutlineThickness() != styledText.mStyle.GetOutlineThickness(); - - // Write font info. - if( hasFontFace || hasFontStyle || hasFontSize || hasFontColor ) - { - markupString += LESS_THAN + XHTML_FONT_TAG; - - if( hasFontFace ) - { - markupString += WHITE_SPACE + XHTML_FACE_PROPERTY + EQUAL + QUOTATION_MARK + styledText.mStyle.GetFontName() + QUOTATION_MARK; // face='' - } - - if( hasFontStyle ) - { - markupString += WHITE_SPACE + XHTML_STYLE_PROPERTY + EQUAL + QUOTATION_MARK + styledText.mStyle.GetFontStyle() + QUOTATION_MARK; // style='' - } - - if( hasFontSize ) - { - markupString += WHITE_SPACE + XHTML_SIZE_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetFontPointSize() ) + QUOTATION_MARK; // size='' - } - - if( hasFontColor ) - { - markupString += WHITE_SPACE + XHTML_COLOR_PROPERTY + EQUAL + QUOTATION_MARK + Vector4ToColorString( styledText.mStyle.GetTextColor() ) + QUOTATION_MARK; // color='' - } - - markupString += GREATER_THAN; - } // - - // Write italics. - if( isItalics ) - { - markupString += LESS_THAN + XHTML_I_TAG + GREATER_THAN; - } // - - // Write bold. - if( isBold ) - { - markupString += LESS_THAN + XHTML_B_TAG + GREATER_THAN; - } // - - // Write underline. - if( isUnderline ) - { - markupString += LESS_THAN + XHTML_U_TAG + GREATER_THAN; - } // - - // Write smooth. - if( hasSmooth ) - { - markupString += LESS_THAN + XHTML_SMOOTH_EDGE_TAG + WHITE_SPACE + XHTML_PARAM_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetSmoothEdge() ) + QUOTATION_MARK + GREATER_THAN; - } - - // Write shadow. - if( styledText.mStyle.IsShadowEnabled() ) - { - markupString += LESS_THAN + XHTML_SHADOW_TAG; - - if( hasShadowColor ) - { - markupString += WHITE_SPACE + XHTML_COLOR_PROPERTY + EQUAL + QUOTATION_MARK + Vector4ToColorString( styledText.mStyle.GetShadowColor() ) + QUOTATION_MARK; - } - - if( hasShadowParams ) - { - markupString += WHITE_SPACE + XHTML_PARAM_X_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetShadowOffset().x ) + QUOTATION_MARK; - markupString += WHITE_SPACE + XHTML_PARAM_Y_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetShadowOffset().y ) + QUOTATION_MARK; - } - - markupString += GREATER_THAN; - } - - // Write glow. - if( styledText.mStyle.IsGlowEnabled() ) - { - markupString += LESS_THAN + XHTML_GLOW_TAG; - - if( hasGlowColor ) - { - markupString += WHITE_SPACE + XHTML_COLOR_PROPERTY + EQUAL + QUOTATION_MARK + Vector4ToColorString( styledText.mStyle.GetGlowColor() ) + QUOTATION_MARK; // color='' - } - - if( hasGlowParams ) - { - markupString += WHITE_SPACE + XHTML_PARAM_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetGlowIntensity() ) + QUOTATION_MARK; // param='' - } - - markupString += GREATER_THAN; - } // - - // Write outline. - if( styledText.mStyle.IsOutlineEnabled() ) - { - markupString += LESS_THAN + XHTML_OUTLINE_TAG; - - if( hasOutlineColor ) - { - markupString += WHITE_SPACE + XHTML_COLOR_PROPERTY + EQUAL + QUOTATION_MARK + Vector4ToColorString( styledText.mStyle.GetOutlineColor() ) + QUOTATION_MARK; // color = '' - } - - if( hasOutlineParams ) - { - markupString += WHITE_SPACE + XHTML_PARAM_X_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetOutlineThickness().x ) + QUOTATION_MARK; // paramx='' - markupString += WHITE_SPACE + XHTML_PARAM_Y_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetOutlineThickness().y ) + QUOTATION_MARK; // paramy='' - } - - markupString += GREATER_THAN; - } // - - // Write text. - if( styledText.mText[0] == lineSeparator[0] ) - { - markupString += LESS_THAN + XHTML_BR_TAG + WHITE_SPACE + SLASH + GREATER_THAN; //
- } - else - { - markupString += styledText.mText.GetText(); - } - - // Write outline close tag. - if( styledText.mStyle.IsOutlineEnabled() ) - { - markupString += LESS_THAN + ( SLASH + XHTML_OUTLINE_TAG + GREATER_THAN ); //
- } - - // Write glow close tag. - if( styledText.mStyle.IsGlowEnabled() ) - { - markupString += LESS_THAN + ( SLASH + XHTML_GLOW_TAG + GREATER_THAN ); //
- } - - // Write shadow close tag. - if( styledText.mStyle.IsShadowEnabled() ) - { - markupString += LESS_THAN + ( SLASH + XHTML_SHADOW_TAG + GREATER_THAN ); // - } - - // Write smooth close tag. - if( hasSmooth ) - { - markupString += LESS_THAN + ( SLASH + XHTML_SMOOTH_EDGE_TAG + GREATER_THAN ); // - } - - // Write underline close tag. - if( isUnderline ) - { - markupString += LESS_THAN + ( SLASH + XHTML_U_TAG + GREATER_THAN ); //
- } - - // Write bold close tag. - if( isBold ) - { - markupString += LESS_THAN + ( SLASH + XHTML_B_TAG + GREATER_THAN ); //
- } - - // Write italics close tag. - if( isItalics ) - { - markupString += LESS_THAN + ( SLASH + XHTML_I_TAG + GREATER_THAN ); //
- } - - // Write font close tag. - if( hasFontFace || hasFontStyle || hasFontSize || hasFontColor ) - { - markupString += LESS_THAN + ( SLASH + XHTML_FONT_TAG + GREATER_THAN ); //
- } - } -} - -void SetTextStyle( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) -{ - if( !styledTextArray.empty() ) - { - const size_t size = styledTextArray.size() - 1; - SetTextStyleToRange( styledTextArray, style, mask, 0, size ); - } -} - -void SetTextStyle( const Text& text, StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) -{ - if( !text.IsEmpty() ) - { - const size_t size = text.GetLength(); - - for( size_t i = 0; i < size; ++i ) - { - StyledText styledText; - styledText.mText = Text( text[i] ); - styledText.mStyle = style; - - styledTextArray.push_back( styledText ); - } - - SetTextStyleToRange( styledTextArray, style, mask, 0, size - 1 ); - } -} - -void SetTextStyleToRange( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask, std::size_t begin, std::size_t end ) -{ - const size_t size = styledTextArray.size(); - DALI_ASSERT_ALWAYS( begin < size ); - DALI_ASSERT_ALWAYS( end < size ); - - for( StyledTextArray::iterator it = styledTextArray.begin() + std::min(begin, end), endIt = styledTextArray.begin() + std::max(begin, end) + 1; it != endIt; ++it ) - { - StyledText& styledText( *it ); - - styledText.mStyle.Copy( style, mask ); - } // for loop -} - -} // namespace MarkupProcessor - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/public-api/markup-processor/markup-processor.h b/dali-toolkit/public-api/markup-processor/markup-processor.h deleted file mode 100644 index 0a10996..0000000 --- a/dali-toolkit/public-api/markup-processor/markup-processor.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef __DALI_TOOLKIT_MARKUP_PROCESSOR_H__ -#define __DALI_TOOLKIT_MARKUP_PROCESSOR_H__ - -/* - * 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. - * - */ - -// EXTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -/** - * @brief Markup Processor enumerations, structures and functions. - * - * See the \link markup-processor Markup Processor \endlink page in the Programming Guide. - */ -namespace MarkupProcessor -{ - -/** - * @brief A pair of Dali::Text and Dali::TextStyle. - * - * mText is a Dali::Text object which can store text in different - * languages. mStyle is a Dali::TextStyle object which can store all - * text styling features provided by Dali::TextActor. - */ -struct StyledText -{ - /** - * @brief Constructor - */ - StyledText() - : mText(), - mStyle() - { - } - - /** - * @brief Constructor - * - * @param[in] text A Text object - * @param[in] style A Style object - */ - StyledText( const Text& text, const TextStyle& style ) - : mText( text ), - mStyle( style ) - { - } - - Text mText; ///< Store text. Could be a mix of different languages. - TextStyle mStyle; ///< Store the style for the text. -}; - -/** - * @brief This type defines a vector of StyledText. - * - * It's used to store a whole text with its style and set it to a - * Dali::Toolkit::TextView. It could be used in other UI - * Dali::Toolkit::Control classes which need text with style. - */ -typedef std::vector StyledTextArray; - -/** - * @brief Creates a text array with its style from a markup string. - * - * Refer to the \link markup-processor Markup Processor \endlink page in the Programming Guide - * to see the html-ish sintax and some examples. - * - * @param [in] markupString A string with style. - * @param [out] styledTextArray A text array split in characters, each one with its style. - * @param [in] scanForMarkup If true will check to see string contains markup, else assume not - */ -DALI_IMPORT_API void GetStyledTextArray( const std::string& markupString, StyledTextArray& styledTextArray, bool scanForMarkup ); - -/** - * @brief Creates a plain string from a text array (thus stripping the style meta). - * - * @param [in] styledTextArray A text array split in characters, each one with its style. - * @param [out] plainString A string without style. - */ -DALI_IMPORT_API void GetPlainString( const StyledTextArray& styledTextArray, std::string& plainString ); - -/** - * @brief Creates a markup string from a text array with its style. - * - * @param [in] styledTextArray A text array split in characters, each one with its style. - * @param [out] markupString A string with style. - */ -DALI_IMPORT_API void GetMarkupString( const StyledTextArray& styledTextArray, std::string& markupString ); - -/** - * @brief Sets a text style to the given text. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @param[in,out] styledTextArray The given text - * @param[in] style The given style - * @param[in] mask The bit mask. - */ -DALI_IMPORT_API void SetTextStyle( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask = TextStyle::ALL ); - -/** - * @brief Sets a text style to the given text. - * - * @see SetTextStyle( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) - * - * @param[in] text The input text. - * @param[out] styledTextArray The input text with the given style. - * @param[in] style The given style. - * @param[in] mask The bit mask. - */ -DALI_IMPORT_API void SetTextStyle( const Text& text, StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask = TextStyle::ALL ); - -/** - * @brief Sets a text style to a range of characters of the given text. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @param[in,out] styledTextArray The given text - * @param[in] style The given style - * @param[in] mask The bit mask. - * @param[in] begin The first character of the range. - * @param[in] end The last character of the range. - * @note It will assert if begin or end are out of range, or if begin > end. - */ -DALI_IMPORT_API void SetTextStyleToRange( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask, std::size_t begin, std::size_t end ); - -} // namespace MarkupProcessor - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_MARKUP_PROCESSOR_H__ diff --git a/dali-toolkit/public-api/shader-effects/carousel-effect.cpp b/dali-toolkit/public-api/shader-effects/carousel-effect.cpp index 9e360c2..49246cd 100644 --- a/dali-toolkit/public-api/shader-effects/carousel-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/carousel-effect.cpp @@ -69,7 +69,7 @@ CarouselEffect CarouselEffect::New() ShaderEffect shaderEffectCustom = ShaderEffect::New(vertexShader, "", - GeometryType( GEOMETRY_TYPE_IMAGE | GEOMETRY_TYPE_TEXT ), + GeometryType( GEOMETRY_TYPE_IMAGE ), ShaderEffect::GeometryHints( ShaderEffect::HINT_GRID | ShaderEffect::HINT_DEPTH_BUFFER )); // Pass ownership to CarouselEffect through overloaded constructor, So that it now has access to the diff --git a/dali-toolkit/public-api/shader-effects/ripple-effect.cpp b/dali-toolkit/public-api/shader-effects/ripple-effect.cpp index 9ebf825..bdbeaec 100644 --- a/dali-toolkit/public-api/shader-effects/ripple-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/ripple-effect.cpp @@ -94,7 +94,7 @@ RippleEffect RippleEffect::New() // Create the implementation, temporarily owned on stack Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( - vertexShader, imageFragmentShader, vertexShader, "", GeometryHints(HINT_GRID) ); + vertexShader, imageFragmentShader, GeometryType(GEOMETRY_TYPE_IMAGE), GeometryHints(HINT_GRID) ); /* Pass ownership to RippleEffect through overloaded constructor, So that it now has access to the Dali::ShaderEffect implementation */ diff --git a/dali-toolkit/public-api/shader-effects/shear-effect.cpp b/dali-toolkit/public-api/shader-effects/shear-effect.cpp index 51d64b7..fb0dd37 100644 --- a/dali-toolkit/public-api/shader-effects/shear-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/shear-effect.cpp @@ -71,7 +71,7 @@ ShearEffect ShearEffect::New() ShaderEffect shaderEffectCustom = Dali::ShaderEffect::New( vertexShader, "", - GeometryType( GEOMETRY_TYPE_IMAGE | GEOMETRY_TYPE_TEXT ), + GeometryType( GEOMETRY_TYPE_IMAGE ), GeometryHints( HINT_GRID )); // Pass ownership to ShearEffect through overloaded constructor, So that it now has access to the diff --git a/dali-toolkit/public-api/text/rendering-backend.h b/dali-toolkit/public-api/text/rendering-backend.h new file mode 100644 index 0000000..522a307 --- /dev/null +++ b/dali-toolkit/public-api/text/rendering-backend.h @@ -0,0 +1,45 @@ +#ifndef __DALI_TOOLKIT_RENDERING_BACKEND_H__ +#define __DALI_TOOLKIT_RENDERING_BACKEND_H__ + +/* + * Copyright (c) 2015 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 +{ + +// The type of text renderer required +enum RenderingType +{ + RENDERING_BASIC, ///< A bitmap-based reference implementation + RENDERING_SHARED_ATLAS ///< A bitmap-based solution where renderers can share a texture atlas +}; + +const unsigned int DEFAULT_RENDERING_BACKEND = RENDERING_SHARED_ATLAS; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_RENDERING_BACKEND_H__ diff --git a/dali-toolkit/styles/mobile/tizen-dark-theme.json b/dali-toolkit/styles/mobile/tizen-dark-theme.json new file mode 100644 index 0000000..8deaa50 --- /dev/null +++ b/dali-toolkit/styles/mobile/tizen-dark-theme.json @@ -0,0 +1,93 @@ +/* +Copyright (c) 2000-2014 Samsung Electronics Co., Ltd All Rights Reserved + +This file is part of Dali Toolkit + +PROPRIETARY/CONFIDENTIAL + +This software is the confidential and proprietary information of +SAMSUNG ELECTRONICS ("Confidential Information"). You shall not +disclose such Confidential Information and shall use it only in +accordance with the terms of the license agreement you entered +into with SAMSUNG ELECTRONICS. + +SAMSUNG make no representations or warranties about the suitability +of the software, either express or implied, including but not limited +to the implied warranties of merchantability, fitness for a particular +purpose, or non-infringement. SAMSUNG shall not be liable for any +damages suffered by licensee as a result of using, modifying or +distributing this software or its derivatives. +*/ + + + +//****************************************************************************** +// +// Default style theme for Tizen dark theme, The values should come from +// UX design document. +// +//****************************************************************************** + +{ + "styles": + { + "textlabel": + { + "font-family":"SamsungSans", + "font-style":"Regular" + }, + + "textlabel-font-size-0": + { + "point-size":8 + }, + "textlabel-font-size-1": + { + "point-size":10 + }, + "textlabel-font-size-2": + { + "point-size":15 + }, + "textlabel-font-size-3": + { + "point-size":19 + }, + "textlabel-font-size-4": + { + "point-size":25 + }, + + "textfield": + { + "font-family":"SamsungSans", + "font-style":"Regular" + }, + + "textfield-font-size-0": + { + "point-size":10 + }, + "textfield-font-size-1": + { + "point-size":10 + }, + "textfield-font-size-2": + { + "point-size":10 + }, + "textfield-font-size-3": + { + "point-size":10 + }, + "textfield-font-size-4": + { + "point-size":10 + }, + + "scrollview": + { + "overshoot-effect-color":"B018" + } + } +} diff --git a/dali-toolkit/styles/mobile/tizen-default-theme.json b/dali-toolkit/styles/mobile/tizen-default-theme.json new file mode 120000 index 0000000..bdcd8ba --- /dev/null +++ b/dali-toolkit/styles/mobile/tizen-default-theme.json @@ -0,0 +1 @@ +./tizen-dark-theme.json \ No newline at end of file diff --git a/dali-toolkit/styles/tizen-dark-theme.json b/dali-toolkit/styles/tizen-dark-theme.json index a771860..f850715 100644 --- a/dali-toolkit/styles/tizen-dark-theme.json +++ b/dali-toolkit/styles/tizen-dark-theme.json @@ -31,23 +31,17 @@ distributing this software or its derivatives. { "styles": { - "textinput": + "textlabel": { - "highlight-color":"F060", - "cut-and-paste-bg-color":"B061L41", - "cut-and-paste-pressed-color":"B061L41P", - "cut-and-paste-border-color":"B061L42", - "cut-and-paste-icon-color":"T126", - "cut-and-paste-icon-pressed-color":"T126P", - "cut-and-paste-text-color":"T1221", - "cut-and-paste-text-pressed-color":"T1221P", - "cut-button-position-priority":4, - "copy-button-position-priority":3, - "paste-button-position-priority":5, - "select-button-position-priority":1, - "select-all-button-position-priority":2, - "clipboard-button-position-priority":6, - "cursor-color":"F052" + "font-family":"HelveticaNeue", + "font-style":"Regular", + "point-size":18 + }, + "textfield": + { + "font-family":"HelveticaNeue", + "font-style":"Regular", + "point-size":18 }, "scrollview": { diff --git a/docs/content/images/background/BackgroundTextView.png b/docs/content/images/background/BackgroundTextLabel.png similarity index 100% rename from docs/content/images/background/BackgroundTextView.png rename to docs/content/images/background/BackgroundTextLabel.png diff --git a/docs/content/images/text-controls/ArabicBegin.png b/docs/content/images/text-controls/ArabicBegin.png new file mode 100644 index 0000000..56dcec1 Binary files /dev/null and b/docs/content/images/text-controls/ArabicBegin.png differ diff --git a/docs/content/images/text-controls/ArabicCenter.png b/docs/content/images/text-controls/ArabicCenter.png new file mode 100644 index 0000000..cbc77d3 Binary files /dev/null and b/docs/content/images/text-controls/ArabicCenter.png differ diff --git a/docs/content/images/text-controls/ArabicEnd.png b/docs/content/images/text-controls/ArabicEnd.png new file mode 100644 index 0000000..e35e1a8 Binary files /dev/null and b/docs/content/images/text-controls/ArabicEnd.png differ diff --git a/docs/content/images/text-controls/LatinBegin.png b/docs/content/images/text-controls/LatinBegin.png new file mode 100644 index 0000000..bec2507 Binary files /dev/null and b/docs/content/images/text-controls/LatinBegin.png differ diff --git a/docs/content/images/text-controls/LatinCenter.png b/docs/content/images/text-controls/LatinCenter.png new file mode 100644 index 0000000..ef5aa57 Binary files /dev/null and b/docs/content/images/text-controls/LatinCenter.png differ diff --git a/docs/content/images/text-controls/LatinEnd.png b/docs/content/images/text-controls/LatinEnd.png new file mode 100644 index 0000000..4e22cbc Binary files /dev/null and b/docs/content/images/text-controls/LatinEnd.png differ diff --git a/docs/content/images/text-controls/TextLabelCenter.png b/docs/content/images/text-controls/TextLabelCenter.png new file mode 100644 index 0000000..07558e3 Binary files /dev/null and b/docs/content/images/text-controls/TextLabelCenter.png differ diff --git a/docs/content/images/text-controls/TextLabelTopLeft.png b/docs/content/images/text-controls/TextLabelTopLeft.png new file mode 100644 index 0000000..ad8f492 Binary files /dev/null and b/docs/content/images/text-controls/TextLabelTopLeft.png differ diff --git a/docs/content/images/text-view/AlessBlessC.png b/docs/content/images/text-view/AlessBlessC.png deleted file mode 100644 index b4cc01c..0000000 Binary files a/docs/content/images/text-view/AlessBlessC.png and /dev/null differ diff --git a/docs/content/images/text-view/Black-Shadow.png b/docs/content/images/text-view/Black-Shadow.png deleted file mode 100644 index 899c8b3..0000000 Binary files a/docs/content/images/text-view/Black-Shadow.png and /dev/null differ diff --git a/docs/content/images/text-view/Blue-Glow.png b/docs/content/images/text-view/Blue-Glow.png deleted file mode 100644 index a9b6cfb..0000000 Binary files a/docs/content/images/text-view/Blue-Glow.png and /dev/null differ diff --git a/docs/content/images/text-view/Bold.png b/docs/content/images/text-view/Bold.png deleted file mode 100644 index 0f4f60e..0000000 Binary files a/docs/content/images/text-view/Bold.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix01.png b/docs/content/images/text-view/FontAppendix01.png deleted file mode 100644 index e600bf4..0000000 Binary files a/docs/content/images/text-view/FontAppendix01.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix02.png b/docs/content/images/text-view/FontAppendix02.png deleted file mode 100644 index 7b002b3..0000000 Binary files a/docs/content/images/text-view/FontAppendix02.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix03.png b/docs/content/images/text-view/FontAppendix03.png deleted file mode 100644 index 024a977..0000000 Binary files a/docs/content/images/text-view/FontAppendix03.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix04.png b/docs/content/images/text-view/FontAppendix04.png deleted file mode 100644 index 337a1d7..0000000 Binary files a/docs/content/images/text-view/FontAppendix04.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix05.png b/docs/content/images/text-view/FontAppendix05.png deleted file mode 100644 index 331daf4..0000000 Binary files a/docs/content/images/text-view/FontAppendix05.png and /dev/null differ diff --git a/docs/content/images/text-view/FreeSerifFont.png b/docs/content/images/text-view/FreeSerifFont.png deleted file mode 100644 index fa945ff..0000000 Binary files a/docs/content/images/text-view/FreeSerifFont.png and /dev/null differ diff --git a/docs/content/images/text-view/Italic.png b/docs/content/images/text-view/Italic.png deleted file mode 100644 index 61fe21e..0000000 Binary files a/docs/content/images/text-view/Italic.png and /dev/null differ diff --git a/docs/content/images/text-view/Red-Outline.png b/docs/content/images/text-view/Red-Outline.png deleted file mode 100644 index 794960b..0000000 Binary files a/docs/content/images/text-view/Red-Outline.png and /dev/null differ diff --git a/docs/content/images/text-view/Smooth-Text.png b/docs/content/images/text-view/Smooth-Text.png deleted file mode 100644 index 7ca0d3b..0000000 Binary files a/docs/content/images/text-view/Smooth-Text.png and /dev/null differ diff --git a/docs/content/images/text-view/Underline.png b/docs/content/images/text-view/Underline.png deleted file mode 100644 index 468cac3..0000000 Binary files a/docs/content/images/text-view/Underline.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-01.png b/docs/content/images/text-view/text-view-example-01.png deleted file mode 100644 index 3b8eacd..0000000 Binary files a/docs/content/images/text-view/text-view-example-01.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-02.png b/docs/content/images/text-view/text-view-example-02.png deleted file mode 100644 index 32a532a..0000000 Binary files a/docs/content/images/text-view/text-view-example-02.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-03.png b/docs/content/images/text-view/text-view-example-03.png deleted file mode 100644 index 0fd7457..0000000 Binary files a/docs/content/images/text-view/text-view-example-03.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-04.png b/docs/content/images/text-view/text-view-example-04.png deleted file mode 100644 index 5d0a2dc..0000000 Binary files a/docs/content/images/text-view/text-view-example-04.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-05.png b/docs/content/images/text-view/text-view-example-05.png deleted file mode 100644 index eccfde5..0000000 Binary files a/docs/content/images/text-view/text-view-example-05.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-06.png b/docs/content/images/text-view/text-view-example-06.png deleted file mode 100644 index 02a5f19..0000000 Binary files a/docs/content/images/text-view/text-view-example-06.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-07.png b/docs/content/images/text-view/text-view-example-07.png deleted file mode 100644 index 2326de4..0000000 Binary files a/docs/content/images/text-view/text-view-example-07.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-08.png b/docs/content/images/text-view/text-view-example-08.png deleted file mode 100644 index 0224b2e..0000000 Binary files a/docs/content/images/text-view/text-view-example-08.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view.png b/docs/content/images/text-view/text-view.png deleted file mode 100644 index 5d11c48..0000000 Binary files a/docs/content/images/text-view/text-view.png and /dev/null differ diff --git a/docs/content/main-page.h b/docs/content/main-page.h index ab76aa7..3802d3d 100644 --- a/docs/content/main-page.h +++ b/docs/content/main-page.h @@ -14,7 +14,7 @@ * - \link hello-world Hello World - explained \endlink * * \section Actors Actors - * - \link image-text-mesh-actor Image, Text and Mesh actors \endlink + * - \link image-mesh-actor Image and Mesh actors \endlink * - \link event-system Event Handling \endlink * - \link custom-actor Custom Actor \endlink * @@ -34,12 +34,10 @@ * - \link size-negotiation Size Negotiation \endlink * * \section UIControls UI Controls + * - \link text-label Text Label \endlink * - \link item-view Item View \endlink - * - \link text-view Text View \endlink - * - \link text-input Text Input \endlink * - \link scroll-view Scroll View \endlink * - \link size-negotiation-controls Size Negotiation for Controls \endlink - * - \link markup-processor Markup Processor \endlink * - \link type-registration Type Registration \endlink * - \link properties Properties \endlink * - \link background Background \endlink diff --git a/docs/content/programming-guide/background.h b/docs/content/programming-guide/background.h index 44972f4..a8dc916 100644 --- a/docs/content/programming-guide/background.h +++ b/docs/content/programming-guide/background.h @@ -16,15 +16,15 @@ control.SetBackgroundColor( Dali::Color::RED ); -This can be used for ALL existing controls like TextView as well: +This can be used for ALL existing controls like TextLabel as well: @code -Dali::Toolkit::TextView textView = Dali::Toolkit::TextView::New( "Hello World" ); -textView.SetBackgroundColor( Dali::Color::RED ); +Dali::Toolkit::TextLabel label = Dali::Toolkit::TextLabel::New( "Hello World" ); +label.SetBackgroundColor( Dali::Color::RED ); @endcode
-\image html BackgroundTextView.png +\image html BackgroundTextLabel.png
diff --git a/docs/content/programming-guide/image-text-mesh-actor.h b/docs/content/programming-guide/image-mesh-actor.h similarity index 66% rename from docs/content/programming-guide/image-text-mesh-actor.h rename to docs/content/programming-guide/image-mesh-actor.h index 014c95e..c579101 100644 --- a/docs/content/programming-guide/image-text-mesh-actor.h +++ b/docs/content/programming-guide/image-mesh-actor.h @@ -1,12 +1,11 @@ -/*! \page image-text-mesh-actor Image, Text and Mesh actors +/*! \page image-mesh-actor Image and Mesh actors * * *

Overview

- * The Dali::ImageActor, Dali::TextActor, Dali::MeshActor are inherited from Dali::Actor and provide means to display resources like Images, Text and Geometries (Triangle meshes) on the stage. + * The Dali::ImageActor & Dali::MeshActor are inherited from Dali::Actor and provide means to display resources like Images and Geometries (Triangle meshes) on the stage. * All the Dali::Actor methods can be called on them.
* * - ImageActor: An actor for displaying Images. It allows the developer to display a Dali::Image object on the stage.
- * - TextActor: An actor for displaying text.
* - MeshActor: An actor for displaying one or more mesh geometries. It may have children, which may be plain actors or other mesh actors.
* *

Image Actor

@@ -107,80 +106,6 @@ * @endcode * * - * - * - * - *

Text Actor

- * - * - *

Displaying Text

- * The text displayed by the text actor is initialised/set on construction, which can be changed later. - * - * @code - * Dali::TextActor myTextActor = Dali::TextActor::New("Hi"); - * std::string str("Hello"); - * if (myTextActor.GetText() != str) - * { - * myTextActor.SetText(str); - * } - * @endcode - * - * - *

Fonts

- * It's possible to specify a font for the text displayed by the text actor. - * @code - * Dali::Font freeSerif = Dali::Font::New("FreeSerif", 8); - * myTextActor.SetFont(freeSerif); - * @endcode - * - * - *

Ellipsis

- * It is possible to display an ellipsis in the TextActor when the text is truncated. - * @code - * std::string str("..."); - * if (myTextActor.GetEllipsis() != str) - * { - * myTextActor.SetEllipsis(str); - * } - * @endcode - * - *

Style

- * - * By calling the Dali::TextActor::SetTextStyle or by passing a Dali::TextStyle to the constructor, it's possible to define styling parameters such as color, font, size, outline, glow, shadow, italics or bold. - * @code - * TextStyle style; - * style.SetItalic( true ); - * - * myTextActor.SetTextStyle( style ); - * @endcode - * - * @see Dali::TextActor::SetTextStyle() - * - * It is possible to specify the text fit style for the text actor. The developer can specify whether the ellipsis should appear on the left, centre, or at the end - * @code - * // default : NONE - * myTextActor.SetTextFitStyle(TextUtilities::EllipsizeRight); - * @endcode - * - *

Loading state

- * It is possible to get the font loading status for the text and do processing accordingly. - * @code - * // observe text loading and do some processing when it's done - * if( Dali::ResourceLoadingSucceeded == myTextActor.GetLoadingState() ) - * { - * // text already loaded, Do the processing here - * OnTextFontLoaded(); - * } - * else - * { - * // text not yet loaded, Connect to the SignalTextAvailable signal and Do the processing when it occurs - * myTextActor.SignalTextAvailable().Connect(this, &MyClass::OnTextFontLoaded); - * } - * @endcode - * - * - * - * *

Mesh Actor

* *

Construction

diff --git a/docs/content/programming-guide/markup-processor.h b/docs/content/programming-guide/markup-processor.h deleted file mode 100644 index bd8ba9a..0000000 --- a/docs/content/programming-guide/markup-processor.h +++ /dev/null @@ -1,184 +0,0 @@ -/*! \page markup-processor Markup processor - * - *

Overview

- * - * Dali::Toolkit::MarkupProcessor functions provide mechanisms to build and modify a Dali::Toolkit::MarkupProcessor::StyledTextArray used to store text with style. - * - *

Build a styled text array from a markup string

- * - * Dali::Toolkit::MarkupProcessor::GetStyledTextArray() could be used to convert an html-ish markup string into a styled text array. This string uses html-ish tags to - * define the text's style as follows: - * - *
    - *
  • \e \\ Bold text. - * i.e. \Bold text\" - * \image html text-view/Bold.png - * - *
  • \e \\ Italic text. - * i.e. \Italic text\" - * \image html text-view/Italic.png - * - *
  • \e \\ Underlined text. - * i.e. \Underline text\" - * \image html text-view/Underline.png - * - *
  • \e \
    New line. - * - *
  • \e \\ Specifies font properties: - *
      - *
    • \e face The name of a font or font family. - *
    • \e style The style of a font. - *
    • \e size Font point size. @see Dali::PointSize. - *
    • \e color Font color. See the \ref color section for more details. - *
    - * - * i.e. \FreeSerif font\ - * \image html text-view/FreeSerifFont.png - * - *
  • \e \\ Specifies shadow properties. - *
      - *
    • \e paramx X offset. - *
    • \e paramy Y offset. - *
    • \e color Shadow color. See the \ref color section for more details. - *
    - * - * i.e. \Black shadow\ - * \image html text-view/Black-Shadow.png - * - * @see Dali::TextActor::SetShadow() - *

    - *
  • \e \\ Specifies glow properties. - *
      - *
    • \e param Glow around the text. - *
    • \e color Glow color. See the \ref color section for more details. - *
    - * - * i.e. \\Blue glow\\ - * \image html text-view/Blue-Glow.png - * - * @see Dali::TextActor::SetGlow() - *

    - *
  • \e \\ Specifies outline properties. - *
      - *
    • \e paramx X thickness. - *
    • \e paramy Y thickness. - *
    • \e color Outline color. See the \ref color section for more details. - *
    - * - * i.e. \Red outline\ - * \image html text-view/Red-Outline.png - * - * @see Dali::TextActor::SetOutline() - *

    - *
  • \e \\ Specify the smooth edge. - *
      - *
    • \e param Distance field. - *
    - * - * i.e. \Smooth text\ - * \image html text-view/Smooth-Text.png - * - * @see Dali::TextActor::SetSmoothEdge() - *
- * - * See also \ref color, \ref special_characters and \ref example for more details. - * - *

Get a markup string from a styled text array

- * - * Dali::Toolkit::MarkupProcessor::GetMarkupString() could be used to convert a styled text array into an html-ish markup string. - * - *

Modify a styled text array

- * - * Different functions are provided to modify whole or part of a styled text array with a given style. A mask could be used to modify only some properties of the style. - * - * @see Dali::Toolkit::MarkupProcessor::SetTextStyle( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) - * @see Dali::Toolkit::MarkupProcessor::SetTextStyle( const Text& text, StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) - * @see Dali::Toolkit::MarkupProcessor::SetTextStyleToRange( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask, std::size_t begin, std::size_t end ) - * - *

Appendix

- * \section color Color - * - * Different options could be used to define a color: - * - *
    - *
  • Hexadecimal with alpha channel. 0xAARRGGBB with the alpha channel in the most significant bits. - *
  • Hexadecimal without alpha channel. 0xRRGGBB. - *
  • Web color format (six or three digits). \#RRGGBB, \#RGB - *
  • Some colors could be defined with natural language: black, white, red, green, blue, yellow, magenta, cyan and \e transparent. - *
- * - * \section special_characters Special characters - * - * \< and \> characters are used to build the html-ish tags. To type them is needed to add a back slash character in front of them. - * @note in c and c++ the back slash is represented with a double back slash '\\\\'. - * - * i.e. text.SetText("a \\< b \\< c"); - * \image html text-view/AlessBlessC.png - * - * It transform any pair CR+LF new line characters into a single LF new line character. - * - * \section fonts Font Style, Weight and Smooth - * - * This appendix shows the differences and relations between the font style, the font weight, the smoothness and the italics. - * - * When a font is loaded, Dali uses different mechanisms to modify the render of glyphs.

- * i.e \Hello World\ produces the "Hello World" bellow. - * \image html text-view/FontAppendix01.png - * By adding the \ \ \ tags to the markup string or using the Dali::TextStyle::SetItalics(), Dali::TextStyle::SetWeight() or Dali::TextStyle::SetSmoothEdge() methods, - * Dali modifies how glyphs of the same font are rendered.

- * i.e \\Hello World\\ - * \image html text-view/FontAppendix02.png - * i.e \\Hello World\\ - * \image html text-view/FontAppendix03.png - * - * The smooth parameter can be used to adjust the thickness of the rendered glyphs.

- * i.e
\\Hello World\\
\

- * \Hello World\\

- * \\Hello World\\\

- * \\Hello World\\\

- * \\Hello World\\ - * - * \image html text-view/FontAppendix04.png - * - * All "Hello World" above have been rendered using the same font, saving some memory. Alternatively, the platform can provide fonts with different styles.
- * - * i.e. Samsung platform provides among others:
- * Samsung Sans:style=Light
- * Samsung Sans:style=Regular
- * Samsung Sans:style=Medium
- * - * \Hello World\\

- * \Hello World\\

- * \Hello World\ - * \image html text-view/FontAppendix05.png - * - * The three "Hello World" above have been rendered with three different fonts.
- * - * The fc-list command can be executed on the platform command line to check with fonts and which styles are supported. - * - * \section example Example - * - * \code - * const std::string text( "" - * "Italics: 기울임 꼴
" - * "Underline: 밑줄
" - * "Bold: 두꺼운
" - * "Font FreeSerif
" - * "Shadow: 그림자
" - * "Glow: 빛나다
" - * "Outline: 윤곽선
" - * "Smooth: 부드럽게
" - * "
" ); - * - * Toolkit::MarkupProcessor::StyledTextArray styledText; - * Toolkit::MarkupProcessor::GetStyledTextArray( text, styledText, true ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( styledText ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * - * \image html text-view/text-view.png - * Text generated with the example above. - */ diff --git a/docs/content/programming-guide/text-input.h b/docs/content/programming-guide/text-input.h deleted file mode 100644 index cc24e46..0000000 --- a/docs/content/programming-guide/text-input.h +++ /dev/null @@ -1,92 +0,0 @@ -/*! \page text-input Text Input - * - TextInput is a Dali::Actor which allows the input of text from an on-screen virtual keyboard or attached hardware keyboard. - - -

Basic Text Input Set-up

- - The below code creates a new TextInput - - @code - Dali::Toolkit::TextInput myTextInput; - myTextInput = Dali::Toolkit::TextInput::New(); - @endcode - - The following code sets the size and adds it to the stage - @code - myTextInput.SetParentOrigin(ParentOrigin::CENTER); - myTextInput.SetSize(stageWidth*0.25f, stageWidth*0.5f); - Stage::GetCurrent().Add(myTextInput); - @endcode - - For a TextInput to receive input from the keyboard it must be in edit mode. - - To enter edit mode the below call can be made. If the virtual on-screen keyboard is supported then it will be displayed. - Internally TextInput will set focus to this TextInput and key events will be sent to it. - - @code myTextInput.SetEditable(true);@endcode - - After this call the TextInput will receive any key press. If you have more than one TextInput the focus will change between them when the edit mode is - initiated on any Text Input. - - To automatically start edit mode when the TextInput is "tapped" you can call the following: - - @code myTextInput.SetEditOnTouch()@endcode - - You will then need to end edit mode by making the call below or swiping away the keyboard (Virtual On-screen Keyboard) - @code myTextInput.SetEditable(false);@endcode - - The call will hide the virtual keyboard if previously shown by Text Input. - - Then the input string as plain text can be retrieved using - @code Dali::Toolkit::TextInput::GetText()@endcode - -

Text Selection

- - The SetTextSelectable API when set to true enables text to be highlighted, once highlighted the text style can be changed, - the text can be cut, or copied, overwritten with new text or deleted. - - The user does a Long-Press on the text to get the option of text selection. - - @code Dali::Toolkit::TextInput::SetTextSelectable( true ) @endcode - -

Text Styling

- - In conjunction with TextView and the Markup processor, TextInput enables text to be styled. - - There are 3 ways to effect the text styling. - - SetActiveStyle, new input text is set to the Red glow style - @code - TextStyle style; - style.SetGlow ( true, Dali::Color::RED ); - myTextInput.SetActiveStyle( style, MarkupProcessor::GLOW ); - @endcode - - ApplyStyle, selected/highlighted text now has the Red glow style - @code - TextStyle style; - style.SetGlow ( true, Dali::Color::RED ); - myTextInput.ApplyStyle( style, MarkupProcessor::GLOW ); - @endcode - - ApplyStyleToAll, all text now has the Red glow style - @code - TextStyle style; - style.SetGlow ( true, Dali::Color::RED ); - myTextInput.ApplyStyleToAll( style, MarkupProcessor::GLOW ); - @endcode - - Then the input string with Mark-up defining the style can be retrieved using - @code Dali::Toolkit::TextInput::GetMarkupText()@endcode - This would be usefull if you wish to save the styled text the user has input so it can be re-displayed another time. - - Signals are emitted when style changes. - - See Dali::Toolkit::TextInput::StyleMask for available styling options. - - - - - */ - diff --git a/docs/content/programming-guide/text-label.h b/docs/content/programming-guide/text-label.h new file mode 100644 index 0000000..35754de --- /dev/null +++ b/docs/content/programming-guide/text-label.h @@ -0,0 +1,108 @@ +/*! \page text-label Text Label + * +\section overview Overview +The Dali::Toolkit::TextLabel is a Dali::Toolkit::Control which renders a short text string.\n +Text labels are lightweight, non-editable and do not respond to user input. + +\subsection basictextlabelusage Basic usage + +To display a TextLabel the TEXT property must be set using a UTF-8 string. + +\code +TextLabel label = TextLabel::New(); +label.SetProperty( TextLabel::Property::TEXT, "Hello World" ); +Stage::GetCurrent().Add( label ); +\endcode + +The label must also be added to the stage, or to an actor which is on the stage.\n +In this example the text-label will be automatically given a natural size i.e. large enough to fit the text.\n +The position of the label on-screen is dependent on the parent-origin and anchor-point properties: + + + + + + + + + + +
+ \image html TextLabelTopLeft.png + + \image html TextLabelCenter.png +
+ (ParentOrigin::TOP_LEFT, AnchorPoint::TOP_LEFT) + + (ParentOrigin::CENTER, AnchorPoint::CENTER) +
+ +\subsection fontselection Font Selection + +By default TextLabel will automatically select a suitable font from the platform.\n +Typically fonts do not support all scripts, for example Latin fonts often do not provide Arabic glyphs.\n +Therefore you should expect TextLabel to select different fonts for each script. + +Alternatively a font may be requested using eiter or all of FONT_FAMILY, FONT_STYLE, and POINT_SIZE properties: +\code +label.SetProperty( TextLabel::Property::FONT_FAMILY, "HelveticaNue" ); +label.SetProperty( TextLabel::Property::FONT_STYLE, "Regular" ); +label.SetProperty( TextLabel::Property::POINT_SIZE, 12.0f ); +\endcode +However the TextLabel will fall-back to using the default font, if the requested font does not support the required scripts. + +\subsection fontselection Text Alignment + +Wrapping can be enabled using the MULTI_LINE property:\n +\code +label.SetProperty( TextLabel::Property::MULTI_LINE, true ); +\endcode + +The text can be either aligned to the start, end, or center of the available area: +\code +label.SetProperty( TextLabel::Property::ALIGNMENT, "BEGIN" ); // "CENTER" or "END" +\endcode + + + + + + + + + + + + + + + + + + + + + + + +
+ Here is the "BEGIN" alignment shown for left-to-right (Latin) and right-to-left (Arabic) scripts: +
+ \image html LatinBegin.png + + \image html ArabicBegin.png +
+ Here is the "CENTER" alignment shown for left-to-right (Latin) and right-to-left (Arabic) scripts: +
+ \image html LatinCenter.png + + \image html ArabicCenter.png +
+ Here is the "END" alignment shown for left-to-right (Latin) and right-to-left (Arabic) scripts: +
+ \image html LatinEnd.png + + \image html ArabicEnd.png +
+ +*/ diff --git a/docs/content/programming-guide/text-view.h b/docs/content/programming-guide/text-view.h deleted file mode 100644 index b64b895..0000000 --- a/docs/content/programming-guide/text-view.h +++ /dev/null @@ -1,447 +0,0 @@ -/*! \page text-view Text View - * - * \section overview Overview - * - * The Dali::Toolkit::TextView class is a UI Dali::Toolkit::Control designed to extend the capabilities of the basic Dali::TextActor. - * It provides support for multi-line wrapping, multi-language font detection, text alignment, scrolling and styling. - * - * Dali::Toolkit::TextView also provides text layout information which could be used in other UI Dali::Toolkit::Control classes or other applications. - * - * \section multiline Multi-line wrapping - * - * Different multi-line and exceed policies could be set to layout the given text. - * - * Both multi-line and exceed policies work together. - * Dali::Toolkit::TextView::MultilinePolicy policies define how to wrap a line if it doesn't fit inside the boundary's width - * whereas Dali::Toolkit::TextView::ExceedPolicy policies define what to do if the wrapped text is bigger than the text view's boundary. - * - * i.e. \e SplitByWord could be used as 'multi-line policy' to wrap a line if it's too long. If one of the words is longer than the text-view's width, \e Split could be - * used as 'width exceed policy' to split a word in different lines. If the text is too long and exceeds the text-view's height, \e EllipsizedEnd could be - * used as 'height exceed policy' to render only the text which fits inside the boundaries of the text-view. - * - * @see more \ref examples. - * - * \subsection multiline_policies Multi-line policies - * - *
    - *
  • Split by new line character. - * Text will be wrapped when an end of line \\n or \
    is found. - * - *
  • Split by word. - * Text will be wrapped when an end of line \\n or \
    is found or if the text doesn't fit in the text view width. - * In that case, some words will be moved to a new line. - * - *
  • Split by character. - * Text will be wrapped when an end of line \\n or \
    is found or if the text doesn't fit in the text view width. - * In that case, words which don't fit will be wrapped in two and the remaining text moved to a new line. - *
- * Dali::Toolkit::TextView::SplitByNewLineChar is set by default. - * - * \subsection exceed_policies Exceed policies - * - *
    - *
  • Original size. - * Text will be displayed with its original size. - * - *
  • Fade. - * Text will be faded out. - * - *
  • Split. - * Text will be wrapped and moved to a new line. - * - *
  • Shrink to fit. - * Text will be shrunk to fit in the text view's boundary. - * - *
  • Ellipsize at the end. - * Text will be truncated to fit in the text view's boundary and the ellipsize text will be added. ( '...' by default). - *
- * Dali::Toolkit::TextView::Original is set by default. - * - * @see Dali::Toolkit::TextView::SetMultilinePolicy - * @see Dali::Toolkit::TextView::SetWidthExceedPolicy - * @see Dali::Toolkit::TextView::SetHeightExceedPolicy - * @see Dali::Toolkit::TextView::SetFadeBoundary - * @see Dali::Toolkit::TextView::SetEllipsizeText - * - * @note Multiple combinations are possible but not all of them are already implemented. - * @see \ref exceed_policies_combinations table to check which combinations are implemented - * - * \section scroll Scroll - * - * Text could be scrolled if it exceeds the boundaries of the text-view. - * - * @see Dali::Toolkit::TextView::SetScrollEnabled - * @see Dali::Toolkit::TextView::SetScrollPosition - * - * \section line_height_spacing Line height spacing - * - * The default space between lines could be modified by setting an offset with Dali::Toolkit::TextView::SetLineHeightOffset(). - * - *

Font support and multi-language detection

- * - * Dali::Toolit::TextView uses the font specified in the styled text array to display the given text. - * - * See \link markup-processor Markup Processor \endlink for more details on how to create styling markup strings and styled text arrays. - * - * To support multi-language texts, text-view does the following actions per character: - *
    - *
  • Check if there is a font defined in the styled text array. - *
  • If there isn't, try to use the default platform font. - *
  • Check if the character is supported by the font. - *
  • If isn't, find the most suitable font for the character. - *
- * - * \section text_alignment Text alignment and justification - * - * Dali::Toolkit::TextView provides a method to align the whole text inside the text view's boundary as well as a method to justify each line - * inside the text. - * - * The Dali::Toolkit::Alignment::Type is used to align the whole text in the text view's area. - * A text could be horizontally aligned (left, center, right) and/or vertically aligned (top, center, bottom). - * Dali::Toolkit::Alignment::HorizontalCenter | Dali::Toolkit::Alignment::VerticalCenter is set by default. - * - * The Dali::Toolkit::TextView::LineJustification is used to justify each line inside the text (left, center, right, justified). - * Dali::Toolkit::TextView::Left is set by default. - * - * @see Dali::Toolkit::TextView::SetTextAlignment @see Dali::Toolkit::TextView::SetLineJustification - * - * \section text_styling Text styling - * - * Dali::Toolkit::TextView supports all text styling features provided by Dali::TextActor (font type, color, size, outline, etc). - * - * Different techniques are provided to set or modify the text view's style: - * - *
    - *
  • By setting a Dali::Toolkit::MarkupProcessor::StyledTextArray with the Dali::Toolkit::TextView::SetText(const MarkupProcessor::StyledTextArray& text) method. - *
  • By setting a new Dali::TextStyle to the current text with the Dali::Toolkit::TextView::SetStyleToCurrentText() method. - *
  • By setting an html-ish markup string which contains both text and style with the Dali::Toolkit::TextView::SetText(const std::string& text) method. - @note By default the style markup processor is disabled. @see Dali::Toolkit::TextView::SetMarkupProcessingEnabled to enable the markup processing. - *
- * - * See \link markup-processor Markup Processor \endlink for more details on how to create styling markup strings and styled text arrays. - * - * \section retrieve Retrieve text layout information - * - * The Dali::Toolkit::TextView::GetTextLayoutInfo() retrieves how the input text has been laid out. - * - * For each character it retrieves its size and position, visibility, etc. @see Dali::Toolkit::TextView::CharacterLayoutInfo. - * - * For each laid-out line it retrieves the index of the first character of the line, size, etc. @see Dali::Toolkit::TextView::LineLayoutInfo. - * - * \section appendix Appendix - * \subsection examples Examples - * - * The following examples show how to use TextView. The grey square is an actor which has been added just to show the size of the text-view. - * - * Creation of a text view actor with all its parameters by default. - * \code - * Toolkit::TextView textView = Toolkit::TextView::New( "Hello world!" ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * - * This example wraps the text in lines only when a \\n character is found. The size of the text-view will be automatically resized to fit the whole text inside. - * \code - * const std::string text( "" - * "Lorem ipsum dolor sit amet, consectetur adipisicing elit,\n" - * "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - * "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( "" ); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Original ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::Original ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-01.png - * - * This example wraps the lines by the next word when it exceeds the width of the text-view. The height exceed policy is set to \e Original so it may exceed the height of the text-view. - * - * \code - * const std::string text( "" - * "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " - * "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - * "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( "" ); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 125.f ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Original ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::Original ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-02.png - * - * This example wraps the lines by the next word when it exceeds the width of the text-view. If a word is bigger than the text-view's width, it splits the word. If the text exceeds the height of the text-view, the text is ellipsized. - * - * \code - * const std::string text( "" - * "Loremipsumdolorsitametconsectetur adipisicing elit,\n" - * "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - * "" ); - * const std::string ellipsizeText( "..." ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( "" ); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetEllipsizeText( ellipsizeText ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 125.f ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Split ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::EllipsizeEnd ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-03.png - * - * This example is similar to the one above but the ellipsized text has been set to "" so nothing is shown. - * - * \code - * const std::string text( "" - * "Loremipsumdolorsitametconsecteturadipisicingelit" - * "seddoeiusmodtemporincididuntutlaboreetdoloremagnaaliqua." - * "" ); - * const std::string ellipsizeText( "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( "" ); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetEllipsizeText( ellipsizeText ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 125.f ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Split ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::EllipsizeEnd ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-04.png - * - * This example shows how to fade the text out when it exceeds the boundaries of the text-view. - * - * \code - * const std::string text( "" - * "Lorem ipsum dolor sit amet,\n" - * "consectetur adipisicing elit,\n" - * "sed do eiusmod tempor incididunt\n" - * "ut labore et dolore magna aliqua." - * "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New(); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 100.f ); - * - * Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( 10 ), PixelSize( 10 ), PixelSize( 10 ), PixelSize( 10 ) ); - * textView.SetFadeBoundary( fadeBoundary ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Fade ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::Fade ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-05.png - * - * This example enables the scroll feature. The screen-shots show three different images of the same text in different scroll positions. - * - * \code - * const std::string text( "" - * "Lorem ipsum dolor sit amet, consectetur adipisicing elit,\n" - * "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - * "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New(); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 60.f ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Original ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::Original ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * textView.SetScrollEnabled( true ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-06.png - * \image html text-view/text-view-example-07.png - * \image html text-view/text-view-example-08.png - * - * See \link markup-processor Markup Processor \endlink \ref example for more styling markup string examples. - * - * \subsection exceed_policies_combinations Implemented exceed policies combinations - * - * The following tables show which exceed policies are implemented for each multi-line policy. Each column has one width exceed policy (Original, Fade, Split, ShrinkToFit and EllipsizeEnd), - * each row has one height exceed policy (Original, Fade, ShrinkToFit and EllipsizeEnd). - * - * @note The Split value is not valid for the height exceed policy. - * - * \htmlonly - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
SplitByNewLineChar
Width exceed policies
OriginalFadeSplitShrinkToFitEllipsizeEnd
Height
exceed
policies
Original
Fade
ShrinkToFit
EllipsizeEnd
- * \endhtmlonly - * - * \n - * - * \htmlonly - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
SplitByWord
Width exceed policies
OriginalFadeSplitShrinkToFitEllipsizeEnd
Height
exceed
policies
Original
Fade
ShrinkToFit
EllipsizeEnd
- * \endhtmlonly - * - * \n - * - * \htmlonly - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
SplitByChar
Width exceed policies
OriginalFadeSplitShrinkToFitEllipsizeEnd
Height
exceed
policies
Original
Fade
ShrinkToFit
EllipsizeEnd
- * \endhtmlonly - */ - diff --git a/packaging/dali-toolkit-mobile.spec b/packaging/dali-toolkit-mobile.spec new file mode 100644 index 0000000..79cadd4 --- /dev/null +++ b/packaging/dali-toolkit-mobile.spec @@ -0,0 +1,108 @@ +Name: dali-toolkit +Summary: The OpenGLES Canvas Core Library Toolkit +Version: 1.0.34 +Release: 1 +Group: System/Libraries +License: Apache-2.0 +URL: https://review.tizen.org/git/?p=platform/core/uifw/dali-toolkit.git;a=summary +Source0: %{name}-%{version}.tar.gz + +%define dali_profile MOBILE + +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +Requires: dali +# Do NOT put an adaptor here - it is an application choice which adaptor to use +BuildRequires: pkgconfig +BuildRequires: pkgconfig(dlog) +BuildRequires: boost-devel +BuildRequires: pkgconfig(dali) +BuildRequires: pkgconfig(dali-core) + +%description +The OpenGLES Canvas Core Library Toolkit - a set of controls that provide +user interface functionality. + +############################## +# devel +############################## +%package devel +Summary: Application development package for the OpenGLES Canvas toolkit +Group: Development/Building +Requires: %{name} = %{version}-%{release} +Requires: boost-devel + +%description devel +Application development package for the OpenGLES Canvas toolkit - headers and package config + +############################## +# Preparation +############################## +%prep +%setup -q +%define dali_data_rw_dir /opt/usr/share/dali/ +%define dali_data_ro_dir /usr/share/dali/ +%define dali_toolkit_image_files %{dali_data_ro_dir}/toolkit/images/ +%define dali_toolkit_sound_files %{dali_data_ro_dir}/toolkit/sounds/ +%define dali_toolkit_style_files %{dali_data_ro_dir}/toolkit/styles/ +%define dev_include_path %{_includedir} + +############################## +# Build +############################## +%build +PREFIX="/usr" +CXXFLAGS+=" -Wall -g -Os -fPIC -fvisibility-inlines-hidden -fdata-sections -ffunction-sections " +LDFLAGS+=" -Wl,--rpath=$PREFIX/lib -Wl,--as-needed -Wl,--gc-sections -Wl,-Bsymbolic-functions " + +libtoolize --force +cd %{_builddir}/dali-toolkit-%{version}/build/tizen +autoreconf --install +DALI_DATA_RW_DIR="%{dali_data_rw_dir}" ; export DALI_DATA_RW_DIR +DALI_DATA_RO_DIR="%{dali_data_ro_dir}" ; export DALI_DATA_RO_DIR +%configure --enable-profile=%{dali_profile} +make %{?jobs:-j%jobs} + +############################## +# Installation +############################## +%install +rm -rf %{buildroot} +cd build/tizen +%make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}" + +# LICENSE +mkdir -p %{buildroot}/usr/share/license +cp -af %{_builddir}/%{name}-%{version}/LICENSE %{buildroot}/usr/share/license/%{name} + +############################## +# Post Install +############################## +%post +/sbin/ldconfig +exit 0 + +############################## +# Post Uninstall +############################## +%postun +/sbin/ldconfig +exit 0 + +############################## +# Files in Binary Packages +############################## +%files +%manifest dali-toolkit.manifest-smack +%defattr(-,root,root,-) +%{_libdir}/lib%{name}.so* +%{dali_toolkit_image_files}/* +%{dali_toolkit_sound_files}/* +%{dali_toolkit_style_files}/* +%{_datadir}/license/%{name} + +%files devel +%defattr(-,root,root,-) +%{dev_include_path}/%{name}/* +%{_libdir}/pkgconfig/*.pc + diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index e38d022..b0e9668 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -7,6 +7,8 @@ License: Apache-2.0 URL: https://review.tizen.org/git/?p=platform/core/uifw/dali-toolkit.git;a=summary Source0: %{name}-%{version}.tar.gz +%define dali_profile MOBILE + Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig Requires: dali @@ -16,7 +18,6 @@ BuildRequires: pkgconfig(dlog) BuildRequires: boost-devel BuildRequires: pkgconfig(dali) BuildRequires: pkgconfig(dali-core) -BuildRequires: fribidi-devel %description The OpenGLES Canvas Core Library Toolkit - a set of controls that provide @@ -59,7 +60,7 @@ cd %{_builddir}/dali-toolkit-%{version}/build/tizen autoreconf --install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" ; export DALI_DATA_RW_DIR DALI_DATA_RO_DIR="%{dali_data_ro_dir}" ; export DALI_DATA_RO_DIR -%configure +%configure --enable-profile=%{dali_profile} make %{?jobs:-j%jobs} ############################## diff --git a/plugins/dali-script-v8/file.list b/plugins/dali-script-v8/file.list index d87322f..91b3661 100644 --- a/plugins/dali-script-v8/file.list +++ b/plugins/dali-script-v8/file.list @@ -12,14 +12,11 @@ script_v8_plugin_src_files = \ $(v8_plugin_dir)/actors/actor-wrapper.cpp \ $(v8_plugin_dir)/actors/actor-api.cpp \ $(v8_plugin_dir)/actors/layer-api.cpp \ - $(v8_plugin_dir)/actors/text-actor-api.cpp \ $(v8_plugin_dir)/actors/image-actor-api.cpp \ $(v8_plugin_dir)/actors/camera-actor-api.cpp \ $(v8_plugin_dir)/actors/mesh-actor-api.cpp \ $(v8_plugin_dir)/actors/renderable-actor-api.cpp \ $(v8_plugin_dir)/constants/constants-wrapper.cpp \ - $(v8_plugin_dir)/text/font-api.cpp \ - $(v8_plugin_dir)/text/font-wrapper.cpp \ $(v8_plugin_dir)/animation/animation-api.cpp \ $(v8_plugin_dir)/animation/animation-wrapper.cpp \ $(v8_plugin_dir)/animation/path-api.cpp \ diff --git a/plugins/dali-script-v8/src/actors/actor-api.cpp b/plugins/dali-script-v8/src/actors/actor-api.cpp index 7237547..926c5cd 100644 --- a/plugins/dali-script-v8/src/actors/actor-api.cpp +++ b/plugins/dali-script-v8/src/actors/actor-api.cpp @@ -19,7 +19,7 @@ #include "actor-api.h" // EXTERNAL INCLUDES -#include +#include // INTERNAL INCLUDES #include @@ -42,11 +42,11 @@ Actor GetActor( v8::Isolate* isolate, const v8::FunctionCallbackInfo& } //unanmed namespace -namespace TextViewApi +namespace TextLabelApi { Actor New( const v8::FunctionCallbackInfo< v8::Value >& args ) { - return Dali::Toolkit::TextView::New(); + return Dali::Toolkit::TextLabel::New(); } } @@ -486,7 +486,7 @@ void ActorApi::IsKeyboardFocusable( const v8::FunctionCallbackInfo& a * * @for Actor * @method getActorType - * @return {String} Actor, ImageActor, TextActor, MeshActor, Layer, CameraActor ... + * @return {String} Actor, ImageActor, MeshActor, Layer, CameraActor ... */ void ActorApi::GetActorType( const v8::FunctionCallbackInfo& args ) { diff --git a/plugins/dali-script-v8/src/actors/actor-api.h b/plugins/dali-script-v8/src/actors/actor-api.h index b1dfd4b..509c976 100644 --- a/plugins/dali-script-v8/src/actors/actor-api.h +++ b/plugins/dali-script-v8/src/actors/actor-api.h @@ -28,7 +28,7 @@ namespace Dali namespace V8Plugin { -namespace TextViewApi +namespace TextLabelApi { /** * Temporary TextView constructor diff --git a/plugins/dali-script-v8/src/actors/actor-wrapper.cpp b/plugins/dali-script-v8/src/actors/actor-wrapper.cpp index 7613178..112dfeb 100644 --- a/plugins/dali-script-v8/src/actors/actor-wrapper.cpp +++ b/plugins/dali-script-v8/src/actors/actor-wrapper.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -40,11 +39,10 @@ namespace V8Plugin v8::Persistent ActorWrapper::mActorTemplate; v8::Persistent ActorWrapper::mImageActorTemplate; -v8::Persistent ActorWrapper::mTextActorTemplate; v8::Persistent ActorWrapper::mMeshActorTemplate; v8::Persistent ActorWrapper::mCameraActorTemplate; v8::Persistent ActorWrapper::mLayerActorTemplate; -v8::Persistent ActorWrapper::mTextViewTemplate; +v8::Persistent ActorWrapper::mTextLabelTemplate; namespace { @@ -65,11 +63,10 @@ const ActorTemplate ActorTemplateLookup[]= { { &ActorWrapper::mActorTemplate }, // ACTOR { &ActorWrapper::mImageActorTemplate }, // IMAGE_ACTOR - { &ActorWrapper::mTextActorTemplate }, // TEXT_ACTOR { &ActorWrapper::mMeshActorTemplate }, // MESH_ACTOR { &ActorWrapper::mLayerActorTemplate }, // LAYER_ACTOR { &ActorWrapper::mCameraActorTemplate}, // CAMERA_ACTOR - { &ActorWrapper::mTextViewTemplate } + { &ActorWrapper::mTextLabelTemplate } }; /** @@ -80,10 +77,9 @@ enum ActorApiBitMask ACTOR_API = 1 << 0, RENDERABLE_ACTOR_API = 1 << 1, IMAGE_ACTOR_API = 1 << 2, - TEXT_ACTOR_API = 1 << 3, - MESH_ACTOR_API = 1 << 4, - LAYER_API = 1 << 5, - CAMERA_ACTOR_API = 1 << 6, + MESH_ACTOR_API = 1 << 3, + LAYER_API = 1 << 4, + CAMERA_ACTOR_API = 1 << 5, }; /** @@ -104,11 +100,10 @@ const ActorApiStruct ActorApiLookup[]= { {"Actor", ActorWrapper::ACTOR, ActorApi::New, ACTOR_API }, {"ImageActor", ActorWrapper::IMAGE_ACTOR, ImageActorApi::New, ACTOR_API | RENDERABLE_ACTOR_API | IMAGE_ACTOR_API }, - {"TextActor", ActorWrapper::TEXT_ACTOR, TextActorApi::New, ACTOR_API | RENDERABLE_ACTOR_API | TEXT_ACTOR_API }, {"MeshActor", ActorWrapper::MESH_ACTOR, MeshActorApi::New, ACTOR_API | RENDERABLE_ACTOR_API | MESH_ACTOR_API }, {"Layer", ActorWrapper::LAYER_ACTOR, LayerApi::New, ACTOR_API | LAYER_API }, {"CameraActor",ActorWrapper::CAMERA_ACTOR, CameraActorApi::New, ACTOR_API | CAMERA_ACTOR_API }, - {"TextView", ActorWrapper::TEXT_VIEW, TextViewApi::New, ACTOR_API }, + {"TextLabel", ActorWrapper::TEXT_LABEL, TextLabelApi::New, ACTOR_API }, }; @@ -148,7 +143,7 @@ Actor CreateActor( const v8::FunctionCallbackInfo< v8::Value >& args, else { // run the constructor for this type of actor so it can pull out - // custom parameters, e.g. new TextActor("hello world"); or ImageActor( MyImage ); + // custom parameters, e.g. new ImageActor( MyImage ); actor = (ActorApiLookup[actorType].constructor)( args ); } return actor; @@ -314,40 +309,6 @@ const ActorFunctions ActorFunctionTable[]= // ignore GetFadeInDuration use imageActor.fadeInDuration //{ "GetCurrentImageSize", ImageActorApi::GetCurrentImageSize, IMAGE_ACTOR_API }, - - /************************************** - * Text Actor API (in order of text-actor.h) - **************************************/ - //ignore SetText use textActor.text - { "SetToNaturalSize", TextActorApi::SetToNaturalSize, TEXT_ACTOR_API }, - // ignore GetFont use textActor.font - // ignore SetFont use textActor.font - // ignore SetGradient use textActor.gradientColor - // ignore GetGradient textActor.gradientColor - // ignore SetGradientStartPoint use textActor.gradientStartPoint - // ignore GetGradientStartPoint textActor.gradientStartPoint - // ignore SetGradientEndPoint use textActor.gradientEndPoint - // ignore GetGradientEndPoint textActor.gradientEndPoint - // @todo? SetTextStyle ( can use individual properties as a work around ) - // @todo? GetTextStyle ( can use individual properties as a work around ) - // ignore SetTextColor use textActor.textColor - // ignore GetTextColor use textActor.textColor - // ignore SetSmoothEdge use textActor.smoothEdge - // ignore SetOutline use textActor.outLineEnable, outlineColor, thicknessWidth - // ignore SetGlow use textActor.glowEnable, glowColor, glowIntensity - // ignore SetShadow use textActor.shadowEnable, shadowColor, shadowOffset, shadowSize - // ignore SetItalics use textActor.italicsAngle ? - // ignore GetItalics @todo add italics flag? or just stick with angle - // ignore GetItalicsAngle use textActor.italicsAngle - // ignore SetUnderline use textActor.underline - // ignore GetUnderline use textActor.underline - // ignore SetWeight use textActor.weight - // ignore GetWeight use textActor.weight - // ignore SetFontDetectionAutomatic use textActor.fontDetectionAutomatic - // ignore IsFontDetectionAutomatic use textActor.fontDetectionAutomatic - // ignore GetLoadingState text is loaded synchronously - // ignore TextAvailableSignal text is loaded synchronously - /************************************** * Mesh Actor API (in order of mesh-actor.h) **************************************/ @@ -489,7 +450,7 @@ void ActorWrapper::NewActor( const v8::FunctionCallbackInfo< v8::Value >& args) return; } - // find out the callee function name...e.g. TextActor, ImageActor, MeshActor + // find out the callee function name...e.g. ImageActor, MeshActor v8::Local callee = args.Callee(); v8::Local v8String = callee->GetName(); std::string typeName = V8Utils::v8StringToStdString( v8String ); diff --git a/plugins/dali-script-v8/src/actors/actor-wrapper.h b/plugins/dali-script-v8/src/actors/actor-wrapper.h index 76eee47..06b2e06 100644 --- a/plugins/dali-script-v8/src/actors/actor-wrapper.h +++ b/plugins/dali-script-v8/src/actors/actor-wrapper.h @@ -48,11 +48,10 @@ public: UNKNOWN_ACTOR = -1, ACTOR = 0, IMAGE_ACTOR =1, - TEXT_ACTOR =2, - MESH_ACTOR =3, - LAYER_ACTOR =4, - CAMERA_ACTOR =5, - TEXT_VIEW =6 + MESH_ACTOR =2, + LAYER_ACTOR =3, + CAMERA_ACTOR =4, + TEXT_LABEL =5 }; /** @@ -90,11 +89,10 @@ public: // The Actor ObjectTemplates. static v8::Persistent mActorTemplate; static v8::Persistent mImageActorTemplate; - static v8::Persistent mTextActorTemplate; static v8::Persistent mMeshActorTemplate; static v8::Persistent mCameraActorTemplate; static v8::Persistent mLayerActorTemplate; - static v8::Persistent mTextViewTemplate; + static v8::Persistent mTextLabelTemplate; /** * @return the wrapped actor diff --git a/plugins/dali-script-v8/src/actors/text-actor-api.cpp b/plugins/dali-script-v8/src/actors/text-actor-api.cpp deleted file mode 100644 index 483b345..0000000 --- a/plugins/dali-script-v8/src/actors/text-actor-api.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2015 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 "text-actor-api.h" - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - - -namespace Dali -{ - -namespace V8Plugin -{ - -namespace //unnamed name space -{ - -struct TextActorParametersInternal -{ - TextActorParametersInternal() - : fontDetection( true ) - { - } - bool fontDetection; - Font font; -}; - - -TextActor GetTextActor( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - HandleWrapper* handleWrapper = HandleWrapper::Unwrap( isolate, args.This() ); - return TextActor::DownCast( handleWrapper->mHandle ); -} - - -void GetTextOptions( v8::Isolate* isolate, - v8::Local options, - TextActorParametersInternal& textParams ) -{ - // fontDetection: true / false ( default true) - // font: dali font object - v8::HandleScope handleScope( isolate ); - - if( options->IsObject() ) - { - v8::Local obj = options->ToObject(); - - v8::Local fontDetect = obj->Get( v8::String::NewFromUtf8( isolate, "fontDetection" ) ); - if( fontDetect->IsBoolean() ) - { - - textParams.fontDetection = fontDetect->ToBoolean()->Value(); - } - - v8::Local fontValue = obj->Get( v8::String::NewFromUtf8( isolate, "font" ) ); - if( fontValue->IsObject() ) - { - textParams.font = FontApi::GetFont( isolate, fontValue ); - } - - } -} - -} - -/** - * @constructor - * @for TextActor - * @method TextActor - * @param {String} text - * @param {Object} [textOptions] data - * Options text options struct - * @param {Boolean} [textOptions.fontDetection] - * if true the fontDetection is used to make sure the text is displayed. - * E.g. if the current font used by the text-actor does not support certain characters - * it will find a new font that does. Default = true. - * @param {Object} [textOptions.font] - * Dali font object - * @return {Object} TextActor - */ -Actor TextActorApi::New( const v8::FunctionCallbackInfo& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - // - // TextActor( text, options (optional) ) - // - // options = - // { - // font: font - // fontDetection: true / false ( default true) - // } - - // get the text (if passed in) - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - - TextActorParametersInternal params; - TextActor actor; - - GetTextOptions( isolate, args[1], params ); - - TextStyle style; - - if( params.font ) - { - style.SetFontName( params.font.GetName() ); - style.SetFontStyle( params.font.GetStyle() ); - style.SetFontPointSize( PointSize(params.font.GetPointSize())); - - } - TextActorParameters textActorParameters( style, params.fontDetection? TextActorParameters::FONT_DETECTION_OFF:TextActorParameters::FONT_DETECTION_ON ); - - actor = TextActor::New( text, textActorParameters ); - - return actor; - -} - -/** - * Set text to the natural size of the text string. - * - * After this method the text actor always uses the natural size of the text - * when SetText is called unless SetSize is called to override the size. - * - * @for TextActor - * @method setToNaturalSize - */ -void TextActorApi::SetToNaturalSize( const v8::FunctionCallbackInfo& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - TextActor textActor = GetTextActor( isolate, args ); - textActor.SetToNaturalSize(); -} - -} // namespace V8Plugin - -} // namespace Dali diff --git a/plugins/dali-script-v8/src/dali-wrapper.cpp b/plugins/dali-script-v8/src/dali-wrapper.cpp index 5bce721..f674551 100644 --- a/plugins/dali-script-v8/src/dali-wrapper.cpp +++ b/plugins/dali-script-v8/src/dali-wrapper.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -60,7 +59,6 @@ const ApiFunction ConstructorFunctionTable[]= { { "Rotation", PropertyValueWrapper::NewRotation}, { "Matrix", PropertyValueWrapper::NewMatrix}, - { "Font", FontWrapper::NewFont }, { "Path", PathWrapper::NewPath }, { "PathConstraint", PathConstraintWrapper::NewPathConstraint }, { "Actor", ActorWrapper::NewActor }, @@ -222,10 +220,6 @@ void DaliWrapper::Initialize() v8::Local stageObject = StageWrapper::WrapStage( mIsolate, Stage::GetCurrent() ); daliObject->Set( v8::String::NewFromUtf8( mIsolate, "stage") , stageObject ); - // fontObject provides static font functionality like GetFontList... - v8::Local fontObject = FontWrapper::GetStaticFontObject( mIsolate ); - daliObject->Set( v8::String::NewFromUtf8( mIsolate, "font") , fontObject ); - // keyboard focus manager is a singleton v8::Local keyboardObject = KeyboardFocusManagerWrapper::WrapKeyboardFocusManager( mIsolate,Toolkit::KeyboardFocusManager::Get() ); daliObject->Set( v8::String::NewFromUtf8( mIsolate, "keyboardFocusManager") , keyboardObject ); diff --git a/plugins/dali-script-v8/src/shader-effects/shader-effect-api.cpp b/plugins/dali-script-v8/src/shader-effects/shader-effect-api.cpp index d7bd2a5..4d65e64 100644 --- a/plugins/dali-script-v8/src/shader-effects/shader-effect-api.cpp +++ b/plugins/dali-script-v8/src/shader-effects/shader-effect-api.cpp @@ -47,7 +47,6 @@ struct GeometryTypePair const GeometryTypePair GeometryTypeTable[]= { {"image", GEOMETRY_TYPE_IMAGE }, - {"text", GEOMETRY_TYPE_TEXT }, {"mesh", GEOMETRY_TYPE_UNTEXTURED_MESH }, {"textured-mesh", GEOMETRY_TYPE_TEXTURED_MESH }, }; diff --git a/plugins/dali-script-v8/src/text/font-api.cpp b/plugins/dali-script-v8/src/text/font-api.cpp deleted file mode 100644 index 385f58d..0000000 --- a/plugins/dali-script-v8/src/text/font-api.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 2015 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 "font-api.h" - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace V8Plugin -{ - -namespace // un named namespace -{ - - - - -} //un named namespace - -/*************************************** - * IMAGE FUNCTIONS - * - ****************************************/ -Font FontApi::GetFont( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::HandleScope handleScope( isolate ); - - v8::Local object = args.This(); - v8::Local field = v8::Local::Cast( object->GetInternalField(0) ); - void* ptr = field->Value(); - - FontWrapper* wrapper = static_cast< FontWrapper *>(ptr); - return wrapper->GetFont(); -} -Font FontApi::GetFont( v8::Isolate* isolate, v8::Local& value ) -{ - v8::HandleScope handleScope( isolate ); - v8::Local object = value->ToObject(); - v8::Local field = v8::Local::Cast( object->GetInternalField(0) ); - void* ptr = field->Value(); - - FontWrapper* wrapper = static_cast< FontWrapper *>(ptr); - return wrapper->GetFont(); -} - -struct FontParams -{ - typedef enum - { - NO_SIZE_SET, - USE_POINT_SIZE, - USE_PIXEL_SIZE, - USE_CAP_SIZE, - } SizeType; - - - FontParams() - :pointSize( 0 ), - pixelSize( 0 ), - capsSize( 0 ), - sizeType( FontParams::NO_SIZE_SET ) - { - } - - std::string family; - std::string style; - PointSize pointSize; - PixelSize pixelSize; - CapsHeight capsSize; - SizeType sizeType; - - -}; - - -void ReadFontParameters( v8::Isolate* isolate, - v8::Local options, - FontParams& fontParams ) -{ - // foont options is an optional parameter passed in which holds - // optional settings - // var fontOptions = { - // family: "arial", - // style: "bold", - // // one of the following - // pixelSize: xx - // pointSize: xx - // capsHeight:xx // height of a capital letter above the baseline for a particular typeface. - // - // }; - v8::HandleScope handleScope( isolate ); - if( !options->IsObject() ) - { - DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 0 ( font parameters)" ); - return; - } - v8::Local obj = options->ToObject(); - - v8::Local familyValue = obj->Get( v8::String::NewFromUtf8( isolate, "family" ) ); - if( familyValue->IsString() ) - { - fontParams.family = V8Utils::v8StringToStdString( familyValue ); - } - - v8::Local styleValue = obj->Get( v8::String::NewFromUtf8( isolate, "style" ) ); - if( styleValue->IsString() ) - { - fontParams.style = V8Utils::v8StringToStdString( styleValue ); - } - - v8::Local pixelSize = obj->Get( v8::String::NewFromUtf8( isolate, "pixelSize" ) ); - v8::Local pointSize = obj->Get( v8::String::NewFromUtf8( isolate, "pointSize" ) ); - v8::Local capsHeight = obj->Get( v8::String::NewFromUtf8( isolate, "capsHeight" ) ); - - if( pixelSize->IsUint32() ) - { - fontParams.pixelSize.value = pixelSize->ToUint32()->Value(); - fontParams.sizeType = FontParams::USE_PIXEL_SIZE; - } - else if( pointSize->IsUint32() ) - { - fontParams.pointSize.value = pointSize->ToUint32()->Value(); - fontParams.sizeType = FontParams::USE_POINT_SIZE; - } - else if( capsHeight->IsUint32() ) - { - fontParams.capsSize.value = capsHeight->ToUint32()->Value(); - fontParams.sizeType = FontParams::USE_CAP_SIZE; - } - -} - -Font FontApi::New( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - // if no parameters just create a default font - if ( args.Length() == 0) - { - return Font::New(); - } - FontParams params; - - ReadFontParameters( isolate, args[0], params ); - - FontParameters fontParams; - // construct a dali font parameters object - switch( params.sizeType) - { - case FontParams::USE_PIXEL_SIZE: - { - fontParams = FontParameters( params.family, params.style, params.pixelSize ); - break; - } - case FontParams::USE_POINT_SIZE: - { - fontParams = FontParameters( params.family, params.style, params.pointSize ); - break; - } - case FontParams::USE_CAP_SIZE: - { - fontParams = FontParameters( params.family, params.style, params.capsSize ); - break; - } - default: - { - fontParams = FontParameters( params.family, params.style, PointSize(0.f)); - break; - } - } - return Font::New( fontParams ); - -} - - -void FontApi::GetFamilyForText( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - - bool foundString; - std::string text = V8Utils::GetStringParameter( PARAMETER_0, foundString, isolate, args ); - if( !foundString ) - { - DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 0 ( text )" ); - return; - } - std::string family = Font::GetFamilyForText( text ); - - args.GetReturnValue().Set( v8::String::NewFromUtf8( isolate, family.c_str()) ); - -} -void FontApi::GetLineHeightFromCapsHeight( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - FontParams params; - ReadFontParameters( isolate, args[0], params ); - if( params.sizeType != FontParams::USE_CAP_SIZE ) - { - DALI_SCRIPT_EXCEPTION( isolate, "caps height not found" ); - return; - } - - PixelSize size = Font::GetLineHeightFromCapsHeight( params.family, params.style, params.capsSize); - args.GetReturnValue().Set( v8::Integer::New( isolate, size.value ) ); -} - -void FontApi::GetInstalledFonts( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - bool found( false ); - std::vector fontList; - - std::string mode = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - - if( mode == "LIST_APPLICATION_FONTS" ) - { - fontList = Font::GetInstalledFonts( Font::LIST_APPLICATION_FONTS ); - } - else if( mode == "LIST_ALL_FONTS") - { - fontList = Font::GetInstalledFonts( Font::LIST_ALL_FONTS ); - } - else // default - { - fontList = Font::GetInstalledFonts( Font::LIST_SYSTEM_FONTS ); - } - // create a javascript array - v8::Local array = v8::Array::New(isolate, fontList.size() ); - for( std::size_t i = 0; i < fontList.size(); i++) - { - const char* fontName = fontList[i].c_str(); - array->Set(v8::Integer::New(args.GetIsolate(), i), v8::String::NewFromUtf8( isolate,fontName)); - } - - args.GetReturnValue().Set( array ); -} - -void FontApi::MeasureTextWidth( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - //float MeasureTextWidth(const std::string& text, float textHeightPx) const; - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "text not found" ); - return; - } - int height = V8Utils::GetIntegerParameter( PARAMETER_1, found, isolate, args, 0 ); - if( !found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "missing text height" ); - return; - } - float width = font.MeasureTextWidth( text, height ); - - args.GetReturnValue().Set( v8::Integer::New( isolate, width ) ); - -} -void FontApi::MeasureTextHeight( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - //float MeasureTextHeight(const std::string& text, float textHeightPx) const; - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "text not found" ); - return; - } - int width= V8Utils::GetIntegerParameter( PARAMETER_1, found, isolate, args, 0 ); - if( !found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "missing text height" ); - return; - } - float height = font.MeasureTextHeight( text, width ); - - args.GetReturnValue().Set( v8::Integer::New( isolate, height ) ); -} -void FontApi::MeasureText( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "text not found" ); - return; - } - - Vector3 vec3 = font.MeasureText( text ); - Dali::Property::Value value( vec3 ); - v8::Local object = PropertyValueWrapper::WrapDaliProperty( isolate, value); - args.GetReturnValue().Set( object ); - -} -void FontApi::AllGlyphsSupported( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "text not found" ); - return; - } - - bool supported = font.AllGlyphsSupported( text ); - args.GetReturnValue().Set( v8::Boolean::New( isolate, supported) ); - -} - -// This one function is use to create a property map, instead of the many individual property -// getters used by the C++ Dali API. -// propertyMap -// { -// name: -// style: -// pointSize: -// pixelSize: -// lineHeight: -// ascender: -// underlineThickness: -// underlinePosition: -// isDefaultSystemFont: -// isDefaultSystemSize: -// } - -void FontApi::GetProperties( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - v8::Local keyObject = v8::Object::New( isolate ); - - keyObject->Set( v8::String::NewFromUtf8( isolate, "family" ), v8::String::NewFromUtf8( isolate, font.GetName().c_str() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "style" ), v8::String::NewFromUtf8( isolate, font.GetStyle().c_str() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "pointSize" ), v8::Integer::New( isolate, font.GetPointSize() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "pixelSize" ), v8::Integer::New( isolate, font.GetPixelSize() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "lineHeight" ), v8::Integer::New( isolate, font.GetLineHeight() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "ascender" ), v8::Integer::New( isolate, font.GetAscender() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "underlineThickness" ), v8::Integer::New( isolate, font.GetUnderlineThickness() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "underlinePosition" ), v8::Integer::New( isolate, font.GetUnderlinePosition()) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "isDefaultSystemFont" ), v8::Boolean::New( isolate, font.IsDefaultSystemFont() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "isDefaultSystemSize" ), v8::Boolean::New( isolate, font.IsDefaultSystemSize() ) ); - - args.GetReturnValue().Set( keyObject ); - -} - -void FontApi::GetMetrics( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "character not found" ); - return; - } - - Text textObject( text ); - - Font::Metrics metric = font.GetMetrics( textObject[0] ); - - v8::Local keyObject = v8::Object::New( isolate ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "advance" ), v8::Integer::New( isolate, metric.GetAdvance() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "bearing" ), v8::Integer::New( isolate, metric.GetBearing() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "width" ), v8::Integer::New( isolate, metric.GetWidth() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "height" ), v8::Integer::New( isolate, metric.GetHeight() ) ); - - args.GetReturnValue().Set( keyObject ); - -} - - -void FontApi::PointsToPixels( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - bool found(false); - int pointSize= V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 ); - if( !found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "missing pointSize" ); - return; - } - args.GetReturnValue().Set( v8::Integer::New( isolate, Font::PointsToPixels(pointSize) ) ); - -} -void FontApi::PixelsToPoints( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - bool found(false); - int pixelSize= V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 ); - if( !found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "missing pixelSize" ); - return; - } - args.GetReturnValue().Set( v8::Integer::New( isolate, Font::PixelsToPoints(pixelSize) ) ); -} - - - -} // namespace V8Plugin - -} // namespace Dali diff --git a/plugins/dali-script-v8/src/text/font-api.h b/plugins/dali-script-v8/src/text/font-api.h deleted file mode 100644 index 129c240..0000000 --- a/plugins/dali-script-v8/src/text/font-api.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef __DALI_V8PLUGIN_FONT_API_H__ -#define __DALI_V8PLUGIN_FONT_API_H__ - -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// EXTERNAL INCLUDES -#include -#include - - -namespace Dali -{ - -namespace V8Plugin -{ - -namespace FontApi -{ - Font GetFont( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args ); - Font GetFont( v8::Isolate* isolate, v8::Local& value ); - - Font GetFontFromParams( int paramIndex, - bool& found, - v8::Isolate* isolate, - const v8::FunctionCallbackInfo< v8::Value >& args ); - - /** - * Constructor - */ - Font New( const v8::FunctionCallbackInfo< v8::Value >& args ); - - /** - * Font API see image.h for a description - */ - void GetFamilyForText( const v8::FunctionCallbackInfo< v8::Value >& args ); - void GetLineHeightFromCapsHeight( const v8::FunctionCallbackInfo< v8::Value >& args ); - void GetInstalledFonts( const v8::FunctionCallbackInfo< v8::Value >& args ); - void MeasureTextWidth( const v8::FunctionCallbackInfo< v8::Value >& args ); - void MeasureTextHeight( const v8::FunctionCallbackInfo< v8::Value >& args ); - void MeasureText( const v8::FunctionCallbackInfo< v8::Value >& args ); - void AllGlyphsSupported( const v8::FunctionCallbackInfo< v8::Value >& args ); - void GetProperties( const v8::FunctionCallbackInfo< v8::Value >& args ); - void GetMetrics( const v8::FunctionCallbackInfo< v8::Value >& args ); - void PointsToPixels( const v8::FunctionCallbackInfo< v8::Value >& args ); - void PixelsToPoints( const v8::FunctionCallbackInfo< v8::Value >& args ); - -}; // namespace FontApi - -} // namespace V8Plugin - -} // namespace Dali - -#endif // header __DALI_V8PLUGIN_FONT_API_H__ diff --git a/plugins/dali-script-v8/src/text/font-wrapper.cpp b/plugins/dali-script-v8/src/text/font-wrapper.cpp deleted file mode 100644 index 9760f51..0000000 --- a/plugins/dali-script-v8/src/text/font-wrapper.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2015 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 "font-wrapper.h" - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace V8Plugin -{ - -namespace // un-named name space -{ - -/** - * Contains a list of all functions that can be called on the font object - */ -const ApiFunction FontFunctionTable[]= -{ - /************************************** - * Font API (in order of font.h) - **************************************/ - { "MeasureTextWidth", FontApi::MeasureTextWidth }, - { "MeasureTextHeight", FontApi::MeasureTextHeight }, - { "MeasureText", FontApi::MeasureText }, - { "AllGlyphsSupported", FontApi::AllGlyphsSupported }, - { "GetProperties", FontApi::GetProperties }, // replace all getters - { "GetMetrics", FontApi::GetMetrics }, -}; - -const unsigned int FontFunctionTableCount = sizeof(FontFunctionTable)/sizeof(FontFunctionTable[0]); - -/** - * Contains a list of all functions that can be called - */ -const ApiFunction StaticFontFunctionTable[]= -{ - /************************************** - * Static font functions, called without a font object - **************************************/ - { "GetFamilyForText", FontApi::GetFamilyForText }, - { "GetLineHeightFromCapsHeight", FontApi::GetLineHeightFromCapsHeight }, - { "GetInstalledFonts", FontApi::GetInstalledFonts }, - { "PointsToPixels", FontApi::PointsToPixels }, - { "PixelsToPoints", FontApi::PixelsToPoints }, -}; - -const unsigned int StaticFontFunctionTableCount = sizeof(StaticFontFunctionTable)/sizeof(FontFunctionTable[0]); - -} //un-named space - - -FontWrapper::FontWrapper( const Dali::Font& font, GarbageCollectorInterface& gc ) -: BaseWrappedObject( BaseWrappedObject::FONT , gc ) -{ - mFont = font; -} - -v8::Handle FontWrapper::WrapFont(v8::Isolate* isolate, const Dali::Font& font ) -{ - v8::EscapableHandleScope handleScope( isolate ); - v8::Local objectTemplate; - - objectTemplate = MakeFontTemplate( isolate ); - - // create an instance of the template - v8::Local localObject = objectTemplate->NewInstance(); - - // create the Font wrapper - FontWrapper* pointer = new FontWrapper( font, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() ); - - // assign the JavaScript object to the wrapper. - pointer->SetJavascriptObject( isolate, localObject ); - - printf("Created Font!\n"); - return handleScope.Escape( localObject ); -} - - -v8::Handle FontWrapper::MakeFontTemplate( v8::Isolate* isolate ) -{ - v8::EscapableHandleScope handleScope( isolate ); - - v8::Local objTemplate = v8::ObjectTemplate::New(); - - objTemplate->SetInternalFieldCount( BaseWrappedObject::FIELD_COUNT ); - - // add our function properties - ObjectTemplateHelper::InstallFunctions( isolate, objTemplate, FontFunctionTable, FontFunctionTableCount ); - - return handleScope.Escape( objTemplate ); -} - -void FontWrapper::NewFont( const v8::FunctionCallbackInfo< v8::Value >& args) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate); - - if(!args.IsConstructCall()) - { - DALI_SCRIPT_EXCEPTION( isolate, "Font constructor called without 'new'"); - return; - } - - // attribs can be passed by value - Dali::Font font = FontApi::New( args ); - if( !font ) - { - DALI_SCRIPT_EXCEPTION( isolate, "bad font parameters\n"); - return; - } - - v8::Local localObject = WrapFont( isolate, font ); - args.GetReturnValue().Set( localObject ); -} - -Font FontWrapper::GetFont() -{ - return mFont; -} - -v8::Handle FontWrapper::GetStaticFontObject(v8::Isolate* isolate) -{ - v8::EscapableHandleScope handleScope( isolate ); - - v8::Local objTemplate = v8::ObjectTemplate::New(); - - // add our functions properties - ObjectTemplateHelper::InstallFunctions( isolate, objTemplate, StaticFontFunctionTable, StaticFontFunctionTableCount ); - - v8::Local localObject = objTemplate->NewInstance(); - - return handleScope.Escape( localObject ); - - } - - -} // namespace V8Plugin - -} // namespace Dali diff --git a/plugins/dali-script-v8/src/text/font-wrapper.h b/plugins/dali-script-v8/src/text/font-wrapper.h deleted file mode 100644 index 328416a..0000000 --- a/plugins/dali-script-v8/src/text/font-wrapper.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __DALI_V8PLUGIN_FONT_WRAPPER_H__ -#define __DALI_V8PLUGIN_FONT_WRAPPER_H__ - -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// EXTERNAL INCLUDES -#include -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace V8Plugin -{ - - -/** - * An Font wrapper. - * Provides access to Font specific functionality and V8 memory handling. - */ -class FontWrapper : public BaseWrappedObject -{ - -public: - - FontWrapper( const Font& font, - GarbageCollectorInterface& gc ); - - virtual ~FontWrapper() - { - }; - - /** - * @brief Creates a new Font wrapped inside a Javascript Object. - * @note: the actor type ie 'FontFont' is expected to be the name of the callee function. - * @param[in] args v8 function call arguments interpreted - */ - static void NewFont( const v8::FunctionCallbackInfo< v8::Value >& args); - - /** - * Wraps a font - */ - static v8::Handle WrapFont(v8::Isolate* isolate, const Dali::Font& ); - - Font GetFont(); - - static v8::Handle GetStaticFontObject(v8::Isolate* isolate); - -private: - - Font mFont; - static v8::Handle MakeFontTemplate( v8::Isolate* isolate ); - -}; - -} // namespace V8Plugin - -} // namespace Dali - -#endif // __DALI_V8PLUGIN_FONT_WRAPPER_H__ diff --git a/plugins/dali-script-v8/src/toolkit/builder/builder-api.cpp b/plugins/dali-script-v8/src/toolkit/builder/builder-api.cpp index 7feb259..3c499a4 100644 --- a/plugins/dali-script-v8/src/toolkit/builder/builder-api.cpp +++ b/plugins/dali-script-v8/src/toolkit/builder/builder-api.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include @@ -293,11 +292,6 @@ void BuilderApi::Create( const v8::FunctionCallbackInfo< v8::Value >& args ) v8::Local image = ImageWrapper::WrapImage(isolate, Image::DownCast(handle) ); args.GetReturnValue().Set( image ); } - if( typeName == "Font ") - { - v8::Local font = FontWrapper::WrapFont(isolate, Font::DownCast(handle) ); - args.GetReturnValue().Set( font ); - } if( typeName == "Shader") { v8::Local shader = ShaderEffectWrapper::WrapShaderEffect(isolate, ShaderEffect::DownCast( handle ));