From 1d6351bc6c29b125b71b266f4a8d0f25413e099d Mon Sep 17 00:00:00 2001 From: ssabah Date: Tue, 1 Mar 2022 00:45:57 +0300 Subject: [PATCH 1/1] Support character-spacing tag in markup How to apply it in TextEditor: textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::TEXT, "Hello Hello " "Hello " "Hello " "Hello " "Hello "); textEditor.SetProperty(Dali::Toolkit::TextEditor::Property::ENABLE_MARKUP, true); Change-Id: Ic24b6cd7e0b88fba175fdc008345956a8fa7980f --- .../dali-toolkit-test-utils/toolkit-text-utils.cpp | 3 +- .../dali-toolkit-internal/utc-Dali-Text-Markup.cpp | 19 +++--- .../utc-Dali-TextEditor-internal.cpp | 55 +++++++++++++++++ .../utc-Dali-TextField-internal.cpp | 55 +++++++++++++++++ .../utc-Dali-TextLabel-internal.cpp | 56 +++++++++++++++++ dali-toolkit/devel-api/text/text-utils-devel.cpp | 13 +++- dali-toolkit/internal/file.list | 4 +- .../text/character-spacing-character-run.h | 59 ++++++++++++++++++ .../internal/text/character-spacing-glyph-run.h | 57 +++++++++++++++++ .../internal/text/cursor-helper-functions.cpp | 14 ++++- .../internal/text/glyph-metrics-helper.cpp | 11 +++- .../layouts/layout-engine-helper-functions.cpp | 29 ++++++--- .../internal/text/layouts/layout-engine.cpp | 35 ++++++++--- dali-toolkit/internal/text/logical-model-impl.cpp | 17 +++++ dali-toolkit/internal/text/logical-model-impl.h | 22 ++++++- .../text/markup-processor-character-spacing.cpp | 66 ++++++++++++++++++++ .../text/markup-processor-character-spacing.h | 53 ++++++++++++++++ dali-toolkit/internal/text/markup-processor.cpp | 59 +++++++++++++----- dali-toolkit/internal/text/markup-processor.h | 39 +++++++----- .../styles/character-spacing-helper-functions.cpp | 63 +++++++++++++++++++ .../styles/character-spacing-helper-functions.h | 61 ++++++++++++++++++ .../internal/text/rendering/text-typesetter.cpp | 19 +++--- .../internal/text/rendering/view-model.cpp | 10 +++ dali-toolkit/internal/text/rendering/view-model.h | 10 +++ .../text/text-controller-background-actor.cpp | 8 ++- .../text/text-controller-impl-model-updater.cpp | 1 + .../internal/text/text-controller-impl.cpp | 33 ++++++++++ dali-toolkit/internal/text/text-controller-impl.h | 6 ++ .../internal/text/text-controller-text-updater.cpp | 3 +- dali-toolkit/internal/text/text-model-interface.h | 15 +++++ dali-toolkit/internal/text/text-model.cpp | 10 +++ dali-toolkit/internal/text/text-model.h | 11 ++++ .../text/text-selection-handle-controller.cpp | 13 ++-- dali-toolkit/internal/text/text-view-interface.h | 15 +++++ dali-toolkit/internal/text/text-view.cpp | 19 +++++- dali-toolkit/internal/text/text-view.h | 10 +++ dali-toolkit/internal/text/visual-model-impl.cpp | 10 +++ dali-toolkit/internal/text/visual-model-impl.h | 72 +++++++++++++--------- 38 files changed, 938 insertions(+), 117 deletions(-) create mode 100644 dali-toolkit/internal/text/character-spacing-character-run.h create mode 100644 dali-toolkit/internal/text/character-spacing-glyph-run.h create mode 100644 dali-toolkit/internal/text/markup-processor-character-spacing.cpp create mode 100644 dali-toolkit/internal/text/markup-processor-character-spacing.h create mode 100644 dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp create mode 100644 dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp index e22071a..e8bbb21 100644 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp @@ -116,7 +116,8 @@ void CreateTextModel(const std::string& text, logicalModel->mUnderlinedCharacterRuns, logicalModel->mBackgroundColorRuns, logicalModel->mStrikethroughCharacterRuns, - logicalModel->mBoundedParagraphRuns); + logicalModel->mBoundedParagraphRuns, + logicalModel->mCharacterSpacingCharacterRuns); Length textSize = 0u; const uint8_t* utf8 = NULL; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp index 7817c02..36117f7 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp @@ -178,15 +178,16 @@ bool XHTMLEntityToUTF8Test(const XHTMLEntityToUTF8Data& data) { std::cout << " testing " << data.description << std::endl; - Vector colorRuns; - Vector fontRuns; - Vector items; - Vector anchors; - Vector underlinedCharacterRuns; - Vector backgroundColorRuns; - Vector strikethroughCharacterRuns; - Vector boundedParagraphRuns; - MarkupProcessData markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns); + Vector colorRuns; + Vector fontRuns; + Vector items; + Vector anchors; + Vector underlinedCharacterRuns; + Vector backgroundColorRuns; + Vector strikethroughCharacterRuns; + Vector boundedParagraphRuns; + Vector characterSpacingCharacterRuns; + MarkupProcessData markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns, characterSpacingCharacterRuns); ProcessMarkupString(data.xHTMLEntityString, markupProcessData); for(Vector::Iterator it = items.Begin(), diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp index d19326f..5f7328f 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp @@ -1327,3 +1327,58 @@ int UtcDaliTextEditorMarkupParagraphTagAlignAttribute(void) END_TEST; } + +int UtcDaliTextEditorMarkupCharacterSpacingTag(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMarkupCharacterSpacingTag "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + TextEditor textEditor = TextEditor::New(); + + textEditor.SetProperty(TextEditor::Property::TEXT, "ABC EF\nABC EF\nABC EF\n"); + textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(textEditor); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextEditor& textEditorImpl = GetImpl(textEditor); + Text::ViewInterface& view = textEditorImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp index 02aa540..f8210dc 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp @@ -1235,4 +1235,59 @@ int UtcDaliTextFieldMarkupStrikethroughNoEndTag(void) DALI_TEST_EQUALS(numberOfStrikethroughRuns, expectedNumberOfStrikethroughGlyphs, TEST_LOCATION); END_TEST; +} + +int UtcDaliTextFieldMarkupCharacterSpacingTag(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldMarkupCharacterSpacingTag "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + TextField textField = TextField::New(); + + textField.SetProperty(TextField::Property::TEXT, "ABC EF\nABC EF\nABC EF\n"); + textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true); + + application.GetScene().Add(textField); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextField& textFieldImpl = GetImpl(textField); + Text::ViewInterface& view = textFieldImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; } \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp index 1ac00b5..2f1d1c6 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp @@ -1221,3 +1221,59 @@ int UtcDaliTextLabelMarkupParagraphTagAlignAttribute(void) END_TEST; } + +int UtcDaliTextLabelMarkupCharacterSpacingTag(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelMarkupCharacterSpacingTag "); + + const Length EXPECTED_NUMBER_OF_GLYPHS = 21u; + + const float expandedCharSpacing = 10.0f; + const float condensedCharSpacing = -5.0f; + + TextLabel textLabel = TextLabel::New(); + + textLabel.SetProperty(TextLabel::Property::TEXT, "ABC EF\nABC EF\nABC EF\n"); + textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true); + textLabel.SetProperty(TextLabel::Property::MULTI_LINE, true); + + application.GetScene().Add(textLabel); + + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextLabel& textLabelImpl = GetImpl(textLabel); + Text::ViewInterface& view = textLabelImpl.GetTextController()->GetView(); + + Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + DALI_TEST_EQUALS(numberOfGlyphs, EXPECTED_NUMBER_OF_GLYPHS, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + float alignmentOffset = 0u; + numberOfGlyphs = view.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + const Length numberOfGlyphsOneLine = 7u; + for(Length i = 0; i < numberOfGlyphsOneLine - 1u; i++) + { + float diffLineNoCharSpacing = positions[i + 1].x - positions[i].x; + + float diffLineCondensedCharSpacing = positions[numberOfGlyphsOneLine + i + 1].x - positions[numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineCondensedCharSpacing, diffLineNoCharSpacing + condensedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + + float diffLineExpandedCharSpacing = positions[2u * numberOfGlyphsOneLine + i + 1].x - positions[2u * numberOfGlyphsOneLine + i].x; + DALI_TEST_EQUALS(diffLineExpandedCharSpacing, diffLineNoCharSpacing + expandedCharSpacing, Math::MACHINE_EPSILON_1000, TEST_LOCATION); + } + + END_TEST; +} \ No newline at end of file diff --git a/dali-toolkit/devel-api/text/text-utils-devel.cpp b/dali-toolkit/devel-api/text/text-utils-devel.cpp index 7b5e36e..c9ab7b5 100644 --- a/dali-toolkit/devel-api/text/text-utils-devel.cpp +++ b/dali-toolkit/devel-api/text/text-utils-devel.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -178,7 +179,8 @@ void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstracti textModel->mLogicalModel->mUnderlinedCharacterRuns, textModel->mLogicalModel->mBackgroundColorRuns, textModel->mLogicalModel->mStrikethroughCharacterRuns, - textModel->mLogicalModel->mBoundedParagraphRuns); + textModel->mLogicalModel->mBoundedParagraphRuns, + textModel->mLogicalModel->mCharacterSpacingCharacterRuns); if(textParameters.markupEnabled) { @@ -819,10 +821,14 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen Vector& lines = textModel->mVisualModel->mLines; // The laid out lines. Vector& isEmoji = internalDataModel.isEmoji; const Size textLayoutArea = internalDataModel.textLayoutArea; - const float characterSpacing = textModel->mVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = textModel->mVisualModel->GetCharacterSpacing(); float calculatedAdvance = 0.f; Vector& glyphToCharacterMap = textModel->mVisualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = textModel->mVisualModel->GetCharacterSpacingGlyphRuns(); + //////////////////////////////////////////////////////////////////////////////// // Ellipsis the text. //////////////////////////////////////////////////////////////////////////////// @@ -908,7 +914,8 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen firstPenSet = true; } - calculatedAdvance = GetCalculatedAdvance(*(textModel->mLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyphToRemove.advance); + const float characterSpacing = GetGlyphCharacterSpacing(index, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textModel->mLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyphToRemove.advance); removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width)); // Calculate the width of the ellipsis glyph and check if it fits. diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 7e9c1aa..65d46fb 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -154,6 +154,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/markup-processor-span.cpp ${toolkit_src_dir}/text/markup-processor-strikethrough.cpp ${toolkit_src_dir}/text/markup-processor-underline.cpp + ${toolkit_src_dir}/text/markup-processor-character-spacing.cpp ${toolkit_src_dir}/text/markup-processor-helper-functions.cpp ${toolkit_src_dir}/text/markup-processor-attribute-helper-functions.cpp ${toolkit_src_dir}/text/multi-language-support.cpp @@ -203,7 +204,8 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/rendering/text-typesetter.cpp ${toolkit_src_dir}/text/rendering/view-model.cpp ${toolkit_src_dir}/text/rendering/styles/underline-helper-functions.cpp - ${toolkit_src_dir}/text/rendering/styles/strikethrough-helper-functions + ${toolkit_src_dir}/text/rendering/styles/strikethrough-helper-functions.cpp + ${toolkit_src_dir}/text/rendering/styles/character-spacing-helper-functions.cpp ${toolkit_src_dir}/transition/fade-transition-impl.cpp ${toolkit_src_dir}/transition/slide-transition-impl.cpp ${toolkit_src_dir}/transition/scale-transition-impl.cpp diff --git a/dali-toolkit/internal/text/character-spacing-character-run.h b/dali-toolkit/internal/text/character-spacing-character-run.h new file mode 100644 index 0000000..5c4238e --- /dev/null +++ b/dali-toolkit/internal/text/character-spacing-character-run.h @@ -0,0 +1,59 @@ +#ifndef DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H +#define DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Run of character-spacing characters with same properties. + */ +struct CharacterSpacingCharacterRun +{ + /** + * Default constructor to set the default values of bitfields + */ + CharacterSpacingCharacterRun() + : characterRun{}, + value{0.f} //The default value is 0.f which does nothing. + { + } + + CharacterRun characterRun; ///< The initial character index and the number of characters of the run. + float value; /// The spaces between characters in Pixels. A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed). + + //TODO: Add unit property to choose between Pixel or Scale (%) +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_CHARACTER_SPACING_CHARACTER_RUN_H diff --git a/dali-toolkit/internal/text/character-spacing-glyph-run.h b/dali-toolkit/internal/text/character-spacing-glyph-run.h new file mode 100644 index 0000000..7375533 --- /dev/null +++ b/dali-toolkit/internal/text/character-spacing-glyph-run.h @@ -0,0 +1,57 @@ +#ifndef DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H +#define DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Run of character-spacing glyphs with same properties. + */ +struct CharacterSpacingGlyphRun +{ + /** + * Default constructor to set the default values of bitfields + */ + CharacterSpacingGlyphRun() + : glyphRun{}, + value{0.f} //The default value is 0.f which does nothing. + { + } + + GlyphRun glyphRun; ///< The initial glyph index and the number of glyphs in the run. + float value; ///< The spaces between characters in Pixels. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_CHARACTER_SPACING_GLYPH_RUN_H diff --git a/dali-toolkit/internal/text/cursor-helper-functions.cpp b/dali-toolkit/internal/text/cursor-helper-functions.cpp index 3bfc059..3b3bf44 100644 --- a/dali-toolkit/internal/text/cursor-helper-functions.cpp +++ b/dali-toolkit/internal/text/cursor-helper-functions.cpp @@ -23,6 +23,7 @@ // INTERNAL INCLUDES #include +#include namespace { @@ -214,7 +215,10 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, { return logicalIndex; } - const float characterSpacing = visualModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); // Whether there is a hit on a line. bool matchedLine = false; @@ -289,7 +293,8 @@ CharacterIndex GetClosestCursorIndex(VisualModelPtr visualModel, // Get the metrics for the group of glyphs. GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + firstLogicalGlyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + firstLogicalGlyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(firstLogicalGlyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + firstLogicalGlyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + firstLogicalGlyphIndex)).advance); GetGlyphsMetrics(firstLogicalGlyphIndex, numberOfGlyphs, glyphMetrics, @@ -606,7 +611,9 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, const Length* const charactersPerGlyphBuffer = parameters.visualModel->mCharactersPerGlyph.Begin(); const CharacterIndex* const glyphsToCharactersBuffer = parameters.visualModel->mGlyphsToCharacters.Begin(); const Vector2* const glyphPositionsBuffer = parameters.visualModel->mGlyphPositions.Begin(); - const float characterSpacing = parameters.visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = parameters.visualModel->GetCharacterSpacing(); + + const Vector& characterSpacingGlyphRuns = parameters.visualModel->GetCharacterSpacingGlyphRuns(); // Get the metrics for the group of glyphs. GetGlyphMetricsFromCharacterIndex(index, parameters.visualModel, parameters.logicalModel, metrics, glyphMetrics, glyphIndex, numberOfGlyphs); @@ -723,6 +730,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, const bool addGlyphAdvance = ((!isFirstPositionOfLine && !isCurrentRightToLeft) || (isFirstPositionOfLine && !isRightToLeftParagraph)); + const float characterSpacing = GetGlyphCharacterSpacing(secondaryGlyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + (addGlyphAdvance ? (glyphMetrics.advance + characterSpacing) : 0.f); cursorInfo.secondaryPosition.y = cursorInfo.lineOffset + cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight; diff --git a/dali-toolkit/internal/text/glyph-metrics-helper.cpp b/dali-toolkit/internal/text/glyph-metrics-helper.cpp index 01c62c7..c46fefd 100644 --- a/dali-toolkit/internal/text/glyph-metrics-helper.cpp +++ b/dali-toolkit/internal/text/glyph-metrics-helper.cpp @@ -19,6 +19,9 @@ // FILE HEADER #include +// INTERNAL INCLUDES +#include + namespace Dali { namespace Toolkit @@ -114,7 +117,10 @@ void GetGlyphMetricsFromCharacterIndex(CharacterIndex index, const GlyphInfo* const glyphInfoBuffer = visualModel->mGlyphs.Begin(); Vector& glyphToCharacterMap = visualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); - const float characterSpacing = visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); //Takes the character index, obtains the glyph index (and the number of Glyphs) from it and finally gets the glyph metrics. glyphIndex = *(charactersToGlyphBuffer + index); @@ -122,7 +128,8 @@ void GetGlyphMetricsFromCharacterIndex(CharacterIndex index, float calculatedAdvance = 0.f; - calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + glyphIndex)).advance); // Get the metrics for the group of glyphs. GetGlyphsMetrics(glyphIndex, diff --git a/dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp b/dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp index 85676cf..db2fddf 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine-helper-functions.cpp @@ -20,6 +20,7 @@ // INTERNAL INCLUDE #include +#include namespace Dali { @@ -38,13 +39,16 @@ void CalculateGlyphPositionsLTR(const VisualModelPtr& visualModel, Vector2* glyphPositionsBuffer, float& penX) { - const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); - const float characterSpacing = visualModel->GetCharacterSpacing(); - const Character* const textBuffer = logicalModel->mText.Begin(); + const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); + const Character* const textBuffer = logicalModel->mText.Begin(); Vector& glyphToCharacterMap = visualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); + float calculatedAdvance = 0.f; for(GlyphIndex i = 0u; i < numberOfGlyphs; ++i) @@ -55,7 +59,8 @@ void CalculateGlyphPositionsLTR(const VisualModelPtr& visualModel, position.x = penX + glyph.xBearing; position.y = -glyph.yBearing; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + (startIndexForGlyph + i)))), characterSpacing, glyph.advance); + const float characterSpacing = GetGlyphCharacterSpacing((startIndexForGlyph + i), characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + (startIndexForGlyph + i)))), characterSpacing, glyph.advance); penX += (calculatedAdvance + interGlyphExtraAdvance); } } @@ -73,7 +78,10 @@ void CalculateGlyphPositionsRTL(const VisualModelPtr& visualModel, const BidirectionalLineInfoRun& bidiLine = logicalModel->mBidirectionalLineInfo[bidiLineIndex]; const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); const GlyphIndex* const charactersToGlyphsBuffer = visualModel->mCharactersToGlyph.Begin(); - const float characterSpacing = visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); float calculatedAdvance = 0.f; @@ -86,7 +94,8 @@ void CalculateGlyphPositionsRTL(const VisualModelPtr& visualModel, position.x = penX; position.y = -glyph.yBearing; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance); penX += calculatedAdvance; ++characterLogicalIndex; @@ -106,9 +115,12 @@ void TraversesCharactersForGlyphPositionsRTL(const VisualModelPtr& visualModel, { const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin(); const GlyphIndex* const charactersToGlyphsBuffer = visualModel->mCharactersToGlyph.Begin(); - const float characterSpacing = visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); const Length* const glyphsPerCharacterBuffer = visualModel->mGlyphsPerCharacter.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); + float calculatedAdvance = 0.f; for(; characterLogicalIndex < bidiLineCharacterRun.numberOfCharacters; @@ -133,7 +145,8 @@ void TraversesCharactersForGlyphPositionsRTL(const VisualModelPtr& visualModel, position.x = penX + glyph.xBearing; position.y = -glyph.yBearing; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyph.advance); penX += (calculatedAdvance + interGlyphExtraAdvance); } } diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index aff78c6..3fcc82c 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace Dali { @@ -299,7 +300,10 @@ struct Engine::Impl const float outlineWidth = static_cast(parameters.textModel->GetOutlineWidth()); const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs; - const float characterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns(); CharacterIndex characterLogicalIndex = 0u; CharacterIndex characterVisualIndex = 0u; @@ -330,7 +334,8 @@ struct Engine::Impl { const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex)); - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance); + const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance); whiteSpaceLengthEndOfLine += calculatedAdvance; ++characterLogicalIndex; @@ -352,7 +357,8 @@ struct Engine::Impl { const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex)); - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance); + const float characterSpacing = GetGlyphCharacterSpacing(characterVisualIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, glyphInfo.advance); whiteSpaceLengthEndOfLine += calculatedAdvance; ++characterLogicalIndex; @@ -370,7 +376,8 @@ struct Engine::Impl charactersPerGlyphBuffer); GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); GetGlyphsMetrics(glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -401,7 +408,8 @@ struct Engine::Impl characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u); GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); GetGlyphsMetrics(glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -463,7 +471,8 @@ struct Engine::Impl characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u); GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + characterVisualIndex), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); GetGlyphsMetrics(glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -700,13 +709,17 @@ struct Engine::Impl bool isSecondHalf = false; // Character Spacing - const float characterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = parameters.textModel->mVisualModel->GetCharacterSpacing(); float calculatedAdvance = 0.f; Vector& glyphToCharacterMap = parameters.textModel->mVisualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = parameters.textModel->mVisualModel->GetCharacterSpacingGlyphRuns(); + GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(lineLayout.glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + lineLayout.glyphIndex))), characterSpacing, (*(glyphsBuffer + lineLayout.glyphIndex)).advance); GetGlyphsMetrics(lineLayout.glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -747,7 +760,8 @@ struct Engine::Impl charactersPerGlyphBuffer); GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(glyphsBuffer + glyphIndex)).advance); GetGlyphsMetrics(glyphIndex, numberOfGLyphsInGroup, glyphMetrics, @@ -847,7 +861,8 @@ struct Engine::Impl while(tmpLineLayout.length + tmpLineLayout.whiteSpaceLengthEndOfLine > targetWidth && glyphIndexToRemove < glyphIndex) { GlyphMetrics glyphMetrics; - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndexToRemove, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + glyphIndexToRemove))), characterSpacing, (*(glyphsBuffer + glyphIndexToRemove)).advance); GetGlyphsMetrics(glyphIndexToRemove, numberOfGLyphsInGroup, glyphMetrics, diff --git a/dali-toolkit/internal/text/logical-model-impl.cpp b/dali-toolkit/internal/text/logical-model-impl.cpp index 9ad00bc..7ebf2a7 100644 --- a/dali-toolkit/internal/text/logical-model-impl.cpp +++ b/dali-toolkit/internal/text/logical-model-impl.cpp @@ -345,6 +345,13 @@ void LogicalModel::UpdateTextStyleRuns(CharacterIndex index, int numberOfCharact totalNumberOfCharacters, mBoundedParagraphRuns, removedBoundedParagraphRuns); + + Vector removedCharacterSpacingCharacterRuns; + UpdateCharacterRuns(index, + numberOfCharacters, + totalNumberOfCharacters, + mCharacterSpacingCharacterRuns, + removedCharacterSpacingCharacterRuns); } void LogicalModel::RetrieveStyle(CharacterIndex index, InputStyle& style) @@ -624,6 +631,16 @@ const Vector& LogicalModel::GetBoundedParagraphRuns() const return mBoundedParagraphRuns; } +Length LogicalModel::GetNumberOfCharacterSpacingCharacterRuns() const +{ + return mCharacterSpacingCharacterRuns.Count(); +} + +const Vector& LogicalModel::GetCharacterSpacingCharacterRuns() const +{ + return mCharacterSpacingCharacterRuns; +} + void LogicalModel::ClearEmbeddedImages() { FreeEmbeddedItems(mEmbeddedItems); diff --git a/dali-toolkit/internal/text/logical-model-impl.h b/dali-toolkit/internal/text/logical-model-impl.h index c54c523..0fa3df2 100644 --- a/dali-toolkit/internal/text/logical-model-impl.h +++ b/dali-toolkit/internal/text/logical-model-impl.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,20 @@ public: */ const Vector& GetBoundedParagraphRuns() const; + /** + * @brief Retrieves the number of character-spacing runs. + * + * @return The number of character-spacing runs. + */ + Length GetNumberOfCharacterSpacingCharacterRuns() const; + + /** + * @brief Retrieves the reference for character-spacing runs. + * + * @return The reference for character-spacing runs. + */ + const Vector& GetCharacterSpacingCharacterRuns() const; + // Embedded images /** @@ -241,9 +256,10 @@ public: Vector mBidirectionalLineInfo; Vector mEmbeddedItems; Vector mAnchors; - Vector mUnderlinedCharacterRuns; ///< The underlined character run from markup-processor - Vector mStrikethroughCharacterRuns; ///< The strikethrough character run from markup-processor - Vector mBoundedParagraphRuns; ///< The bounded paragraph is used to handle a paragraph mark-up tag and it's attributes. Like TextAlign, TextDirection, TextIndent, LineHeight, etc. + Vector mUnderlinedCharacterRuns; ///< The underlined character run from markup-processor + Vector mStrikethroughCharacterRuns; ///< The strikethrough character run from markup-processor + Vector mBoundedParagraphRuns; ///< The bounded paragraph is used to handle a paragraph mark-up tag and it's attributes. Like TextAlign, TextDirection, TextIndent, LineHeight, etc. + Vector mCharacterSpacingCharacterRuns; ///< The character-spacing character run from markup-processor. BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info. }; diff --git a/dali-toolkit/internal/text/markup-processor-character-spacing.cpp b/dali-toolkit/internal/text/markup-processor-character-spacing.cpp new file mode 100644 index 0000000..f0ef362 --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-character-spacing.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// FILE HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +namespace +{ +const std::string XHTML_VALUE_ATTRIBUTE("value"); + +} // namespace + +void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun) +{ + characterSpacingCharacterRun.value = ProcessFloatAttribute(attribute); +} + +void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun) +{ + for(Vector::ConstIterator it = tag.attributes.Begin(), + endIt = tag.attributes.End(); + it != endIt; + ++it) + { + const Attribute& attribute(*it); + + if(TokenComparison(XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ProcessValueAttribute(attribute, characterSpacingCharacterRun); + } + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/markup-processor-character-spacing.h b/dali-toolkit/internal/text/markup-processor-character-spacing.h new file mode 100644 index 0000000..b8b9beb --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-character-spacing.h @@ -0,0 +1,53 @@ +#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H +#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +struct Tag; +struct Attribute; +struct CharacterSpacingCharacterRun; + +/** + * @brief Fill the character-spacing character run with the value (space or advance) attribute. + * + * @param[in] attribute the value attribute. + * @param[out] characterSpacingCharacterRun The underlined character run + */ +void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun); + +/** + * @brief Retrieves the character-spacing run info from the tag and sets it to the character-spacing run. + * + * @param[in] tag The character-spacing tag and its attributes. + * @param[in,out] characterSpacingCharacterRun The character-spacing character run + */ +void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index 9c26b39..a11b303 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ const std::string XHTML_BACKGROUND_TAG("background"); const std::string XHTML_SPAN_TAG("span"); const std::string XHTML_STRIKETHROUGH_TAG("s"); const std::string XHTML_PARAGRAPH_TAG("p"); +const std::string XHTML_CHARACTER_SPACING_TAG("char-spacing"); const char LESS_THAN = '<'; const char GREATER_THAN = '>'; @@ -240,6 +242,18 @@ void Initialize(BoundedParagraphRun& boundedParagraphRun) } /** + * @brief Initializes a character-spacing run to its defaults. + * + * @param[in,out] characterSpacingCharacterRun The character-spacing run to initialize. + */ +void Initialize(CharacterSpacingCharacterRun& characterSpacingCharacterRun) +{ + characterSpacingCharacterRun.characterRun.characterIndex = 0u; + characterSpacingCharacterRun.characterRun.numberOfCharacters = 0u; + characterSpacingCharacterRun.value = 0.0f; +} + +/** * @brief Splits the tag string into the tag name and its attributes. * * The attributes are stored in a vector in the tag. @@ -893,6 +907,7 @@ void ProcessSpanForRun( * @param[in] strikethroughCharacterRunIndex The strikethroughed character run index * @param[in] backgroundRunIndex The background run index * @param[in] boundedParagraphRunIndex The bounded paragraph run index + * @param[in] characterSpacingCharacterRunIndex The character-spacing character run index * */ void ResizeModelVectors(MarkupProcessData& markupProcessData, @@ -901,7 +916,8 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData, const RunIndex underlinedCharacterRunIndex, const RunIndex strikethroughCharacterRunIndex, const RunIndex backgroundRunIndex, - const RunIndex boundedParagraphRunIndex) + const RunIndex boundedParagraphRunIndex, + const RunIndex characterSpacingCharacterRunIndex) { markupProcessData.fontRuns.Resize(fontRunIndex); markupProcessData.colorRuns.Resize(colorRunIndex); @@ -909,6 +925,7 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData, markupProcessData.strikethroughCharacterRuns.Resize(strikethroughCharacterRunIndex); markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex); markupProcessData.boundedParagraphRuns.Resize(boundedParagraphRunIndex); + markupProcessData.characterSpacingCharacterRuns.Resize(characterSpacingCharacterRunIndex); #ifdef DEBUG_ENABLED for(unsigned int i = 0; i < colorRunIndex; ++i) @@ -1028,23 +1045,25 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar StyleStack spanStack; // Points the next free position in the vector of runs. - RunIndex colorRunIndex = 0u; - RunIndex fontRunIndex = 0u; - RunIndex underlinedCharacterRunIndex = 0u; - RunIndex backgroundRunIndex = 0u; - RunIndex strikethroughCharacterRunIndex = 0u; - RunIndex boundedParagraphRunIndex = 0u; + RunIndex colorRunIndex = 0u; + RunIndex fontRunIndex = 0u; + RunIndex underlinedCharacterRunIndex = 0u; + RunIndex backgroundRunIndex = 0u; + RunIndex strikethroughCharacterRunIndex = 0u; + RunIndex boundedParagraphRunIndex = 0u; + RunIndex characterSpacingCharacterRunIndex = 0u; // check tag reference - int colorTagReference = 0u; - int fontTagReference = 0u; - int iTagReference = 0u; - int bTagReference = 0u; - int uTagReference = 0u; - int backgroundTagReference = 0u; - int spanTagReference = 0u; - int sTagReference = 0u; - int pTagReference = 0u; + int colorTagReference = 0u; + int fontTagReference = 0u; + int iTagReference = 0u; + int bTagReference = 0u; + int uTagReference = 0u; + int backgroundTagReference = 0u; + int spanTagReference = 0u; + int sTagReference = 0u; + int pTagReference = 0u; + int characterSpacingTagReference = 0u; // Give an initial default value to the model's vectors. markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE); @@ -1052,6 +1071,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.strikethroughCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); + markupProcessData.characterSpacingCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); // Get the mark-up string buffer. const char* markupStringBuffer = markupString.c_str(); @@ -1167,6 +1187,11 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar ProcessTagForRun( markupProcessData.boundedParagraphRuns, styleStack, tag, characterIndex, boundedParagraphRunIndex, pTagReference, [](const Tag& tag, BoundedParagraphRun& run) { ProcessAttributesOfParagraphTag(tag, run); }); } //

+ else if(TokenComparison(XHTML_CHARACTER_SPACING_TAG, tag.buffer, tag.length)) + { + ProcessTagForRun( + markupProcessData.characterSpacingCharacterRuns, styleStack, tag, characterIndex, characterSpacingCharacterRunIndex, characterSpacingTagReference, [](const Tag& tag, CharacterSpacingCharacterRun& run) { ProcessCharacterSpacingTag(tag, run); }); + } // } // end if( IsTag() ) else if(markupStringBuffer < markupStringEndBuffer) { @@ -1175,7 +1200,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar } // Resize the model's vectors. - ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex); + ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex, characterSpacingCharacterRunIndex); // Handle the nested tags OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns); diff --git a/dali-toolkit/internal/text/markup-processor.h b/dali-toolkit/internal/text/markup-processor.h index 3ef7a2d..f751843 100644 --- a/dali-toolkit/internal/text/markup-processor.h +++ b/dali-toolkit/internal/text/markup-processor.h @@ -25,6 +25,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -42,14 +43,15 @@ namespace Text */ struct MarkupProcessData { - MarkupProcessData(Vector& colorRuns, - Vector& fontRuns, - Vector& items, - Vector& anchors, - Vector& underlinedCharacterRuns, - Vector& backgroundColorRuns, - Vector& strikethroughCharacterRuns, - Vector& boundedParagraphRuns) + MarkupProcessData(Vector& colorRuns, + Vector& fontRuns, + Vector& items, + Vector& anchors, + Vector& underlinedCharacterRuns, + Vector& backgroundColorRuns, + Vector& strikethroughCharacterRuns, + Vector& boundedParagraphRuns, + Vector& characterSpacingCharacterRuns) : colorRuns(colorRuns), fontRuns(fontRuns), items(items), @@ -58,19 +60,22 @@ struct MarkupProcessData backgroundColorRuns(backgroundColorRuns), strikethroughCharacterRuns(strikethroughCharacterRuns), boundedParagraphRuns(boundedParagraphRuns), + characterSpacingCharacterRuns(characterSpacingCharacterRuns), markupProcessedText() { } - Vector& colorRuns; ///< The color runs. - Vector& fontRuns; ///< The font description runs. - Vector& items; ///< The embedded items. - Vector& anchors; ///< The anchors. - Vector& underlinedCharacterRuns; ///< The underlined character runs. - Vector& backgroundColorRuns; ///< The background color runs. - Vector& strikethroughCharacterRuns; ///< The strikethrough character runs. - Vector& boundedParagraphRuns; ///< The bounded paragraph runs - std::string markupProcessedText; ///< The mark-up string. + Vector& colorRuns; ///< The color runs. + Vector& fontRuns; ///< The font description runs. + Vector& items; ///< The embedded items. + Vector& anchors; ///< The anchors. + Vector& underlinedCharacterRuns; ///< The underlined character runs. + Vector& backgroundColorRuns; ///< The background color runs. + Vector& strikethroughCharacterRuns; ///< The strikethrough character runs. + Vector& boundedParagraphRuns; ///< The bounded paragraph runs + Vector& characterSpacingCharacterRuns; ///< The character-spacing runs + + std::string markupProcessedText; ///< The mark-up string. }; /** diff --git a/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp new file mode 100644 index 0000000..b166c99 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +namespace +{ +static const Vector EMPTY_CHARACTER_SPACING_GLYPH_RUNS; +} +float GetGlyphCharacterSpacing(const GlyphIndex& index, + const Vector& characterSpacingGlyphRuns, + const float modelCharacterSpacing) +{ + float characterSpacing = modelCharacterSpacing; + for(Vector::ConstIterator it = characterSpacingGlyphRuns.Begin(), + endIt = characterSpacingGlyphRuns.End(); + it != endIt; + ++it) + { + const CharacterSpacingGlyphRun& run = *it; + + if((run.glyphRun.glyphIndex <= index) && (index < run.glyphRun.glyphIndex + run.glyphRun.numberOfGlyphs)) + { + // Retrieve the latest run to handle the nested case. + //TODO: Using reverse Iterator will improve performance in this loop + characterSpacing = run.value; + } + } + + return characterSpacing; +} + +const Vector& GetEmptyCharacterSpacingGlyphRuns() +{ + // This is needed to return a common empty vector for CharacterSpacingGlyphRun + return EMPTY_CHARACTER_SPACING_GLYPH_RUNS; +} +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h new file mode 100644 index 0000000..3865b97 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h @@ -0,0 +1,61 @@ +#ifndef DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H +#define DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Check the glyph at index is had character-spacing or not then return its value. Otherwise return the model character-spacing height. + * + * @param[in] index the index of glyph. + * @param[in] characterSpacingGlyphRuns the character-spacing glyph runs. + * @param[in] modelCharacterSpacing the model character-spacing value. + * + * @return the determined character-spacing value + */ +float GetGlyphCharacterSpacing(const GlyphIndex& index, + const Vector& characterSpacingGlyphRuns, + const float modelCharacterSpacing); + +/** + * @brief Create static empty vector and retrun it. + * + * @return The reference for the empty character-spacing glyph runs. + */ +const Vector& GetEmptyCharacterSpacingGlyphRuns(); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_RENDERING_STYLES_CHARACTER_SPACING_HELPER_FUNCTIONS_H \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index 9d58934..628434e 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -26,6 +26,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -877,9 +878,12 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, } } - const bool underlineEnabled = mModel->IsUnderlineEnabled(); - const bool strikethroughEnabled = mModel->IsStrikethroughEnabled(); - const float characterSpacing = mModel->GetCharacterSpacing(); + const bool underlineEnabled = mModel->IsUnderlineEnabled(); + const bool strikethroughEnabled = mModel->IsStrikethroughEnabled(); + const float modelCharacterSpacing = mModel->GetCharacterSpacing(); + + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = mModel->GetCharacterSpacingGlyphRuns(); // Aggregate underline-style-properties from mModel const UnderlineStyleProperties modelUnderlineProperties{mModel->GetUnderlineType(), @@ -1024,10 +1028,11 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, if(addHyphen) { - GlyphInfo tempInfo = *(glyphsBuffer + elidedGlyphIndex); - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + elidedGlyphIndex))), characterSpacing, tempInfo.advance); - position.x = position.x + calculatedAdvance - tempInfo.xBearing + glyphInfo->xBearing; - position.y = -glyphInfo->yBearing; + GlyphInfo tempInfo = *(glyphsBuffer + elidedGlyphIndex); + const float characterSpacing = GetGlyphCharacterSpacing(glyphIndex, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + elidedGlyphIndex))), characterSpacing, tempInfo.advance); + position.x = position.x + calculatedAdvance - tempInfo.xBearing + glyphInfo->xBearing; + position.y = -glyphInfo->yBearing; } if(baseline < position.y + glyphInfo->yBearing) diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp index 0b26e4e..f02bb95 100644 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -655,6 +655,16 @@ const Vector& ViewModel::GetBoundedParagraphRuns() const return mModel->GetBoundedParagraphRuns(); } +Length ViewModel::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return mModel->GetNumberOfCharacterSpacingGlyphRuns(); +} + +const Vector& ViewModel::GetCharacterSpacingGlyphRuns() const +{ + return mModel->GetCharacterSpacingGlyphRuns(); +} + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/rendering/view-model.h b/dali-toolkit/internal/text/rendering/view-model.h index 73b7fa6..c7b0b18 100644 --- a/dali-toolkit/internal/text/rendering/view-model.h +++ b/dali-toolkit/internal/text/rendering/view-model.h @@ -329,6 +329,16 @@ public: */ void GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns, StrikethroughRunIndex index, Length numberOfRuns) const override; + /** + * @copydoc ModelInterface::GetNumberOfCharacterSpacingGlyphRuns() + */ + Length GetNumberOfCharacterSpacingGlyphRuns() const override; + + /** + * @copydoc ModelInterface::GetCharacterSpacingGlyphRuns() + */ + const Vector& GetCharacterSpacingGlyphRuns() const override; + private: const ModelInterface* const mModel; ///< Pointer to the text's model. Vector mElidedGlyphs; ///< Stores the glyphs of the elided text. diff --git a/dali-toolkit/internal/text/text-controller-background-actor.cpp b/dali-toolkit/internal/text/text-controller-background-actor.cpp index a129c5e..7def7e8 100644 --- a/dali-toolkit/internal/text/text-controller-background-actor.cpp +++ b/dali-toolkit/internal/text/text-controller-background-actor.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace Dali::Toolkit::Text @@ -98,11 +99,14 @@ Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr const Vector4* const backgroundColorsBuffer = textView.GetBackgroundColors(); const ColorIndex* const backgroundColorIndicesBuffer = textView.GetBackgroundColorIndices(); const Vector4& defaultBackgroundColor = textVisualModel->IsBackgroundEnabled() ? textVisualModel->GetBackgroundColor() : Color::TRANSPARENT; - const float characterSpacing = textVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = textVisualModel->GetCharacterSpacing(); Vector& glyphToCharacterMap = textVisualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); float calculatedAdvance = 0.f; + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = textVisualModel->GetCharacterSpacingGlyphRuns(); + Vector4 quad; uint32_t numberOfQuads = 0u; Length yLineOffset = 0; @@ -137,6 +141,8 @@ Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr // Only create quads for glyphs with a background color if(backgroundColor != Color::TRANSPARENT) { + const float characterSpacing = GetGlyphCharacterSpacing(i, characterSpacingGlyphRuns, modelCharacterSpacing); + const Vector2 position = *(positionsBuffer + i); calculatedAdvance = GetCalculatedAdvance(*(textLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + i))), characterSpacing, glyph.advance); diff --git a/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp b/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp index e6ec978..de18e85 100644 --- a/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp @@ -572,6 +572,7 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o { impl.CopyUnderlinedFromLogicalToVisualModels(true); impl.CopyStrikethroughFromLogicalToVisualModels(); + impl.CopyCharacterSpacingFromLogicalToVisualModels(); } updated = true; diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index e97535c..318c196 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -1692,6 +1692,39 @@ void Controller::Impl::CopyStrikethroughFromLogicalToVisualModels() } } +void Controller::Impl::CopyCharacterSpacingFromLogicalToVisualModels() +{ + //CharacterSpacing character runs from markup-processor + const Vector& characterSpacingCharacterRuns = mModel->mLogicalModel->mCharacterSpacingCharacterRuns; + const Vector& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph; + const Vector& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter; + + mModel->mVisualModel->mCharacterSpacingRuns.Clear(); + + for(Vector::ConstIterator it = characterSpacingCharacterRuns.Begin(), endIt = characterSpacingCharacterRuns.End(); it != endIt; ++it) + { + const CharacterIndex& characterIndex = it->characterRun.characterIndex; + const Length& numberOfCharacters = it->characterRun.numberOfCharacters; + + if(numberOfCharacters == 0) + { + continue; + } + + CharacterSpacingGlyphRun characterSpacingGlyphRun; + characterSpacingGlyphRun.value = it->value; + characterSpacingGlyphRun.glyphRun.glyphIndex = charactersToGlyph[characterIndex]; + characterSpacingGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex]; + + for(Length index = 1u; index < numberOfCharacters; index++) + { + characterSpacingGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index]; + } + + mModel->mVisualModel->mCharacterSpacingRuns.PushBack(characterSpacingGlyphRun); + } +} + void Controller::Impl::SetAutoScrollEnabled(bool enable) { if(mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX) diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 0757bc0..8be1767 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -961,6 +961,12 @@ private: */ void CopyStrikethroughFromLogicalToVisualModels(); + /** + * @brief Copy CharacterSpacing-Character-Runs from Logical-Model to CharacterSpacing-Glyph-Runs in Visual-Model + * + */ + void CopyCharacterSpacingFromLogicalToVisualModels(); + public: ControlInterface* mControlInterface; ///< Reference to the text controller. EditableControlInterface* mEditableControlInterface; ///< Reference to the editable text controller. diff --git a/dali-toolkit/internal/text/text-controller-text-updater.cpp b/dali-toolkit/internal/text/text-controller-text-updater.cpp index 0b24bc0..e31a3f1 100644 --- a/dali-toolkit/internal/text/text-controller-text-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-text-updater.cpp @@ -92,7 +92,8 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string& logicalModel->mUnderlinedCharacterRuns, logicalModel->mBackgroundColorRuns, logicalModel->mStrikethroughCharacterRuns, - logicalModel->mBoundedParagraphRuns); + logicalModel->mBoundedParagraphRuns, + logicalModel->mCharacterSpacingCharacterRuns); Length textSize = 0u; const uint8_t* utf8 = NULL; diff --git a/dali-toolkit/internal/text/text-model-interface.h b/dali-toolkit/internal/text/text-model-interface.h index c7e7b98..0f2bd7b 100644 --- a/dali-toolkit/internal/text/text-model-interface.h +++ b/dali-toolkit/internal/text/text-model-interface.h @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -403,6 +404,20 @@ public: virtual const Vector& GetBoundedParagraphRuns() const = 0; /** + * @brief Retrieves the number of character-spacing glyph runs. + * + * @return The number of character-spacing glyph runs. + */ + virtual Length GetNumberOfCharacterSpacingGlyphRuns() const = 0; + + /** + * @brief Retrieves the reference for character-spacing glyph runs. + * + * @return The reference for character-spacing glyph runs. + */ + virtual const Vector& GetCharacterSpacingGlyphRuns() const = 0; + + /** * @brief Retrieves the strikethrough runs. * * @param[out] strikethroughRuns Pointer to a buffer where the strikethrough runs are copied. diff --git a/dali-toolkit/internal/text/text-model.cpp b/dali-toolkit/internal/text/text-model.cpp index 924343c..0ac67ca 100644 --- a/dali-toolkit/internal/text/text-model.cpp +++ b/dali-toolkit/internal/text/text-model.cpp @@ -291,6 +291,16 @@ void Model::GetStrikethroughRuns(StrikethroughGlyphRun* strikethroughRuns, Strik mVisualModel->GetStrikethroughRuns(strikethroughRuns, index, numberOfRuns); } +Length Model::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return mVisualModel->GetNumberOfCharacterSpacingGlyphRuns(); +} + +const Vector& Model::GetCharacterSpacingGlyphRuns() const +{ + return mVisualModel->GetCharacterSpacingGlyphRuns(); +} + const float Model::GetCharacterSpacing() const { return mVisualModel->GetCharacterSpacing(); diff --git a/dali-toolkit/internal/text/text-model.h b/dali-toolkit/internal/text/text-model.h index ded9496..416df17 100644 --- a/dali-toolkit/internal/text/text-model.h +++ b/dali-toolkit/internal/text/text-model.h @@ -23,6 +23,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -313,6 +314,16 @@ public: */ virtual const Vector& GetBoundedParagraphRuns() const override; + /** + * @copydoc ModelInterface::GetNumberOfCharacterSpacingGlyphRuns() + */ + Length GetNumberOfCharacterSpacingGlyphRuns() const override; + + /** + * @copydoc ModelInterface::GetCharacterSpacingGlyphRuns() + */ + const Vector& GetCharacterSpacingGlyphRuns() const override; + private: // Private contructors & copy operator. /** * @brief Private constructor. diff --git a/dali-toolkit/internal/text/text-selection-handle-controller.cpp b/dali-toolkit/internal/text/text-selection-handle-controller.cpp index a36f81f..05d8ad5 100644 --- a/dali-toolkit/internal/text/text-selection-handle-controller.cpp +++ b/dali-toolkit/internal/text/text-selection-handle-controller.cpp @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include using namespace Dali; @@ -108,10 +109,13 @@ void SelectionHandleController::Reposition(Controller::Impl& impl) const GlyphIndex glyphStart = *(charactersToGlyphBuffer + selectionStart); const Length numberOfGlyphs = *(glyphsPerCharacterBuffer + selectionEndMinusOne); const GlyphIndex glyphEnd = *(charactersToGlyphBuffer + selectionEndMinusOne) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u); - const float characterSpacing = visualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = visualModel->GetCharacterSpacing(); Vector& glyphToCharacterMap = visualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = visualModel->GetCharacterSpacingGlyphRuns(); + // Get the lines where the glyphs are laid-out. const LineRun* lineRun = visualModel->mLines.Begin(); @@ -174,9 +178,10 @@ void SelectionHandleController::Reposition(Controller::Impl& impl) // Traverse the glyphs. for(GlyphIndex index = glyphStart; index <= glyphEnd; ++index) { - const GlyphInfo& glyph = *(glyphsBuffer + index); - const Vector2& position = *(positionsBuffer + index); - calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyph.advance); + const float characterSpacing = GetGlyphCharacterSpacing(index, characterSpacingGlyphRuns, modelCharacterSpacing); + const GlyphInfo& glyph = *(glyphsBuffer + index); + const Vector2& position = *(positionsBuffer + index); + calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + index))), characterSpacing, glyph.advance); if(splitStartGlyph) { diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index 9caf068..98b420d 100644 --- a/dali-toolkit/internal/text/text-view-interface.h +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -338,6 +339,20 @@ public: virtual const Vector& GetBoundedParagraphRuns() const = 0; /** + * @brief Retrieves the number of character-spacing glyph runs. + * + * @return The number of character-spacing glyph runs. + */ + virtual Length GetNumberOfCharacterSpacingGlyphRuns() const = 0; + + /** + * @brief Retrieves the reference for character-spacing glyph runs. + * + * @return The reference for character-spacing glyph runs. + */ + virtual const Vector& GetCharacterSpacingGlyphRuns() const = 0; + + /** * @brief Retrieves the strikethrough runs. * * @param[out] strikethroughRuns Pointer to a buffer where the strikethrough runs are copied. diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index fdccbe1..1ec978d 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -25,6 +25,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -107,12 +108,15 @@ Length View::GetGlyphs(GlyphInfo* glyphs, { Length numberOfLaidOutGlyphs = 0u; Length numberOfActualLaidOutGlyphs = 0u; - const float characterSpacing = mImpl->mVisualModel->GetCharacterSpacing(); + const float modelCharacterSpacing = mImpl->mVisualModel->GetCharacterSpacing(); Vector& glyphToCharacterMap = mImpl->mVisualModel->mGlyphsToCharacters; const CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); float calculatedAdvance = 0.f; const Character* textBuffer = mImpl->mLogicalModel->mText.Begin(); + // Get the character-spacing runs. + const Vector& characterSpacingGlyphRuns = mImpl->mVisualModel->GetCharacterSpacingGlyphRuns(); + if(mImpl->mVisualModel) { bool textElided = false; @@ -356,7 +360,8 @@ Length View::GetGlyphs(GlyphInfo* glyphs, firstPenSet = true; } - calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + indexOfEllipsis))), characterSpacing, glyphToRemove.advance); + const float characterSpacing = GetGlyphCharacterSpacing(indexOfEllipsis, characterSpacingGlyphRuns, modelCharacterSpacing); + calculatedAdvance = GetCalculatedAdvance(*(textBuffer + (*(glyphToCharacterMapBuffer + indexOfEllipsis))), characterSpacing, glyphToRemove.advance); removedGlypsWidth += std::min(calculatedAdvance, (glyphToRemove.xBearing + glyphToRemove.width)); // Calculate the width of the ellipsis glyph and check if it fits. @@ -839,6 +844,16 @@ const Vector& View::GetBoundedParagraphRuns() const return mImpl->mLogicalModel->GetBoundedParagraphRuns(); } +Length View::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetNumberOfCharacterSpacingGlyphRuns() : 0u; +} + +const Vector& View::GetCharacterSpacingGlyphRuns() const +{ + return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacingGlyphRuns() : GetEmptyCharacterSpacingGlyphRuns(); +} + const float View::GetCharacterSpacing() const { return (mImpl->mVisualModel) ? mImpl->mVisualModel->GetCharacterSpacing() : 0.f; diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index 06bf838..93542cc 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -259,6 +259,16 @@ public: virtual const Vector& GetBoundedParagraphRuns() const; /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfCharacterSpacingGlyphRuns() + */ + Length GetNumberOfCharacterSpacingGlyphRuns() const override; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetCharacterSpacingGlyphRuns() + */ + const Vector& GetCharacterSpacingGlyphRuns() const override; + + /** * @copydoc Dali::Toolkit::Text::ViewInterface::GetCharacterSpacing() */ const float GetCharacterSpacing() const override; diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index ce0fb7c..5ef2b50 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -609,6 +609,16 @@ Length VisualModel::GetNumberOfStrikethroughRuns() const return mStrikethroughRuns.Count(); } +Length VisualModel::GetNumberOfCharacterSpacingGlyphRuns() const +{ + return mCharacterSpacingRuns.Count(); +} + +const Vector& VisualModel::GetCharacterSpacingGlyphRuns() const +{ + return mCharacterSpacingRuns; +} + void VisualModel::ClearCaches() { mCachedLineIndex = 0u; diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index 4bae17c..9c0af3a 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -26,6 +26,7 @@ #include // INTERNAL INCLUDES +#include #include #include #include @@ -596,6 +597,20 @@ public: */ Length GetNumberOfStrikethroughRuns() const; + /** + * @brief Retrieves the number of character-spacing glyph runs. + * + * @return The number of character-spacing glyph runs. + */ + Length GetNumberOfCharacterSpacingGlyphRuns() const; + + /** + * @brief Retrieves the reference for character-spacing glyph runs. + * + * @return The reference for character-spacing glyph runs. + */ + const Vector& GetCharacterSpacingGlyphRuns() const; + protected: /** * @brief A reference counted object may only be deleted by calling Unreference(). @@ -615,34 +630,35 @@ private: VisualModel& operator=(const VisualModel& handle); public: - Vector mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics. - Vector mGlyphsToCharacters; ///< For each glyph, the index of the first character. - Vector mCharactersToGlyph; ///< For each character, the index of the first glyph. - Vector mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph. - Vector mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped. - Vector mGlyphPositions; ///< For each glyph, the position. - Vector mLines; ///< The laid out lines. - Vector mUnderlineRuns; ///< Runs of glyphs that are underlined. - Vector mColors; ///< Colors of the glyphs. - Vector mColorIndices; ///< Indices to the vector of colors for each glyphs. - Vector mBackgroundColors; ///< Background colors of the glyphs. - Vector mBackgroundColorIndices; ///< Indices to the vector of background colors for each glyphs. - Vector4 mTextColor; ///< The text color - Vector4 mShadowColor; ///< Color of drop shadow - Vector4 mUnderlineColor; ///< Color of underline - Vector4 mOutlineColor; ///< Color of outline - Vector4 mBackgroundColor; ///< Color of text background - Vector4 mStrikethroughColor; ///< Color of text background - Size mControlSize; ///< The size of the UI control. - Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow - float mUnderlineHeight; ///< Fixed height for underline to override font metrics. - float mStrikethroughHeight; ///< Fixed height for strikethrough to override font metrics. - Text::Underline::Type mUnderlineType; ///< The type of the underline. - float mDashedUnderlineWidth; ///< The width of the dashes of the dashed underline. - float mDashedUnderlineGap; ///< The gap between the dashes of the dashed underline. - float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur. - uint16_t mOutlineWidth; ///< Width of outline. - Vector mStrikethroughRuns; ///< Runs of glyphs that have strikethrough. + Vector mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics. + Vector mGlyphsToCharacters; ///< For each glyph, the index of the first character. + Vector mCharactersToGlyph; ///< For each character, the index of the first glyph. + Vector mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph. + Vector mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped. + Vector mGlyphPositions; ///< For each glyph, the position. + Vector mLines; ///< The laid out lines. + Vector mUnderlineRuns; ///< Runs of glyphs that are underlined. + Vector mColors; ///< Colors of the glyphs. + Vector mColorIndices; ///< Indices to the vector of colors for each glyphs. + Vector mBackgroundColors; ///< Background colors of the glyphs. + Vector mBackgroundColorIndices; ///< Indices to the vector of background colors for each glyphs. + Vector4 mTextColor; ///< The text color + Vector4 mShadowColor; ///< Color of drop shadow + Vector4 mUnderlineColor; ///< Color of underline + Vector4 mOutlineColor; ///< Color of outline + Vector4 mBackgroundColor; ///< Color of text background + Vector4 mStrikethroughColor; ///< Color of text background + Size mControlSize; ///< The size of the UI control. + Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow + float mUnderlineHeight; ///< Fixed height for underline to override font metrics. + float mStrikethroughHeight; ///< Fixed height for strikethrough to override font metrics. + Text::Underline::Type mUnderlineType; ///< The type of the underline. + float mDashedUnderlineWidth; ///< The width of the dashes of the dashed underline. + float mDashedUnderlineGap; ///< The gap between the dashes of the dashed underline. + float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur. + uint16_t mOutlineWidth; ///< Width of outline. + Vector mStrikethroughRuns; ///< Runs of glyphs that have strikethrough. + Vector mCharacterSpacingRuns; ///< Runs of glyphs that have character-spacing. private: Size mNaturalSize; ///< Size of the text with no line wrapping. -- 2.7.4