From: Bowon Ryu Date: Fri, 1 Apr 2022 10:04:07 +0000 (+0000) Subject: Merge "fix linespacing calculation in TextLabel" into devel/master X-Git-Tag: dali_2.1.17~8 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=a5167c61104580ae0ab724f904537a3a01ea3061;hp=4004ce518172d141a2dc93621c1091f0b0cd7e1e Merge "fix linespacing calculation in TextLabel" into devel/master --- diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 198d183..035f6c3 100755 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -18,6 +18,7 @@ SET(TC_SOURCES utc-Dali-ItemView-internal.cpp utc-Dali-LogicalModel.cpp utc-Dali-PropertyHelper.cpp + utc-Dali-Text-Characters.cpp utc-Dali-Text-CharacterSetConversion.cpp utc-Dali-Text-Circular.cpp utc-Dali-Text-Controller.cpp @@ -72,6 +73,7 @@ SET(TEST_HARNESS_SOURCES ../dali-toolkit/dali-toolkit-test-utils/toolkit-tts-player.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-vector-image-renderer.cpp + ../dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-window.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-scene-holder.cpp ../dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp index e22071a..e8bbb21 100644 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp @@ -116,7 +116,8 @@ void CreateTextModel(const std::string& text, logicalModel->mUnderlinedCharacterRuns, logicalModel->mBackgroundColorRuns, logicalModel->mStrikethroughCharacterRuns, - logicalModel->mBoundedParagraphRuns); + logicalModel->mBoundedParagraphRuns, + logicalModel->mCharacterSpacingCharacterRuns); Length textSize = 0u; const uint8_t* utf8 = NULL; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp index c156b6e..9a3ef2b 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1299,3 +1300,36 @@ int UtcDaliAccessibilityCheckHighlight(void) Dali::Accessibility::TestEnableSC( false ); END_TEST; } + +int UtcDaliWebViewAccessible(void) +{ + ToolkitTestApplication application; + + auto webView = Dali::Toolkit::WebView::New(); + auto webViewAccessible = Dali::Accessibility::Accessible::Get(webView); + + DALI_TEST_CHECK(webViewAccessible); + + auto children = webViewAccessible->GetChildren(); + + DALI_TEST_CHECK(children.empty()); + + Dali::Accessibility::TestEnableSC(true); + + children = webViewAccessible->GetChildren(); + + DALI_TEST_EQUALS(children.size(), 1u, TEST_LOCATION); + + auto address = children[0]->GetAddress(); + + DALI_TEST_CHECK(address); + DALI_TEST_NOT_EQUALS(address.GetBus(), webViewAccessible->GetAddress().GetBus(), 0.0f, TEST_LOCATION); + + Dali::Accessibility::TestEnableSC(false); + + children = webViewAccessible->GetChildren(); + + DALI_TEST_CHECK(children.empty()); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Characters.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Characters.cpp new file mode 100755 index 0000000..259d682 --- /dev/null +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Characters.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +using namespace Dali; +using namespace Toolkit; +using namespace Text; + +// Tests the following function. +// +// CharacterRun RetrieveClusteredCharactersOfCharacterIndex(const VisualModelPtr& visualModel, +// const LogicalModelPtr& logicalModel, +// const CharacterIndex& characterIndex) + +////////////////////////////////////////////////////////// + +namespace +{ +const std::string DEFAULT_FONT_DIR("/resources/fonts"); +const unsigned int DEFAULT_FONT_SIZE = 1152u; + +struct RetrieveClusteredCharactersOfCharacterIndexData +{ + std::string description; ///< Description of the test. + std::string text; ///< Input text. + bool markupProcessorEnabled; //< Enable markup processor to use markup text. + unsigned int numberOfTests; ///< The number of tests. + CharacterIndex* characterIndex; ///< The character index for each test. + CharacterRun* clusteredCharacters; ///< The expected clustered characters run for each test. +}; + +bool GetRetrieveClusteredCharactersOfCharacterIndexTest(const RetrieveClusteredCharactersOfCharacterIndexData& data) +{ + std::cout << " testing : " << data.description << std::endl; + + // 1) Create the model. + ModelPtr textModel; + MetricsPtr metrics; + Size textArea(400.f, 600.f); + Size layoutSize; + + Vector fontDescriptionRuns; + LayoutOptions options; + CreateTextModel(data.text, + textArea, + fontDescriptionRuns, + options, + layoutSize, + textModel, + metrics, + data.markupProcessorEnabled, + LineWrap::WORD, + false, + Toolkit::DevelText::EllipsisPosition::END, + 0.0f, // lineSpacing + 0.0f // characterSpacing + ); + + LogicalModelPtr logicalModel = textModel->mLogicalModel; + VisualModelPtr visualModel = textModel->mVisualModel; + + for(unsigned int index = 0; index < data.numberOfTests; ++index) + { + CharacterRun clusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, data.characterIndex[index]); + + if(clusteredCharacters.characterIndex != data.clusteredCharacters[index].characterIndex) + { + std::cout << " test " << index << " failed. Different clusteredCharacters.characterIndex : " << clusteredCharacters.characterIndex << ", expected : " << data.clusteredCharacters[index].characterIndex << std::endl; + return false; + } + + if(clusteredCharacters.numberOfCharacters != data.clusteredCharacters[index].numberOfCharacters) + { + std::cout << " test " << index << " failed. Different clusteredCharacters.numberOfCharacters : " << clusteredCharacters.numberOfCharacters << ", expected : " << data.clusteredCharacters[index].numberOfCharacters << std::endl; + return false; + } + } + + return true; +} + +} // namespace + +////////////////////////////////////////////////////////// +// +// UtcDaliRetrieveClusteredCharactersOfCharacterIndex +// +////////////////////////////////////////////////////////// + +int UtcDaliRetrieveClusteredCharactersOfCharacterIndex(void) +{ + tet_infoline(" UtcDaliRetrieveClusteredCharactersOfCharacterIndex"); + + CharacterIndex characterIndex01[] = {0u, 1u, 2u, 10u}; + + CharacterRun clusteredCharacters01[] = { + {0u, 1u}, + {1u, 1u}, + {2u, 1u}, + {10u, 1u}}; + + CharacterIndex characterIndex02[] = {0u, 4u, 6u}; + + CharacterRun clusteredCharacters02[] = { + {0u, 7u}, + {0u, 7u}, + {0u, 7u}}; + + CharacterIndex characterIndex03[] = {3u, 9u, 14u}; + + CharacterRun clusteredCharacters03[] = { + {2u, 7u}, + {9u, 1u}, + {11u, 4u}}; + + CharacterIndex characterIndex04[] = {0u, 1u, 2u, 10u}; + + CharacterRun clusteredCharacters04[] = { + {0u, 1u}, + {1u, 1u}, + {2u, 1u}, + {10u, 1u}}; + + struct RetrieveClusteredCharactersOfCharacterIndexData data[] = + { + {"Easy latin script", + "Hello world", + true, + 4u, + characterIndex01, + clusteredCharacters01}, + + {"FamilyManWomanGirlBoy Single Complex Emoji script", + "👨‍👩‍👧‍👦", + true, + 3u, + characterIndex02, + clusteredCharacters02}, + + {"Long text many Emojis with letters", + "AB👨‍👩‍👧‍👦AB👩🏻‍🔬B👨‍👩‍👧‍👦AA☪︎B☪️AB", + true, + 3u, + characterIndex03, + clusteredCharacters03}, + + {"Arabic script", + "اهلا و سهلا", + true, + 4u, + characterIndex04, + clusteredCharacters04}, + }; + const unsigned int numberOfTests = 4u; + + for(unsigned int index = 0; index < numberOfTests; ++index) + { + ToolkitTestApplication application; + if(!GetRetrieveClusteredCharactersOfCharacterIndexTest(data[index])) + { + tet_result(TET_FAIL); + } + } + + tet_result(TET_PASS); + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp index 11c6343..cd1abcb 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp @@ -60,14 +60,15 @@ struct GetClosestLineData struct GetClosestCursorIndexData { - std::string description; ///< Description of the test. - std::string text; ///< Input text. - unsigned int numberOfTests; ///< The number of tests. - float* visualX; ///< The visual 'x' position for each test. - float* visualY; ///< The visual 'y' position for each test. - CharacterHitTest::Mode* mode; ///< The type of hit test. - CharacterIndex* logicalIndex; ///< The expected logical cursor index for each test. - bool* isCharacterHit; ///< The expected character hit value for each test. + std::string description; ///< Description of the test. + std::string text; ///< Input text. + unsigned int numberOfTests; ///< The number of tests. + float* visualX; ///< The visual 'x' position for each test. + float* visualY; ///< The visual 'y' position for each test. + CharacterHitTest::Mode* mode; ///< The type of hit test. + bool markupProcessorEnabled; //< Enable markup processor to use markup text. + CharacterIndex* logicalIndex; ///< The expected logical cursor index for each test. + bool* isCharacterHit; ///< The expected character hit value for each test. }; struct GetCursorPositionData @@ -173,7 +174,7 @@ bool GetClosestCursorIndexTest(const GetClosestCursorIndexData& data) layoutSize, textModel, metrics, - false, + data.markupProcessorEnabled, LineWrap::WORD, false, Toolkit::DevelText::EllipsisPosition::END, @@ -579,6 +580,12 @@ int UtcDaliGetClosestCursorIndex(void) CharacterIndex logicalIndex08[] = {1u}; bool isCharacterHit08[] = {true}; + float visualX09[] = {9.f}; + float visualY09[] = {12.f}; + CharacterHitTest::Mode mode09[] = {CharacterHitTest::TAP}; + CharacterIndex logicalIndex09[] = {1u}; + bool isCharacterHit09[] = {true}; + struct GetClosestCursorIndexData data[] = { {"Void text.", @@ -587,24 +594,30 @@ int UtcDaliGetClosestCursorIndex(void) visualX01, visualY01, mode01, + false, logicalIndex01, isCharacterHit01}, + {"Single line text.", "Hello world שלום עולם", 7u, visualX02, visualY02, mode02, + false, logicalIndex02, isCharacterHit02}, + {"Single line with ligatures", "different الأربعاء", 4u, visualX03, visualY03, mode03, + false, logicalIndex03, isCharacterHit03}, + {"Multiline. Single line paragraphs", "Hello world\n" "שלום עולם\n" @@ -613,8 +626,10 @@ int UtcDaliGetClosestCursorIndex(void) visualX04, visualY04, mode04, + false, logicalIndex04, isCharacterHit04}, + {"Multiline. Single bidirectional paragraph, starts LTR, wrapped lines", "abcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuדאוvwxה" "סתyzטזץabcשנבdefגקכghiעיןjklחלךmnoצמםpqrפרףstuד" @@ -626,8 +641,10 @@ int UtcDaliGetClosestCursorIndex(void) visualX05, visualY05, mode05, + false, logicalIndex05, isCharacterHit05}, + {"Multiline. Single bidirectional paragraph, starts RTL, wrapped lines", "שנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוstuהסתv" "wxטזץyzשנבabcגקכdefעיןghiחלךjklצמםmnoפרףpqrדאוs" @@ -639,25 +656,42 @@ int UtcDaliGetClosestCursorIndex(void) visualX06, visualY06, mode06, + false, logicalIndex06, isCharacterHit06}, + {"Testing complex characters. Arabic ligatures", "الأَبْجَدِيَّة العَرَبِيَّة", 1u, visualX07, visualY07, mode07, + false, logicalIndex07, isCharacterHit07}, + {"Testing complex characters. Latin ligatures", "fi ligature", 1u, visualX08, visualY08, mode08, + false, logicalIndex08, - isCharacterHit08}}; - const unsigned int numberOfTests = 8u; + isCharacterHit08}, + + {"Testing complex characters. Emoji", + "A👨‍👩‍👧‍👦B", + 1u, + visualX09, + visualY09, + mode09, + true, + logicalIndex09, + isCharacterHit09} + + }; + const unsigned int numberOfTests = 9u; for(unsigned int index = 0; index < numberOfTests; ++index) { diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp index 7817c02..36117f7 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp @@ -178,15 +178,16 @@ bool XHTMLEntityToUTF8Test(const XHTMLEntityToUTF8Data& data) { std::cout << " testing " << data.description << std::endl; - Vector colorRuns; - Vector fontRuns; - Vector items; - Vector anchors; - Vector underlinedCharacterRuns; - Vector backgroundColorRuns; - Vector strikethroughCharacterRuns; - Vector boundedParagraphRuns; - MarkupProcessData markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns); + Vector colorRuns; + Vector fontRuns; + Vector items; + Vector anchors; + Vector underlinedCharacterRuns; + Vector backgroundColorRuns; + Vector strikethroughCharacterRuns; + Vector boundedParagraphRuns; + Vector characterSpacingCharacterRuns; + MarkupProcessData markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns, characterSpacingCharacterRuns); ProcessMarkupString(data.xHTMLEntityString, markupProcessData); for(Vector::Iterator it = items.Begin(), diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp index d19326f..f768255 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp @@ -1327,3 +1327,118 @@ int UtcDaliTextEditorMarkupParagraphTagAlignAttribute(void) END_TEST; } + +int UtcDaliTextEditorMarkupCharacterSpacingTag(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMarkupCharacterSpacingTag "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + TextEditor textEditor = TextEditor::New(); + + textEditor.SetProperty(TextEditor::Property::TEXT, "ABC EF\nABC EF\nABC EF\n"); + textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(textEditor); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextEditor& textEditorImpl = GetImpl(textEditor); + Text::ViewInterface& view = textEditorImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliTextEditorMarkupSpanCharacterSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMarkupSpanCharacterSpacing "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + std::string testText = + "ABC EF\n" + "ABC EF\n" + "ABC EF\n"; + + TextEditor textEditor = TextEditor::New(); + + textEditor.SetProperty(TextEditor::Property::TEXT, testText); + textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(textEditor); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextEditor& textEditorImpl = GetImpl(textEditor); + Text::ViewInterface& view = textEditorImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp index 02aa540..da3ffc3 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp @@ -1235,4 +1235,119 @@ int UtcDaliTextFieldMarkupStrikethroughNoEndTag(void) DALI_TEST_EQUALS(numberOfStrikethroughRuns, expectedNumberOfStrikethroughGlyphs, TEST_LOCATION); END_TEST; +} + +int UtcDaliTextFieldMarkupCharacterSpacingTag(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldMarkupCharacterSpacingTag "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + TextField textField = TextField::New(); + + textField.SetProperty(TextField::Property::TEXT, "ABC EF\nABC EF\nABC EF\n"); + textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(textField); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextField& textFieldImpl = GetImpl(textField); + Text::ViewInterface& view = textFieldImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliTextFieldMarkupSpanCharacterSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldMarkupSpanCharacterSpacing "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + std::string testText = + "ABC EF\n" + "ABC EF\n" + "ABC EF\n"; + + TextField textField = TextField::New(); + + textField.SetProperty(TextField::Property::TEXT, testText); + textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(textField); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextField& textFieldImpl = GetImpl(textField); + Text::ViewInterface& view = textFieldImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; } \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp index 1ac00b5..d9a3c04 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp @@ -1221,3 +1221,120 @@ int UtcDaliTextLabelMarkupParagraphTagAlignAttribute(void) END_TEST; } + +int UtcDaliTextLabelMarkupCharacterSpacingTag(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelMarkupCharacterSpacingTag "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + TextLabel textLabel = TextLabel::New(); + + textLabel.SetProperty(TextLabel::Property::TEXT, "ABC EF\nABC EF\nABC EF\n"); + textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true); + textLabel.SetProperty(TextLabel::Property::MULTI_LINE, true); + + application.GetScene().Add(textLabel); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextLabel& textLabelImpl = GetImpl(textLabel); + Text::ViewInterface& view = textLabelImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliTextLabelMarkupSpanCharacterSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelMarkupSpanCharacterSpacing "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + std::string testText = + "ABC EF\n" + "ABC EF\n" + "ABC EF\n"; + + TextLabel textLabel = TextLabel::New(); + + textLabel.SetProperty(TextLabel::Property::TEXT, testText); + textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true); + textLabel.SetProperty(TextLabel::Property::MULTI_LINE, true); + + application.GetScene().Add(textLabel); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextLabel& textLabelImpl = GetImpl(textLabel); + Text::ViewInterface& view = textLabelImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp index ab2548a..000bfa7 100755 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp @@ -1455,6 +1455,11 @@ public: return mScaleFactor; } + Dali::Accessibility::Address GetAccessibilityAddress() + { + return {":9.99", "root"}; + } + Dali::PixelData GetScreenshot(Dali::Rect viewArea, float scaleFactor) { uint32_t bufferSize = viewArea.width * viewArea.height * 4 ; @@ -2226,6 +2231,11 @@ void WebEngine::ActivateAccessibility(bool activated) { } +Accessibility::Address WebEngine::GetAccessibilityAddress() +{ + return Internal::Adaptor::GetImplementation(*this).GetAccessibilityAddress(); +} + bool WebEngine::HighlightText(const std::string& text, Dali::WebEnginePlugin::FindOption options, uint32_t maxMatchCount) { return true; @@ -2471,4 +2481,3 @@ void WebEngine::GetPlainTextAsynchronously(Dali::WebEnginePlugin::PlainTextRecei } } // namespace Dali; - diff --git a/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp b/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp index 7b08e1a..1ca7bd4 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp @@ -1936,8 +1936,8 @@ int UtcDaliKeyboardFocusManagerSetAndGetCurrentFocusActorInTouchMode(void) application.SendNotification(); application.Render(); - // Check that the focus is successfully to clear - DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor()); + // Since no focus has been moved, the current focus actor is the same. + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first); // Make the second actor focusableInTouchMode second.SetProperty(DevelActor::Property::TOUCH_FOCUSABLE, true); @@ -2210,3 +2210,46 @@ int UtcDaliKeyboardFocusManagerChangeFocusDirectionByCustomWheelEvent(void) END_TEST; } + +int UtcDaliKeyboardFocusManagerWithUserInteractionEnabled(void) +{ + ToolkitTestApplication application; + + tet_infoline(" UtcDaliKeyboardFocusManagerWithUserInteractionEnabled"); + + KeyboardFocusManager manager = KeyboardFocusManager::Get(); + DALI_TEST_CHECK(manager); + + // Create the first actor and add it to the stage + Actor first = Actor::New(); + first.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true); + application.GetScene().Add(first); + + // Create the second actor and add it to the first actor. + Actor second = Actor::New(); + second.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true); + first.Add(second); + + // Check that no actor is being focused yet. + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor()); + + // Check that the focus is set on the first actor + DALI_TEST_CHECK(manager.SetCurrentFocusActor(first) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first); + + // Set USER_INTERACTION_ENABLED false. + second.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false); + + // Check that it will fail to set focus on the second actor as it's not userInteractionEnabled + DALI_TEST_CHECK(manager.SetCurrentFocusActor(second) == false); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first); + + // Set KeyboardFocusableChildren true. + second.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true); + + // Check that the focus is set on the second actor + DALI_TEST_CHECK(manager.SetCurrentFocusActor(second) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == second); + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 9d9567b..c21f9a3 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -20,6 +20,8 @@ #include #include #include + +#include #include #include #include @@ -3630,6 +3632,9 @@ int UtcDaliTextEditorEnableEditing(void) application.SendNotification(); application.Render(); + textEditor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true); + DALI_TEST_EQUALS(textEditor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get(), true, TEST_LOCATION); + textEditor.SetKeyInputFocus(); textEditor.SetProperty(DevelTextEditor::Property::ENABLE_EDITING, false); application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE)); @@ -3652,6 +3657,24 @@ int UtcDaliTextEditorEnableEditing(void) DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get(), "D", TEST_LOCATION); DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::ENABLE_EDITING).Get(), true, TEST_LOCATION); + // Check the user interaction enabled and for coverage + DevelTextEditor::SelectWholeText(textEditor); + + // Render and notify + application.SendNotification(); + application.Render(); + + textEditor.SetKeyInputFocus(); + textEditor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false); + application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE)); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get(), "D", TEST_LOCATION); + DALI_TEST_EQUALS(textEditor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get(), false, TEST_LOCATION); + END_TEST; } @@ -5924,4 +5947,83 @@ int UtcDaliToolkitTexteditorParagraphTag(void) application.Render(); END_TEST; +} + +//Handle Emoji clustering for cursor handling +int utcDaliTextEditorClusteredEmojiDeletionBackSpaceKey(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextEditorClusteredEmojiDeletionBackSpaceKey "); + TextEditor textEditor = TextEditor::New(); + DALI_TEST_CHECK(textEditor); + + application.GetScene().Add(textEditor); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); + + textEditor.SetProperty(TextEditor::Property::TEXT, "ABC👨‍👩‍👧‍👦XY"); + textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::ENABLE_MARKUP, true); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set currsor + textEditor.SetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION, 10); + application.SendNotification(); + application.Render(); + + // Set focus and remove Emoji + textEditor.SetKeyInputFocus(); + application.ProcessEvent(GenerateKey("", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE)); + + //Check the changed text and cursor position + DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get(), "ABCXY", TEST_LOCATION); + DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION).Get(), 3, TEST_LOCATION); + + // Render and notify + application.SendNotification(); + application.Render(); + + END_TEST; +} + +int utcDaliTextEditorClusteredEmojiDeletionDeleteKey(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextEditorClusteredEmojiDeletionDeleteKey "); + TextEditor textEditor = TextEditor::New(); + DALI_TEST_CHECK(textEditor); + + application.GetScene().Add(textEditor); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); + + textEditor.SetProperty(TextEditor::Property::TEXT, "ABC👨‍👩‍👧‍👦XY"); + textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::ENABLE_MARKUP, true); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set currsor + textEditor.SetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION, 3); + application.SendNotification(); + application.Render(); + + // Set focus and remove Emoji + textEditor.SetKeyInputFocus(); + application.ProcessEvent(GenerateKey("", "", "", Dali::DevelKey::DALI_KEY_DELETE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE)); + + //Check the changed text and cursor position + DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get(), "ABCXY", TEST_LOCATION); + DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION).Get(), 3, TEST_LOCATION); + + // Render and notify + application.SendNotification(); + application.Render(); + + END_TEST; } \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index 3f5ff1b..b86f96b 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -3836,6 +3837,9 @@ int UtcDaliTextFieldEnableEditing(void) application.SendNotification(); application.Render(); + textField.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true); + DALI_TEST_EQUALS(textField.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get(), true, TEST_LOCATION); + textField.SetKeyInputFocus(); textField.SetProperty(DevelTextField::Property::ENABLE_EDITING, false); application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE)); @@ -3858,6 +3862,24 @@ int UtcDaliTextFieldEnableEditing(void) DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get(), "D", TEST_LOCATION); DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::ENABLE_EDITING).Get(), true, TEST_LOCATION); + // Check the user interaction enabled and for coverage + DevelTextField::SelectWholeText(textField); + + // Render and notify + application.SendNotification(); + application.Render(); + + textField.SetKeyInputFocus(); + textField.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false); + application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE)); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get(), "D", TEST_LOCATION); + DALI_TEST_EQUALS(textField.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get(), false, TEST_LOCATION); + END_TEST; } @@ -5319,4 +5341,83 @@ int UtcDaliToolkitTextfieldParagraphTag(void) application.Render(); END_TEST; +} + +//Handle Emoji clustering for cursor handling +int utcDaliTextFieldClusteredEmojiDeletionBackSpaceKey(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldClusteredEmojiDeletionBackSpaceKey "); + TextField textField = TextField::New(); + DALI_TEST_CHECK(textField); + + application.GetScene().Add(textField); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); + + textField.SetProperty(TextField::Property::TEXT, "ABC👨‍👩‍👧‍👦XY"); + textField.SetProperty(Dali::Toolkit::TextField::Property::ENABLE_MARKUP, true); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set currsor + textField.SetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION, 10); + application.SendNotification(); + application.Render(); + + // Set focus and remove Emoji + textField.SetKeyInputFocus(); + application.ProcessEvent(GenerateKey("", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE)); + + //Check the changed text and cursor position + DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get(), "ABCXY", TEST_LOCATION); + DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION).Get(), 3, TEST_LOCATION); + + // Render and notify + application.SendNotification(); + application.Render(); + + END_TEST; +} + +int utcDaliTextFieldClusteredEmojiDeletionDeleteKey(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldClusteredEmojiDeletionDeleteKey "); + TextField textField = TextField::New(); + DALI_TEST_CHECK(textField); + + application.GetScene().Add(textField); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); + + textField.SetProperty(TextField::Property::TEXT, "ABC👨‍👩‍👧‍👦XY"); + textField.SetProperty(Dali::Toolkit::TextField::Property::ENABLE_MARKUP, true); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set currsor + textField.SetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION, 3); + application.SendNotification(); + application.Render(); + + // Set focus and remove Emoji + textField.SetKeyInputFocus(); + application.ProcessEvent(GenerateKey("", "", "", Dali::DevelKey::DALI_KEY_DELETE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE)); + + //Check the changed text and cursor position + DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get(), "ABCXY", TEST_LOCATION); + DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION).Get(), 3, TEST_LOCATION); + + // Render and notify + application.SendNotification(); + application.Render(); + + END_TEST; } \ No newline at end of file diff --git a/dali-toolkit/devel-api/focus-manager/focus-finder.cpp b/dali-toolkit/devel-api/focus-manager/focus-finder.cpp index d338e39..2fdf285 100644 --- a/dali-toolkit/devel-api/focus-manager/focus-finder.cpp +++ b/dali-toolkit/devel-api/focus-manager/focus-finder.cpp @@ -343,6 +343,7 @@ bool IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rec bool IsFocusable(Actor& actor) { return (actor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && + actor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED) && actor.GetProperty(Actor::Property::VISIBLE) && actor.GetProperty(Actor::Property::WORLD_COLOR).a > FULLY_TRANSPARENT); } diff --git a/dali-toolkit/devel-api/text/text-utils-devel.cpp b/dali-toolkit/devel-api/text/text-utils-devel.cpp index 7b5e36e..c9ab7b5 100644 --- a/dali-toolkit/devel-api/text/text-utils-devel.cpp +++ b/dali-toolkit/devel-api/text/text-utils-devel.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -178,7 +179,8 @@ void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstracti textModel->mLogicalModel->mUnderlinedCharacterRuns, textModel->mLogicalModel->mBackgroundColorRuns, textModel->mLogicalModel->mStrikethroughCharacterRuns, - textModel->mLogicalModel->mBoundedParagraphRuns); + textModel->mLogicalModel->mBoundedParagraphRuns, + textModel->mLogicalModel->mCharacterSpacingCharacterRuns); if(textParameters.markupEnabled) { @@ -819,10 +821,14 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen Vector& lines = textModel->mVisualModel->mLines; // The laid out lines. Vector& isEmoji = internalDataModel.isEmoji; const Size textLayoutArea = internalDataModel.textLayoutArea; - const float characterSpacing = textModel->mVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = textModel->mVisualModel->GetCharacterSpacing(); float calculatedAdvance = 0.f; Vector& glyphToCharacterMap = textModel->mVisualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = textModel->mVisualModel->GetCharacterSpacingGlyphRuns(); + //////////////////////////////////////////////////////////////////////////////// // Ellipsis the text. //////////////////////////////////////////////////////////////////////////////// @@ -908,7 +914,8 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen firstPenSet = true; } - calculatedAdvance = GetCalculatedAdvance(*(textModel->mLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyphToRemove.advance); + const float characterSpacing = GetGlyphCharacterSpacing(index, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textModel->mLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyphToRemove.advance); removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width)); // Calculate the width of the ellipsis glyph and check if it fits. diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp index d6bae90..42153dc 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -672,6 +673,31 @@ void TextEditor::ResizeActor(Actor& actor, const Vector2& size) } } +void TextEditor::OnPropertySet(Property::Index index, const Property::Value& propertyValue) +{ + DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnPropertySet index[%d]\n", index); + + switch(index) + { + case DevelActor::Property::USER_INTERACTION_ENABLED: + { + const bool enabled = propertyValue.Get(); + mController->SetUserInteractionEnabled(enabled); + if(mStencil) + { + float opacity = enabled ? 1.0f : mController->GetDisabledColorOpacity(); + mStencil.SetProperty(Actor::Property::OPACITY, opacity); + } + break; + } + default: + { + Control::OnPropertySet(index, propertyValue); // up call to control for non-handled properties + break; + } + } +} + void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) { DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor OnRelayout\n"); @@ -810,7 +836,10 @@ void TextEditor::OnKeyInputFocusGained() notifier.ContentSelectedSignal().Connect(this, &TextEditor::OnClipboardTextSelected); } - mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event + if(IsEditable() && mController->IsUserInteractionEnabled()) + { + mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event + } EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last. } @@ -862,6 +891,11 @@ void TextEditor::OnTap(const TapGesture& gesture) mController->TapEvent(gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top); mController->AnchorEvent(localPoint.x - padding.start, localPoint.y - padding.top); + Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get(); + if (keyboardFocusManager) + { + keyboardFocusManager.SetCurrentFocusActor(Self()); + } SetKeyInputFocus(); } @@ -893,6 +927,11 @@ bool TextEditor::OnKeyEvent(const KeyEvent& event) // Make sure ClearKeyInputFocus when only key is up if(event.GetState() == KeyEvent::UP) { + Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get(); + if (keyboardFocusManager) + { + keyboardFocusManager.ClearFocus(); + } ClearKeyInputFocus(); } diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h index 5739ac2..c62988a 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -221,6 +221,11 @@ private: // From Control void OnSceneConnection(int depth) override; /** + * @copydoc Control::OnPropertySet() + */ + void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override; + + /** * @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&) */ bool OnKeyEvent(const KeyEvent& event) override; diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index 3cbd0b9..b7a6eb4 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -607,6 +608,31 @@ void TextField::ResizeActor(Actor& actor, const Vector2& size) } } +void TextField::OnPropertySet(Property::Index index, const Property::Value& propertyValue) +{ + DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnPropertySet index[%d]\n", index); + + switch(index) + { + case DevelActor::Property::USER_INTERACTION_ENABLED: + { + const bool enabled = propertyValue.Get(); + mController->SetUserInteractionEnabled(enabled); + if(mStencil) + { + float opacity = enabled ? 1.0f : mController->GetDisabledColorOpacity(); + mStencil.SetProperty(Actor::Property::OPACITY, opacity); + } + break; + } + default: + { + Control::OnPropertySet(index, propertyValue); // up call to control for non-handled properties + break; + } + } +} + void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container) { DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField OnRelayout\n"); @@ -745,7 +771,10 @@ void TextField::OnKeyInputFocusGained() notifier.ContentSelectedSignal().Connect(this, &TextField::OnClipboardTextSelected); } - mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event + if(IsEditable() && mController->IsUserInteractionEnabled()) + { + mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event + } EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last. } @@ -796,6 +825,11 @@ void TextField::OnTap(const TapGesture& gesture) mController->TapEvent(gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top); mController->AnchorEvent(localPoint.x - padding.start, localPoint.y - padding.top); + Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get(); + if (keyboardFocusManager) + { + keyboardFocusManager.SetCurrentFocusActor(Self()); + } SetKeyInputFocus(); } @@ -827,6 +861,11 @@ bool TextField::OnKeyEvent(const KeyEvent& event) // Make sure ClearKeyInputFocus when only key is up if(event.GetState() == KeyEvent::UP) { + Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get(); + if (keyboardFocusManager) + { + keyboardFocusManager.ClearFocus(); + } ClearKeyInputFocus(); } diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h index d2d7fdf..6c4faa6 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -212,6 +212,11 @@ private: // From Control void OnSceneConnection(int depth) override; /** + * @copydoc Control::OnPropertySet() + */ + void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override; + + /** * @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&) */ bool OnKeyEvent(const KeyEvent& event) override; diff --git a/dali-toolkit/internal/controls/web-view/web-view-impl.cpp b/dali-toolkit/internal/controls/web-view/web-view-impl.cpp index 0a8c129..7fc2117 100755 --- a/dali-toolkit/internal/controls/web-view/web-view-impl.cpp +++ b/dali-toolkit/internal/controls/web-view/web-view-impl.cpp @@ -204,6 +204,13 @@ void WebView::OnInitialize() mWebSettings = std::unique_ptr(new WebSettings(mWebEngine.GetSettings())); mWebBackForwardList = std::unique_ptr(new WebBackForwardList(mWebEngine.GetBackForwardList())); } + + self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER); +} + +DevelControl::ControlAccessible* WebView::CreateAccessibleObject() +{ + return new WebViewAccessible(Self(), mWebEngine); } Dali::Toolkit::WebSettings* WebView::GetSettings() const @@ -1236,6 +1243,58 @@ bool WebView::SetVisibility(bool visible) return mWebEngine ? mWebEngine.SetVisibility(visible) : false; } +WebView::WebViewAccessible::WebViewAccessible(Dali::Actor self, Dali::WebEngine& webEngine) +: ControlAccessible(self), mRemoteChild{}, mWebEngine{webEngine} +{ + Dali::Accessibility::Bridge::EnabledSignal().Connect(this, &WebViewAccessible::OnAccessibilityEnabled); + Dali::Accessibility::Bridge::DisabledSignal().Connect(this, &WebViewAccessible::OnAccessibilityDisabled); + + if(Dali::Accessibility::IsUp()) + { + OnAccessibilityEnabled(); + } + else + { + OnAccessibilityDisabled(); + } +} + +void WebView::WebViewAccessible::DoGetChildren(std::vector& children) +{ + if(mRemoteChild.GetAddress()) + { + children.push_back(&mRemoteChild); + } +} + +void WebView::WebViewAccessible::OnAccessibilityEnabled() +{ + if(!mWebEngine) + { + return; + } + + mWebEngine.ActivateAccessibility(true); + SetRemoteChildAddress(mWebEngine.GetAccessibilityAddress()); +} + +void WebView::WebViewAccessible::OnAccessibilityDisabled() +{ + if(!mWebEngine) + { + return; + } + + SetRemoteChildAddress({}); + mWebEngine.ActivateAccessibility(false); +} + +void WebView::WebViewAccessible::SetRemoteChildAddress(Dali::Accessibility::Address address) +{ + mRemoteChild.SetAddress(std::move(address)); + OnChildrenChanged(); +} + #undef GET_ENUM_STRING #undef GET_ENUM_VALUE diff --git a/dali-toolkit/internal/controls/web-view/web-view-impl.h b/dali-toolkit/internal/controls/web-view/web-view-impl.h index 2d8a523..6a0da6e 100755 --- a/dali-toolkit/internal/controls/web-view/web-view-impl.h +++ b/dali-toolkit/internal/controls/web-view/web-view-impl.h @@ -20,12 +20,14 @@ // EXTERNAL INCLUDES #include +#include #include #include #include #include // INTERNAL INCLUDES +#include #include #include #include @@ -423,6 +425,11 @@ private: // From Control void OnInitialize() override; /** + * @copydoc Toolkit::Internal::Control::CreateAccessibleObject() + */ + DevelControl::ControlAccessible* CreateAccessibleObject() override; + + /** * @copydoc Toolkit::Control::GetNaturalSize */ Vector3 GetNaturalSize() override; @@ -663,6 +670,29 @@ private: */ void OnScreenshotCaptured(Dali::PixelData pixel); +protected: + class WebViewAccessible : public DevelControl::ControlAccessible + { + public: + WebViewAccessible() = delete; + + WebViewAccessible(Dali::Actor self, Dali::WebEngine& webEngine); + + protected: + /** + * @copydoc Dali::Accessibility::ActorAccessible::DoGetChildren() + */ + void DoGetChildren(std::vector& children) override; + + private: + void OnAccessibilityEnabled(); + void OnAccessibilityDisabled(); + void SetRemoteChildAddress(Dali::Accessibility::Address address); + + Dali::Accessibility::ProxyAccessible mRemoteChild; + Dali::WebEngine& mWebEngine; + }; + private: Dali::Toolkit::Visual::Base mVisual; Dali::Size mWebViewSize; diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 7e9c1aa..355667e 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -140,6 +140,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/bidirectional-support.cpp ${toolkit_src_dir}/text/bounded-paragraph-helper-functions.cpp ${toolkit_src_dir}/text/character-set-conversion.cpp + ${toolkit_src_dir}/text/characters-helper-functions.cpp ${toolkit_src_dir}/text/color-segmentation.cpp ${toolkit_src_dir}/text/cursor-helper-functions.cpp ${toolkit_src_dir}/text/glyph-metrics-helper.cpp @@ -154,6 +155,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/markup-processor-span.cpp ${toolkit_src_dir}/text/markup-processor-strikethrough.cpp ${toolkit_src_dir}/text/markup-processor-underline.cpp + ${toolkit_src_dir}/text/markup-processor-character-spacing.cpp ${toolkit_src_dir}/text/markup-processor-helper-functions.cpp ${toolkit_src_dir}/text/markup-processor-attribute-helper-functions.cpp ${toolkit_src_dir}/text/multi-language-support.cpp @@ -203,7 +205,8 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/rendering/text-typesetter.cpp ${toolkit_src_dir}/text/rendering/view-model.cpp ${toolkit_src_dir}/text/rendering/styles/underline-helper-functions.cpp - ${toolkit_src_dir}/text/rendering/styles/strikethrough-helper-functions + ${toolkit_src_dir}/text/rendering/styles/strikethrough-helper-functions.cpp + ${toolkit_src_dir}/text/rendering/styles/character-spacing-helper-functions.cpp ${toolkit_src_dir}/transition/fade-transition-impl.cpp ${toolkit_src_dir}/transition/slide-transition-impl.cpp ${toolkit_src_dir}/transition/scale-transition-impl.cpp diff --git a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp index 977e2e0..a64690e 100644 --- a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp @@ -220,7 +220,7 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor) } } - if(actor && actor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) + if(actor && actor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED) && actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { Integration::SceneHolder currentWindow = Integration::SceneHolder::Get(actor); @@ -244,18 +244,13 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor) } // Check whether the actor is in the stage and is keyboard focusable. - if(actor && actor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) + if(actor && actor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED) && actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { if((mIsFocusIndicatorShown == SHOW) && (mEnableFocusIndicator == ENABLE)) { actor.Add(GetFocusIndicatorActor()); } - // Send notification for the change of focus actor - if(!mFocusChangedSignal.Empty()) - { - mFocusChangedSignal.Emit(currentFocusedActor, actor); - } Toolkit::Control currentlyFocusedControl = Toolkit::Control::DownCast(currentFocusedActor); if(currentlyFocusedControl) @@ -265,8 +260,6 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor) currentlyFocusedControl.ClearKeyInputFocus(); } - DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__); - // Save the current focused actor mCurrentFocusActor = actor; @@ -303,6 +296,11 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor(Actor actor) mFocusHistory.erase(beginPos); } + // Send notification for the change of focus actor + if(!mFocusChangedSignal.Empty()) + { + mFocusChangedSignal.Emit(currentFocusedActor, actor); + } DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__); success = true; } @@ -554,7 +552,7 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction } } - if(nextFocusableActor && nextFocusableActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE)) + if(nextFocusableActor && nextFocusableActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && nextFocusableActor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED)) { // Whether the next focusable actor is a layout control if(IsLayoutControl(nextFocusableActor)) @@ -580,7 +578,7 @@ bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control contr Actor nextFocusableActor = GetImplementation(control).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled); if(nextFocusableActor) { - if(!nextFocusableActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE)) + if(!(nextFocusableActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) || nextFocusableActor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED))) { // If the actor is not focusable, ask the same layout control for the next actor to focus return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction); @@ -599,7 +597,7 @@ bool KeyboardFocusManager::DoMoveFocusWithinLayoutControl(Toolkit::Control contr mIsWaitingKeyboardFocusChangeCommit = false; } - if(committedFocusActor && committedFocusActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE)) + if(committedFocusActor && committedFocusActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && committedFocusActor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED)) { // Whether the commited focusable actor is a layout control if(IsLayoutControl(committedFocusActor)) @@ -681,14 +679,10 @@ void KeyboardFocusManager::DoKeyboardEnter(Actor actor) void KeyboardFocusManager::ClearFocus() { + ClearFocusIndicator(); Actor actor = GetCurrentFocusActor(); if(actor) { - if(mFocusIndicatorActor) - { - actor.Remove(mFocusIndicatorActor); - } - // Send notification for the change of focus actor if(!mFocusChangedSignal.Empty()) { @@ -702,8 +696,19 @@ void KeyboardFocusManager::ClearFocus() currentlyFocusedControl.ClearKeyInputFocus(); } } - mCurrentFocusActor.Reset(); +} + +void KeyboardFocusManager::ClearFocusIndicator() +{ + Actor actor = GetCurrentFocusActor(); + if(actor) + { + if(mFocusIndicatorActor) + { + actor.Remove(mFocusIndicatorActor); + } + } mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE; } @@ -1005,18 +1010,30 @@ void KeyboardFocusManager::OnTouch(const TouchEvent& touch) // We only do this on a Down event, otherwise the clear action may override a manually focused actor. if(((touch.GetPointCount() < 1) || (touch.GetState(0) == PointState::DOWN))) { - // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen. - if(mClearFocusOnTouch) + // If you touch the currently focused actor again, you don't need to do SetCurrentFocusActor again. + Actor hitActor = touch.GetHitActor(0); + if(hitActor && hitActor == GetCurrentFocusActor()) { - ClearFocus(); + return; } - // If KEYBOARD_FOCUSABLE and TOUCH_FOCUSABLE is true, set focus actor - Actor hitActor = touch.GetHitActor(0); if(hitActor && hitActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE) && hitActor.GetProperty(DevelActor::Property::TOUCH_FOCUSABLE)) { + // If mClearFocusOnTouch is false, do not clear the focus + if(mClearFocusOnTouch) + { + ClearFocus(); + } SetCurrentFocusActor(hitActor); } + else + { + // If mClearFocusOnTouch is false, do not clear the focus indicator even if user touch the screen. + if(mClearFocusOnTouch) + { + ClearFocusIndicator(); + } + } } } diff --git a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h index 3b09623..ae06097 100644 --- a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h +++ b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h @@ -323,6 +323,11 @@ private: */ bool EmitCustomWheelSignals(Actor actor, const WheelEvent& event); + /** + * Clear the focus indicator actor. + */ + void ClearFocusIndicator(); + private: // Undefined KeyboardFocusManager(const KeyboardFocusManager&); diff --git a/dali-toolkit/internal/text/character-spacing-character-run.h b/dali-toolkit/internal/text/character-spacing-character-run.h new file mode 100644 index 0000000..5c4238e --- /dev/null +++ b/dali-toolkit/internal/text/character-spacing-character-run.h @@ -0,0 +1,59 @@ +#ifndef DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H +#define DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Run of character-spacing characters with same properties. + */ +struct CharacterSpacingCharacterRun +{ + /** + * Default constructor to set the default values of bitfields + */ + CharacterSpacingCharacterRun() + : characterRun{}, + value{0.f} //The default value is 0.f which does nothing. + { + } + + CharacterRun characterRun; ///< The initial character index and the number of characters of the run. + float value; /// The spaces between characters in Pixels. A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed). + + //TODO: Add unit property to choose between Pixel or Scale (%) +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H diff --git a/dali-toolkit/internal/text/character-spacing-glyph-run.h b/dali-toolkit/internal/text/character-spacing-glyph-run.h new file mode 100644 index 0000000..7375533 --- /dev/null +++ b/dali-toolkit/internal/text/character-spacing-glyph-run.h @@ -0,0 +1,57 @@ +#ifndef DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H +#define DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Run of character-spacing glyphs with same properties. + */ +struct CharacterSpacingGlyphRun +{ + /** + * Default constructor to set the default values of bitfields + */ + CharacterSpacingGlyphRun() + : glyphRun{}, + value{0.f} //The default value is 0.f which does nothing. + { + } + + GlyphRun glyphRun; ///< The initial glyph index and the number of glyphs in the run. + float value; ///< The spaces between characters in Pixels. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H diff --git a/dali-toolkit/internal/text/characters-helper-functions.cpp b/dali-toolkit/internal/text/characters-helper-functions.cpp new file mode 100644 index 0000000..d89f1fb --- /dev/null +++ b/dali-toolkit/internal/text/characters-helper-functions.cpp @@ -0,0 +1,60 @@ +// FILE HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +CharacterRun RetrieveClusteredCharactersOfCharacterIndex(const VisualModelPtr& visualModel, + const LogicalModelPtr& logicalModel, + const CharacterIndex& characterIndex) +{ + // Initialization + CharacterRun clusteredCharacters; + clusteredCharacters.characterIndex = characterIndex; + clusteredCharacters.numberOfCharacters = 1u; + + const GlyphIndex* const charactersToGlyphBuffer = visualModel->mCharactersToGlyph.Begin(); + const Length* const charactersPerGlyphBuffer = visualModel->mCharactersPerGlyph.Begin(); + const CharacterIndex* const glyphsToCharacters = visualModel->mGlyphsToCharacters.Begin(); + + GlyphIndex glyphIndex = *(charactersToGlyphBuffer + characterIndex); + Length actualNumberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex); + + if(actualNumberOfCharacters > 1u) + { + const Script script = logicalModel->GetScript(characterIndex); + // Prevents to break the Latin ligatures like fi, ff, or Arabic ï»», ... + // Keep actual index of character as is. Because these characters cannot be clustered. + + if(!HasLigatureMustBreak(script)) + { + clusteredCharacters.numberOfCharacters = actualNumberOfCharacters; + clusteredCharacters.characterIndex = *(glyphsToCharacters + glyphIndex); // firstCharacterIndex + } + } + else + { + while(0u == actualNumberOfCharacters) + { + ++glyphIndex; + actualNumberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex); + } + + clusteredCharacters.characterIndex = *(glyphsToCharacters + glyphIndex); // firstCharacterIndex + clusteredCharacters.numberOfCharacters = actualNumberOfCharacters; + } + + return clusteredCharacters; +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/characters-helper-functions.h b/dali-toolkit/internal/text/characters-helper-functions.h new file mode 100644 index 0000000..00b1b4e --- /dev/null +++ b/dali-toolkit/internal/text/characters-helper-functions.h @@ -0,0 +1,52 @@ +#ifndef DALI_TOOLKIT_TEXT_CHARACTERS_HELPER_FUNCTIONS_H +#define DALI_TOOLKIT_TEXT_CHARACTERS_HELPER_FUNCTIONS_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Retrieve the clustered consecutive characters that contains current character index. + * Found the first index of clustered characters and number of characters. + * + * @param[in] visualModel The visual model. + * @param[in] logicalModel The logical model. + * @param[in] characterIndex The character index. + * + * @return CharacterRun for the clustered characters contains character Index + */ +CharacterRun RetrieveClusteredCharactersOfCharacterIndex(const VisualModelPtr& visualModel, + const LogicalModelPtr& logicalModel, + const CharacterIndex& characterIndex); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_CHARACTERS_HELPER_FUNCTIONS_H \ No newline at end of file diff --git a/dali-toolkit/internal/text/cursor-helper-functions.cpp b/dali-toolkit/internal/text/cursor-helper-functions.cpp index 3bfc059..5dfebde 100644 --- a/dali-toolkit/internal/text/cursor-helper-functions.cpp +++ b/dali-toolkit/internal/text/cursor-helper-functions.cpp @@ -22,7 +22,10 @@ #include // INTERNAL INCLUDES +#include +#include #include +#include namespace { @@ -214,7 +217,10 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, { return logicalIndex; } - const float characterSpacing = visualModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); // Whether there is a hit on a line. bool matchedLine = false; @@ -289,7 +295,8 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, // Get the metrics for the group of glyphs. GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + firstLogicalGlyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + firstLogicalGlyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(firstLogicalGlyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + firstLogicalGlyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + firstLogicalGlyphIndex)).advance); GetGlyphsMetrics(firstLogicalGlyphIndex, numberOfGlyphs, glyphMetrics, @@ -458,6 +465,19 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, logicalIndex = (bidiLineFetched ? logicalModel->GetLogicalCursorIndex(visualIndex) : visualIndex); + // Handle Emoji clustering for cursor handling: + // Fixing this case: + // - When there is Emoji contains multi unicodes and it is layoutted at the end of line (LineWrap case , is not new line case) + // - Try to click at the center or at the end of Emoji then the cursor appears inside Emoji + // - Example:"FamilyManWomanGirlBoy 👨‍👩‍👧‍👦" + const Script script = logicalModel->GetScript(logicalIndex); + if(IsOneOfEmojiScripts(script)) + { + //TODO: Use this clustering for Emoji cases only. This needs more testing to generalize to all scripts. + CharacterRun emojiClusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, logicalIndex); + logicalIndex = emojiClusteredCharacters.characterIndex; + } + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "closest visualIndex %d logicalIndex %d\n", visualIndex, logicalIndex); DALI_ASSERT_DEBUG((logicalIndex <= logicalModel->mText.Count() && logicalIndex >= 0) && "GetClosestCursorIndex - Out of bounds index"); @@ -606,7 +626,9 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, const Length* const charactersPerGlyphBuffer = parameters.visualModel->mCharactersPerGlyph.Begin(); const CharacterIndex* const glyphsToCharactersBuffer = parameters.visualModel->mGlyphsToCharacters.Begin(); const Vector2* const glyphPositionsBuffer = parameters.visualModel->mGlyphPositions.Begin(); - const float characterSpacing = parameters.visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = parameters.visualModel->GetCharacterSpacing(); + + const Vector& characterSpacingGlyphRuns = parameters.visualModel->GetCharacterSpacingGlyphRuns(); // Get the metrics for the group of glyphs. GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs); @@ -723,6 +745,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, const bool addGlyphAdvance = ((!isFirstPositionOfLine && !isCurrentRightToLeft) || (isFirstPositionOfLine && !isRightToLeftParagraph)); + const float characterSpacing = GetGlyphCharacterSpacing(secondaryGlyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + (addGlyphAdvance ? (glyphMetrics.advance + characterSpacing) : 0.f); cursorInfo.secondaryPosition.y = cursorInfo.lineOffset + cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight; diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp index f4d2ca4..d89adf9 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.cpp +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -2109,6 +2109,27 @@ int Decorator::GetCursorWidth() const void Decorator::SetEditable(bool editable) { mImpl->mHidePrimaryCursorAndGrabHandle = !editable; + // If editable is false, all decorators should be disabled. + if(!editable) + { + if(IsHighlightActive()) + { + SetHighlightActive(false); + } + if(IsHandleActive(LEFT_SELECTION_HANDLE)) + { + SetHandleActive(LEFT_SELECTION_HANDLE, false); + } + if(IsHandleActive(RIGHT_SELECTION_HANDLE)) + { + SetHandleActive(RIGHT_SELECTION_HANDLE, false); + } + if(IsPopupActive()) + { + SetPopupActive(false); + } + } + mImpl->Relayout(mImpl->mControlSize); } /** Handles **/ diff --git a/dali-toolkit/internal/text/glyph-metrics-helper.cpp b/dali-toolkit/internal/text/glyph-metrics-helper.cpp index 01c62c7..c46fefd 100644 --- a/dali-toolkit/internal/text/glyph-metrics-helper.cpp +++ b/dali-toolkit/internal/text/glyph-metrics-helper.cpp @@ -19,6 +19,9 @@ // FILE HEADER #include +// INTERNAL INCLUDES +#include + namespace Dali { namespace Toolkit @@ -114,7 +117,10 @@ void GetGlyphMetricsFromCharacterIndex(CharacterIndex index, const GlyphInfo* const glyphInfoBuffer = visualModel->mGlyphs.Begin(); Vector& glyphToCharacterMap = visualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); - const float characterSpacing = visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); //Takes the character index, obtains the glyph index (and the number of Glyphs) from it and finally gets the glyph metrics. glyphIndex = *(charactersToGlyphBuffer + index); @@ -122,7 +128,8 @@ void GetGlyphMetricsFromCharacterIndex(CharacterIndex index, float calculatedAdvance = 0.f; - calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + glyphIndex)).advance); // Get the metrics for the group of glyphs. GetGlyphsMetrics(glyphIndex, diff --git a/dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp b/dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp index 85676cf..db2fddf 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp @@ -20,6 +20,7 @@ // INTERNAL INCLUDE #include +#include namespace Dali { @@ -38,13 +39,16 @@ void CalculateGlyphPositionsLTR(const VisualModelPtr& visualModel, Vector2* glyphPositionsBuffer, float& penX) { - const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); - const float characterSpacing = visualModel->GetCharacterSpacing(); - const Character* const textBuffer = logicalModel->mText.Begin(); + const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); + const Character* const textBuffer = logicalModel->mText.Begin(); Vector& glyphToCharacterMap = visualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); + float calculatedAdvance = 0.f; for(GlyphIndex i = 0u; i < numberOfGlyphs; ++i) @@ -55,7 +59,8 @@ void CalculateGlyphPositionsLTR(const VisualModelPtr& visualModel, position.x = penX + glyph.xBearing; position.y = -glyph.yBearing; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + (startIndexForGlyph + i)))), characterSpacing, glyph.advance); + const float characterSpacing = GetGlyphCharacterSpacing((startIndexForGlyph + i), characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + (startIndexForGlyph + i)))), characterSpacing, glyph.advance); penX += (calculatedAdvance + interGlyphExtraAdvance); } } @@ -73,7 +78,10 @@ void CalculateGlyphPositionsRTL(const VisualModelPtr& visualModel, const BidirectionalLineInfoRun& bidiLine = logicalModel->mBidirectionalLineInfo[bidiLineIndex]; const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); const GlyphIndex* const charactersToGlyphsBuffer = visualModel->mCharactersToGlyph.Begin(); - const float characterSpacing = visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); float calculatedAdvance = 0.f; @@ -86,7 +94,8 @@ void CalculateGlyphPositionsRTL(const VisualModelPtr& visualModel, position.x = penX; position.y = -glyph.yBearing; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance); penX += calculatedAdvance; ++characterLogicalIndex; @@ -106,9 +115,12 @@ void TraversesCharactersForGlyphPositionsRTL(const VisualModelPtr& visualModel, { const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); const GlyphIndex* const charactersToGlyphsBuffer = visualModel->mCharactersToGlyph.Begin(); - const float characterSpacing = visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); const Length* const glyphsPerCharacterBuffer = visualModel->mGlyphsPerCharacter.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); + float calculatedAdvance = 0.f; for(; characterLogicalIndex < bidiLineCharacterRun.numberOfCharacters; @@ -133,7 +145,8 @@ void TraversesCharactersForGlyphPositionsRTL(const VisualModelPtr& visualModel, position.x = penX + glyph.xBearing; position.y = -glyph.yBearing; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance); penX += (calculatedAdvance + interGlyphExtraAdvance); } } diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index aff78c6..3fcc82c 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace Dali { @@ -299,7 +300,10 @@ struct Engine::Impl const float outlineWidth = static_cast(parameters.textModel->GetOutlineWidth()); const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs; - const float characterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns(); CharacterIndex characterLogicalIndex = 0u; CharacterIndex characterVisualIndex = 0u; @@ -330,7 +334,8 @@ struct Engine::Impl { const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex)); - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance); + const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance); whiteSpaceLengthEndOfLine += calculatedAdvance; ++characterLogicalIndex; @@ -352,7 +357,8 @@ struct Engine::Impl { const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex)); - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance); + const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance); whiteSpaceLengthEndOfLine += calculatedAdvance; ++characterLogicalIndex; @@ -370,7 +376,8 @@ struct Engine::Impl charactersPerGlyphBuffer); GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); GetGlyphsMetrics(glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -401,7 +408,8 @@ struct Engine::Impl characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u); GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); GetGlyphsMetrics(glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -463,7 +471,8 @@ struct Engine::Impl characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u); GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); GetGlyphsMetrics(glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -700,13 +709,17 @@ struct Engine::Impl bool isSecondHalf = false; // Character Spacing - const float characterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing(); float calculatedAdvance = 0.f; Vector& glyphToCharacterMap = parameters.textModel->mVisualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns(); + GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(lineLayout.glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance); GetGlyphsMetrics(lineLayout.glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -747,7 +760,8 @@ struct Engine::Impl charactersPerGlyphBuffer); GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); GetGlyphsMetrics(glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -847,7 +861,8 @@ struct Engine::Impl while(tmpLineLayout.length + tmpLineLayout.whiteSpaceLengthEndOfLine > targetWidth && glyphIndexToRemove < glyphIndex) { GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndexToRemove, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance); GetGlyphsMetrics(glyphIndexToRemove, numberOfGLyphsInGroup, glyphMetrics, diff --git a/dali-toolkit/internal/text/logical-model-impl.cpp b/dali-toolkit/internal/text/logical-model-impl.cpp index 9ad00bc..7ebf2a7 100644 --- a/dali-toolkit/internal/text/logical-model-impl.cpp +++ b/dali-toolkit/internal/text/logical-model-impl.cpp @@ -345,6 +345,13 @@ void LogicalModel::UpdateTextStyleRuns(CharacterIndex index, int numberOfCharact totalNumberOfCharacters, mBoundedParagraphRuns, removedBoundedParagraphRuns); + + Vector removedCharacterSpacingCharacterRuns; + UpdateCharacterRuns(index, + numberOfCharacters, + totalNumberOfCharacters, + mCharacterSpacingCharacterRuns, + removedCharacterSpacingCharacterRuns); } void LogicalModel::RetrieveStyle(CharacterIndex index, InputStyle& style) @@ -624,6 +631,16 @@ const Vector& LogicalModel::GetBoundedParagraphRuns() const return mBoundedParagraphRuns; } +Length LogicalModel::GetNumberOfCharacterSpacingCharacterRuns() const +{ + return mCharacterSpacingCharacterRuns.Count(); +} + +const Vector& LogicalModel::GetCharacterSpacingCharacterRuns() const +{ + return mCharacterSpacingCharacterRuns; +} + void LogicalModel::ClearEmbeddedImages() { FreeEmbeddedItems(mEmbeddedItems); diff --git a/dali-toolkit/internal/text/logical-model-impl.h b/dali-toolkit/internal/text/logical-model-impl.h index c54c523..0fa3df2 100644 --- a/dali-toolkit/internal/text/logical-model-impl.h +++ b/dali-toolkit/internal/text/logical-model-impl.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,20 @@ public: */ const Vector& GetBoundedParagraphRuns() const; + /** + * @brief Retrieves the number of character-spacing runs. + * + * @return The number of character-spacing runs. + */ + Length GetNumberOfCharacterSpacingCharacterRuns() const; + + /** + * @brief Retrieves the reference for character-spacing runs. + * + * @return The reference for character-spacing runs. + */ + const Vector& GetCharacterSpacingCharacterRuns() const; + // Embedded images /** @@ -241,9 +256,10 @@ public: Vector mBidirectionalLineInfo; Vector mEmbeddedItems; Vector mAnchors; - Vector mUnderlinedCharacterRuns; ///< The underlined character run from markup-processor - Vector mStrikethroughCharacterRuns; ///< The strikethrough character run from markup-processor - Vector mBoundedParagraphRuns; ///< The bounded paragraph is used to handle a paragraph mark-up tag and it's attributes. Like TextAlign, TextDirection, TextIndent, LineHeight, etc. + Vector mUnderlinedCharacterRuns; ///< The underlined character run from markup-processor + Vector mStrikethroughCharacterRuns; ///< The strikethrough character run from markup-processor + Vector mBoundedParagraphRuns; ///< The bounded paragraph is used to handle a paragraph mark-up tag and it's attributes. Like TextAlign, TextDirection, TextIndent, LineHeight, etc. + Vector mCharacterSpacingCharacterRuns; ///< The character-spacing character run from markup-processor. BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info. }; diff --git a/dali-toolkit/internal/text/markup-processor-character-spacing.cpp b/dali-toolkit/internal/text/markup-processor-character-spacing.cpp new file mode 100644 index 0000000..f0ef362 --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-character-spacing.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// FILE HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +namespace +{ +const std::string XHTML_VALUE_ATTRIBUTE("value"); + +} // namespace + +void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun) +{ + characterSpacingCharacterRun.value = ProcessFloatAttribute(attribute); +} + +void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun) +{ + for(Vector::ConstIterator it = tag.attributes.Begin(), + endIt = tag.attributes.End(); + it != endIt; + ++it) + { + const Attribute& attribute(*it); + + if(TokenComparison(XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ProcessValueAttribute(attribute, characterSpacingCharacterRun); + } + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/markup-processor-character-spacing.h b/dali-toolkit/internal/text/markup-processor-character-spacing.h new file mode 100644 index 0000000..b8b9beb --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-character-spacing.h @@ -0,0 +1,53 @@ +#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H +#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +struct Tag; +struct Attribute; +struct CharacterSpacingCharacterRun; + +/** + * @brief Fill the character-spacing character run with the value (space or advance) attribute. + * + * @param[in] attribute the value attribute. + * @param[out] characterSpacingCharacterRun The underlined character run + */ +void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun); + +/** + * @brief Retrieves the character-spacing run info from the tag and sets it to the character-spacing run. + * + * @param[in] tag The character-spacing tag and its attributes. + * @param[in,out] characterSpacingCharacterRun The character-spacing character run + */ +void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H diff --git a/dali-toolkit/internal/text/markup-processor-span.cpp b/dali-toolkit/internal/text/markup-processor-span.cpp index 1b3cdc2..19810ee 100644 --- a/dali-toolkit/internal/text/markup-processor-span.cpp +++ b/dali-toolkit/internal/text/markup-processor-span.cpp @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -57,20 +58,26 @@ const std::string XHTML_UNDERLINE_DASH_WIDTH_ATTRIBUTE("u-dash-width"); const std::string XHTML_STRIKETHROUGH_COLOR_ATTRIBUTE("s-color"); const std::string XHTML_STRIKETHROUGH_HEIGHT_ATTRIBUTE("s-height"); -} // namespace +//the character-spacing character's attributes +const std::string XHTML_CHARACTER_SPACING_VALUE_ATTRIBUTE("char-space-value"); + +//NOTE: the MAX_NUM_OF_ATTRIBUTES in "markup-processor.cpp" should be updated when add a new attribute for span tag. -void ProcessSpanTag(const Tag& tag, - ColorRun& colorRun, - FontDescriptionRun& fontRun, - UnderlinedCharacterRun& underlinedCharacterRun, - ColorRun& backgroundColorRun, - StrikethroughCharacterRun& strikethroughRun, - bool& isColorDefined, - bool& isFontDefined, - bool& isUnderlinedCharacterDefined, - bool& isBackgroundColorDefined, - bool& isStrikethroughDefined) +} // namespace +void ProcessSpanTag(const Tag& tag, + ColorRun& colorRun, + FontDescriptionRun& fontRun, + UnderlinedCharacterRun& underlinedCharacterRun, + ColorRun& backgroundColorRun, + StrikethroughCharacterRun& strikethroughRun, + CharacterSpacingCharacterRun& characterSpacingCharacterRun, + bool& isColorDefined, + bool& isFontDefined, + bool& isUnderlinedCharacterDefined, + bool& isBackgroundColorDefined, + bool& isStrikethroughDefined, + bool& isCharacterSpacingDefined) { for(Vector::ConstIterator it = tag.attributes.Begin(), endIt = tag.attributes.End(); @@ -149,6 +156,11 @@ void ProcessSpanTag(const Tag& tag, isStrikethroughDefined = true; ProcessHeightAttribute(attribute, strikethroughRun); } + else if(TokenComparison(XHTML_CHARACTER_SPACING_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + isCharacterSpacingDefined = true; + ProcessValueAttribute(attribute, characterSpacingCharacterRun); + } } } diff --git a/dali-toolkit/internal/text/markup-processor-span.h b/dali-toolkit/internal/text/markup-processor-span.h index 6c29554..5630fd3 100644 --- a/dali-toolkit/internal/text/markup-processor-span.h +++ b/dali-toolkit/internal/text/markup-processor-span.h @@ -36,23 +36,27 @@ struct MarkupProcessData; * @param[out] underlinedCharacterRun the underlined character run to be filled. * @param[out] backgroundColorRun the background color run to be filled. * @param[out] strikethroughRun the strikethrough run to be filled. + * @param[out] characterSpacingCharacterRun the character-spacing run to be filled. * @param[out] isColorDefined if the span has color defined. * @param[out] isFontDefined if the span has font defined. * @param[out] isUnderlinedCharacterDefined if the span has underlined-character defined. * @param[out] isBackgroundColorDefined if the span has background color defined. * @param[out] isStrikethroughDefined if the span has strikethrough defined. + * @param[out] isCharacterSpacingDefined if the span has character-spacing defined. */ -void ProcessSpanTag(const Tag& tag, - ColorRun& colorRun, - FontDescriptionRun& fontRun, - UnderlinedCharacterRun& underlinedCharacterRun, - ColorRun& backgroundColorRun, - StrikethroughCharacterRun& strikethroughRun, - bool& isColorDefined, - bool& isFontDefined, - bool& isUnderlinedCharacterDefined, - bool& isBackgroundColorDefined, - bool& isStrikethroughDefined); +void ProcessSpanTag(const Tag& tag, + ColorRun& colorRun, + FontDescriptionRun& fontRun, + UnderlinedCharacterRun& underlinedCharacterRun, + ColorRun& backgroundColorRun, + StrikethroughCharacterRun& strikethroughRun, + CharacterSpacingCharacterRun& characterSpacingCharacterRun, + bool& isColorDefined, + bool& isFontDefined, + bool& isUnderlinedCharacterDefined, + bool& isBackgroundColorDefined, + bool& isStrikethroughDefined, + bool& isCharacterSpacingDefined); } // namespace Text diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index 9c26b39..1df19ca 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ const std::string XHTML_BACKGROUND_TAG("background"); const std::string XHTML_SPAN_TAG("span"); const std::string XHTML_STRIKETHROUGH_TAG("s"); const std::string XHTML_PARAGRAPH_TAG("p"); +const std::string XHTML_CHARACTER_SPACING_TAG("char-spacing"); const char LESS_THAN = '<'; const char GREATER_THAN = '>'; @@ -83,7 +85,8 @@ const char NEW_LINE = 0x0A; // ASCII value of the newline. // Range 3 0x10000u < XHTML_DECIMAL_ENTITY_RANGE <= 0x10FFFFu const unsigned long XHTML_DECIMAL_ENTITY_RANGE[] = {0x0u, 0xD7FFu, 0xE000u, 0xFFFDu, 0x10000u, 0x10FFFFu}; -const unsigned int MAX_NUM_OF_ATTRIBUTES = 13u; ///< The span tag has the 'font-family', 'font-size' 'font-weight', 'font-width', 'font-slant','text-color', 'u-color', 'u-height','u-type','u-dash-gap', 'u-dash-width', 's-color' and 's-height' attrubutes. +// The MAX_NUM_OF_ATTRIBUTES is the number of attributes in span tag "markup-processor-span.cpp". Because it contains the maximum number of attributes in all tags. +const unsigned int MAX_NUM_OF_ATTRIBUTES = 14u; ///< The span tag has the 'font-family', 'font-size' 'font-weight', 'font-width', 'font-slant','text-color', 'u-color', 'u-height','u-type','u-dash-gap', 'u-dash-width', 's-color', 's-height' and 'char-space-value' attrubutes. const unsigned int DEFAULT_VECTOR_SIZE = 16u; ///< Default size of run vectors. #if defined(DEBUG_ENABLED) @@ -143,12 +146,14 @@ struct Span RunIndex underlinedCharacterRunIndex; RunIndex backgroundColorRunIndex; RunIndex strikethroughCharacterRunIndex; + RunIndex characterSpacingCharacterRunIndex; bool isColorDefined; bool isFontDefined; bool isUnderlinedCharacterDefined; bool isBackgroundColorDefined; bool isStrikethroughDefined; + bool isCharacterSpacingDefined; }; /** @@ -202,10 +207,12 @@ void Initialize(UnderlinedCharacterRun& underlinedCharacterRun) */ void Initialize(Span& span) { - span.colorRunIndex = 0u; - span.isColorDefined = false; - span.fontRunIndex = 0u; - span.isFontDefined = false; + span.colorRunIndex = 0u; + span.isColorDefined = false; + + span.fontRunIndex = 0u; + span.isFontDefined = false; + span.underlinedCharacterRunIndex = 0u; span.isUnderlinedCharacterDefined = false; span.backgroundColorRunIndex = 0u; @@ -214,6 +221,10 @@ void Initialize(Span& span) //strikethrough span.strikethroughCharacterRunIndex = 0u; span.isStrikethroughDefined = false; + + //characterSpacing + span.characterSpacingCharacterRunIndex = 0u; + span.isCharacterSpacingDefined = false; } /** @@ -240,6 +251,18 @@ void Initialize(BoundedParagraphRun& boundedParagraphRun) } /** + * @brief Initializes a character-spacing run to its defaults. + * + * @param[in,out] characterSpacingCharacterRun The character-spacing run to initialize. + */ +void Initialize(CharacterSpacingCharacterRun& characterSpacingCharacterRun) +{ + characterSpacingCharacterRun.characterRun.characterIndex = 0u; + characterSpacingCharacterRun.characterRun.numberOfCharacters = 0u; + characterSpacingCharacterRun.value = 0.0f; +} + +/** * @brief Splits the tag string into the tag name and its attributes. * * The attributes are stored in a vector in the tag. @@ -738,20 +761,22 @@ void ProcessAnchorTag( * @param[in] tagReference The tagReference we should increment/decrement */ void ProcessSpanForRun( - const Tag& spanTag, - StyleStack& spanStack, - Vector& colorRuns, - Vector& fontRuns, - Vector& underlinedCharacterRuns, - Vector& backgroundColorRuns, - Vector& strikethroughCharacterRuns, - RunIndex& colorRunIndex, - RunIndex& fontRunIndex, - RunIndex& underlinedCharacterRunIndex, - RunIndex& backgroundColorRunIndex, - RunIndex& strikethroughCharacterRunIndex, - const CharacterIndex characterIndex, - int& tagReference) + const Tag& spanTag, + StyleStack& spanStack, + Vector& colorRuns, + Vector& fontRuns, + Vector& underlinedCharacterRuns, + Vector& backgroundColorRuns, + Vector& strikethroughCharacterRuns, + Vector& characterSpacingCharacterRuns, + RunIndex& colorRunIndex, + RunIndex& fontRunIndex, + RunIndex& underlinedCharacterRunIndex, + RunIndex& backgroundColorRunIndex, + RunIndex& strikethroughCharacterRunIndex, + RunIndex& characterSpacingCharacterRunIndex, + const CharacterIndex characterIndex, + int& tagReference) { if(!spanTag.isEndTag) { @@ -771,21 +796,26 @@ void ProcessSpanForRun( StrikethroughCharacterRun strikethroughCharacterRun; Initialize(strikethroughCharacterRun); + CharacterSpacingCharacterRun characterSpacingCharacterRun; + Initialize(characterSpacingCharacterRun); + Span span; Initialize(span); // Fill the run with the parameters. - colorRun.characterRun.characterIndex = characterIndex; - fontRun.characterRun.characterIndex = characterIndex; - underlinedCharacterRun.characterRun.characterIndex = characterIndex; - backgroundColorRun.characterRun.characterIndex = characterIndex; - strikethroughCharacterRun.characterRun.characterIndex = characterIndex; - - span.colorRunIndex = colorRunIndex; - span.fontRunIndex = fontRunIndex; - span.underlinedCharacterRunIndex = underlinedCharacterRunIndex; - span.backgroundColorRunIndex = backgroundColorRunIndex; - span.strikethroughCharacterRunIndex = strikethroughCharacterRunIndex; + colorRun.characterRun.characterIndex = characterIndex; + fontRun.characterRun.characterIndex = characterIndex; + underlinedCharacterRun.characterRun.characterIndex = characterIndex; + backgroundColorRun.characterRun.characterIndex = characterIndex; + strikethroughCharacterRun.characterRun.characterIndex = characterIndex; + characterSpacingCharacterRun.characterRun.characterIndex = characterIndex; + + span.colorRunIndex = colorRunIndex; + span.fontRunIndex = fontRunIndex; + span.underlinedCharacterRunIndex = underlinedCharacterRunIndex; + span.backgroundColorRunIndex = backgroundColorRunIndex; + span.strikethroughCharacterRunIndex = strikethroughCharacterRunIndex; + span.characterSpacingCharacterRunIndex = characterSpacingCharacterRunIndex; ProcessSpanTag(spanTag, colorRun, @@ -793,11 +823,13 @@ void ProcessSpanForRun( underlinedCharacterRun, backgroundColorRun, strikethroughCharacterRun, + characterSpacingCharacterRun, span.isColorDefined, span.isFontDefined, span.isUnderlinedCharacterDefined, span.isBackgroundColorDefined, - span.isStrikethroughDefined); + span.isStrikethroughDefined, + span.isCharacterSpacingDefined); // Push the span into the stack. spanStack.Push(span); @@ -838,6 +870,13 @@ void ProcessSpanForRun( ++strikethroughCharacterRunIndex; } + if(span.isCharacterSpacingDefined) + { + // Push the run in the logical model. + characterSpacingCharacterRuns.PushBack(characterSpacingCharacterRun); + ++characterSpacingCharacterRunIndex; + } + // Increase reference ++tagReference; } @@ -878,6 +917,12 @@ void ProcessSpanForRun( strikethroughCharacterRun.characterRun.numberOfCharacters = characterIndex - strikethroughCharacterRun.characterRun.characterIndex; } + if(span.isCharacterSpacingDefined) + { + CharacterSpacingCharacterRun& characterSpacingCharacterRun = *(characterSpacingCharacterRuns.Begin() + span.characterSpacingCharacterRunIndex); + characterSpacingCharacterRun.characterRun.numberOfCharacters = characterIndex - characterSpacingCharacterRun.characterRun.characterIndex; + } + --tagReference; } } @@ -893,6 +938,7 @@ void ProcessSpanForRun( * @param[in] strikethroughCharacterRunIndex The strikethroughed character run index * @param[in] backgroundRunIndex The background run index * @param[in] boundedParagraphRunIndex The bounded paragraph run index + * @param[in] characterSpacingCharacterRunIndex The character-spacing character run index * */ void ResizeModelVectors(MarkupProcessData& markupProcessData, @@ -901,7 +947,8 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData, const RunIndex underlinedCharacterRunIndex, const RunIndex strikethroughCharacterRunIndex, const RunIndex backgroundRunIndex, - const RunIndex boundedParagraphRunIndex) + const RunIndex boundedParagraphRunIndex, + const RunIndex characterSpacingCharacterRunIndex) { markupProcessData.fontRuns.Resize(fontRunIndex); markupProcessData.colorRuns.Resize(colorRunIndex); @@ -909,6 +956,7 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData, markupProcessData.strikethroughCharacterRuns.Resize(strikethroughCharacterRunIndex); markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex); markupProcessData.boundedParagraphRuns.Resize(boundedParagraphRunIndex); + markupProcessData.characterSpacingCharacterRuns.Resize(characterSpacingCharacterRunIndex); #ifdef DEBUG_ENABLED for(unsigned int i = 0; i < colorRunIndex; ++i) @@ -1028,23 +1076,25 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar StyleStack spanStack; // Points the next free position in the vector of runs. - RunIndex colorRunIndex = 0u; - RunIndex fontRunIndex = 0u; - RunIndex underlinedCharacterRunIndex = 0u; - RunIndex backgroundRunIndex = 0u; - RunIndex strikethroughCharacterRunIndex = 0u; - RunIndex boundedParagraphRunIndex = 0u; + RunIndex colorRunIndex = 0u; + RunIndex fontRunIndex = 0u; + RunIndex underlinedCharacterRunIndex = 0u; + RunIndex backgroundRunIndex = 0u; + RunIndex strikethroughCharacterRunIndex = 0u; + RunIndex boundedParagraphRunIndex = 0u; + RunIndex characterSpacingCharacterRunIndex = 0u; // check tag reference - int colorTagReference = 0u; - int fontTagReference = 0u; - int iTagReference = 0u; - int bTagReference = 0u; - int uTagReference = 0u; - int backgroundTagReference = 0u; - int spanTagReference = 0u; - int sTagReference = 0u; - int pTagReference = 0u; + int colorTagReference = 0u; + int fontTagReference = 0u; + int iTagReference = 0u; + int bTagReference = 0u; + int uTagReference = 0u; + int backgroundTagReference = 0u; + int spanTagReference = 0u; + int sTagReference = 0u; + int pTagReference = 0u; + int characterSpacingTagReference = 0u; // Give an initial default value to the model's vectors. markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE); @@ -1052,6 +1102,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.strikethroughCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); + markupProcessData.characterSpacingCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); // Get the mark-up string buffer. const char* markupStringBuffer = markupString.c_str(); @@ -1148,11 +1199,13 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar markupProcessData.underlinedCharacterRuns, markupProcessData.backgroundColorRuns, markupProcessData.strikethroughCharacterRuns, + markupProcessData.characterSpacingCharacterRuns, colorRunIndex, fontRunIndex, underlinedCharacterRunIndex, backgroundRunIndex, strikethroughCharacterRunIndex, + characterSpacingCharacterRunIndex, characterIndex, spanTagReference); } @@ -1167,6 +1220,11 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar ProcessTagForRun( markupProcessData.boundedParagraphRuns, styleStack, tag, characterIndex, boundedParagraphRunIndex, pTagReference, [](const Tag& tag, BoundedParagraphRun& run) { ProcessAttributesOfParagraphTag(tag, run); }); } //

+ else if(TokenComparison(XHTML_CHARACTER_SPACING_TAG, tag.buffer, tag.length)) + { + ProcessTagForRun( + markupProcessData.characterSpacingCharacterRuns, styleStack, tag, characterIndex, characterSpacingCharacterRunIndex, characterSpacingTagReference, [](const Tag& tag, CharacterSpacingCharacterRun& run) { ProcessCharacterSpacingTag(tag, run); }); + } // } // end if( IsTag() ) else if(markupStringBuffer < markupStringEndBuffer) { @@ -1175,7 +1233,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar } // Resize the model's vectors. - ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex); + ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex, characterSpacingCharacterRunIndex); // Handle the nested tags OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns); diff --git a/dali-toolkit/internal/text/markup-processor.h b/dali-toolkit/internal/text/markup-processor.h index 3ef7a2d..f751843 100644 --- a/dali-toolkit/internal/text/markup-processor.h +++ b/dali-toolkit/internal/text/markup-processor.h @@ -25,6 +25,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -42,14 +43,15 @@ namespace Text */ struct MarkupProcessData { - MarkupProcessData(Vector& colorRuns, - Vector& fontRuns, - Vector& items, - Vector& anchors, - Vector& underlinedCharacterRuns, - Vector& backgroundColorRuns, - Vector& strikethroughCharacterRuns, - Vector& boundedParagraphRuns) + MarkupProcessData(Vector& colorRuns, + Vector& fontRuns, + Vector& items, + Vector& anchors, + Vector& underlinedCharacterRuns, + Vector& backgroundColorRuns, + Vector& strikethroughCharacterRuns, + Vector& boundedParagraphRuns, + Vector& characterSpacingCharacterRuns) : colorRuns(colorRuns), fontRuns(fontRuns), items(items), @@ -58,19 +60,22 @@ struct MarkupProcessData backgroundColorRuns(backgroundColorRuns), strikethroughCharacterRuns(strikethroughCharacterRuns), boundedParagraphRuns(boundedParagraphRuns), + characterSpacingCharacterRuns(characterSpacingCharacterRuns), markupProcessedText() { } - Vector& colorRuns; ///< The color runs. - Vector& fontRuns; ///< The font description runs. - Vector& items; ///< The embedded items. - Vector& anchors; ///< The anchors. - Vector& underlinedCharacterRuns; ///< The underlined character runs. - Vector& backgroundColorRuns; ///< The background color runs. - Vector& strikethroughCharacterRuns; ///< The strikethrough character runs. - Vector& boundedParagraphRuns; ///< The bounded paragraph runs - std::string markupProcessedText; ///< The mark-up string. + Vector& colorRuns; ///< The color runs. + Vector& fontRuns; ///< The font description runs. + Vector& items; ///< The embedded items. + Vector& anchors; ///< The anchors. + Vector& underlinedCharacterRuns; ///< The underlined character runs. + Vector& backgroundColorRuns; ///< The background color runs. + Vector& strikethroughCharacterRuns; ///< The strikethrough character runs. + Vector& boundedParagraphRuns; ///< The bounded paragraph runs + Vector& characterSpacingCharacterRuns; ///< The character-spacing runs + + std::string markupProcessedText; ///< The mark-up string. }; /** diff --git a/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp new file mode 100644 index 0000000..b166c99 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +namespace +{ +static const Vector EMPTY_CHARACTER_SPACING_GLYPH_RUNS; +} +float GetGlyphCharacterSpacing(const GlyphIndex& index, + const Vector& characterSpacingGlyphRuns, + const float modelCharacterSpacing) +{ + float characterSpacing = modelCharacterSpacing; + for(Vector::ConstIterator it = characterSpacingGlyphRuns.Begin(), + endIt = characterSpacingGlyphRuns.End(); + it != endIt; + ++it) + { + const CharacterSpacingGlyphRun& run = *it; + + if((run.glyphRun.glyphIndex <= index) && (index < run.glyphRun.glyphIndex + run.glyphRun.numberOfGlyphs)) + { + // Retrieve the latest run to handle the nested case. + //TODO: Using reverse Iterator will improve performance in this loop + characterSpacing = run.value; + } + } + + return characterSpacing; +} + +const Vector& GetEmptyCharacterSpacingGlyphRuns() +{ + // This is needed to return a common empty vector for CharacterSpacingGlyphRun + return EMPTY_CHARACTER_SPACING_GLYPH_RUNS; +} +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h new file mode 100644 index 0000000..3865b97 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h @@ -0,0 +1,61 @@ +#ifndef DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H +#define DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Check the glyph at index is had character-spacing or not then return its value. Otherwise return the model character-spacing height. + * + * @param[in] index the index of glyph. + * @param[in] characterSpacingGlyphRuns the character-spacing glyph runs. + * @param[in] modelCharacterSpacing the model character-spacing value. + * + * @return the determined character-spacing value + */ +float GetGlyphCharacterSpacing(const GlyphIndex& index, + const Vector& characterSpacingGlyphRuns, + const float modelCharacterSpacing); + +/** + * @brief Create static empty vector and retrun it. + * + * @return The reference for the empty character-spacing glyph runs. + */ +const Vector& GetEmptyCharacterSpacingGlyphRuns(); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index 33df43d..500a081 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -26,6 +26,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -871,9 +872,12 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, } } - const bool underlineEnabled = mModel->IsUnderlineEnabled(); - const bool strikethroughEnabled = mModel->IsStrikethroughEnabled(); - const float characterSpacing = mModel->GetCharacterSpacing(); + const bool underlineEnabled = mModel->IsUnderlineEnabled(); + const bool strikethroughEnabled = mModel->IsStrikethroughEnabled(); + const float modelCharacterSpacing = mModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = mModel->GetCharacterSpacingGlyphRuns(); // Aggregate underline-style-properties from mModel const UnderlineStyleProperties modelUnderlineProperties{mModel->GetUnderlineType(), @@ -1018,10 +1022,11 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, if(addHyphen) { - GlyphInfo tempInfo = *(glyphsBuffer + elidedGlyphIndex); - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + elidedGlyphIndex))), characterSpacing, tempInfo.advance); - position.x = position.x + calculatedAdvance - tempInfo.xBearing + glyphInfo->xBearing; - position.y = -glyphInfo->yBearing; + GlyphInfo tempInfo = *(glyphsBuffer + elidedGlyphIndex); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + elidedGlyphIndex))), characterSpacing, tempInfo.advance); + position.x = position.x + calculatedAdvance - tempInfo.xBearing + glyphInfo->xBearing; + position.y = -glyphInfo->yBearing; } if(baseline < position.y + glyphInfo->yBearing) diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp index 0b26e4e..f02bb95 100644 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -655,6 +655,16 @@ const Vector& ViewModel::GetBoundedParagraphRuns() const return mModel->GetBoundedParagraphRuns(); } +Length ViewModel::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return mModel->GetNumberOfCharacterSpacingGlyphRuns(); +} + +const Vector& ViewModel::GetCharacterSpacingGlyphRuns() const +{ + return mModel->GetCharacterSpacingGlyphRuns(); +} + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/rendering/view-model.h b/dali-toolkit/internal/text/rendering/view-model.h index 73b7fa6..c7b0b18 100644 --- a/dali-toolkit/internal/text/rendering/view-model.h +++ b/dali-toolkit/internal/text/rendering/view-model.h @@ -329,6 +329,16 @@ public: */ void GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns, StrikethroughRunIndex index, Length numberOfRuns) const override; + /** + * @copydoc ModelInterface::GetNumberOfCharacterSpacingGlyphRuns() + */ + Length GetNumberOfCharacterSpacingGlyphRuns() const override; + + /** + * @copydoc ModelInterface::GetCharacterSpacingGlyphRuns() + */ + const Vector& GetCharacterSpacingGlyphRuns() const override; + private: const ModelInterface* const mModel; ///< Pointer to the text's model. Vector mElidedGlyphs; ///< Stores the glyphs of the elided text. diff --git a/dali-toolkit/internal/text/text-controller-background-actor.cpp b/dali-toolkit/internal/text/text-controller-background-actor.cpp index a129c5e..7def7e8 100644 --- a/dali-toolkit/internal/text/text-controller-background-actor.cpp +++ b/dali-toolkit/internal/text/text-controller-background-actor.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace Dali::Toolkit::Text @@ -98,11 +99,14 @@ Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr const Vector4* const backgroundColorsBuffer = textView.GetBackgroundColors(); const ColorIndex* const backgroundColorIndicesBuffer = textView.GetBackgroundColorIndices(); const Vector4& defaultBackgroundColor = textVisualModel->IsBackgroundEnabled() ? textVisualModel->GetBackgroundColor() : Color::TRANSPARENT; - const float characterSpacing = textVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = textVisualModel->GetCharacterSpacing(); Vector& glyphToCharacterMap = textVisualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); float calculatedAdvance = 0.f; + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = textVisualModel->GetCharacterSpacingGlyphRuns(); + Vector4 quad; uint32_t numberOfQuads = 0u; Length yLineOffset = 0; @@ -137,6 +141,8 @@ Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr // Only create quads for glyphs with a background color if(backgroundColor != Color::TRANSPARENT) { + const float characterSpacing = GetGlyphCharacterSpacing(i, characterSpacingGlyphRuns, modelCharacterSpacing); + const Vector2 position = *(positionsBuffer + i); calculatedAdvance = GetCalculatedAdvance(*(textLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + i))), characterSpacing, glyph.advance); diff --git a/dali-toolkit/internal/text/text-controller-event-handler.cpp b/dali-toolkit/internal/text/text-controller-event-handler.cpp index 7494cb6..d5c41a1 100644 --- a/dali-toolkit/internal/text/text-controller-event-handler.cpp +++ b/dali-toolkit/internal/text/text-controller-event-handler.cpp @@ -117,6 +117,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE bool textChanged = false; bool relayoutNeeded = false; + bool isEditable = controller.IsEditable() && controller.IsUserInteractionEnabled(); if((NULL != controller.mImpl->mEventData) && (keyEvent.GetState() == KeyEvent::DOWN)) @@ -148,7 +149,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE (Dali::DALI_KEY_CURSOR_DOWN == keyCode)) { // If don't have any text, do nothing. - if(!controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters) + if(!controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters || !isEditable) { return false; } @@ -207,7 +208,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE // Do nothing return false; } - else if(keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier()) + else if(keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier() && isEditable) { bool consumed = false; if(keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME || logicalKey == KEY_C_NAME || logicalKey == KEY_INSERT_NAME) @@ -273,7 +274,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE else { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", &controller, keyString.c_str()); - if(!controller.IsEditable()) return false; + if(!isEditable) return false; std::string refinedKey = keyString; if(controller.mImpl->mInputFilter != NULL && !refinedKey.empty()) diff --git a/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp b/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp index e6ec978..de18e85 100644 --- a/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp @@ -572,6 +572,7 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o { impl.CopyUnderlinedFromLogicalToVisualModels(true); impl.CopyStrikethroughFromLogicalToVisualModels(); + impl.CopyCharacterSpacingFromLogicalToVisualModels(); } updated = true; diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index e97535c..c24a5cf 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -909,7 +909,8 @@ void Controller::Impl::SetEditable(bool editable) if(mEventData->mDecorator) { - mEventData->mDecorator->SetEditable(editable); + bool decoratorEditable = editable && mIsUserInteractionEnabled; + mEventData->mDecorator->SetEditable(decoratorEditable); } } } @@ -1692,6 +1693,39 @@ void Controller::Impl::CopyStrikethroughFromLogicalToVisualModels() } } +void Controller::Impl::CopyCharacterSpacingFromLogicalToVisualModels() +{ + //CharacterSpacing character runs from markup-processor + const Vector& characterSpacingCharacterRuns = mModel->mLogicalModel->mCharacterSpacingCharacterRuns; + const Vector& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph; + const Vector& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter; + + mModel->mVisualModel->mCharacterSpacingRuns.Clear(); + + for(Vector::ConstIterator it = characterSpacingCharacterRuns.Begin(), endIt = characterSpacingCharacterRuns.End(); it != endIt; ++it) + { + const CharacterIndex& characterIndex = it->characterRun.characterIndex; + const Length& numberOfCharacters = it->characterRun.numberOfCharacters; + + if(numberOfCharacters == 0) + { + continue; + } + + CharacterSpacingGlyphRun characterSpacingGlyphRun; + characterSpacingGlyphRun.value = it->value; + characterSpacingGlyphRun.glyphRun.glyphIndex = charactersToGlyph[characterIndex]; + characterSpacingGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex]; + + for(Length index = 1u; index < numberOfCharacters; index++) + { + characterSpacingGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index]; + } + + mModel->mVisualModel->mCharacterSpacingRuns.PushBack(characterSpacingGlyphRun); + } +} + void Controller::Impl::SetAutoScrollEnabled(bool enable) { if(mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX) @@ -1841,6 +1875,17 @@ void Controller::Impl::SetDefaultColor(const Vector4& color) } } +void Controller::Impl::SetUserInteractionEnabled(bool enabled) +{ + mIsUserInteractionEnabled = enabled; + + if(mEventData && mEventData->mDecorator) + { + bool editable = mEventData->mEditingEnabled && enabled; + mEventData->mDecorator->SetEditable(editable); + } +} + void Controller::Impl::ClearFontData() { if(mFontDefaults) diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 0757bc0..5944039 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -41,6 +41,7 @@ const float DEFAULT_TEXTFIT_MIN = 10.f; const float DEFAULT_TEXTFIT_MAX = 100.f; const float DEFAULT_TEXTFIT_STEP = 1.f; const float DEFAULT_FONT_SIZE_SCALE = 1.f; +const float DEFAULT_DISABLED_COLOR_OPACITY = 0.3f; //Forward declarations struct CursorInfo; @@ -358,10 +359,12 @@ struct Controller::Impl mTextFitMaxSize(DEFAULT_TEXTFIT_MAX), mTextFitStepSize(DEFAULT_TEXTFIT_STEP), mFontSizeScale(DEFAULT_FONT_SIZE_SCALE), + mDisabledColorOpacity(DEFAULT_DISABLED_COLOR_OPACITY), mFontSizeScaleEnabled(true), mTextFitEnabled(false), mTextFitChanged(false), - mIsLayoutDirectionChanged(false) + mIsLayoutDirectionChanged(false), + mIsUserInteractionEnabled(true) { mModel = Model::New(); @@ -874,6 +877,11 @@ struct Controller::Impl void SetDefaultColor(const Vector4& color); /** + * @copydoc Controller::SetUserInteractionEnabled() + */ + void SetUserInteractionEnabled(bool enabled); + + /** * @brief Helper to clear font-specific data (only). */ void ClearFontData(); @@ -961,6 +969,12 @@ private: */ void CopyStrikethroughFromLogicalToVisualModels(); + /** + * @brief Copy CharacterSpacing-Character-Runs from Logical-Model to CharacterSpacing-Glyph-Runs in Visual-Model + * + */ + void CopyCharacterSpacingFromLogicalToVisualModels(); + public: ControlInterface* mControlInterface; ///< Reference to the text controller. EditableControlInterface* mEditableControlInterface; ///< Reference to the editable text controller. @@ -1008,10 +1022,12 @@ public: float mTextFitMaxSize; ///< Maximum Font Size for text fit. Default 100 float mTextFitStepSize; ///< Step Size for font intervalse. Default 1 float mFontSizeScale; ///< Scale value for Font Size. Default 1.0 + float mDisabledColorOpacity; ///< Color opacity when disabled. bool mFontSizeScaleEnabled : 1; ///< Whether the font size scale is enabled. bool mTextFitEnabled : 1; ///< Whether the text's fit is enabled. bool mTextFitChanged : 1; ///< Whether the text fit property has changed. bool mIsLayoutDirectionChanged : 1; ///< Whether the layout has changed. + bool mIsUserInteractionEnabled : 1; ///< Whether the user interaction is enabled. private: friend ControllerImplEventHandler; diff --git a/dali-toolkit/internal/text/text-controller-text-updater.cpp b/dali-toolkit/internal/text/text-controller-text-updater.cpp index 0b24bc0..35408da 100644 --- a/dali-toolkit/internal/text/text-controller-text-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-text-updater.cpp @@ -24,6 +24,8 @@ // INTERNAL INCLUDES #include +#include +#include #include #include #include @@ -92,7 +94,8 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string& logicalModel->mUnderlinedCharacterRuns, logicalModel->mBackgroundColorRuns, logicalModel->mStrikethroughCharacterRuns, - logicalModel->mBoundedParagraphRuns); + logicalModel->mBoundedParagraphRuns, + logicalModel->mCharacterSpacingCharacterRuns); Length textSize = 0u; const uint8_t* utf8 = NULL; @@ -481,6 +484,7 @@ bool Controller::TextUpdater::RemoveText( ModelPtr& model = impl.mModel; LogicalModelPtr& logicalModel = model->mLogicalModel; + VisualModelPtr& visualModel = model->mVisualModel; DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n", &controller, logicalModel->mText.Count(), eventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters); @@ -498,6 +502,25 @@ bool Controller::TextUpdater::RemoveText( cursorIndex = eventData->mPrimaryCursorPosition + cursorOffset; } + //Handle Emoji clustering for cursor handling + // Deletion case: this is handling the deletion cases when the cursor is before or after Emoji + // - Before: when use delete key and cursor is before Emoji (cursorOffset = -1) + // - After: when use backspace key and cursor is after Emoji (cursorOffset = 0) + + const Script script = logicalModel->GetScript(cursorIndex); + if((numberOfCharacters == 1u) && + (IsOneOfEmojiScripts(script))) + { + //TODO: Use this clustering for Emoji cases only. This needs more testing to generalize to all scripts. + CharacterRun emojiClusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, cursorIndex); + Length actualNumberOfCharacters = emojiClusteredCharacters.numberOfCharacters; + + //Set cursorIndex at the first characterIndex of clustred Emoji + cursorIndex = emojiClusteredCharacters.characterIndex; + + numberOfCharacters = actualNumberOfCharacters; + } + if((cursorIndex + numberOfCharacters) > currentText.Count()) { numberOfCharacters = currentText.Count() - cursorIndex; diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index b0f740d..bf92f6a 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -747,6 +747,26 @@ const Vector4& Controller::GetDefaultColor() const return mImpl->mTextColor; } +void Controller::SetDisabledColorOpacity(float opacity) +{ + mImpl->mDisabledColorOpacity = opacity; +} + +float Controller::GetDisabledColorOpacity() const +{ + return mImpl->mDisabledColorOpacity; +} + +void Controller::SetUserInteractionEnabled(bool enabled) +{ + mImpl->SetUserInteractionEnabled(enabled); +} + +bool Controller::IsUserInteractionEnabled() const +{ + return mImpl->mIsUserInteractionEnabled; +} + void Controller::SetPlaceholderTextColor(const Vector4& textColor) { PlaceholderHandler::SetPlaceholderTextColor(*this, textColor); diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 81a0318..3e987dd 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -504,6 +504,20 @@ public: // Configure the text controller. bool IsTextFitChanged() const; /** + * @brief Sets disabled color opacity. + * + * @param[in] opacity The color opacity value in disabled state. + */ + void SetDisabledColorOpacity(float opacity); + + /** + * @brief Retrieves the disabled color opacity. + * + * @return The disabled color opacity value for disabled state. + */ + float GetDisabledColorOpacity() const; + + /** * @brief Enable or disable the placeholder text elide. * @param enabled Whether to enable the placeholder text elide. */ @@ -1004,6 +1018,20 @@ public: // Default style & Input style const Vector4& GetDefaultColor() const; /** + * @brief Sets the user interaction enabled. + * + * @param enabled whether to enable the user interaction. + */ + void SetUserInteractionEnabled(bool enabled); + + /** + * @brief Whether the user interaction is enabled. + * + * @return true if the user interaction is enabled, false otherwise. + */ + bool IsUserInteractionEnabled() const; + + /** * @brief Set the text color * * @param textColor The text color diff --git a/dali-toolkit/internal/text/text-model-interface.h b/dali-toolkit/internal/text/text-model-interface.h index c7e7b98..0f2bd7b 100644 --- a/dali-toolkit/internal/text/text-model-interface.h +++ b/dali-toolkit/internal/text/text-model-interface.h @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -403,6 +404,20 @@ public: virtual const Vector& GetBoundedParagraphRuns() const = 0; /** + * @brief Retrieves the number of character-spacing glyph runs. + * + * @return The number of character-spacing glyph runs. + */ + virtual Length GetNumberOfCharacterSpacingGlyphRuns() const = 0; + + /** + * @brief Retrieves the reference for character-spacing glyph runs. + * + * @return The reference for character-spacing glyph runs. + */ + virtual const Vector& GetCharacterSpacingGlyphRuns() const = 0; + + /** * @brief Retrieves the strikethrough runs. * * @param[out] strikethroughRuns Pointer to a buffer where the strikethrough runs are copied. diff --git a/dali-toolkit/internal/text/text-model.cpp b/dali-toolkit/internal/text/text-model.cpp index 924343c..0ac67ca 100644 --- a/dali-toolkit/internal/text/text-model.cpp +++ b/dali-toolkit/internal/text/text-model.cpp @@ -291,6 +291,16 @@ void Model::GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns, Strik mVisualModel->GetStrikethroughRuns(strikethroughRuns, index, numberOfRuns); } +Length Model::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return mVisualModel->GetNumberOfCharacterSpacingGlyphRuns(); +} + +const Vector& Model::GetCharacterSpacingGlyphRuns() const +{ + return mVisualModel->GetCharacterSpacingGlyphRuns(); +} + const float Model::GetCharacterSpacing() const { return mVisualModel->GetCharacterSpacing(); diff --git a/dali-toolkit/internal/text/text-model.h b/dali-toolkit/internal/text/text-model.h index ded9496..416df17 100644 --- a/dali-toolkit/internal/text/text-model.h +++ b/dali-toolkit/internal/text/text-model.h @@ -23,6 +23,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -313,6 +314,16 @@ public: */ virtual const Vector& GetBoundedParagraphRuns() const override; + /** + * @copydoc ModelInterface::GetNumberOfCharacterSpacingGlyphRuns() + */ + Length GetNumberOfCharacterSpacingGlyphRuns() const override; + + /** + * @copydoc ModelInterface::GetCharacterSpacingGlyphRuns() + */ + const Vector& GetCharacterSpacingGlyphRuns() const override; + private: // Private contructors & copy operator. /** * @brief Private constructor. diff --git a/dali-toolkit/internal/text/text-selection-handle-controller.cpp b/dali-toolkit/internal/text/text-selection-handle-controller.cpp index a36f81f..05d8ad5 100644 --- a/dali-toolkit/internal/text/text-selection-handle-controller.cpp +++ b/dali-toolkit/internal/text/text-selection-handle-controller.cpp @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include using namespace Dali; @@ -108,10 +109,13 @@ void SelectionHandleController::Reposition(Controller::Impl& impl) const GlyphIndex glyphStart = *(charactersToGlyphBuffer + selectionStart); const Length numberOfGlyphs = *(glyphsPerCharacterBuffer + selectionEndMinusOne); const GlyphIndex glyphEnd = *(charactersToGlyphBuffer + selectionEndMinusOne) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u); - const float characterSpacing = visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); Vector& glyphToCharacterMap = visualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); + // Get the lines where the glyphs are laid-out. const LineRun* lineRun = visualModel->mLines.Begin(); @@ -174,9 +178,10 @@ void SelectionHandleController::Reposition(Controller::Impl& impl) // Traverse the glyphs. for(GlyphIndex index = glyphStart; index <= glyphEnd; ++index) { - const GlyphInfo& glyph = *(glyphsBuffer + index); - const Vector2& position = *(positionsBuffer + index); - calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyph.advance); + const float characterSpacing = GetGlyphCharacterSpacing(index, characterSpacingGlyphRuns, modelCharacterSpacing); + const GlyphInfo& glyph = *(glyphsBuffer + index); + const Vector2& position = *(positionsBuffer + index); + calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyph.advance); if(splitStartGlyph) { diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index 9caf068..98b420d 100644 --- a/dali-toolkit/internal/text/text-view-interface.h +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -338,6 +339,20 @@ public: virtual const Vector& GetBoundedParagraphRuns() const = 0; /** + * @brief Retrieves the number of character-spacing glyph runs. + * + * @return The number of character-spacing glyph runs. + */ + virtual Length GetNumberOfCharacterSpacingGlyphRuns() const = 0; + + /** + * @brief Retrieves the reference for character-spacing glyph runs. + * + * @return The reference for character-spacing glyph runs. + */ + virtual const Vector& GetCharacterSpacingGlyphRuns() const = 0; + + /** * @brief Retrieves the strikethrough runs. * * @param[out] strikethroughRuns Pointer to a buffer where the strikethrough runs are copied. diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index fdccbe1..697dc04 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -25,6 +25,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -107,14 +108,18 @@ Length View::GetGlyphs(GlyphInfo* glyphs, { Length numberOfLaidOutGlyphs = 0u; Length numberOfActualLaidOutGlyphs = 0u; - const float characterSpacing = mImpl->mVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = mImpl->mVisualModel->GetCharacterSpacing(); Vector& glyphToCharacterMap = mImpl->mVisualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); float calculatedAdvance = 0.f; const Character* textBuffer = mImpl->mLogicalModel->mText.Begin(); + if(mImpl->mVisualModel) { + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = mImpl->mVisualModel->GetCharacterSpacingGlyphRuns(); + bool textElided = false; DevelText::EllipsisPosition::Type ellipsisPosition = GetEllipsisPosition(); @@ -356,7 +361,8 @@ Length View::GetGlyphs(GlyphInfo* glyphs, firstPenSet = true; } - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + indexOfEllipsis))), characterSpacing, glyphToRemove.advance); + const float characterSpacing = GetGlyphCharacterSpacing(indexOfEllipsis, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + indexOfEllipsis))), characterSpacing, glyphToRemove.advance); removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width)); // Calculate the width of the ellipsis glyph and check if it fits. @@ -839,6 +845,16 @@ const Vector& View::GetBoundedParagraphRuns() const return mImpl->mLogicalModel->GetBoundedParagraphRuns(); } +Length View::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetNumberOfCharacterSpacingGlyphRuns() : 0u; +} + +const Vector& View::GetCharacterSpacingGlyphRuns() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacingGlyphRuns() : GetEmptyCharacterSpacingGlyphRuns(); +} + const float View::GetCharacterSpacing() const { return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacing() : 0.f; diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index 06bf838..93542cc 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -259,6 +259,16 @@ public: virtual const Vector& GetBoundedParagraphRuns() const; /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfCharacterSpacingGlyphRuns() + */ + Length GetNumberOfCharacterSpacingGlyphRuns() const override; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetCharacterSpacingGlyphRuns() + */ + const Vector& GetCharacterSpacingGlyphRuns() const override; + + /** * @copydoc Dali::Toolkit::Text::ViewInterface::GetCharacterSpacing() */ const float GetCharacterSpacing() const override; diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index ce0fb7c..5ef2b50 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -609,6 +609,16 @@ Length VisualModel::GetNumberOfStrikethroughRuns() const return mStrikethroughRuns.Count(); } +Length VisualModel::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return mCharacterSpacingRuns.Count(); +} + +const Vector& VisualModel::GetCharacterSpacingGlyphRuns() const +{ + return mCharacterSpacingRuns; +} + void VisualModel::ClearCaches() { mCachedLineIndex = 0u; diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index 4bae17c..9c0af3a 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -26,6 +26,7 @@ #include // INTERNAL INCLUDES +#include #include #include #include @@ -596,6 +597,20 @@ public: */ Length GetNumberOfStrikethroughRuns() const; + /** + * @brief Retrieves the number of character-spacing glyph runs. + * + * @return The number of character-spacing glyph runs. + */ + Length GetNumberOfCharacterSpacingGlyphRuns() const; + + /** + * @brief Retrieves the reference for character-spacing glyph runs. + * + * @return The reference for character-spacing glyph runs. + */ + const Vector& GetCharacterSpacingGlyphRuns() const; + protected: /** * @brief A reference counted object may only be deleted by calling Unreference(). @@ -615,34 +630,35 @@ private: 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. - Vector mUnderlineRuns; ///< Runs of glyphs that are underlined. - Vector mColors; ///< Colors of the glyphs. - Vector mColorIndices; ///< Indices to the vector of colors for each glyphs. - Vector mBackgroundColors; ///< Background colors of the glyphs. - Vector mBackgroundColorIndices; ///< Indices to the vector of background colors for each glyphs. - Vector4 mTextColor; ///< The text color - Vector4 mShadowColor; ///< Color of drop shadow - Vector4 mUnderlineColor; ///< Color of underline - Vector4 mOutlineColor; ///< Color of outline - Vector4 mBackgroundColor; ///< Color of text background - Vector4 mStrikethroughColor; ///< Color of text background - Size mControlSize; ///< The size of the UI control. - Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow - float mUnderlineHeight; ///< Fixed height for underline to override font metrics. - float mStrikethroughHeight; ///< Fixed height for strikethrough to override font metrics. - Text::Underline::Type mUnderlineType; ///< The type of the underline. - float mDashedUnderlineWidth; ///< The width of the dashes of the dashed underline. - float mDashedUnderlineGap; ///< The gap between the dashes of the dashed underline. - float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur. - uint16_t mOutlineWidth; ///< Width of outline. - Vector mStrikethroughRuns; ///< Runs of glyphs that have strikethrough. + 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. + Vector mUnderlineRuns; ///< Runs of glyphs that are underlined. + Vector mColors; ///< Colors of the glyphs. + Vector mColorIndices; ///< Indices to the vector of colors for each glyphs. + Vector mBackgroundColors; ///< Background colors of the glyphs. + Vector mBackgroundColorIndices; ///< Indices to the vector of background colors for each glyphs. + Vector4 mTextColor; ///< The text color + Vector4 mShadowColor; ///< Color of drop shadow + Vector4 mUnderlineColor; ///< Color of underline + Vector4 mOutlineColor; ///< Color of outline + Vector4 mBackgroundColor; ///< Color of text background + Vector4 mStrikethroughColor; ///< Color of text background + Size mControlSize; ///< The size of the UI control. + Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow + float mUnderlineHeight; ///< Fixed height for underline to override font metrics. + float mStrikethroughHeight; ///< Fixed height for strikethrough to override font metrics. + Text::Underline::Type mUnderlineType; ///< The type of the underline. + float mDashedUnderlineWidth; ///< The width of the dashes of the dashed underline. + float mDashedUnderlineGap; ///< The gap between the dashes of the dashed underline. + float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur. + uint16_t mOutlineWidth; ///< Width of outline. + Vector mStrikethroughRuns; ///< Runs of glyphs that have strikethrough. + Vector mCharacterSpacingRuns; ///< Runs of glyphs that have character-spacing. private: Size mNaturalSize; ///< Size of the text with no line wrapping. diff --git a/dali-toolkit/styles/images-common/button-down.9.png b/dali-toolkit/styles/images-common/button-down.9.png index f6e25ab..cb7df7b 100644 Binary files a/dali-toolkit/styles/images-common/button-down.9.png and b/dali-toolkit/styles/images-common/button-down.9.png differ diff --git a/dali-toolkit/styles/images-common/button-up.9.png b/dali-toolkit/styles/images-common/button-up.9.png index a2e2e01..252880d 100644 Binary files a/dali-toolkit/styles/images-common/button-up.9.png and b/dali-toolkit/styles/images-common/button-up.9.png differ diff --git a/dali-toolkit/styles/images-common/checkbox-selected-disabled.png b/dali-toolkit/styles/images-common/checkbox-selected-disabled.png index a6517b8..c5996ee 100644 Binary files a/dali-toolkit/styles/images-common/checkbox-selected-disabled.png and b/dali-toolkit/styles/images-common/checkbox-selected-disabled.png differ diff --git a/dali-toolkit/styles/images-common/checkbox-selected.png b/dali-toolkit/styles/images-common/checkbox-selected.png index e3a8c43..91be569 100644 Binary files a/dali-toolkit/styles/images-common/checkbox-selected.png and b/dali-toolkit/styles/images-common/checkbox-selected.png differ diff --git a/dali-toolkit/styles/images-common/checkbox-unselected-disabled.png b/dali-toolkit/styles/images-common/checkbox-unselected-disabled.png index 022c1cf..7aba7cf 100644 Binary files a/dali-toolkit/styles/images-common/checkbox-unselected-disabled.png and b/dali-toolkit/styles/images-common/checkbox-unselected-disabled.png differ diff --git a/dali-toolkit/styles/images-common/checkbox-unselected.png b/dali-toolkit/styles/images-common/checkbox-unselected.png index 58e9390..b8a7d0d 100644 Binary files a/dali-toolkit/styles/images-common/checkbox-unselected.png and b/dali-toolkit/styles/images-common/checkbox-unselected.png differ diff --git a/dali-toolkit/styles/images-common/radio-button-selected-disabled.png b/dali-toolkit/styles/images-common/radio-button-selected-disabled.png index 5c40e4b..4e30b7f 100644 Binary files a/dali-toolkit/styles/images-common/radio-button-selected-disabled.png and b/dali-toolkit/styles/images-common/radio-button-selected-disabled.png differ diff --git a/dali-toolkit/styles/images-common/radio-button-selected.png b/dali-toolkit/styles/images-common/radio-button-selected.png index d49cbb5..7c3afab 100644 Binary files a/dali-toolkit/styles/images-common/radio-button-selected.png and b/dali-toolkit/styles/images-common/radio-button-selected.png differ diff --git a/dali-toolkit/styles/images-common/radio-button-unselected-disabled.png b/dali-toolkit/styles/images-common/radio-button-unselected-disabled.png index 0c5fa5f..dc659f8 100644 Binary files a/dali-toolkit/styles/images-common/radio-button-unselected-disabled.png and b/dali-toolkit/styles/images-common/radio-button-unselected-disabled.png differ diff --git a/dali-toolkit/styles/images-common/radio-button-unselected.png b/dali-toolkit/styles/images-common/radio-button-unselected.png index 6f647e8..65d93c6 100644 Binary files a/dali-toolkit/styles/images-common/radio-button-unselected.png and b/dali-toolkit/styles/images-common/radio-button-unselected.png differ diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 3e50c92..ea8a871 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -169,9 +169,7 @@ cmake \ %if 0%{?enable_debug} -DCMAKE_BUILD_TYPE=Debug \ %endif -%if 0%{?enable_trace} -DENABLE_TRACE=ON \ -%endif -DCMAKE_INSTALL_PREFIX=%{_prefix} \ -DCMAKE_INSTALL_LIBDIR=%{_libdir} \ -DCMAKE_INSTALL_INCLUDEDIR=%{_includedir} \