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
../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
logicalModel->mUnderlinedCharacterRuns,
logicalModel->mBackgroundColorRuns,
logicalModel->mStrikethroughCharacterRuns,
- logicalModel->mBoundedParagraphRuns);
+ logicalModel->mBoundedParagraphRuns,
+ logicalModel->mCharacterSpacingCharacterRuns);
Length textSize = 0u;
const uint8_t* utf8 = NULL;
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/controls/popup/popup.h>
#include <dali-toolkit/devel-api/controls/table-view/table-view.h>
+#include <dali-toolkit/devel-api/controls/web-view/web-view.h>
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/common/stage.h>
#include <cstdlib>
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;
+}
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+#include <toolkit-text-utils.h>
+
+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<FontDescriptionRun> 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;
+}
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
layoutSize,
textModel,
metrics,
- false,
+ data.markupProcessorEnabled,
LineWrap::WORD,
false,
Toolkit::DevelText::EllipsisPosition::END,
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.",
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"
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ד"
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"
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)
{
{
std::cout << " testing " << data.description << std::endl;
- Vector<ColorRun> colorRuns;
- Vector<FontDescriptionRun> fontRuns;
- Vector<EmbeddedItem> items;
- Vector<Anchor> anchors;
- Vector<UnderlinedCharacterRun> underlinedCharacterRuns;
- Vector<ColorRun> backgroundColorRuns;
- Vector<StrikethroughCharacterRun> strikethroughCharacterRuns;
- Vector<BoundedParagraphRun> boundedParagraphRuns;
- MarkupProcessData markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns);
+ Vector<ColorRun> colorRuns;
+ Vector<FontDescriptionRun> fontRuns;
+ Vector<EmbeddedItem> items;
+ Vector<Anchor> anchors;
+ Vector<UnderlinedCharacterRun> underlinedCharacterRuns;
+ Vector<ColorRun> backgroundColorRuns;
+ Vector<StrikethroughCharacterRun> strikethroughCharacterRuns;
+ Vector<BoundedParagraphRun> boundedParagraphRuns;
+ Vector<CharacterSpacingCharacterRun> characterSpacingCharacterRuns;
+ MarkupProcessData markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns, characterSpacingCharacterRuns);
ProcessMarkupString(data.xHTMLEntityString, markupProcessData);
for(Vector<EmbeddedItem>::Iterator it = items.Begin(),
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\n<char-spacing value='-5.0f'>ABC EF\n</char-spacing><char-spacing value='10.0f'>ABC EF\n</char-spacing>");
+ 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<GlyphInfo> glyphs;
+ glyphs.Resize(numberOfGlyphs);
+
+ Vector<Vector2> 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 =
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='blue' >ABC EF\n</span>"
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' char-space-value='-5.0f'>ABC EF\n</span>"
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='green' char-space-value='10.0f'>ABC EF\n</span>";
+
+ 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<GlyphInfo> glyphs;
+ glyphs.Resize(numberOfGlyphs);
+
+ Vector<Vector2> 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
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\n<char-spacing value='-5.0f'>ABC EF\n</char-spacing><char-spacing value='10.0f'>ABC EF\n</char-spacing>");
+ 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<GlyphInfo> glyphs;
+ glyphs.Resize(numberOfGlyphs);
+
+ Vector<Vector2> 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 =
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='blue' >ABC EF\n</span>"
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' char-space-value='-5.0f'>ABC EF\n</span>"
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='green' char-space-value='10.0f'>ABC EF\n</span>";
+
+ 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<GlyphInfo> glyphs;
+ glyphs.Resize(numberOfGlyphs);
+
+ Vector<Vector2> 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
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\n<char-spacing value='-5.0f'>ABC EF\n</char-spacing><char-spacing value='10.0f'>ABC EF\n</char-spacing>");
+ 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<GlyphInfo> glyphs;
+ glyphs.Resize(numberOfGlyphs);
+
+ Vector<Vector2> 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 =
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='blue' >ABC EF\n</span>"
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red' char-space-value='-5.0f'>ABC EF\n</span>"
+ "<span font-size='20' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='green' char-space-value='10.0f'>ABC EF\n</span>";
+
+ 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<GlyphInfo> glyphs;
+ glyphs.Resize(numberOfGlyphs);
+
+ Vector<Vector2> 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
return mScaleFactor;
}
+ Dali::Accessibility::Address GetAccessibilityAddress()
+ {
+ return {":9.99", "root"};
+ }
+
Dali::PixelData GetScreenshot(Dali::Rect<int32_t> viewArea, float scaleFactor)
{
uint32_t bufferSize = viewArea.width * viewArea.height * 4 ;
{
}
+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;
}
} // namespace Dali;
-
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<std::string>(), "ABCXY", TEST_LOCATION);
+ DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 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<std::string>(), "ABCXY", TEST_LOCATION);
+ DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 3, TEST_LOCATION);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
}
\ No newline at end of file
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<std::string>(), "ABCXY", TEST_LOCATION);
+ DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 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<std::string>(), "ABCXY", TEST_LOCATION);
+ DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 3, TEST_LOCATION);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
}
\ No newline at end of file
#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
#include <dali-toolkit/internal/text/markup-processor.h>
#include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
#include <dali-toolkit/internal/text/segmentation.h>
#include <dali-toolkit/internal/text/shaper.h>
#include <dali-toolkit/internal/text/text-enumerations-impl.h>
textModel->mLogicalModel->mUnderlinedCharacterRuns,
textModel->mLogicalModel->mBackgroundColorRuns,
textModel->mLogicalModel->mStrikethroughCharacterRuns,
- textModel->mLogicalModel->mBoundedParagraphRuns);
+ textModel->mLogicalModel->mBoundedParagraphRuns,
+ textModel->mLogicalModel->mCharacterSpacingCharacterRuns);
if(textParameters.markupEnabled)
{
Vector<LineRun>& lines = textModel->mVisualModel->mLines; // The laid out lines.
Vector<bool>& 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<CharacterIndex>& glyphToCharacterMap = textModel->mVisualModel->mGlyphsToCharacters;
const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+
+ // Get the character-spacing runs.
+ const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = textModel->mVisualModel->GetCharacterSpacingGlyphRuns();
+
////////////////////////////////////////////////////////////////////////////////
// Ellipsis the text.
////////////////////////////////////////////////////////////////////////////////
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.
mWebSettings = std::unique_ptr<Dali::Toolkit::WebSettings>(new WebSettings(mWebEngine.GetSettings()));
mWebBackForwardList = std::unique_ptr<Dali::Toolkit::WebBackForwardList>(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
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<Dali::Accessibility::Accessible*>& 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
// EXTERNAL INCLUDES
#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/adaptor-framework/proxy-accessible.h>
#include <dali/devel-api/adaptor-framework/web-engine.h>
#include <dali/public-api/images/image-operations.h>
#include <dali/public-api/object/property-notification.h>
#include <memory>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-accessible.h>
#include <dali-toolkit/devel-api/controls/web-view/web-view.h>
#include <dali-toolkit/devel-api/visual-factory/visual-base.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
void OnInitialize() override;
/**
+ * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+ */
+ DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+ /**
* @copydoc Toolkit::Control::GetNaturalSize
*/
Vector3 GetNaturalSize() override;
*/
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<Dali::Accessibility::Accessible*>& 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;
${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
${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
${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
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)
currentlyFocusedControl.ClearKeyInputFocus();
}
- DALI_LOG_INFO(gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
-
// Save the current focused actor
mCurrentFocusActor = 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;
}
--- /dev/null
+#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 <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+
+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
--- /dev/null
+#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 <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/glyph-run.h>
+
+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
--- /dev/null
+// FILE HEADER
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/emoji-helper.h>
+
+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
--- /dev/null
+#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 <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/text-model.h>
+
+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
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+#include <dali-toolkit/internal/text/emoji-helper.h>
#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
namespace
{
{
return logicalIndex;
}
- const float characterSpacing = visualModel->GetCharacterSpacing();
+
+ // Get the character-spacing runs.
+ const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
+ const float modelCharacterSpacing = visualModel->GetCharacterSpacing();
// Whether there is a hit on a line.
bool matchedLine = false;
// 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,
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");
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<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = parameters.visualModel->GetCharacterSpacingGlyphRuns();
// Get the metrics for the group of glyphs.
GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs);
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;
// FILE HEADER
#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
+
namespace Dali
{
namespace Toolkit
const GlyphInfo* const glyphInfoBuffer = visualModel->mGlyphs.Begin();
Vector<CharacterIndex>& 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<CharacterSpacingGlyphRun>& 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);
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,
// INTERNAL INCLUDE
#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
namespace Dali
{
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<CharacterIndex>& glyphToCharacterMap = visualModel->mGlyphsToCharacters;
const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+ // Get the character-spacing runs.
+ const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
+
float calculatedAdvance = 0.f;
for(GlyphIndex i = 0u; i < numberOfGlyphs; ++i)
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);
}
}
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<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
float calculatedAdvance = 0.f;
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;
{
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<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
+
float calculatedAdvance = 0.f;
for(; characterLogicalIndex < bidiLineCharacterRun.numberOfCharacters;
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);
}
}
#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
#include <dali-toolkit/internal/text/layouts/layout-engine-helper-functions.h>
#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
namespace Dali
{
const float outlineWidth = static_cast<float>(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<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns();
CharacterIndex characterLogicalIndex = 0u;
CharacterIndex characterVisualIndex = 0u;
{
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;
{
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;
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,
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,
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,
bool isSecondHalf = false;
// Character Spacing
- const float characterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing();
+ const float modelCharacterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing();
float calculatedAdvance = 0.f;
Vector<CharacterIndex>& glyphToCharacterMap = parameters.textModel->mVisualModel->mGlyphsToCharacters;
const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+ // Get the character-spacing runs.
+ const Vector<CharacterSpacingGlyphRun>& 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,
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,
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,
totalNumberOfCharacters,
mBoundedParagraphRuns,
removedBoundedParagraphRuns);
+
+ Vector<CharacterSpacingCharacterRun> removedCharacterSpacingCharacterRuns;
+ UpdateCharacterRuns<CharacterSpacingCharacterRun>(index,
+ numberOfCharacters,
+ totalNumberOfCharacters,
+ mCharacterSpacingCharacterRuns,
+ removedCharacterSpacingCharacterRuns);
}
void LogicalModel::RetrieveStyle(CharacterIndex index, InputStyle& style)
return mBoundedParagraphRuns;
}
+Length LogicalModel::GetNumberOfCharacterSpacingCharacterRuns() const
+{
+ return mCharacterSpacingCharacterRuns.Count();
+}
+
+const Vector<CharacterSpacingCharacterRun>& LogicalModel::GetCharacterSpacingCharacterRuns() const
+{
+ return mCharacterSpacingCharacterRuns;
+}
+
void LogicalModel::ClearEmbeddedImages()
{
FreeEmbeddedItems(mEmbeddedItems);
#include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
#include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-character-run.h>
#include <dali-toolkit/internal/text/color-run.h>
#include <dali-toolkit/internal/text/embedded-item.h>
#include <dali-toolkit/internal/text/font-description-run.h>
*/
const Vector<BoundedParagraphRun>& 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<CharacterSpacingCharacterRun>& GetCharacterSpacingCharacterRuns() const;
+
// Embedded images
/**
Vector<BidirectionalLineInfoRun> mBidirectionalLineInfo;
Vector<EmbeddedItem> mEmbeddedItems;
Vector<Anchor> mAnchors;
- Vector<UnderlinedCharacterRun> mUnderlinedCharacterRuns; ///< The underlined character run from markup-processor
- Vector<StrikethroughCharacterRun> mStrikethroughCharacterRuns; ///< The strikethrough character run from markup-processor
- Vector<BoundedParagraphRun> mBoundedParagraphRuns; ///< The bounded paragraph is used to handle a paragraph mark-up tag and it's attributes. Like TextAlign, TextDirection, TextIndent, LineHeight, etc.
+ Vector<UnderlinedCharacterRun> mUnderlinedCharacterRuns; ///< The underlined character run from markup-processor
+ Vector<StrikethroughCharacterRun> mStrikethroughCharacterRuns; ///< The strikethrough character run from markup-processor
+ Vector<BoundedParagraphRun> mBoundedParagraphRuns; ///< The bounded paragraph is used to handle a paragraph mark-up tag and it's attributes. Like TextAlign, TextDirection, TextIndent, LineHeight, etc.
+ Vector<CharacterSpacingCharacterRun> mCharacterSpacingCharacterRuns; ///< The character-spacing character run from markup-processor.
BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info.
};
--- /dev/null
+/*
+ * 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 <dali-toolkit/internal/text/markup-processor-character-spacing.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-spacing-character-run.h>
+#include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+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<Attribute>::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
--- /dev/null
+#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
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/color-run.h>
#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/markup-processor-character-spacing.h>
#include <dali-toolkit/internal/text/markup-processor-font.h>
#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
#include <dali-toolkit/internal/text/markup-processor-strikethrough.h>
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<Attribute>::ConstIterator it = tag.attributes.Begin(),
endIt = tag.attributes.End();
isStrikethroughDefined = true;
ProcessHeightAttribute(attribute, strikethroughRun);
}
+ else if(TokenComparison(XHTML_CHARACTER_SPACING_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+ {
+ isCharacterSpacingDefined = true;
+ ProcessValueAttribute(attribute, characterSpacingCharacterRun);
+ }
}
}
* @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
#include <dali-toolkit/internal/text/character-set-conversion.h>
#include <dali-toolkit/internal/text/markup-processor-anchor.h>
#include <dali-toolkit/internal/text/markup-processor-background.h>
+#include <dali-toolkit/internal/text/markup-processor-character-spacing.h>
#include <dali-toolkit/internal/text/markup-processor-color.h>
#include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
#include <dali-toolkit/internal/text/markup-processor-font.h>
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 = '>';
// 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)
RunIndex underlinedCharacterRunIndex;
RunIndex backgroundColorRunIndex;
RunIndex strikethroughCharacterRunIndex;
+ RunIndex characterSpacingCharacterRunIndex;
bool isColorDefined;
bool isFontDefined;
bool isUnderlinedCharacterDefined;
bool isBackgroundColorDefined;
bool isStrikethroughDefined;
+ bool isCharacterSpacingDefined;
};
/**
*/
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;
//strikethrough
span.strikethroughCharacterRunIndex = 0u;
span.isStrikethroughDefined = false;
+
+ //characterSpacing
+ span.characterSpacingCharacterRunIndex = 0u;
+ span.isCharacterSpacingDefined = false;
}
/**
}
/**
+ * @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.
* @param[in] tagReference The tagReference we should increment/decrement
*/
void ProcessSpanForRun(
- const Tag& spanTag,
- StyleStack<Span>& spanStack,
- Vector<ColorRun>& colorRuns,
- Vector<FontDescriptionRun>& fontRuns,
- Vector<UnderlinedCharacterRun>& underlinedCharacterRuns,
- Vector<ColorRun>& backgroundColorRuns,
- Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns,
- RunIndex& colorRunIndex,
- RunIndex& fontRunIndex,
- RunIndex& underlinedCharacterRunIndex,
- RunIndex& backgroundColorRunIndex,
- RunIndex& strikethroughCharacterRunIndex,
- const CharacterIndex characterIndex,
- int& tagReference)
+ const Tag& spanTag,
+ StyleStack<Span>& spanStack,
+ Vector<ColorRun>& colorRuns,
+ Vector<FontDescriptionRun>& fontRuns,
+ Vector<UnderlinedCharacterRun>& underlinedCharacterRuns,
+ Vector<ColorRun>& backgroundColorRuns,
+ Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns,
+ Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns,
+ RunIndex& colorRunIndex,
+ RunIndex& fontRunIndex,
+ RunIndex& underlinedCharacterRunIndex,
+ RunIndex& backgroundColorRunIndex,
+ RunIndex& strikethroughCharacterRunIndex,
+ RunIndex& characterSpacingCharacterRunIndex,
+ const CharacterIndex characterIndex,
+ int& tagReference)
{
if(!spanTag.isEndTag)
{
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,
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);
++strikethroughCharacterRunIndex;
}
+ if(span.isCharacterSpacingDefined)
+ {
+ // Push the run in the logical model.
+ characterSpacingCharacterRuns.PushBack(characterSpacingCharacterRun);
+ ++characterSpacingCharacterRunIndex;
+ }
+
// Increase reference
++tagReference;
}
strikethroughCharacterRun.characterRun.numberOfCharacters = characterIndex - strikethroughCharacterRun.characterRun.characterIndex;
}
+ if(span.isCharacterSpacingDefined)
+ {
+ CharacterSpacingCharacterRun& characterSpacingCharacterRun = *(characterSpacingCharacterRuns.Begin() + span.characterSpacingCharacterRunIndex);
+ characterSpacingCharacterRun.characterRun.numberOfCharacters = characterIndex - characterSpacingCharacterRun.characterRun.characterIndex;
+ }
+
--tagReference;
}
}
* @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,
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);
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)
StyleStack<Span> 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);
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();
markupProcessData.underlinedCharacterRuns,
markupProcessData.backgroundColorRuns,
markupProcessData.strikethroughCharacterRuns,
+ markupProcessData.characterSpacingCharacterRuns,
colorRunIndex,
fontRunIndex,
underlinedCharacterRunIndex,
backgroundRunIndex,
strikethroughCharacterRunIndex,
+ characterSpacingCharacterRunIndex,
characterIndex,
spanTagReference);
}
ProcessTagForRun<BoundedParagraphRun>(
markupProcessData.boundedParagraphRuns, styleStack, tag, characterIndex, boundedParagraphRunIndex, pTagReference, [](const Tag& tag, BoundedParagraphRun& run) { ProcessAttributesOfParagraphTag(tag, run); });
} // <p></p>
+ else if(TokenComparison(XHTML_CHARACTER_SPACING_TAG, tag.buffer, tag.length))
+ {
+ ProcessTagForRun<CharacterSpacingCharacterRun>(
+ markupProcessData.characterSpacingCharacterRuns, styleStack, tag, characterIndex, characterSpacingCharacterRunIndex, characterSpacingTagReference, [](const Tag& tag, CharacterSpacingCharacterRun& run) { ProcessCharacterSpacingTag(tag, run); });
+ } // <char-spacing></char-spacing>
} // end if( IsTag() )
else if(markupStringBuffer < markupStringEndBuffer)
{
}
// 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);
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/anchor.h>
#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-character-run.h>
#include <dali-toolkit/internal/text/color-run.h>
#include <dali-toolkit/internal/text/embedded-item.h>
#include <dali-toolkit/internal/text/font-description-run.h>
*/
struct MarkupProcessData
{
- MarkupProcessData(Vector<ColorRun>& colorRuns,
- Vector<FontDescriptionRun>& fontRuns,
- Vector<EmbeddedItem>& items,
- Vector<Anchor>& anchors,
- Vector<UnderlinedCharacterRun>& underlinedCharacterRuns,
- Vector<ColorRun>& backgroundColorRuns,
- Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns,
- Vector<BoundedParagraphRun>& boundedParagraphRuns)
+ MarkupProcessData(Vector<ColorRun>& colorRuns,
+ Vector<FontDescriptionRun>& fontRuns,
+ Vector<EmbeddedItem>& items,
+ Vector<Anchor>& anchors,
+ Vector<UnderlinedCharacterRun>& underlinedCharacterRuns,
+ Vector<ColorRun>& backgroundColorRuns,
+ Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns,
+ Vector<BoundedParagraphRun>& boundedParagraphRuns,
+ Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns)
: colorRuns(colorRuns),
fontRuns(fontRuns),
items(items),
backgroundColorRuns(backgroundColorRuns),
strikethroughCharacterRuns(strikethroughCharacterRuns),
boundedParagraphRuns(boundedParagraphRuns),
+ characterSpacingCharacterRuns(characterSpacingCharacterRuns),
markupProcessedText()
{
}
- Vector<ColorRun>& colorRuns; ///< The color runs.
- Vector<FontDescriptionRun>& fontRuns; ///< The font description runs.
- Vector<EmbeddedItem>& items; ///< The embedded items.
- Vector<Anchor>& anchors; ///< The anchors.
- Vector<UnderlinedCharacterRun>& underlinedCharacterRuns; ///< The underlined character runs.
- Vector<ColorRun>& backgroundColorRuns; ///< The background color runs.
- Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns; ///< The strikethrough character runs.
- Vector<BoundedParagraphRun>& boundedParagraphRuns; ///< The bounded paragraph runs
- std::string markupProcessedText; ///< The mark-up string.
+ Vector<ColorRun>& colorRuns; ///< The color runs.
+ Vector<FontDescriptionRun>& fontRuns; ///< The font description runs.
+ Vector<EmbeddedItem>& items; ///< The embedded items.
+ Vector<Anchor>& anchors; ///< The anchors.
+ Vector<UnderlinedCharacterRun>& underlinedCharacterRuns; ///< The underlined character runs.
+ Vector<ColorRun>& backgroundColorRuns; ///< The background color runs.
+ Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns; ///< The strikethrough character runs.
+ Vector<BoundedParagraphRun>& boundedParagraphRuns; ///< The bounded paragraph runs
+ Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns; ///< The character-spacing runs
+
+ std::string markupProcessedText; ///< The mark-up string.
};
/**
--- /dev/null
+/*
+ * 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 <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+static const Vector<CharacterSpacingGlyphRun> EMPTY_CHARACTER_SPACING_GLYPH_RUNS;
+}
+float GetGlyphCharacterSpacing(const GlyphIndex& index,
+ const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns,
+ const float modelCharacterSpacing)
+{
+ float characterSpacing = modelCharacterSpacing;
+ for(Vector<CharacterSpacingGlyphRun>::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<CharacterSpacingGlyphRun>& 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
--- /dev/null
+#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 <dali/devel-api/text-abstraction/font-metrics.h>
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
+#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
+
+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<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns,
+ const float modelCharacterSpacing);
+
+/**
+ * @brief Create static empty vector and retrun it.
+ *
+ * @return The reference for the empty character-spacing glyph runs.
+ */
+const Vector<CharacterSpacingGlyphRun>& GetEmptyCharacterSpacingGlyphRuns();
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H
\ No newline at end of file
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
#include <dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h>
#include <dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h>
#include <dali-toolkit/internal/text/rendering/view-model.h>
}
}
- 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<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = mModel->GetCharacterSpacingGlyphRuns();
// Aggregate underline-style-properties from mModel
const UnderlineStyleProperties modelUnderlineProperties{mModel->GetUnderlineType(),
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)
return mModel->GetBoundedParagraphRuns();
}
+Length ViewModel::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+ return mModel->GetNumberOfCharacterSpacingGlyphRuns();
+}
+
+const Vector<CharacterSpacingGlyphRun>& ViewModel::GetCharacterSpacingGlyphRuns() const
+{
+ return mModel->GetCharacterSpacingGlyphRuns();
+}
+
} // namespace Text
} // namespace Toolkit
*/
void GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns, StrikethroughRunIndex index, Length numberOfRuns) const override;
+ /**
+ * @copydoc ModelInterface::GetNumberOfCharacterSpacingGlyphRuns()
+ */
+ Length GetNumberOfCharacterSpacingGlyphRuns() const override;
+
+ /**
+ * @copydoc ModelInterface::GetCharacterSpacingGlyphRuns()
+ */
+ const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const override;
+
private:
const ModelInterface* const mModel; ///< Pointer to the text's model.
Vector<GlyphInfo> mElidedGlyphs; ///< Stores the glyphs of the elided text.
#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
#include <dali-toolkit/internal/text/text-view.h>
namespace Dali::Toolkit::Text
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<CharacterIndex>& glyphToCharacterMap = textVisualModel->mGlyphsToCharacters;
const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
float calculatedAdvance = 0.f;
+ // Get the character-spacing runs.
+ const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = textVisualModel->GetCharacterSpacingGlyphRuns();
+
Vector4 quad;
uint32_t numberOfQuads = 0u;
Length yLineOffset = 0;
// 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);
{
impl.CopyUnderlinedFromLogicalToVisualModels(true);
impl.CopyStrikethroughFromLogicalToVisualModels();
+ impl.CopyCharacterSpacingFromLogicalToVisualModels();
}
updated = true;
}
}
+void Controller::Impl::CopyCharacterSpacingFromLogicalToVisualModels()
+{
+ //CharacterSpacing character runs from markup-processor
+ const Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns = mModel->mLogicalModel->mCharacterSpacingCharacterRuns;
+ const Vector<GlyphIndex>& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph;
+ const Vector<Length>& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter;
+
+ mModel->mVisualModel->mCharacterSpacingRuns.Clear();
+
+ for(Vector<CharacterSpacingCharacterRun>::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)
*/
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.
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+#include <dali-toolkit/internal/text/emoji-helper.h>
#include <dali-toolkit/internal/text/markup-processor.h>
#include <dali-toolkit/internal/text/text-controller-impl.h>
#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
logicalModel->mUnderlinedCharacterRuns,
logicalModel->mBackgroundColorRuns,
logicalModel->mStrikethroughCharacterRuns,
- logicalModel->mBoundedParagraphRuns);
+ logicalModel->mBoundedParagraphRuns,
+ logicalModel->mCharacterSpacingCharacterRuns);
Length textSize = 0u;
const uint8_t* utf8 = NULL;
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);
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;
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
#include <dali-toolkit/internal/text/line-run.h>
#include <dali-toolkit/internal/text/script-run.h>
#include <dali-toolkit/internal/text/strikethrough-glyph-run.h>
virtual const Vector<BoundedParagraphRun>& 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<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const = 0;
+
+ /**
* @brief Retrieves the strikethrough runs.
*
* @param[out] strikethroughRuns Pointer to a buffer where the strikethrough runs are copied.
mVisualModel->GetStrikethroughRuns(strikethroughRuns, index, numberOfRuns);
}
+Length Model::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+ return mVisualModel->GetNumberOfCharacterSpacingGlyphRuns();
+}
+
+const Vector<CharacterSpacingGlyphRun>& Model::GetCharacterSpacingGlyphRuns() const
+{
+ return mVisualModel->GetCharacterSpacingGlyphRuns();
+}
+
const float Model::GetCharacterSpacing() const
{
return mVisualModel->GetCharacterSpacing();
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
#include <dali-toolkit/internal/text/logical-model-impl.h>
#include <dali-toolkit/internal/text/text-model-interface.h>
#include <dali-toolkit/internal/text/visual-model-impl.h>
*/
virtual const Vector<BoundedParagraphRun>& GetBoundedParagraphRuns() const override;
+ /**
+ * @copydoc ModelInterface::GetNumberOfCharacterSpacingGlyphRuns()
+ */
+ Length GetNumberOfCharacterSpacingGlyphRuns() const override;
+
+ /**
+ * @copydoc ModelInterface::GetCharacterSpacingGlyphRuns()
+ */
+ const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const override;
+
private: // Private contructors & copy operator.
/**
* @brief Private constructor.
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/cursor-helper-functions.h>
#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
using namespace Dali;
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<CharacterIndex>& glyphToCharacterMap = visualModel->mGlyphsToCharacters;
const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+ // Get the character-spacing runs.
+ const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns();
+
// Get the lines where the glyphs are laid-out.
const LineRun* lineRun = visualModel->mLines.Begin();
// 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)
{
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
#include <dali-toolkit/internal/text/text-definitions.h>
#include <dali-toolkit/internal/text/underlined-glyph-run.h>
#include <dali-toolkit/public-api/text/text-enumerations.h>
virtual const Vector<BoundedParagraphRun>& 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<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const = 0;
+
+ /**
* @brief Retrieves the strikethrough runs.
*
* @param[out] strikethroughRuns Pointer to a buffer where the strikethrough runs are copied.
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
namespace Dali
{
{
Length numberOfLaidOutGlyphs = 0u;
Length numberOfActualLaidOutGlyphs = 0u;
- const float characterSpacing = mImpl->mVisualModel->GetCharacterSpacing();
+ const float modelCharacterSpacing = mImpl->mVisualModel->GetCharacterSpacing();
Vector<CharacterIndex>& 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<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = mImpl->mVisualModel->GetCharacterSpacingGlyphRuns();
+
bool textElided = false;
DevelText::EllipsisPosition::Type ellipsisPosition = GetEllipsisPosition();
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.
return mImpl->mLogicalModel->GetBoundedParagraphRuns();
}
+Length View::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+ return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetNumberOfCharacterSpacingGlyphRuns() : 0u;
+}
+
+const Vector<CharacterSpacingGlyphRun>& View::GetCharacterSpacingGlyphRuns() const
+{
+ return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacingGlyphRuns() : GetEmptyCharacterSpacingGlyphRuns();
+}
+
const float View::GetCharacterSpacing() const
{
return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacing() : 0.f;
virtual const Vector<BoundedParagraphRun>& GetBoundedParagraphRuns() const;
/**
+ * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfCharacterSpacingGlyphRuns()
+ */
+ Length GetNumberOfCharacterSpacingGlyphRuns() const override;
+
+ /**
+ * @copydoc Dali::Toolkit::Text::ViewInterface::GetCharacterSpacingGlyphRuns()
+ */
+ const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const override;
+
+ /**
* @copydoc Dali::Toolkit::Text::ViewInterface::GetCharacterSpacing()
*/
const float GetCharacterSpacing() const override;
return mStrikethroughRuns.Count();
}
+Length VisualModel::GetNumberOfCharacterSpacingGlyphRuns() const
+{
+ return mCharacterSpacingRuns.Count();
+}
+
+const Vector<CharacterSpacingGlyphRun>& VisualModel::GetCharacterSpacingGlyphRuns() const
+{
+ return mCharacterSpacingRuns;
+}
+
void VisualModel::ClearCaches()
{
mCachedLineIndex = 0u;
#include <dali/public-api/object/ref-object.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-spacing-glyph-run.h>
#include <dali-toolkit/internal/text/color-run.h>
#include <dali-toolkit/internal/text/line-run.h>
#include <dali-toolkit/internal/text/strikethrough-glyph-run.h>
*/
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<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const;
+
protected:
/**
* @brief A reference counted object may only be deleted by calling Unreference().
VisualModel& operator=(const VisualModel& handle);
public:
- Vector<GlyphInfo> mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
- Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
- Vector<GlyphIndex> mCharactersToGlyph; ///< For each character, the index of the first glyph.
- Vector<Length> mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
- Vector<Length> mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
- Vector<Vector2> mGlyphPositions; ///< For each glyph, the position.
- Vector<LineRun> mLines; ///< The laid out lines.
- Vector<UnderlinedGlyphRun> mUnderlineRuns; ///< Runs of glyphs that are underlined.
- Vector<Vector4> mColors; ///< Colors of the glyphs.
- Vector<ColorIndex> mColorIndices; ///< Indices to the vector of colors for each glyphs.
- Vector<Vector4> mBackgroundColors; ///< Background colors of the glyphs.
- Vector<ColorIndex> 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<StrikethroughGlyphRun> mStrikethroughRuns; ///< Runs of glyphs that have strikethrough.
+ Vector<GlyphInfo> mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
+ Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
+ Vector<GlyphIndex> mCharactersToGlyph; ///< For each character, the index of the first glyph.
+ Vector<Length> mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
+ Vector<Length> mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
+ Vector<Vector2> mGlyphPositions; ///< For each glyph, the position.
+ Vector<LineRun> mLines; ///< The laid out lines.
+ Vector<UnderlinedGlyphRun> mUnderlineRuns; ///< Runs of glyphs that are underlined.
+ Vector<Vector4> mColors; ///< Colors of the glyphs.
+ Vector<ColorIndex> mColorIndices; ///< Indices to the vector of colors for each glyphs.
+ Vector<Vector4> mBackgroundColors; ///< Background colors of the glyphs.
+ Vector<ColorIndex> 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<StrikethroughGlyphRun> mStrikethroughRuns; ///< Runs of glyphs that have strikethrough.
+ Vector<CharacterSpacingGlyphRun> mCharacterSpacingRuns; ///< Runs of glyphs that have character-spacing.
private:
Size mNaturalSize; ///< Size of the text with no line wrapping.
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 15;
+const unsigned int TOOLKIT_MICRO_VERSION = 16;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.1.15
+Version: 2.1.16
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT
%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} \