From a3c24db302ffb83a32a0b5d8fba0b2c9de2b6634 Mon Sep 17 00:00:00 2001 From: ssabah Date: Wed, 9 Feb 2022 18:24:55 +0200 Subject: [PATCH] Support Markup Underline attributes Underline attributes: - type - color - height - dash-gap - dash-width How to apply it: ========================================================================================= TextLabel textLabel = TextLabel::New(); std::string exampleText = "STARTonly underlineTHEN" "type is solidTHEN" "type is dashedTHEN" "type is doubleTHEN" "color is greenTHEN" "height is 5THEN" "dashGap is 3THEN" "dashWidth is 4THEN" "all attributesEND"; textLabel.SetProperty(Dali::Toolkit::TextLabel::Property::TEXT, exampleText); textLabel.SetProperty(Dali::Toolkit::TextLabel::Property::ENABLE_MARKUP, true); textLabel.SetProperty(Dali::Toolkit::TextLabel::Property::MULTI_LINE, true); ========================================================================================= This patch should be preceded by the patch below: https://review.tizen.org/gerrit/c/platform/core/uifw/dali-toolkit/+/271187 Change-Id: I4ca7f11a1b0eeab51e90b48c3d1bbc470ad628e8 --- .../utc-Dali-TextEditor-internal.cpp | 249 +++++++++++++++++++- .../utc-Dali-TextField-internal.cpp | 249 +++++++++++++++++++- .../utc-Dali-TextLabel-internal.cpp | 250 ++++++++++++++++++++- dali-toolkit/internal/file.list | 3 + .../internal/text/markup-processor-underline.cpp | 115 ++++++++++ .../internal/text/markup-processor-underline.h | 85 +++++++ dali-toolkit/internal/text/markup-processor.cpp | 3 +- .../text/rendering/atlas/text-atlas-renderer.cpp | 228 +++++++++---------- .../styles/strikethrough-helper-functions.cpp | 53 +++++ .../styles/strikethrough-helper-functions.h | 50 +++++ .../styles/underline-helper-functions.cpp | 122 ++++++++++ .../rendering/styles/underline-helper-functions.h | 101 +++++++++ .../internal/text/rendering/text-typesetter.cpp | 232 ++++++++----------- .../internal/text/rendering/view-model.cpp | 4 +- dali-toolkit/internal/text/rendering/view-model.h | 2 +- .../text/text-controller-impl-model-updater.cpp | 30 +-- .../internal/text/text-controller-impl.cpp | 20 +- dali-toolkit/internal/text/text-effects-style.cpp | 30 ++- dali-toolkit/internal/text/text-effects-style.h | 29 ++- dali-toolkit/internal/text/text-model-interface.h | 3 +- dali-toolkit/internal/text/text-model.cpp | 2 +- dali-toolkit/internal/text/text-model.h | 2 +- dali-toolkit/internal/text/text-view-interface.h | 7 +- dali-toolkit/internal/text/text-view.cpp | 6 +- dali-toolkit/internal/text/text-view.h | 6 +- .../internal/text/underline-style-properties.h | 123 ++++++++++ .../internal/text/underlined-character-run.h | 19 +- dali-toolkit/internal/text/underlined-glyph-run.h | 58 +++++ dali-toolkit/internal/text/visual-model-impl.cpp | 8 +- dali-toolkit/internal/text/visual-model-impl.h | 9 +- 30 files changed, 1760 insertions(+), 338 deletions(-) create mode 100644 dali-toolkit/internal/text/markup-processor-underline.cpp create mode 100644 dali-toolkit/internal/text/markup-processor-underline.h create mode 100644 dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.cpp create mode 100644 dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h create mode 100644 dali-toolkit/internal/text/rendering/styles/underline-helper-functions.cpp create mode 100644 dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h create mode 100644 dali-toolkit/internal/text/underline-style-properties.h create mode 100644 dali-toolkit/internal/text/underlined-glyph-run.h 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 c52141b..46abf15 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 @@ -94,18 +94,255 @@ int UtcDaliTextEditorMarkupUnderline(void) DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION); - Vector underlineRuns; + Vector underlineRuns; underlineRuns.Resize(numberOfUnderlineRuns); textEditorImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); //ABC are underlined - DALI_TEST_EQUALS(underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[1u].glyphIndex, 1u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[2u].glyphIndex, 2u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.glyphIndex, 0u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 1u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[2u].glyphRun.glyphIndex, 2u, TEST_LOCATION); //GH are underlined - DALI_TEST_EQUALS(underlineRuns[3u].glyphIndex, 5u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[4u].glyphIndex, 6u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[3u].glyphRun.glyphIndex, 5u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[4u].glyphRun.glyphIndex, 6u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTextEditorMarkupUnderlineAttributes(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMarkupUnderlineAttributes "); + + TextEditor textEditor = TextEditor::New(); + + application.GetScene().Add(textEditor); + + std::string testText = + "startABC1then" + "ABC2then" + "ABC3then" + "ABC4then" + "ABC5then" + "ABC6then" + "ABC7then" + "ABC8then" + "ABC9end" + + ; + + textEditor.SetProperty(TextEditor::Property::TEXT, testText); + textEditor.SetProperty(TextEditor ::Property::ENABLE_MARKUP, true); + + application.SendNotification(); + application.Render(); + + const uint32_t NUMBER_OF_CASES = 9u; + uint32_t expectedNumberOfUnderlinedGlyphs = 36u; + + Toolkit::Internal::TextEditor& textEditorImpl = GetImpl(textEditor); + const Text::Length numberOfUnderlineRuns = textEditorImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns(); + + DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION); + + Vector underlineRuns; + underlineRuns.Resize(numberOfUnderlineRuns); + textEditorImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); + + struct DataOfCase + { + std::string title; + uint32_t startIndex; + uint32_t endIndex; + GlyphIndex startGlyphIndex; + GlyphIndex endGlyphIndex; + UnderlineStyleProperties properties; + }; + DataOfCase data[] = + { + //ABC1 + {"ABC1", + 0u, + 3u, + 5u, + 8u, + { + Text::Underline::SOLID, + Color::BLACK, + 0u, + 1u, + 2u, + false, + false, + false, + false, + false, + }}, + + //ABC2 + {"ABC2", + 4u, + 7u, + 13u, + 16u, + { + Text::Underline::SOLID, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC3 + {"ABC3", + 8u, + 11u, + 21u, + 24u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC4 + {"ABC4", + 12u, + 15u, + 29u, + 32u, + { + Text::Underline::DOUBLE, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC5 + {"ABC5", + 16u, + 19u, + 37u, + 40u, + { + Text::Underline::SOLID, + Color::GREEN, + 0u, + 1u, + 2u, + false, + true, + false, + false, + false, + }}, + + //ABC6 + {"ABC6", + 20u, + 23u, + 45u, + 48u, + { + Text::Underline::SOLID, + Color::BLACK, + 5u, + 1u, + 2u, + false, + false, + true, + false, + false, + }}, + + //ABC7 + {"ABC7", + 24u, + 27u, + 53u, + 56u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 3u, + 2u, + true, + false, + false, + true, + false, + }}, + + //ABC8 + {"ABC8", + 28u, + 31u, + 61u, + 64u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 1u, + 4u, + true, + false, + false, + false, + true, + }}, + + // + {"", + 32u, + 35u, + 69u, + 72u, + { + Text::Underline::DASHED, + Color::BLUE, + 4u, + 2u, + 3u, + true, + true, + true, + true, + true, + }}, + + }; + + for(uint32_t i = 0; i < NUMBER_OF_CASES; i++) + { + tet_infoline(data[i].title.c_str()); + DALI_TEST_EQUALS(underlineRuns[data[i].startIndex].glyphRun.glyphIndex, data[i].startGlyphIndex, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[data[i].endIndex].glyphRun.glyphIndex, data[i].endGlyphIndex, TEST_LOCATION); + + DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].startIndex].properties); + DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].endIndex].properties); + } END_TEST; } 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 ae1c1fc..77366b6 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 @@ -176,18 +176,255 @@ int UtcDaliTextFieldMarkupUnderline(void) DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION); - Vector underlineRuns; + Vector underlineRuns; underlineRuns.Resize(numberOfUnderlineRuns); textFieldImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); //ABC are underlined - DALI_TEST_EQUALS(underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[1u].glyphIndex, 1u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[2u].glyphIndex, 2u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.glyphIndex, 0u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 1u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[2u].glyphRun.glyphIndex, 2u, TEST_LOCATION); //GH are underlined - DALI_TEST_EQUALS(underlineRuns[3u].glyphIndex, 5u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[4u].glyphIndex, 6u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[3u].glyphRun.glyphIndex, 5u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[4u].glyphRun.glyphIndex, 6u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTextFieldMarkupUnderlineAttributes(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldMarkupUnderlineAttributes "); + + TextField textField = TextField::New(); + + application.GetScene().Add(textField); + + std::string testText = + "startABC1then" + "ABC2then" + "ABC3then" + "ABC4then" + "ABC5then" + "ABC6then" + "ABC7then" + "ABC8then" + "ABC9end" + + ; + + textField.SetProperty(TextField::Property::TEXT, testText); + textField.SetProperty(TextField ::Property::ENABLE_MARKUP, true); + + application.SendNotification(); + application.Render(); + + const uint32_t NUMBER_OF_CASES = 9u; + uint32_t expectedNumberOfUnderlinedGlyphs = 36u; + + Toolkit::Internal::TextField& textFieldImpl = GetImpl(textField); + const Text::Length numberOfUnderlineRuns = textFieldImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns(); + + DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION); + + Vector underlineRuns; + underlineRuns.Resize(numberOfUnderlineRuns); + textFieldImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); + + struct DataOfCase + { + std::string title; + uint32_t startIndex; + uint32_t endIndex; + GlyphIndex startGlyphIndex; + GlyphIndex endGlyphIndex; + UnderlineStyleProperties properties; + }; + DataOfCase data[] = + { + //ABC1 + {"ABC1", + 0u, + 3u, + 5u, + 8u, + { + Text::Underline::SOLID, + Color::BLACK, + 0u, + 1u, + 2u, + false, + false, + false, + false, + false, + }}, + + //ABC2 + {"ABC2", + 4u, + 7u, + 13u, + 16u, + { + Text::Underline::SOLID, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC3 + {"ABC3", + 8u, + 11u, + 21u, + 24u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC4 + {"ABC4", + 12u, + 15u, + 29u, + 32u, + { + Text::Underline::DOUBLE, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC5 + {"ABC5", + 16u, + 19u, + 37u, + 40u, + { + Text::Underline::SOLID, + Color::GREEN, + 0u, + 1u, + 2u, + false, + true, + false, + false, + false, + }}, + + //ABC6 + {"ABC6", + 20u, + 23u, + 45u, + 48u, + { + Text::Underline::SOLID, + Color::BLACK, + 5u, + 1u, + 2u, + false, + false, + true, + false, + false, + }}, + + //ABC7 + {"ABC7", + 24u, + 27u, + 53u, + 56u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 3u, + 2u, + true, + false, + false, + true, + false, + }}, + + //ABC8 + {"ABC8", + 28u, + 31u, + 61u, + 64u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 1u, + 4u, + true, + false, + false, + false, + true, + }}, + + // + {"", + 32u, + 35u, + 69u, + 72u, + { + Text::Underline::DASHED, + Color::BLUE, + 4u, + 2u, + 3u, + true, + true, + true, + true, + true, + }}, + + }; + + for(uint32_t i = 0; i < NUMBER_OF_CASES; i++) + { + tet_infoline(data[i].title.c_str()); + DALI_TEST_EQUALS(underlineRuns[data[i].startIndex].glyphRun.glyphIndex, data[i].startGlyphIndex, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[data[i].endIndex].glyphRun.glyphIndex, data[i].endGlyphIndex, TEST_LOCATION); + + DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].startIndex].properties); + DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].endIndex].properties); + } END_TEST; } 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 81519c2..b1c380a 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 @@ -15,6 +15,7 @@ * */ +#include #include #include @@ -53,18 +54,255 @@ int UtcDaliTextLabelMarkupUnderline(void) DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION); - Vector underlineRuns; + Vector underlineRuns; underlineRuns.Resize(numberOfUnderlineRuns); textLabelImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); //ABC are underlined - DALI_TEST_EQUALS(underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[1u].glyphIndex, 1u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[2u].glyphIndex, 2u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[0u].glyphRun.glyphIndex, 0u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[1u].glyphRun.glyphIndex, 1u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[2u].glyphRun.glyphIndex, 2u, TEST_LOCATION); //GH are underlined - DALI_TEST_EQUALS(underlineRuns[3u].glyphIndex, 5u, TEST_LOCATION); - DALI_TEST_EQUALS(underlineRuns[4u].glyphIndex, 6u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[3u].glyphRun.glyphIndex, 5u, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[4u].glyphRun.glyphIndex, 6u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTextLabelMarkupUnderlineAttributes(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelMarkupUnderlineAttributes "); + + TextLabel textLabel = TextLabel::New(); + + application.GetScene().Add(textLabel); + + std::string testText = + "startABC1then" + "ABC2then" + "ABC3then" + "ABC4then" + "ABC5then" + "ABC6then" + "ABC7then" + "ABC8then" + "ABC9end" + + ; + + textLabel.SetProperty(TextLabel::Property::TEXT, testText); + textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true); + + application.SendNotification(); + application.Render(); + + const uint32_t NUMBER_OF_CASES = 9u; + uint32_t expectedNumberOfUnderlinedGlyphs = 36u; + + Toolkit::Internal::TextLabel& textLabelImpl = GetImpl(textLabel); + const Text::Length numberOfUnderlineRuns = textLabelImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns(); + + DALI_TEST_EQUALS(numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION); + + Vector underlineRuns; + underlineRuns.Resize(numberOfUnderlineRuns); + textLabelImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); + + struct DataOfCase + { + std::string title; + uint32_t startIndex; + uint32_t endIndex; + GlyphIndex startGlyphIndex; + GlyphIndex endGlyphIndex; + UnderlineStyleProperties properties; + }; + DataOfCase data[] = + { + //ABC1 + {"ABC1", + 0u, + 3u, + 5u, + 8u, + { + Text::Underline::SOLID, + Color::BLACK, + 0u, + 1u, + 2u, + false, + false, + false, + false, + false, + }}, + + //ABC2 + {"ABC2", + 4u, + 7u, + 13u, + 16u, + { + Text::Underline::SOLID, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC3 + {"ABC3", + 8u, + 11u, + 21u, + 24u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC4 + {"ABC4", + 12u, + 15u, + 29u, + 32u, + { + Text::Underline::DOUBLE, + Color::BLACK, + 0u, + 1u, + 2u, + true, + false, + false, + false, + false, + }}, + + //ABC5 + {"ABC5", + 16u, + 19u, + 37u, + 40u, + { + Text::Underline::SOLID, + Color::GREEN, + 0u, + 1u, + 2u, + false, + true, + false, + false, + false, + }}, + + //ABC6 + {"ABC6", + 20u, + 23u, + 45u, + 48u, + { + Text::Underline::SOLID, + Color::BLACK, + 5u, + 1u, + 2u, + false, + false, + true, + false, + false, + }}, + + //ABC7 + {"ABC7", + 24u, + 27u, + 53u, + 56u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 3u, + 2u, + true, + false, + false, + true, + false, + }}, + + //ABC8 + {"ABC8", + 28u, + 31u, + 61u, + 64u, + { + Text::Underline::DASHED, + Color::BLACK, + 0u, + 1u, + 4u, + true, + false, + false, + false, + true, + }}, + + // + {"", + 32u, + 35u, + 69u, + 72u, + { + Text::Underline::DASHED, + Color::BLUE, + 4u, + 2u, + 3u, + true, + true, + true, + true, + true, + }}, + + }; + + for(uint32_t i = 0; i < NUMBER_OF_CASES; i++) + { + tet_infoline(data[i].title.c_str()); + DALI_TEST_EQUALS(underlineRuns[data[i].startIndex].glyphRun.glyphIndex, data[i].startGlyphIndex, TEST_LOCATION); + DALI_TEST_EQUALS(underlineRuns[data[i].endIndex].glyphRun.glyphIndex, data[i].endGlyphIndex, TEST_LOCATION); + + DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].startIndex].properties); + DALI_TEST_CHECK(data[i].properties == underlineRuns[data[i].endIndex].properties); + } END_TEST; } diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 8c84b35..c65b61e 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -149,6 +149,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/markup-processor-background.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-helper-functions.cpp ${toolkit_src_dir}/text/markup-processor-attribute-helper-functions.cpp ${toolkit_src_dir}/text/multi-language-support.cpp @@ -197,6 +198,8 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/rendering/text-backend-impl.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}/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/markup-processor-underline.cpp b/dali-toolkit/internal/text/markup-processor-underline.cpp new file mode 100644 index 0000000..063f3fe --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-underline.cpp @@ -0,0 +1,115 @@ +/* + * 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 +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +namespace +{ +const std::string XHTML_COLOR_ATTRIBUTE("color"); +const std::string XHTML_HEIGHT_ATTRIBUTE("height"); +const std::string XHTML_TYPE_ATTRIBUTE("type"); +const std::string XHTML_DASH_GAP_ATTRIBUTE("dash-gap"); +const std::string XHTML_DASH_WIDTH_ATTRIBUTE("dash-width"); + +const unsigned int MAX_TYPE_ATTRIBUTE_SIZE = 7u; ///< The maximum length of any of the possible 'type' values. + +} // namespace + +void ProcessTypeAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun) +{ + underlinedCharacterRun.properties.typeDefined = ProcessEnumerationAttribute(attribute, + MAX_TYPE_ATTRIBUTE_SIZE, + &StringToUnderlineType, + underlinedCharacterRun.properties.type); +} + +void ProcessDashGapAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun) +{ + underlinedCharacterRun.properties.dashGap = ProcessFloatAttribute(attribute); + underlinedCharacterRun.properties.dashGapDefined = true; +} + +void ProcessDashWidthAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun) +{ + underlinedCharacterRun.properties.dashWidth = ProcessFloatAttribute(attribute); + underlinedCharacterRun.properties.dashWidthDefined = true; +} +void ProcessHeightAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun) +{ + underlinedCharacterRun.properties.height = ProcessFloatAttribute(attribute); + underlinedCharacterRun.properties.heightDefined = true; +} + +void ProcessColorAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun) +{ + ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, underlinedCharacterRun.properties.color); + underlinedCharacterRun.properties.colorDefined = true; +} + +void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedCharacterRun) +{ + for(Vector::ConstIterator it = tag.attributes.Begin(), + endIt = tag.attributes.End(); + it != endIt; + ++it) + { + const Attribute& attribute(*it); + + if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ProcessColorAttribute(attribute, underlinedCharacterRun); + } + else if(TokenComparison(XHTML_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ProcessHeightAttribute(attribute, underlinedCharacterRun); + } + else if(TokenComparison(XHTML_TYPE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ProcessTypeAttribute(attribute, underlinedCharacterRun); + } + else if(TokenComparison(XHTML_DASH_GAP_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ProcessDashGapAttribute(attribute, underlinedCharacterRun); + } + else if(TokenComparison(XHTML_DASH_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ProcessDashWidthAttribute(attribute, underlinedCharacterRun); + } + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/markup-processor-underline.h b/dali-toolkit/internal/text/markup-processor-underline.h new file mode 100644 index 0000000..f210718 --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-underline.h @@ -0,0 +1,85 @@ +#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_H +#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_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 UnderlinedCharacterRun; + +/** + * @brief Fill the underlined character run with the type attribute value. + * + * @param[in] attribute the type attribute. + * @param[out] underlinedCharacterRun The underlined character run + */ +void ProcessTypeAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun); + +/** + * @brief Fill the underlined character run with the dash-gap attribute value. + * + * @param[in] attribute the dash-gap attribute. + * @param[out] underlinedCharacterRun The underlined character run + */ +void ProcessDashGapAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun); + +/** + * @brief Fill the underlined character run with the dash-width attribute value. + * + * @param[in] attribute the dash-width attribute. + * @param[out] underlinedCharacterRun The underlined character run + */ +void ProcessDashWidthAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun); + +/** + * @brief Fill the underlined character run with the height attribute value. + * + * @param[in] attribute the height attribute. + * @param[out] underlinedCharacterRun The underlined character run + */ +void ProcessHeightAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun); + +/** + * @brief Fill the underlined character run with the color attribute value. + * + * @param[in] attribute the color attribute. + * @param[out] underlinedCharacterRun The underlined character run + */ +void ProcessColorAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun); + +/** + * @brief Retrieves the underline run info from the tag and sets it to the underline run. + * + * @param[in] tag The underline tag and its attributes. + * @param[in,out] underlinedCharacterRun The underlined character run + */ +void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedCharacterRun); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_H diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index 7ed1f61..17aae96 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include namespace Dali @@ -940,7 +941,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar else if(TokenComparison(XHTML_U_TAG, tag.buffer, tag.length)) { ProcessTagForRun( - markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {}); + markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) { ProcessUnderlineTag(tag, run); }); } // else if(TokenComparison(XHTML_B_TAG, tag.buffer, tag.length)) { diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index 9946d49..9eb2fd6 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -24,6 +24,7 @@ #include #include #include +#include // INTERNAL INCLUDES #include @@ -32,6 +33,8 @@ #include #include #include +#include +#include #include using namespace Dali; @@ -158,28 +161,10 @@ struct AtlasRenderer::Impl mQuadVertexFormat["aColor"] = Property::VECTOR4; } - bool IsGlyphUnderlined(GlyphIndex index, - const Vector& underlineRuns) - { - for(Vector::ConstIterator it = underlineRuns.Begin(), - endIt = underlineRuns.End(); - it != endIt; - ++it) - { - const GlyphRun& run = *it; - - if((run.glyphIndex <= index) && (index < run.glyphIndex + run.numberOfGlyphs)) - { - return true; - } - } - - return false; - } - - bool doGlyphHaveStrikethrough(GlyphIndex index, - const Vector& strikethroughRuns, - Vector4& strikethroughColor) + bool + doGlyphHaveStrikethrough(GlyphIndex index, + const Vector& strikethroughRuns, + Vector4& strikethroughColor) { for(Vector::ConstIterator it = strikethroughRuns.Begin(), endIt = strikethroughRuns.End(); @@ -456,27 +441,22 @@ struct AtlasRenderer::Impl Vector strikethroughExtents; mDepth = depth; - const Vector2& textSize(view.GetLayoutSize()); - const Vector2 halfTextSize(textSize * 0.5f); - const Vector2& shadowOffset(view.GetShadowOffset()); - const Vector4& shadowColor(view.GetShadowColor()); - const bool underlineEnabled = view.IsUnderlineEnabled(); - const Vector4& underlineColor(view.GetUnderlineColor()); - const float underlineHeight = view.GetUnderlineHeight(); - const Text::Underline::Type underlineType = view.GetUnderlineType(); - const float dashedUnderlineWidth = view.GetDashedUnderlineWidth(); - const float dashedUnderlineGap = view.GetDashedUnderlineGap(); - const uint16_t outlineWidth = view.GetOutlineWidth(); - const Vector4& outlineColor(view.GetOutlineColor()); - const bool isOutline = 0u != outlineWidth; - const GlyphInfo* hyphens = view.GetHyphens(); - const Length* hyphenIndices = view.GetHyphenIndices(); - const Length hyphensCount = view.GetHyphensCount(); - const bool strikethroughEnabled = view.IsStrikethroughEnabled(); - const Vector4& strikethroughColor(view.GetStrikethroughColor()); - const float strikethroughHeight = view.GetStrikethroughHeight(); - Vector4 currentStrikethroughColor; - const float characterSpacing(view.GetCharacterSpacing()); + const Vector2& textSize(view.GetLayoutSize()); + const Vector2 halfTextSize(textSize * 0.5f); + const Vector2& shadowOffset(view.GetShadowOffset()); + const Vector4& shadowColor(view.GetShadowColor()); + const bool underlineEnabled = view.IsUnderlineEnabled(); + const uint16_t outlineWidth = view.GetOutlineWidth(); + const Vector4& outlineColor(view.GetOutlineColor()); + const bool isOutline = 0u != outlineWidth; + const GlyphInfo* hyphens = view.GetHyphens(); + const Length* hyphenIndices = view.GetHyphenIndices(); + const Length hyphensCount = view.GetHyphensCount(); + const bool strikethroughEnabled = view.IsStrikethroughEnabled(); + const Vector4& strikethroughColor(view.GetStrikethroughColor()); + const float strikethroughHeight = view.GetStrikethroughHeight(); + Vector4 currentStrikethroughColor; + const float characterSpacing(view.GetCharacterSpacing()); // Elided text info. Indices according to elided text. const auto startIndexOfGlyphs = view.GetStartIndexOfElidedGlyphs(); @@ -485,14 +465,31 @@ struct AtlasRenderer::Impl const bool useDefaultColor = (NULL == colorsBuffer); + // Get a handle of the font client. Used to retrieve the bitmaps of the glyphs. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + // Get the underline runs. - const Length numberOfUnderlineRuns = view.GetNumberOfUnderlineRuns(); - Vector underlineRuns; + const Length numberOfUnderlineRuns = view.GetNumberOfUnderlineRuns(); + Vector underlineRuns; underlineRuns.Resize(numberOfUnderlineRuns); view.GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); + // Aggregate underline-style-properties from view + const UnderlineStyleProperties viewUnderlineProperties{view.GetUnderlineType(), + view.GetUnderlineColor(), + view.GetUnderlineHeight(), + view.GetDashedUnderlineGap(), + view.GetDashedUnderlineWidth(), + true, + true, + true, + true, + true}; + + float maxUnderlineHeight = viewUnderlineProperties.height; + // Get the strikethrough runs. const Length numberOfStrikethroughRuns = view.GetNumberOfStrikethroughRuns(); Vector strikethroughRuns; @@ -502,12 +499,11 @@ struct AtlasRenderer::Impl bool thereAreUnderlinedGlyphs = false; bool strikethroughGlyphsExist = false; - float currentUnderlinePosition = ZERO; - float currentUnderlineThickness = underlineHeight; - float currentStrikethroughThickness = strikethroughHeight; - FontId lastFontId = 0; - FontId lastUnderlinedFontId = 0; - Style style = STYLE_NORMAL; + float currentUnderlinePosition = ZERO; + float currentStrikethroughHeight = strikethroughHeight; + float maxStrikethroughHeight = currentStrikethroughHeight; + FontId lastFontId = 0; + Style style = STYLE_NORMAL; if(fabsf(shadowOffset.x) > Math::MACHINE_EPSILON_1 || fabsf(shadowOffset.y) > Math::MACHINE_EPSILON_1) { @@ -524,8 +520,10 @@ struct AtlasRenderer::Impl uint32_t hyphenIndex = 0; //For septated underlined chunks. (this is for Markup case) - uint32_t underlineChunkId = 0u; // give id for each chunk. - bool isPreUnderlined = false; // status of underlined for previous glyph. + uint32_t underlineChunkId = 0u; // give id for each chunk. + bool isPreUnderlined = false; // status of underlined for previous glyph. + std::map mapUnderlineChunkIdWithProperties; // mapping underlineChunkId with UnderlineStyleProperties to get properties of underlined chunk + UnderlineStyleProperties preUnderlineProperties = viewUnderlineProperties; // the previous UnderlineStyleProperties uint32_t strikethroughChunkId = 0u; // give id for each chunk. bool isPrevGlyphStrikethrough = false; // status of strikethrough for previous glyph. @@ -544,6 +542,12 @@ struct AtlasRenderer::Impl } } + //To keep the last fontMetrics of lastDecorativeLinesFontId + FontId lastDecorativeLinesFontId = 0; // DecorativeLines like Undeline and Strikethrough + FontMetrics lastDecorativeLinesFontMetrics; + fontClient.GetFontMetrics(lastDecorativeLinesFontId, lastDecorativeLinesFontMetrics); + + // Iteration on glyphs for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i) { GlyphInfo glyph; @@ -558,8 +562,11 @@ struct AtlasRenderer::Impl glyph = *(glyphsBuffer + i); } - const bool isGlyphUnderlined = underlineEnabled || IsGlyphUnderlined(i, underlineRuns); - thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || isGlyphUnderlined; + Vector::ConstIterator currentUnderlinedGlyphRunIt = underlineRuns.End(); + const bool isGlyphUnderlined = underlineEnabled || IsGlyphUnderlined(i, underlineRuns, currentUnderlinedGlyphRunIt); + const UnderlineStyleProperties currentUnderlineProperties = GetCurrentUnderlineProperties(isGlyphUnderlined, underlineRuns, currentUnderlinedGlyphRunIt, viewUnderlineProperties); + float currentUnderlineHeight = GetCurrentUnderlineHeight(underlineRuns, currentUnderlinedGlyphRunIt, viewUnderlineProperties.height); + thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || isGlyphUnderlined; currentStrikethroughColor = strikethroughColor; const bool isStrikethroughGlyph = strikethroughEnabled || doGlyphHaveStrikethrough(i, strikethroughRuns, currentStrikethroughColor); @@ -568,58 +575,42 @@ struct AtlasRenderer::Impl // No operation for white space if(glyph.width && glyph.height) { - // Are we still using the same fontId as previous - if((isGlyphUnderlined || isStrikethroughGlyph) && (glyph.fontId != lastUnderlinedFontId)) + // Check and update decorative-lines informations + if((isGlyphUnderlined || isStrikethroughGlyph) && + ((glyph.fontId != lastDecorativeLinesFontId) || !(currentUnderlineProperties.IsHeightEqualTo(preUnderlineProperties)))) { - // We need to fetch fresh font underline metrics - FontMetrics fontMetrics; - mFontClient.GetFontMetrics(glyph.fontId, fontMetrics); - currentUnderlinePosition = ceil(fabsf(fontMetrics.underlinePosition)); - const float descender = ceil(fabsf(fontMetrics.descender)); - - if(fabsf(underlineHeight) < Math::MACHINE_EPSILON_1000) + bool isDecorativeLinesFontIdUpdated = false; + // Are we still using the same fontId as previous + if(glyph.fontId != lastDecorativeLinesFontId) { - currentUnderlineThickness = fontMetrics.underlineThickness; + // We need to fetch fresh font metrics + lastDecorativeLinesFontId = glyph.fontId; + isDecorativeLinesFontIdUpdated = true; + fontClient.GetFontMetrics(lastDecorativeLinesFontId, lastDecorativeLinesFontMetrics); - // Ensure underline will be at least a pixel high - if(currentUnderlineThickness < ONE) + if(isStrikethroughGlyph || isGlyphUnderlined) { - currentUnderlineThickness = ONE; - } - else - { - currentUnderlineThickness = ceil(currentUnderlineThickness); + //The currentUnderlinePosition will be used for both Underline and/or Strikethrough + currentUnderlinePosition = FetchUnderlinePositionFromFontMetrics(lastDecorativeLinesFontMetrics); } } - if(fabsf(strikethroughHeight) < Math::MACHINE_EPSILON_1000) + if(isGlyphUnderlined && (isDecorativeLinesFontIdUpdated || !(currentUnderlineProperties.IsHeightEqualTo(preUnderlineProperties)))) { - // Ensure strikethrough will be at least a pixel high - if(currentStrikethroughThickness < ONE) - { - currentStrikethroughThickness = ONE; - } - else + //If the Underline Height is changed then we need to recalculate height. + if(!(currentUnderlineProperties.IsHeightEqualTo(preUnderlineProperties))) { - currentStrikethroughThickness = ceil(currentStrikethroughThickness); + maxUnderlineHeight = currentUnderlineHeight; } - } - // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font - if(currentUnderlinePosition > descender) - { - currentUnderlinePosition = descender; + CalcualteUnderlineHeight(lastDecorativeLinesFontMetrics, currentUnderlineHeight, maxUnderlineHeight); } - if(fabsf(currentUnderlinePosition) < Math::MACHINE_EPSILON_1000) + if(isDecorativeLinesFontIdUpdated && isStrikethroughGlyph) { - // Move offset down by one ( EFL behavior ) - currentUnderlinePosition = ONE; + CalcualteStrikethroughHeight(currentStrikethroughHeight, maxStrikethroughHeight); } - - lastUnderlinedFontId = glyph.fontId; - - } // underline + } // decorative-lines AtlasGlyphManager::GlyphStyle style; style.isItalic = glyph.isItalicRequired; @@ -662,6 +653,18 @@ struct AtlasRenderer::Impl const ColorIndex colorIndex = useDefaultColor ? 0u : *(colorIndicesBuffer + i); const Vector4& color = (useDefaultColor || (0u == colorIndex)) ? defaultColor : *(colorsBuffer + colorIndex - 1u); + //The new underlined chunk. Add new id if they are not consecutive indices (this is for Markup case) + // Examples: "Hello World Hello World", "World Hello World", " World Hello World" + if(isPreUnderlined && (!isGlyphUnderlined || (preUnderlineProperties != currentUnderlineProperties))) + { + mapUnderlineChunkIdWithProperties.insert(std::pair(underlineChunkId, preUnderlineProperties)); + underlineChunkId++; + } + + //Keep status of underlined for previous glyph to check consecutive indices + isPreUnderlined = isGlyphUnderlined; + preUnderlineProperties = currentUnderlineProperties; + GenerateMesh(glyph, positionPlusOutlineOffset, color, @@ -669,7 +672,7 @@ struct AtlasRenderer::Impl slot, isGlyphUnderlined, currentUnderlinePosition, - currentUnderlineThickness, + maxUnderlineHeight, meshContainer, newTextCache, extents, @@ -686,7 +689,7 @@ struct AtlasRenderer::Impl slot, strikethroughGlyphsExist, 0.0f, - currentStrikethroughThickness, + maxStrikethroughHeight, meshContainer, newTextCache, strikethroughExtents, @@ -707,7 +710,7 @@ struct AtlasRenderer::Impl slotOutline, false, currentUnderlinePosition, - currentUnderlineThickness, + maxUnderlineHeight, meshContainerOutline, newTextCache, extents, @@ -716,15 +719,6 @@ struct AtlasRenderer::Impl 0u); } - //The new underlined chunk. Add new id if they are not consecutive indices (this is for Markup case) - // Examples: "Hello World Hello World", "World Hello World", " World Hello World" - if(isPreUnderlined && (isPreUnderlined != isGlyphUnderlined)) - { - underlineChunkId++; - } - //Keep status of underlined for previous glyph to check consecutive indices - isPreUnderlined = isGlyphUnderlined; - if(isPrevGlyphStrikethrough && !isStrikethroughGlyph) { strikethroughChunkId++; @@ -746,7 +740,7 @@ struct AtlasRenderer::Impl if(thereAreUnderlinedGlyphs) { // Check to see if any of the text needs an underline - GenerateUnderlines(meshContainer, extents, underlineColor, underlineType, dashedUnderlineWidth, dashedUnderlineGap); + GenerateUnderlines(meshContainer, extents, viewUnderlineProperties, mapUnderlineChunkIdWithProperties); } if(strikethroughGlyphsExist) @@ -1051,15 +1045,14 @@ struct AtlasRenderer::Impl } } - void GenerateUnderlines(std::vector& meshRecords, - Vector& extents, - const Vector4& underlineColor, - const Text::Underline::Type& underlineType, - const float& dashedUnderlineWidth, - const float& dashedUnderlineGap) + void GenerateUnderlines(std::vector& meshRecords, + Vector& extents, + const UnderlineStyleProperties& viewUnderlineProperties, + const std::map& mapUnderlineChunkIdWithProperties) { AtlasManager::Mesh2D newMesh; unsigned short faceIndex = 0; + for(Vector::ConstIterator eIt = extents.Begin(), eEndIt = extents.End(); eIt != eEndIt; @@ -1069,6 +1062,17 @@ struct AtlasRenderer::Impl uint32_t index = eIt->mMeshRecordIndex; Vector2 uv = mGlyphManager.GetAtlasSize(meshRecords[index].mAtlasId); + auto pairUnderlineChunkIdWithProperties = mapUnderlineChunkIdWithProperties.find(eIt->mUnderlineChunkId); + + const UnderlineStyleProperties underlineProperties = (pairUnderlineChunkIdWithProperties == mapUnderlineChunkIdWithProperties.end()) + ? viewUnderlineProperties + : pairUnderlineChunkIdWithProperties->second; + + const Vector4& underlineColor = underlineProperties.colorDefined ? underlineProperties.color : viewUnderlineProperties.color; + const Text::Underline::Type& underlineType = underlineProperties.typeDefined ? underlineProperties.type : viewUnderlineProperties.type; + const float& dashedUnderlineGap = underlineProperties.dashGapDefined ? underlineProperties.dashGap : viewUnderlineProperties.dashGap; + const float& dashedUnderlineWidth = underlineProperties.dashWidthDefined ? underlineProperties.dashWidth : viewUnderlineProperties.dashWidth; + // Make sure we don't hit texture edge for single pixel texture ( filled pixel is in top left of every atlas ) float u = HALF / uv.x; float v = HALF / uv.y; @@ -1082,9 +1086,7 @@ struct AtlasRenderer::Impl { float dashTlx = tlx; float dashBrx = tlx; - faceIndex = 0; - AtlasManager::Mesh2D newMesh; while((dashTlx >= tlx) && (dashTlx < brx) && ((dashTlx + dashedUnderlineWidth) <= brx)) { dashBrx = dashTlx + dashedUnderlineWidth; diff --git a/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.cpp b/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.cpp new file mode 100644 index 0000000..c87fe88 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.cpp @@ -0,0 +1,53 @@ +/* + * 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 +{ +/// Helper method to fetch the underline metrics for the specified font glyph +void CalcualteStrikethroughHeight(float& currentStrikethroughHeight, float& maxStrikethroughHeight) +{ + //Height of strikethrough represents the thickness of line. + + // Ensure strikethrough will be at least a pixel high + if(currentStrikethroughHeight < 1.0f) + { + currentStrikethroughHeight = 1.0f; + } + else + { + currentStrikethroughHeight = ceil(currentStrikethroughHeight); + } + + // The strikethrough height should be the max strikethrough height of all glyphs of the line. + if(currentStrikethroughHeight > maxStrikethroughHeight) + { + maxStrikethroughHeight = currentStrikethroughHeight; + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h b/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h new file mode 100644 index 0000000..b3df7ef --- /dev/null +++ b/dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h @@ -0,0 +1,50 @@ +#ifndef DALI_TOOLKIT_TEXT_RENDERING_STYLES_STRIKETHROUGH_HELPER_FUNCTIONS_H +#define DALI_TOOLKIT_TEXT_RENDERING_STYLES_STRIKETHROUGH_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 Calculate the current underline height and update maximum underline height + * + * @param[inout] currentStrikethroughHeight the current strikethrough height. + * @param[inout] maxStrikethroughHeight the maximum strikethrough height. + * + */ +void CalcualteStrikethroughHeight(float& currentStrikethroughHeight, float& maxStrikethroughHeight); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_RENDERING_STYLES_STRIKETHROUGH_HELPER_FUNCTIONS_H \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/styles/underline-helper-functions.cpp b/dali-toolkit/internal/text/rendering/styles/underline-helper-functions.cpp new file mode 100644 index 0000000..6720b91 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/styles/underline-helper-functions.cpp @@ -0,0 +1,122 @@ +/* + * 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 +{ +bool IsGlyphUnderlined(GlyphIndex index, + const Vector& underlineRuns, + Vector::ConstIterator& currentUnderlinedGlyphRunIt) +{ + for(Vector::ConstIterator it = underlineRuns.Begin(), + endIt = underlineRuns.End(); + it != endIt; + ++it) + { + const UnderlinedGlyphRun& run = *it; + + if((run.glyphRun.glyphIndex <= index) && (index < run.glyphRun.glyphIndex + run.glyphRun.numberOfGlyphs)) + { + currentUnderlinedGlyphRunIt = it; + return true; + } + } + + return false; +} + +float GetCurrentUnderlineHeight(const Vector& underlineRuns, + Vector::ConstIterator currentUnderlinedGlyphRunIt, + const float underlineHeight) +{ + if(currentUnderlinedGlyphRunIt == underlineRuns.End()) + { + return underlineHeight; + } + + const UnderlinedGlyphRun& underlinedGlyphRun = *currentUnderlinedGlyphRunIt; + return (underlinedGlyphRun.properties.heightDefined ? underlinedGlyphRun.properties.height : underlineHeight); +} + +UnderlineStyleProperties GetCurrentUnderlineProperties(const bool& isGlyphUnderlined, + const Vector& underlineRuns, + Vector::ConstIterator currentUnderlinedGlyphRunIt, + const UnderlineStyleProperties& commonUnderlineProperties) +{ + return (isGlyphUnderlined && (currentUnderlinedGlyphRunIt != underlineRuns.End())) + ? currentUnderlinedGlyphRunIt->properties + : commonUnderlineProperties; +} + +float FetchUnderlinePositionFromFontMetrics(const FontMetrics& fontMetrics) +{ + //Helper method to fetch the underline metrics for the specified font glyph + const float descender = ceil(fabsf(fontMetrics.descender)); + float underlinePosition = ceil(fabsf(fontMetrics.underlinePosition)); + + // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font + if(underlinePosition > descender) + { + underlinePosition = descender; + } + + if(fabsf(underlinePosition) < Math::MACHINE_EPSILON_1000) + { + // Move offset down by one ( EFL behavior ) + underlinePosition = 1.0f; + } + + return underlinePosition; +} + +void CalcualteUnderlineHeight(const FontMetrics& fontMetrics, float& currentUnderlineHeight, float& maxUnderlineHeight) +{ + //Helper method to fetch the underline metrics for the specified font glyph + //Height of underline represents the thickness of line. + if(fabsf(currentUnderlineHeight) < Math::MACHINE_EPSILON_1000) + { + currentUnderlineHeight = fontMetrics.underlineThickness; + + // Ensure underline will be at least a pixel high + if(currentUnderlineHeight < 1.0f) + { + currentUnderlineHeight = 1.0f; + } + else + { + currentUnderlineHeight = ceil(currentUnderlineHeight); + } + } + + // The underline height should be the max underline height of all glyphs of the line. + if(currentUnderlineHeight > maxUnderlineHeight) + { + maxUnderlineHeight = currentUnderlineHeight; + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h b/dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h new file mode 100644 index 0000000..825b05c --- /dev/null +++ b/dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h @@ -0,0 +1,101 @@ +#ifndef DALI_TOOLKIT_TEXT_RENDERING_STYLES_UNDERLINE_HELPER_FUNCTIONS_H +#define DALI_TOOLKIT_TEXT_RENDERING_STYLES_UNDERLINE_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 Whether the glyph at index is underlined or not. If true then return iterator to the run containes index. + * + * @param[in] index the index of glyph. + * @param[in] underlineRuns the underline runs. + * @param[out] currentUnderlinedGlyphRunIt the iterator of current underlined glyph run. + * + * @return true if glyph at index is underlined + */ +bool IsGlyphUnderlined(GlyphIndex index, + const Vector& underlineRuns, + Vector::ConstIterator& currentUnderlinedGlyphRunIt); + +/** + * @brief Check the current underlined glyph run iterator if not empty and its height is defined then return ts height. Otherwise return the common underline height. + * + * @param[in] underlineRuns the underline runs. + * @param[in] currentUnderlinedGlyphRunIt the iterator of current underlined glyph run. + * @param[in] underlineHeight the common underline height. + * + * @return the determined underline height + */ +float GetCurrentUnderlineHeight(const Vector& underlineRuns, + Vector::ConstIterator currentUnderlinedGlyphRunIt, + const float underlineHeight); + +/** + * @brief Check the current underlined glyph run iterator if not empty and isGlyphUnderlined is true then return its UnderlineProperties. Otherwise return the common underline properties. + * + * @param[in] isGlyphUnderlined whether the glyph is underlined. + * @param[in] underlineRuns the underline runs. + * @param[in] currentUnderlinedGlyphRunIt the iterator of current underlined glyph run. + * @param[in] commonUnderlineProperties the common underline properties. + * + * @return the determined underline properties + */ +UnderlineStyleProperties GetCurrentUnderlineProperties(const bool& isGlyphUnderlined, + const Vector& underlineRuns, + Vector::ConstIterator currentUnderlinedGlyphRunIt, + const UnderlineStyleProperties& commonUnderlineProperties); + +/** + * @brief Fetch and calculate underline Position using font-metrics + * + * @param[in] fontMetrics the font metrics of glyph. + * + * @return the underline position + */ +float FetchUnderlinePositionFromFontMetrics(const FontMetrics& fontMetrics); + +/** + * @brief Calculate the current underline height using font-metrics and update maximum underline height + * + * @param[in] fontMetrics the font metrics of glyph. + * @param[inout] currentUnderlineHeight the current underline height. + * @param[inout] maxUnderlineHeight the maximum underline height. + * + */ +void CalcualteUnderlineHeight(const FontMetrics& fontMetrics, float& currentUnderlineHeight, float& maxUnderlineHeight); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_RENDERING_STYLES_UNDERLINE_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 96088b5..790e247 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -26,6 +26,8 @@ // INTERNAL INCLUDES #include #include +#include +#include #include namespace Dali @@ -37,6 +39,7 @@ namespace Text namespace { const float HALF(0.5f); +const float ONE_AND_A_HALF(1.5f); /** * @brief Data struct used to set the buffer of the glyph's bitmap into the final bitmap's buffer. */ @@ -257,25 +260,6 @@ void TypesetGlyph(GlyphData& data, } } -bool IsGlyphUnderlined(GlyphIndex index, - const Vector& underlineRuns) -{ - for(Vector::ConstIterator it = underlineRuns.Begin(), - endIt = underlineRuns.End(); - it != endIt; - ++it) - { - const GlyphRun& run = *it; - - if((run.glyphIndex <= index) && (index < run.glyphIndex + run.numberOfGlyphs)) - { - return true; - } - } - - return false; -} - bool doGlyphHaveStrikethrough(GlyphIndex index, const Vector& strikethroughRuns, Vector4& strikethroughColor) @@ -301,79 +285,6 @@ bool doGlyphHaveStrikethrough(GlyphIndex index, return false; } -/// Helper method to fetch the underline metrics for the specified font glyph -void FetchFontDecorationlinesMetrics( - TextAbstraction::FontClient& fontClient, - const GlyphInfo* const glyphInfo, - float& currentUnderlinePosition, - const float underlineHeight, - float& currentUnderlineThickness, - float& maxUnderlineThickness, - FontId& lastlinedFontId, - const float strikethroughHeight, - float& currentStrikethroughThickness, - float& maxStrikethroughThickness) -{ - FontMetrics fontMetrics; - fontClient.GetFontMetrics(glyphInfo->fontId, fontMetrics); - currentUnderlinePosition = ceil(fabsf(fontMetrics.underlinePosition)); - const float descender = ceil(fabsf(fontMetrics.descender)); - - if(fabsf(underlineHeight) < Math::MACHINE_EPSILON_1000) - { - currentUnderlineThickness = fontMetrics.underlineThickness; - - // Ensure underline will be at least a pixel high - if(currentUnderlineThickness < 1.0f) - { - currentUnderlineThickness = 1.0f; - } - else - { - currentUnderlineThickness = ceil(currentUnderlineThickness); - } - } - - if(fabsf(strikethroughHeight) < Math::MACHINE_EPSILON_1000) - { - // Ensure strikethrough will be at least a pixel high - if(currentStrikethroughThickness < 1.0f) - { - currentStrikethroughThickness = 1.0f; - } - else - { - currentStrikethroughThickness = ceil(currentStrikethroughThickness); - } - } - - // The underline thickness should be the max underline thickness of all glyphs of the line. - if(currentUnderlineThickness > maxUnderlineThickness) - { - maxUnderlineThickness = currentUnderlineThickness; - } - - // The strikethrough thickness should be the max strikethrough thickness of all glyphs of the line. - if(currentStrikethroughThickness > maxStrikethroughThickness) - { - maxStrikethroughThickness = currentStrikethroughThickness; - } - - // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font - if(currentUnderlinePosition > descender) - { - currentUnderlinePosition = descender; - } - - if(fabsf(currentUnderlinePosition) < Math::MACHINE_EPSILON_1000) - { - // Move offset down by one ( EFL behavior ) - currentUnderlinePosition = 1.0f; - } - - lastlinedFontId = glyphInfo->fontId; -} - /// Draws the specified color to the pixel buffer void WriteColorToPixelBuffer( GlyphData& glyphData, @@ -398,24 +309,27 @@ void WriteColorToPixelBuffer( /// Draws the specified underline color to the buffer void DrawUnderline( - const Vector4& underlineColor, - const unsigned int bufferWidth, - const unsigned int bufferHeight, - GlyphData& glyphData, - const float baseline, - const float currentUnderlinePosition, - const float maxUnderlineThickness, - const float lineExtentLeft, - const float lineExtentRight, - const Text::Underline::Type underlineType, - const float dashedUnderlineWidth, - const float dashedUnderlineGap, - const LineRun& line) + const unsigned int bufferWidth, + const unsigned int bufferHeight, + GlyphData& glyphData, + const float baseline, + const float currentUnderlinePosition, + const float maxUnderlineHeight, + const float lineExtentLeft, + const float lineExtentRight, + const UnderlineStyleProperties& commonUnderlineProperties, + const UnderlineStyleProperties& currentUnderlineProperties, + const LineRun& line) { + const Vector4& underlineColor = currentUnderlineProperties.colorDefined ? currentUnderlineProperties.color : commonUnderlineProperties.color; + const Text::Underline::Type underlineType = currentUnderlineProperties.typeDefined ? currentUnderlineProperties.type : commonUnderlineProperties.type; + const float dashedUnderlineWidth = currentUnderlineProperties.dashWidthDefined ? currentUnderlineProperties.dashWidth : commonUnderlineProperties.dashWidth; + const float dashedUnderlineGap = currentUnderlineProperties.dashGapDefined ? currentUnderlineProperties.dashGap : commonUnderlineProperties.dashGap; + int underlineYOffset = glyphData.verticalOffset + baseline + currentUnderlinePosition; uint32_t* bitmapBuffer = reinterpret_cast(glyphData.bitmapBuffer.GetBuffer()); - for(unsigned int y = underlineYOffset; y < underlineYOffset + maxUnderlineThickness; y++) + for(unsigned int y = underlineYOffset; y < underlineYOffset + maxUnderlineHeight; y++) { if(y > bufferHeight - 1) { @@ -466,8 +380,8 @@ void DrawUnderline( } if(underlineType == Text::Underline::DOUBLE) { - int secondUnderlineYOffset = glyphData.verticalOffset - line.descender - maxUnderlineThickness; - for(unsigned int y = secondUnderlineYOffset; y < secondUnderlineYOffset + maxUnderlineThickness; y++) + int secondUnderlineYOffset = underlineYOffset - ONE_AND_A_HALF * maxUnderlineHeight; + for(unsigned int y = secondUnderlineYOffset; y < secondUnderlineYOffset + maxUnderlineHeight; y++) { if(y > bufferHeight - 1) { @@ -639,14 +553,14 @@ void DrawStrikethrough( GlyphData& glyphData, const float baseline, const LineRun& line, - const float maxStrikethroughThickness, + const float maxStrikethroughHeight, const float lineExtentLeft, const float lineExtentRight, float strikethroughStartingYPosition) { uint32_t* bitmapBuffer = reinterpret_cast(glyphData.bitmapBuffer.GetBuffer()); - for(unsigned int y = strikethroughStartingYPosition; y < strikethroughStartingYPosition + maxStrikethroughThickness; y++) + for(unsigned int y = strikethroughStartingYPosition; y < strikethroughStartingYPosition + maxStrikethroughHeight; y++) { if(y > bufferHeight - 1) { @@ -987,20 +901,27 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, } } - const bool underlineEnabled = mModel->IsUnderlineEnabled(); - const Vector4& underlineColor = mModel->GetUnderlineColor(); - const float underlineHeight = mModel->GetUnderlineHeight(); - const Text::Underline::Type underlineType = mModel->GetUnderlineType(); - const float dashedUnderlineWidth = mModel->GetDashedUnderlineWidth(); - const float dashedUnderlineGap = mModel->GetDashedUnderlineGap(); - const bool strikethroughEnabled = mModel->IsStrikethroughEnabled(); - const Vector4& strikethroughColor = mModel->GetStrikethroughColor(); - const float strikethroughHeight = mModel->GetStrikethroughHeight(); - const float characterSpacing = mModel->GetCharacterSpacing(); + const bool underlineEnabled = mModel->IsUnderlineEnabled(); + const bool strikethroughEnabled = mModel->IsStrikethroughEnabled(); + const Vector4& strikethroughColor = mModel->GetStrikethroughColor(); + const float strikethroughHeight = mModel->GetStrikethroughHeight(); + const float characterSpacing = mModel->GetCharacterSpacing(); + + // Aggregate underline-style-properties from mModel + const UnderlineStyleProperties modelUnderlineProperties{mModel->GetUnderlineType(), + mModel->GetUnderlineColor(), + mModel->GetUnderlineHeight(), + mModel->GetDashedUnderlineGap(), + mModel->GetDashedUnderlineWidth(), + true, + true, + true, + true, + true}; // Get the underline runs. - const Length numberOfUnderlineRuns = mModel->GetNumberOfUnderlineRuns(); - Vector underlineRuns; + const Length numberOfUnderlineRuns = mModel->GetNumberOfUnderlineRuns(); + Vector underlineRuns; underlineRuns.Resize(numberOfUnderlineRuns); mModel->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); @@ -1013,14 +934,16 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, bool thereAreUnderlinedGlyphs = false; bool strikethroughGlyphsExist = false; - float currentUnderlinePosition = 0.0f; - float currentUnderlineThickness = underlineHeight; - float maxUnderlineThickness = currentUnderlineThickness; - float currentStrikethroughThickness = strikethroughHeight; - float maxStrikethroughThickness = currentStrikethroughThickness; + float currentUnderlinePosition = 0.0f; + float currentUnderlineHeight = modelUnderlineProperties.height; + float maxUnderlineHeight = currentUnderlineHeight; + auto currentUnderlineProperties = modelUnderlineProperties; + + float currentStrikethroughHeight = strikethroughHeight; + float maxStrikethroughHeight = currentStrikethroughHeight; float strikethroughStartingYPosition = 0.0f; - FontId lastUnderlinedFontId = 0; + FontId lastFontId = 0; float lineExtentLeft = bufferWidth; float lineExtentRight = 0.0f; @@ -1079,19 +1002,39 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, continue; } - const bool underlineGlyph = underlineEnabled || IsGlyphUnderlined(glyphIndex, underlineRuns); - thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph; + Vector::ConstIterator currentUnderlinedGlyphRunIt = underlineRuns.End(); + const bool underlineGlyph = underlineEnabled || IsGlyphUnderlined(glyphIndex, underlineRuns, currentUnderlinedGlyphRunIt); + currentUnderlineProperties = GetCurrentUnderlineProperties(underlineGlyph, underlineRuns, currentUnderlinedGlyphRunIt, modelUnderlineProperties); + currentUnderlineHeight = GetCurrentUnderlineHeight(underlineRuns, currentUnderlinedGlyphRunIt, modelUnderlineProperties.height); + thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph; currentStrikethroughColor = strikethroughColor; const bool strikethroughGlyph = strikethroughEnabled || doGlyphHaveStrikethrough(glyphIndex, strikethroughRuns, currentStrikethroughColor); strikethroughGlyphsExist = strikethroughGlyphsExist || strikethroughGlyph; // Are we still using the same fontId as previous - if((strikethroughGlyph || underlineGlyph) && (glyphInfo->fontId != lastUnderlinedFontId)) + if((glyphInfo->fontId != lastFontId) && (strikethroughGlyph || underlineGlyph)) { // We need to fetch fresh font underline metrics - FetchFontDecorationlinesMetrics(fontClient, glyphInfo, currentUnderlinePosition, underlineHeight, currentUnderlineThickness, maxUnderlineThickness, lastUnderlinedFontId, strikethroughHeight, currentStrikethroughThickness, maxStrikethroughThickness); - } // underline + FontMetrics fontMetrics; + fontClient.GetFontMetrics(glyphInfo->fontId, fontMetrics); + + //The currentUnderlinePosition will be used for both Underline and/or Strikethrough + currentUnderlinePosition = FetchUnderlinePositionFromFontMetrics(fontMetrics); + + if(underlineGlyph) + { + CalcualteUnderlineHeight(fontMetrics, currentUnderlineHeight, maxUnderlineHeight); + } + + if(strikethroughGlyph) + { + CalcualteStrikethroughHeight(currentStrikethroughHeight, maxStrikethroughHeight); + } + + // Update lastFontId because fontId is changed + lastFontId = glyphInfo->fontId; // Prevents searching for existing blocksizes when string of the same fontId. + } // Retrieves the glyph's position. Vector2 position = *(positionBuffer + elidedGlyphIndex); @@ -1210,7 +1153,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, // Draw the underline from the leftmost glyph to the rightmost glyph if(thereAreUnderlinedGlyphs && style == Typesetter::STYLE_UNDERLINE) { - DrawUnderline(underlineColor, bufferWidth, bufferHeight, glyphData, baseline, currentUnderlinePosition, maxUnderlineThickness, lineExtentLeft, lineExtentRight, underlineType, dashedUnderlineWidth, dashedUnderlineGap, line); + DrawUnderline(bufferWidth, bufferHeight, glyphData, baseline, currentUnderlinePosition, maxUnderlineHeight, lineExtentLeft, lineExtentRight, modelUnderlineProperties, currentUnderlineProperties, line); } // Draw the background color from the leftmost glyph to the rightmost glyph @@ -1224,7 +1167,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, { //TODO : The currently implemented strikethrough creates a strikethrough on the line level. We need to create different strikethroughs the case of glyphs with different sizes. strikethroughStartingYPosition = (glyphData.verticalOffset + baseline + currentUnderlinePosition) - ((line.ascender) * HALF); // Since Free Type font doesn't contain the strikethrough-position property, strikethrough position will be calculated by moving the underline position upwards by half the value of the line height. - DrawStrikethrough(currentStrikethroughColor, bufferWidth, bufferHeight, glyphData, baseline, line, maxStrikethroughThickness, lineExtentLeft, lineExtentRight, strikethroughStartingYPosition); + DrawStrikethrough(currentStrikethroughColor, bufferWidth, bufferHeight, glyphData, baseline, line, maxStrikethroughHeight, lineExtentLeft, lineExtentRight, strikethroughStartingYPosition); } // Increases the vertical offset with the line's descender. @@ -1300,27 +1243,30 @@ Devel::PixelBuffer Typesetter::ApplyUnderlineMarkupImageBuffer(Devel::PixelBuffe { // Underline-tags (this is for Markup case) // Get the underline runs. - const Length numberOfUnderlineRuns = mModel->GetNumberOfUnderlineRuns(); - Vector underlineRuns; + const Length numberOfUnderlineRuns = mModel->GetNumberOfUnderlineRuns(); + Vector underlineRuns; underlineRuns.Resize(numberOfUnderlineRuns); mModel->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); // Iterate on the consecutive underlined glyph run and connect them into one chunk of underlined characters. - Vector::ConstIterator itGlyphRun = underlineRuns.Begin(); - Vector::ConstIterator endItGlyphRun = underlineRuns.End(); - GlyphIndex startGlyphIndex, endGlyphIndex; + Vector::ConstIterator itGlyphRun = underlineRuns.Begin(); + Vector::ConstIterator endItGlyphRun = underlineRuns.End(); + GlyphIndex startGlyphIndex, endGlyphIndex; //The outer loop to iterate on the separated chunks of underlined glyph runs while(itGlyphRun != endItGlyphRun) { - startGlyphIndex = itGlyphRun->glyphIndex; + const UnderlineStyleProperties& firstUnderlineStyleProperties = itGlyphRun->properties; + + startGlyphIndex = itGlyphRun->glyphRun.glyphIndex; endGlyphIndex = startGlyphIndex; //The inner loop to make a connected underline for the consecutive characters do { - endGlyphIndex += itGlyphRun->numberOfGlyphs; + endGlyphIndex += itGlyphRun->glyphRun.numberOfGlyphs; itGlyphRun++; - } while(itGlyphRun != endItGlyphRun && itGlyphRun->glyphIndex == endGlyphIndex); + } while(itGlyphRun != endItGlyphRun && itGlyphRun->glyphRun.glyphIndex == endGlyphIndex && + (firstUnderlineStyleProperties == itGlyphRun->properties)); endGlyphIndex--; diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp index 5e014df..47aed00 100644 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -23,8 +23,8 @@ #include // INTERNAL INCLUDES -#include #include +#include namespace Dali { @@ -270,7 +270,7 @@ Length ViewModel::GetNumberOfUnderlineRuns() const return mModel->GetNumberOfUnderlineRuns(); } -void ViewModel::GetUnderlineRuns(GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const +void ViewModel::GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const { mModel->GetUnderlineRuns(underlineRuns, index, numberOfRuns); } diff --git a/dali-toolkit/internal/text/rendering/view-model.h b/dali-toolkit/internal/text/rendering/view-model.h index c3ee530..ef8ba87 100644 --- a/dali-toolkit/internal/text/rendering/view-model.h +++ b/dali-toolkit/internal/text/rendering/view-model.h @@ -233,7 +233,7 @@ public: /** * @copydoc ModelInterface::GetUnderlineRuns() */ - void GetUnderlineRuns(GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const override; + void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const override; /** * @copydoc ModelInterface::GetOutlineColor() 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 2d1e28d..e6ec978 100644 --- a/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp @@ -374,9 +374,9 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o case Dali::InputMethodContext::PreeditStyle::UNDERLINE: { // Add the underline for the pre-edit text. - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; + UnderlinedGlyphRun underlineRun; + underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.glyphRun.numberOfGlyphs = numberOfIndices; impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case @@ -451,9 +451,9 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o backgroundColorRun.color = BACKGROUND_SUB4; impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; + UnderlinedGlyphRun underlineRun; + underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.glyphRun.numberOfGlyphs = numberOfIndices; impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case @@ -472,9 +472,9 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o backgroundColorRun.color = BACKGROUND_SUB5; impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; + UnderlinedGlyphRun underlineRun; + underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.glyphRun.numberOfGlyphs = numberOfIndices; impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case @@ -493,9 +493,9 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o backgroundColorRun.color = BACKGROUND_SUB6; impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; + UnderlinedGlyphRun underlineRun; + underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.glyphRun.numberOfGlyphs = numberOfIndices; impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case @@ -514,9 +514,9 @@ bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask o backgroundColorRun.color = BACKGROUND_SUB7; impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - GlyphRun underlineRun; - underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; - underlineRun.numberOfGlyphs = numberOfIndices; + UnderlinedGlyphRun underlineRun; + underlineRun.glyphRun.glyphIndex = attrData.startIndex + numberOfCommit; + underlineRun.glyphRun.numberOfGlyphs = numberOfIndices; impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); //Mark-up processor case diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 1b66665..294b534 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -39,6 +39,7 @@ #include #include #include +#include using namespace Dali; @@ -1620,9 +1621,22 @@ void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearP Length numberOfCharacters = it->characterRun.numberOfCharacters; for(Length index = 0u; index < numberOfCharacters; index++) { - GlyphRun underlineGlyphRun; - underlineGlyphRun.glyphIndex = charactersToGlyph[characterIndex + index]; - underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index]; + UnderlinedGlyphRun underlineGlyphRun; + underlineGlyphRun.glyphRun.glyphIndex = charactersToGlyph[characterIndex + index]; + underlineGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index]; + + //Copy properties (attributes) + underlineGlyphRun.properties.type = it->properties.type; + underlineGlyphRun.properties.color = it->properties.color; + underlineGlyphRun.properties.height = it->properties.height; + underlineGlyphRun.properties.dashGap = it->properties.dashGap; + underlineGlyphRun.properties.dashWidth = it->properties.dashWidth; + underlineGlyphRun.properties.typeDefined = it->properties.typeDefined; + underlineGlyphRun.properties.colorDefined = it->properties.colorDefined; + underlineGlyphRun.properties.heightDefined = it->properties.heightDefined; + underlineGlyphRun.properties.dashGapDefined = it->properties.dashGapDefined; + underlineGlyphRun.properties.dashWidthDefined = it->properties.dashWidthDefined; + mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun); } } diff --git a/dali-toolkit/internal/text/text-effects-style.cpp b/dali-toolkit/internal/text/text-effects-style.cpp index 8d552d4..90c570a 100644 --- a/dali-toolkit/internal/text/text-effects-style.cpp +++ b/dali-toolkit/internal/text/text-effects-style.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * 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. @@ -22,7 +22,6 @@ #include #include #include -#include #include namespace Dali @@ -355,8 +354,8 @@ bool SetUnderlineProperties(ControllerPtr controller, const Property::Value& val { const Property::Map& propertiesMap = value.Get(); - bool enabled = false; - bool colorDefined = false; + bool enabled = false; + bool colorDefined = false; Vector4 color; bool heightDefined = false; float height = 0.f; @@ -976,11 +975,11 @@ bool SetStrikethroughProperties(ControllerPtr controller, const Property::Value& Text::ParsePropertyString(propertyString, parsedStringMap); empty = ParseStrikethroughProperties(parsedStringMap, - enabled, - colorDefined, - color, - heightDefined, - height); + enabled, + colorDefined, + color, + heightDefined, + height); controller->StrikethroughSetByString(!empty); } @@ -1057,7 +1056,7 @@ void GetStrikethroughProperties(ControllerPtr controller, Property::Value& value if(controller->IsStrikethroughSetByString()) { std::string strikethroughProperties = "{\"enable\":"; - const std::string enabledStr = enabled ? "true" : "false"; + const std::string enabledStr = enabled ? "true" : "false"; strikethroughProperties += "\"" + enabledStr + "\","; std::string colorStr; @@ -1092,6 +1091,17 @@ void GetStrikethroughProperties(ControllerPtr controller, Property::Value& value } } +Underline::Type StringToUnderlineType(const char* const underlineTypeStr) +{ + Underline::Type underlineType = Text::Underline::SOLID; + Scripting::GetEnumeration(underlineTypeStr, + UNDERLINE_TYPE_STRING_TABLE, + UNDERLINE_TYPE_STRING_TABLE_COUNT, + underlineType); + + return underlineType; +} + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/text-effects-style.h b/dali-toolkit/internal/text/text-effects-style.h index a1b7bea..d87e810 100644 --- a/dali-toolkit/internal/text/text-effects-style.h +++ b/dali-toolkit/internal/text/text-effects-style.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_INTERNAL_TEXT_EFFECTS_STYLE_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * 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. @@ -20,6 +20,8 @@ // INTERNAL INCLUDES #include +#include +#include namespace Dali { @@ -27,6 +29,12 @@ namespace Toolkit { namespace Text { +const Scripting::StringEnum UNDERLINE_TYPE_STRING_TABLE[] = + { + {"solid", Text::Underline::SOLID}, + {"dashed", Text::Underline::DASHED}, + {"double", Text::Underline::DOUBLE}}; +const unsigned int UNDERLINE_TYPE_STRING_TABLE_COUNT = sizeof(UNDERLINE_TYPE_STRING_TABLE) / sizeof(UNDERLINE_TYPE_STRING_TABLE[0]); namespace EffectStyle { enum Type @@ -116,11 +124,11 @@ bool ParseBackgroundProperties(const Property::Map& backgroundProperties, * @param[out] height The strikethrough's height. */ bool ParseStrikethroughProperties(const Property::Map& strikethroughProperties, - bool& enabled, - bool& colorDefined, - Vector4& color, - bool& heightDefined, - float& height); + bool& enabled, + bool& colorDefined, + Vector4& color, + bool& heightDefined, + float& height); /** * @brief Sets the underline properties. @@ -242,6 +250,15 @@ bool SetBackgroundProperties(ControllerPtr controller, const Property::Value& va */ void GetBackgroundProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type); +/** + * @brief Converts a underline type string into @e Underline::Type + * + * @param[in] underlineTypeStr The underline type string. Must end with '\0'. + * + * @return The @e Underline::Type value corresponding to the string. + */ +Underline::Type StringToUnderlineType(const char* const underlineTypeStr); + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/text-model-interface.h b/dali-toolkit/internal/text/text-model-interface.h index 7d51b16..f9d993a 100644 --- a/dali-toolkit/internal/text/text-model-interface.h +++ b/dali-toolkit/internal/text/text-model-interface.h @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace Dali @@ -300,7 +301,7 @@ public: * @param[in] index Index of the first underline run to be copied. * @param[in] numberOfRuns Number of underline runs to be copied. */ - virtual void GetUnderlineRuns(GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const = 0; + virtual void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const = 0; /** * @brief Retrieve the outline color. diff --git a/dali-toolkit/internal/text/text-model.cpp b/dali-toolkit/internal/text/text-model.cpp index e19618e..7ce74ca 100644 --- a/dali-toolkit/internal/text/text-model.cpp +++ b/dali-toolkit/internal/text/text-model.cpp @@ -212,7 +212,7 @@ Length Model::GetNumberOfUnderlineRuns() const return mVisualModel->GetNumberOfUnderlineRuns(); } -void Model::GetUnderlineRuns(GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const +void Model::GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const { mVisualModel->GetUnderlineRuns(underlineRuns, index, numberOfRuns); } diff --git a/dali-toolkit/internal/text/text-model.h b/dali-toolkit/internal/text/text-model.h index 4f7b9e3..7077c85 100644 --- a/dali-toolkit/internal/text/text-model.h +++ b/dali-toolkit/internal/text/text-model.h @@ -230,7 +230,7 @@ public: /** * @copydoc ModelInterface::GetUnderlineRuns() */ - void GetUnderlineRuns(GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const override; + void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const override; /** * @copydoc ModelInterface::GetOutlineColor() diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index da6b4e1..2dda239 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 namespace Dali @@ -233,9 +234,9 @@ public: * @param[in] index Index of the first underline run to be copied. * @param[in] numberOfRuns Number of underline runs to be copied. */ - virtual void GetUnderlineRuns(GlyphRun* underlineRuns, - UnderlineRunIndex index, - Length numberOfRuns) const = 0; + virtual void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns) const = 0; /** * @brief Retrieve the outline color. diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index b4644e7..137ded2 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -680,9 +680,9 @@ Length View::GetNumberOfUnderlineRuns() const return 0u; } -void View::GetUnderlineRuns(GlyphRun* underlineRuns, - UnderlineRunIndex index, - Length numberOfRuns) const +void View::GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns) const { if(mImpl->mVisualModel) { diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index f673e0e..8eeb882 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -176,9 +176,9 @@ public: /** * @copydoc Dali::Toolkit::Text::ViewInterface::GetUnderlineRuns() */ - virtual void GetUnderlineRuns(GlyphRun* underlineRuns, - UnderlineRunIndex index, - Length numberOfRuns) const; + virtual void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns) const; /** * @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineColor() diff --git a/dali-toolkit/internal/text/underline-style-properties.h b/dali-toolkit/internal/text/underline-style-properties.h new file mode 100644 index 0000000..14016c4 --- /dev/null +++ b/dali-toolkit/internal/text/underline-style-properties.h @@ -0,0 +1,123 @@ +#ifndef DALI_TOOLKIT_TEXT_UNDERLINE_STYLE_PROPERTIES_H +#define DALI_TOOLKIT_TEXT_UNDERLINE_STYLE_PROPERTIES_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 Properties of underline style. + */ +struct UnderlineStyleProperties +{ + // Constructors + + /** + * Default constructor to set the default values of bitfields + */ + UnderlineStyleProperties() + : type{Text::Underline::SOLID}, + color{Color::BLACK}, + height{0u}, + dashGap{1u}, + dashWidth{2u}, + typeDefined{false}, + colorDefined{false}, + heightDefined{false}, + dashGapDefined{false}, + dashWidthDefined{false} + { + } + + UnderlineStyleProperties(Text::Underline::Type type, + Vector4 color, + float height, + float dashGap, + float dashWidth, + bool typeDefined, + bool colorDefined, + bool heightDefined, + bool dashGapDefined, + bool dashWidthDefined) + : type{type}, + color{color}, + height{height}, + dashGap{dashGap}, + dashWidth{dashWidth}, + typeDefined{typeDefined}, + colorDefined{colorDefined}, + heightDefined{heightDefined}, + dashGapDefined{dashGapDefined}, + dashWidthDefined{dashWidthDefined} + { + } + + // Overloading operators + + bool operator==(const UnderlineStyleProperties& other) const + { + //The property is similar when both are not defined or when both are defined and have the same value. + return ((!typeDefined && !other.typeDefined) || ((typeDefined && other.typeDefined) && (type == other.type))) && + ((!colorDefined && !other.colorDefined) || ((colorDefined && other.colorDefined) && (color == other.color))) && + ((!heightDefined && !other.heightDefined) || ((heightDefined && other.heightDefined) && (height == other.height))) && + ((!dashGapDefined && !other.dashGapDefined) || ((dashGapDefined && other.dashGapDefined) && (dashGap == other.dashGap))) && + ((!dashWidthDefined && !other.dashWidthDefined) || ((dashWidthDefined && other.dashWidthDefined) && (dashWidth == other.dashWidth))); + } + + bool operator!=(const UnderlineStyleProperties& other) const + { + return !(*this == other); + } + + bool IsHeightEqualTo(const UnderlineStyleProperties& other) const + { + return ((!heightDefined && !other.heightDefined) || ((heightDefined && other.heightDefined) && (height == other.height))); + } + + //Attributes + Text::Underline::Type type; ///< The type of underline. + Vector4 color; ///< The color of underline. + float height; ///< The height of underline. + float dashGap; ///< The dash-gap of underline. + float dashWidth; ///< The height of underline. + + bool typeDefined : 1; ///< Whether the type is defined. + bool colorDefined : 1; ///< Whether the color is defined. + bool heightDefined : 1; ///< Whether the height is defined. + bool dashGapDefined : 1; ///< Whether the dash-gap is defined. + bool dashWidthDefined : 1; ///< Whether the dash-width is defined. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_UNDERLINE_STYLE_PROPERTIES_H diff --git a/dali-toolkit/internal/text/underlined-character-run.h b/dali-toolkit/internal/text/underlined-character-run.h index 99d5967..4024dff 100644 --- a/dali-toolkit/internal/text/underlined-character-run.h +++ b/dali-toolkit/internal/text/underlined-character-run.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_TEXT_UNDERLINED_CHARACTER_RUN_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * 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. @@ -23,7 +23,7 @@ // INTERNAL INCLUDES #include -#include +#include namespace Dali { @@ -36,10 +36,17 @@ namespace Text */ struct UnderlinedCharacterRun { - CharacterRun characterRun; ///< The initial character index and the number of characters of the run. - //TODO: add properties like color, height and style - //Vector4 color; ///< The color of underline. - //float height; ///< The height of underline. + /** + * Default constructor to set the default values of bitfields + */ + UnderlinedCharacterRun() + : characterRun{}, + properties{} + { + } + + CharacterRun characterRun; ///< The initial character index and the number of characters of the run. + UnderlineStyleProperties properties; /// The properties of underline style }; } // namespace Text diff --git a/dali-toolkit/internal/text/underlined-glyph-run.h b/dali-toolkit/internal/text/underlined-glyph-run.h new file mode 100644 index 0000000..4c5ed7a --- /dev/null +++ b/dali-toolkit/internal/text/underlined-glyph-run.h @@ -0,0 +1,58 @@ +#ifndef DALI_TOOLKIT_TEXT_UNDERLINED_GLYPH_RUN_H +#define DALI_TOOLKIT_TEXT_UNDERLINED_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 +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Run of underlined glyphs with same properties. + */ +struct UnderlinedGlyphRun +{ + /** + * Default constructor to set the default values of bitfields + */ + UnderlinedGlyphRun() + : glyphRun{}, + properties{} + { + } + + GlyphRun glyphRun; ///< The initial glyph index and the number of glyphs in the run. + UnderlineStyleProperties properties; /// The properties of underline style +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_UNDERLINED_GLYPH_RUN_H diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index 3fa3975..ce0fb7c 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -305,13 +305,13 @@ LineIndex VisualModel::GetLineOfCharacter(CharacterIndex characterIndex) return index; } -void VisualModel::GetUnderlineRuns(GlyphRun* underlineRuns, - UnderlineRunIndex index, - Length numberOfRuns) const +void VisualModel::GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns) const { memcpy(underlineRuns, mUnderlineRuns.Begin() + index, - numberOfRuns * sizeof(GlyphRun)); + numberOfRuns * sizeof(UnderlinedGlyphRun)); } void VisualModel::SetNaturalSize(const Vector2& size) diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index ebddb35..4bae17c 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -29,6 +29,7 @@ #include #include #include +#include #include // DEVEL INCLUDES @@ -172,9 +173,9 @@ public: * @param[in] index Index of the first underline run to be copied. * @param[in] numberOfRuns Number of underline runs to be copied. */ - void GetUnderlineRuns(GlyphRun* underlineRuns, - UnderlineRunIndex index, - Length numberOfRuns) const; + void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns) const; // Size interface @@ -621,7 +622,7 @@ public: 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 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. -- 2.7.4