From f91c59cd34c3bc3951661d1b7b7727f4118e095e Mon Sep 17 00:00:00 2001 From: abdullah Date: Sun, 2 May 2021 10:08:25 +0300 Subject: [PATCH] Add support for span tag support span tag to be used for grouping font properties & text color. for example : Hello World using namespace Dali; using namespace Dali::Toolkit; class SimpleApp : public ConnectionTracker { public: SimpleApp(Application& application) : mApplication(application) { mApplication.InitSignal().Connect(this, &SimpleApp::Create); } void Create(Application& application) { Window window = mApplication.GetWindow(); mEditor = TextEditor::New(); mEditor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER); mEditor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER); mEditor.SetProperty(Actor::Property::POSITION, Vector3(0.f, 0.0f, 0.f)); mEditor.SetProperty(Actor::Property::SIZE, Vector2(300, 300.0f)); window.SetBackgroundColor(Vector4(0.04f, 0.345f, 0.392f, 1.0f)); mEditor.SetProperty(TextEditor::Property::POINT_SIZE, 26.f); mEditor.SetProperty(TextEditor::Property::ENABLE_MARKUP, true); mEditor.SetProperty(TextEditor::Property::TEXT, "Hello World"); window.Add(mEditor); } private: Application& mApplication; TextEditor mEditor; }; int DALI_EXPORT_API main(int argc, char** argv) { Application application = Application::New(&argc, &argv); SimpleApp test(application); application.MainLoop(); return 0; } Change-Id: Ie1be3e9d980dbca8ee4f0154000f94defd517a7c --- .../utc-Dali-TextEditor-internal.cpp | 64 +++++++++ .../utc-Dali-TextField-internal.cpp | 64 +++++++++ .../utc-Dali-TextLabel-internal.cpp | 64 +++++++++ dali-toolkit/internal/file.list | 1 + .../internal/text/markup-processor-color.cpp | 7 +- .../internal/text/markup-processor-color.h | 9 ++ .../internal/text/markup-processor-font.cpp | 95 ++++++++----- dali-toolkit/internal/text/markup-processor-font.h | 41 ++++++ .../internal/text/markup-processor-span.cpp | 93 +++++++++++++ dali-toolkit/internal/text/markup-processor-span.h | 47 +++++++ dali-toolkit/internal/text/markup-processor.cpp | 155 ++++++++++++++++++--- 11 files changed, 590 insertions(+), 50 deletions(-) create mode 100644 dali-toolkit/internal/text/markup-processor-span.cpp create mode 100644 dali-toolkit/internal/text/markup-processor-span.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 73d9e12..09c5078 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp @@ -198,4 +198,68 @@ int UtcDaliTextEditorBackgroundTag(void) DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION); END_TEST; +} + +int UtcDaliTextEditorTextWithSpan(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextEditorTextWithSpan\n"); + + TextEditor editor = TextEditor::New(); + DALI_TEST_CHECK( editor ); + + editor.SetProperty( TextEditor ::Property::ENABLE_MARKUP, true ); + editor.SetProperty( TextEditor::Property::TEXT, "Hello Span" ); + application.GetScene().Add( editor ); + + application.SendNotification(); + application.Render(); + + Vector3 originalSize = editor.GetNaturalSize(); + editor.SetProperty( TextEditor::Property::TEXT, "Hello Span" ); + + application.SendNotification(); + application.Render(); + + Vector3 spanSize = editor.GetNaturalSize(); + + DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION); + + Toolkit::Internal::TextEditor& editorImpl = GetImpl( editor ); + const ColorIndex* const colorIndicesBuffer1 = editorImpl.getController()->GetTextModel()->GetColorIndices(); + + DALI_TEST_CHECK( colorIndicesBuffer1 ); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer1[0], 0u, TEST_LOCATION); + + //span color + DALI_TEST_EQUALS( colorIndicesBuffer1[1], 1u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer1[6], 0u, TEST_LOCATION); + + + editor.SetProperty( TextEditor::Property::TEXT, "Hello Span" ); + + application.SendNotification(); + application.Render(); + + const ColorIndex* const colorIndicesBuffer2 = editorImpl.getController()->GetTextModel()->GetColorIndices(); + + DALI_TEST_CHECK( colorIndicesBuffer2 ); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[0], 0u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[1], 0u, TEST_LOCATION); + + //span color + DALI_TEST_EQUALS( colorIndicesBuffer2[6], 1u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION); + + END_TEST; } \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp index 73fe7e2..1fbc13e 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp @@ -282,4 +282,68 @@ int UtcDaliTextFieldBackgroundTag(void) DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION); END_TEST; +} + +int UtcDaliTextFieldTextWithSpan(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextFieldTextWithSpan\n"); + + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + field.SetProperty( TextField ::Property::ENABLE_MARKUP, true ); + field.SetProperty( TextField::Property::TEXT, "Hello Span" ); + application.GetScene().Add( field ); + + application.SendNotification(); + application.Render(); + + Vector3 originalSize = field.GetNaturalSize(); + field.SetProperty( TextField::Property::TEXT, "Hello Span" ); + + application.SendNotification(); + application.Render(); + + Vector3 spanSize = field.GetNaturalSize(); + + DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION); + + Toolkit::Internal::TextField& fieldImpl = GetImpl( field ); + const ColorIndex* const colorIndicesBuffer1 = fieldImpl.getController()->GetTextModel()->GetColorIndices(); + + DALI_TEST_CHECK( colorIndicesBuffer1 ); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer1[0], 0u, TEST_LOCATION); + + //span color + DALI_TEST_EQUALS( colorIndicesBuffer1[1], 1u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer1[6], 0u, TEST_LOCATION); + + + field.SetProperty( TextField::Property::TEXT, "Hello Span" ); + + application.SendNotification(); + application.Render(); + + const ColorIndex* const colorIndicesBuffer2 = fieldImpl.getController()->GetTextModel()->GetColorIndices(); + + DALI_TEST_CHECK( colorIndicesBuffer2 ); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[0], 0u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[1], 0u, TEST_LOCATION); + + //span color + DALI_TEST_EQUALS( colorIndicesBuffer2[6], 1u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION); + + END_TEST; } \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp index f67d88a..e03fec1 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp @@ -97,4 +97,68 @@ int UtcDaliTextLabelBackgroundTag(void) DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION); END_TEST; +} + +int UtcDaliTextLabelTextWithSpan(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextLabelTextWithSpan\n"); + + TextLabel label = TextLabel::New(); + DALI_TEST_CHECK( label ); + + label.SetProperty( TextLabel ::Property::ENABLE_MARKUP, true ); + label.SetProperty( TextLabel::Property::TEXT, "Hello Span" ); + application.GetScene().Add( label ); + + application.SendNotification(); + application.Render(); + + Vector3 originalSize = label.GetNaturalSize(); + label.SetProperty( TextLabel::Property::TEXT, "Hello Span" ); + + application.SendNotification(); + application.Render(); + + Vector3 spanSize = label.GetNaturalSize(); + + DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION); + + Toolkit::Internal::TextLabel& labelImpl = GetImpl( label ); + const ColorIndex* const colorIndicesBuffer1 = labelImpl.getController()->GetTextModel()->GetColorIndices(); + + DALI_TEST_CHECK( colorIndicesBuffer1 ); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer1[0], 0u, TEST_LOCATION); + + //span color + DALI_TEST_EQUALS( colorIndicesBuffer1[1], 1u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer1[6], 0u, TEST_LOCATION); + + + label.SetProperty( TextLabel::Property::TEXT, "Hello Span" ); + + application.SendNotification(); + application.Render(); + + const ColorIndex* const colorIndicesBuffer2 = labelImpl.getController()->GetTextModel()->GetColorIndices(); + + DALI_TEST_CHECK( colorIndicesBuffer2 ); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[0], 0u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[1], 0u, TEST_LOCATION); + + //span color + DALI_TEST_EQUALS( colorIndicesBuffer2[6], 1u, TEST_LOCATION); + + //default color + DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION); + + END_TEST; } \ No newline at end of file diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index f712e9f..41d9978 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -137,6 +137,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/markup-processor-anchor.cpp ${toolkit_src_dir}/text/markup-processor-font.cpp ${toolkit_src_dir}/text/markup-processor-background.cpp + ${toolkit_src_dir}/text/markup-processor-span.cpp ${toolkit_src_dir}/text/markup-processor-helper-functions.cpp ${toolkit_src_dir}/text/multi-language-support.cpp ${toolkit_src_dir}/text/hidden-text.cpp diff --git a/dali-toolkit/internal/text/markup-processor-color.cpp b/dali-toolkit/internal/text/markup-processor-color.cpp index b66e37a..d5fce04 100644 --- a/dali-toolkit/internal/text/markup-processor-color.cpp +++ b/dali-toolkit/internal/text/markup-processor-color.cpp @@ -36,6 +36,11 @@ namespace const std::string XHTML_VALUE_ATTRIBUTE("value"); } +void ProcessColor(const Attribute& attribute, ColorRun& colorRun) +{ + ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color); +} + void ProcessColorTag(const Tag& tag, ColorRun& colorRun) { for(Vector::ConstIterator it = tag.attributes.Begin(), @@ -46,7 +51,7 @@ void ProcessColorTag(const Tag& tag, ColorRun& colorRun) const Attribute& attribute(*it); if(TokenComparison(XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) { - ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color); + ProcessColor(attribute, colorRun); } } } diff --git a/dali-toolkit/internal/text/markup-processor-color.h b/dali-toolkit/internal/text/markup-processor-color.h index 89e9d2a..02210fb 100644 --- a/dali-toolkit/internal/text/markup-processor-color.h +++ b/dali-toolkit/internal/text/markup-processor-color.h @@ -25,11 +25,20 @@ namespace Toolkit namespace Text { struct Tag; +struct Attribute; struct ColorRun; /** * @brief Retrieves the color value from the tag and sets it to the color run. * + * @param[in] attribute the color attribute. + * @param[in,out] colorRun The color run. + */ +void ProcessColor(const Attribute& attribute, ColorRun& colorRun); + +/** + * @brief Retrieves the color value from the tag and sets it to the color run. + * * @param[in] tag The color tag and its attributes. * @param[in,out] colorRun The color run. */ diff --git a/dali-toolkit/internal/text/markup-processor-font.cpp b/dali-toolkit/internal/text/markup-processor-font.cpp index 4ddcd61..df8b6ec 100644 --- a/dali-toolkit/internal/text/markup-processor-font.cpp +++ b/dali-toolkit/internal/text/markup-processor-font.cpp @@ -41,9 +41,64 @@ const std::string XHTML_WEIGHT_ATTRIBUTE("weight"); const std::string XHTML_WIDTH_ATTRIBUTE("width"); const std::string XHTML_SLANT_ATTRIBUTE("slant"); -const unsigned int MAX_FONT_ATTRIBUTE_SIZE = 15u; ///< The maximum length of any of the possible 'weight', 'width' or 'slant' values. +const std::string FONT_PREFIX("font-"); +const unsigned int FONT_PREFIX_LENGTH = 5u; +const unsigned int MIN_FONT_ATTRIBUTE_SIZE = 4u; ///< The minimum length of any of the possible 'weight', 'width' , 'slant' or 'size' values. +const unsigned int MAX_FONT_ATTRIBUTE_SIZE = 15u; ///< The maximum length of any of the possible 'weight', 'width' or 'slant' values. +const float PIXEL_FORMAT_64_FACTOR = 64.f; ///< 64.f is used to convert from point size to 26.6 pixel format. } // namespace +void processFontAttributeValue(char value[], const Attribute& attribute) +{ + // The StringToWeight() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char. + const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength; + memcpy(value, attribute.valueBuffer, length); + value[length] = 0; +} + +void ProcessFontFamily(const Attribute& attribute, FontDescriptionRun& fontRun) +{ + fontRun.familyDefined = true; + fontRun.familyLength = attribute.valueLength; + fontRun.familyName = new char[fontRun.familyLength]; + memcpy(fontRun.familyName, attribute.valueBuffer, fontRun.familyLength); + // The memory is freed when the font run is removed from the logical model. +} + +void ProcessFontSize(const Attribute& attribute, FontDescriptionRun& fontRun) +{ + // 64.f is used to convert from point size to 26.6 pixel format. + fontRun.size = static_cast(StringToFloat(attribute.valueBuffer) * PIXEL_FORMAT_64_FACTOR); + fontRun.sizeDefined = true; +} + +void ProcessFontWeight(const Attribute& attribute, FontDescriptionRun& fontRun) +{ + char value[MAX_FONT_ATTRIBUTE_SIZE + 1u]; + processFontAttributeValue(value, attribute); + + fontRun.weight = StringToWeight(value); + fontRun.weightDefined = true; +} + +void ProcessFontWidth(const Attribute& attribute, FontDescriptionRun& fontRun) +{ + char value[MAX_FONT_ATTRIBUTE_SIZE + 1u]; + processFontAttributeValue(value, attribute); + + fontRun.width = StringToWidth(value); + fontRun.widthDefined = true; +} + +void ProcessFontSlant(const Attribute& attribute, FontDescriptionRun& fontRun) +{ + char value[MAX_FONT_ATTRIBUTE_SIZE + 1u]; + processFontAttributeValue(value, attribute); + + fontRun.slant = StringToSlant(value); + fontRun.slantDefined = true; +} + void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun) { for(Vector::ConstIterator it = tag.attributes.Begin(), @@ -52,52 +107,26 @@ void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun) ++it) { const Attribute& attribute(*it); + if(TokenComparison(XHTML_FAMILY_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) { - fontRun.familyDefined = true; - fontRun.familyLength = attribute.valueLength; - fontRun.familyName = new char[fontRun.familyLength]; - memcpy(fontRun.familyName, attribute.valueBuffer, fontRun.familyLength); - // The memory is freed when the font run is removed from the logical model. + ProcessFontFamily(attribute, fontRun); } else if(TokenComparison(XHTML_SIZE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) { - // 64.f is used to convert from point size to 26.6 pixel format. - fontRun.size = static_cast(StringToFloat(attribute.valueBuffer) * 64.f); - fontRun.sizeDefined = true; + ProcessFontSize(attribute, fontRun); } else if(TokenComparison(XHTML_WEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) { - // The StringToWeight() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char. - char value[MAX_FONT_ATTRIBUTE_SIZE + 1u]; - const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength; - memcpy(value, attribute.valueBuffer, length); - value[length] = 0; - - fontRun.weight = StringToWeight(value); - fontRun.weightDefined = true; + ProcessFontWeight(attribute, fontRun); } else if(TokenComparison(XHTML_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) { - // The StringToWidth() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char. - char value[MAX_FONT_ATTRIBUTE_SIZE + 1u]; - const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength; - memcpy(value, attribute.valueBuffer, length); - value[length] = 0; - - fontRun.width = StringToWidth(value); - fontRun.widthDefined = true; + ProcessFontWidth(attribute, fontRun); } else if(TokenComparison(XHTML_SLANT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) { - // The StringToSlant() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char. - char value[MAX_FONT_ATTRIBUTE_SIZE + 1u]; - const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength; - memcpy(value, attribute.valueBuffer, length); - value[length] = 0; - - fontRun.slant = StringToSlant(value); - fontRun.slantDefined = true; + ProcessFontSlant(attribute, fontRun); } } } diff --git a/dali-toolkit/internal/text/markup-processor-font.h b/dali-toolkit/internal/text/markup-processor-font.h index 8b075bf..6461451 100644 --- a/dali-toolkit/internal/text/markup-processor-font.h +++ b/dali-toolkit/internal/text/markup-processor-font.h @@ -25,6 +25,7 @@ namespace Toolkit namespace Text { struct Tag; +struct Attribute; struct FontDescriptionRun; /** @@ -35,6 +36,46 @@ struct FontDescriptionRun; */ void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun); +/** + * @brief Fill the font run with the font slant attribute value. + * + * @param[in] attribute the font slant attribute. + * @param[out] fontRun The font description run. + */ +void ProcessFontSlant(const Attribute& attribute, FontDescriptionRun& fontRun); + +/** + * @brief Fill the font run with the font width attribute value. + * + * @param[in] attribute the font width attribute. + * @param[out] fontRun The font description run. + */ +void ProcessFontWidth(const Attribute& attribute, FontDescriptionRun& fontRun); + +/** + * @brief Fill the font run with the font weight attribute value. + * + * @param[in] attribute the font weight attribute. + * @param[out] fontRun The font description run. + */ +void ProcessFontWeight(const Attribute& attribute, FontDescriptionRun& fontRun); + +/** + * @brief Fill the font run with the font size attribute value. + * + * @param[in] attribute the font size attribute. + * @param[out] fontRun The font description run. + */ +void ProcessFontSize(const Attribute& attribute, FontDescriptionRun& fontRun); + +/** + * @brief Fill the font run with the font family attribute value. + * + * @param[in] attribute the font family attribute. + * @param[out] fontRun The font description run. + */ +void ProcessFontFamily(const Attribute& attribute, FontDescriptionRun& fontRun); + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/markup-processor-span.cpp b/dali-toolkit/internal/text/markup-processor-span.cpp new file mode 100644 index 0000000..40a508d --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-span.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// FILE HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +namespace +{ +const std::string XHTML_FAMILY_ATTRIBUTE("font-family"); +const std::string XHTML_SIZE_ATTRIBUTE("font-size"); +const std::string XHTML_WEIGHT_ATTRIBUTE("font-weight"); +const std::string XHTML_WIDTH_ATTRIBUTE("font-width"); +const std::string XHTML_SLANT_ATTRIBUTE("font-slant"); + +const std::string XHTML_COLOR_ATTRIBUTE("text-color"); +} // namespace + +void ProcessSpanTag(const Tag& tag, ColorRun& colorRun, FontDescriptionRun& fontRun, bool& isColorDefined, bool& isFontDefined) +{ + 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)) + { + isColorDefined = true; + ProcessColor(attribute, colorRun); + } + else if(TokenComparison(XHTML_FAMILY_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + isFontDefined = true; + ProcessFontFamily(attribute, fontRun); + } + else if(TokenComparison(XHTML_SIZE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + isFontDefined = true; + ProcessFontSize(attribute, fontRun); + } + else if(TokenComparison(XHTML_WEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + isFontDefined = true; + ProcessFontWeight(attribute, fontRun); + } + else if(TokenComparison(XHTML_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + isFontDefined = true; + ProcessFontWidth(attribute, fontRun); + } + else if(TokenComparison(XHTML_SLANT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + isFontDefined = true; + ProcessFontSlant(attribute, fontRun); + } + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/markup-processor-span.h b/dali-toolkit/internal/text/markup-processor-span.h new file mode 100644 index 0000000..330caf1 --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-span.h @@ -0,0 +1,47 @@ +#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H +#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H + +/* + * Copyright (c) 2021 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 MarkupProcessData; + +/** + * @brief process the span from the tag and process all styles in it. + * + * @param[in] tag The span tag and its attributes. + * @param[out] colorRun the color run to be filled. + * @param[out] fontRun the font run to be filled. + * @param[out] isColorDefined if the span has color defined. + * @param[out] isFontDefined if the span has font defined. + */ +void ProcessSpanTag(const Tag& tag, ColorRun& colorRun, FontDescriptionRun& fontRun, bool& isColorDefined, bool& isFontDefined); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index 6fef092..b656aa4 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include namespace Dali @@ -55,6 +56,7 @@ const std::string XHTML_OUTLINE_TAG("outline"); const std::string XHTML_ITEM_TAG("item"); const std::string XHTML_ANCHOR_TAG("a"); const std::string XHTML_BACKGROUND_TAG("background"); +const std::string XHTML_SPAN_TAG("span"); const char LESS_THAN = '<'; const char GREATER_THAN = '>'; @@ -82,15 +84,16 @@ const unsigned int DEFAULT_VECTOR_SIZE = 16u; ///< Default size of run vectors Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_MARKUP_PROCESSOR"); #endif +typedef VectorBase::SizeType RunIndex; + /** * @brief Struct used to retrieve the style runs from the mark-up string. */ +template struct StyleStack { - typedef VectorBase::SizeType RunIndex; - - Vector stack; ///< Use a vector as a style stack. Stores the indices pointing where the run is stored inside the logical model. - unsigned int topIndex; ///< Points the top of the stack. + Vector stack; ///< Use a vector as a style stack. + unsigned int topIndex; ///< Points the top of the stack. StyleStack() : stack(), @@ -99,7 +102,7 @@ struct StyleStack stack.Resize(DEFAULT_VECTOR_SIZE); } - void Push(RunIndex index) + void Push(StyleStackType item) { // Check if there is space inside the style stack. const VectorBase::SizeType size = stack.Count(); @@ -109,14 +112,14 @@ struct StyleStack stack.Resize(2u * size); } - // Set the run index in the top of the stack. - *(stack.Begin() + topIndex) = index; + // Set the item in the top of the stack. + *(stack.Begin() + topIndex) = item; // Reposition the pointer to the top of the stack. ++topIndex; } - RunIndex Pop() + StyleStackType Pop() { // Pop the top of the stack. --topIndex; @@ -125,6 +128,17 @@ struct StyleStack }; /** + * @brief Struct used to retrieve spans from the mark-up string. + */ +struct Span +{ + RunIndex colorRunIndex; + RunIndex fontRunIndex; + bool isColorDefined; + bool isFontDefined; +}; + +/** * @brief Initializes a font run description to its defaults. * * @param[in,out] fontRun The font description run to initialize. @@ -169,6 +183,19 @@ void Initialize(UnderlinedCharacterRun& underlinedCharacterRun) } /** + * @brief Initializes a span to its defaults. + * + * @param[in,out] span The span to be initialized. + */ +void Initialize(Span& span) +{ + span.colorRunIndex = 0u; + span.isColorDefined = false; + span.fontRunIndex = 0u; + span.isFontDefined = false; +} + +/** * @brief Splits the tag string into the tag name and its attributes. * * The attributes are stored in a vector in the tag. @@ -526,10 +553,10 @@ bool XHTMLNumericEntityToUtf8(const char* markupText, char* utf8) template void ProcessTagForRun( Vector& runsContainer, - StyleStack& styleStack, + StyleStack& styleStack, const Tag& tag, const CharacterIndex characterIndex, - StyleStack::RunIndex& runIndex, + RunIndex& runIndex, int& tagReference, std::function parameterSettingFunction) { @@ -627,6 +654,94 @@ void ProcessAnchorTag( } /** + * @brief Processes span tag for the color-run & font-run. + * + * @param[in] spanTag The tag we are currently processing + * @param[in/out] spanStack The spans stack + * @param[int/out] colorRuns The container containing all the color runs + * @param[int/out] fontRuns The container containing all the font description runs + * @param[in/out] colorRunIndex The color run index + * @param[in/out] fontRunIndex The font run index + * @param[in] characterIndex The current character index + * @param[in] tagReference The tagReference we should increment/decrement + */ +void ProcessSpanForRun( + const Tag& spanTag, + StyleStack& spanStack, + Vector& colorRuns, + Vector& fontRuns, + RunIndex& colorRunIndex, + RunIndex& fontRunIndex, + const CharacterIndex characterIndex, + int& tagReference) +{ + if(!spanTag.isEndTag) + { + // Create a new run. + ColorRun colorRun; + Initialize(colorRun); + + FontDescriptionRun fontRun; + Initialize(fontRun); + + Span span; + Initialize(span); + + // Fill the run with the parameters. + colorRun.characterRun.characterIndex = characterIndex; + fontRun.characterRun.characterIndex = characterIndex; + + span.colorRunIndex = colorRunIndex; + span.fontRunIndex = fontRunIndex; + + ProcessSpanTag(spanTag, colorRun, fontRun, span.isColorDefined, span.isFontDefined); + + // Push the span into the stack. + spanStack.Push(span); + + // Point the next free run. + if(span.isColorDefined) + { + // Push the run in the logical model. + colorRuns.PushBack(colorRun); + ++colorRunIndex; + } + + if(span.isFontDefined) + { + // Push the run in the logical model. + fontRuns.PushBack(fontRun); + ++fontRunIndex; + } + + // Increase reference + ++tagReference; + } + else + { + if(tagReference > 0) + { + // Pop the top of the stack and set the number of characters of the run. + Span span = spanStack.Pop(); + + if(span.isColorDefined) + { + ColorRun& colorRun = *(colorRuns.Begin() + span.colorRunIndex); + colorRun.characterRun.numberOfCharacters = characterIndex - colorRun.characterRun.characterIndex; + } + + if(span.isFontDefined) + { + FontDescriptionRun& fontRun = *(fontRuns.Begin() + span.fontRunIndex); + fontRun.characterRun.numberOfCharacters = characterIndex - fontRun.characterRun.characterIndex; + } + + --tagReference; + } + } +} + +/** * @brief Resizes the model's vectors * * @param[in/out] markupProcessData The markup process data @@ -635,7 +750,7 @@ void ProcessAnchorTag( * @param[in] underlinedCharacterRunIndex The underlined character run index * @param[in] backgroundRunIndex The background run index */ -void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex, const StyleStack::RunIndex backgroundRunIndex) +void ResizeModelVectors(MarkupProcessData& markupProcessData, const RunIndex fontRunIndex, const RunIndex colorRunIndex, const RunIndex underlinedCharacterRunIndex, const RunIndex backgroundRunIndex) { markupProcessData.fontRuns.Resize(fontRunIndex); markupProcessData.colorRuns.Resize(colorRunIndex); @@ -754,13 +869,16 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar markupProcessData.markupProcessedText.reserve(markupStringSize); // Stores a struct with the index to the first character of the run, the type of run and its parameters. - StyleStack styleStack; + StyleStack styleStack; + + // Stores a struct with the index to the first character of the color run & color font for the span. + StyleStack spanStack; // Points the next free position in the vector of runs. - StyleStack::RunIndex colorRunIndex = 0u; - StyleStack::RunIndex fontRunIndex = 0u; - StyleStack::RunIndex underlinedCharacterRunIndex = 0u; - StyleStack::RunIndex backgroundRunIndex = 0u; + RunIndex colorRunIndex = 0u; + RunIndex fontRunIndex = 0u; + RunIndex underlinedCharacterRunIndex = 0u; + RunIndex backgroundRunIndex = 0u; // check tag reference int colorTagReference = 0u; @@ -769,6 +887,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar int bTagReference = 0u; int uTagReference = 0u; int backgroundTagReference = 0u; + int spanTagReference = 0u; // Give an initial default value to the model's vectors. markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE); @@ -856,6 +975,10 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar ProcessTagForRun( markupProcessData.backgroundColorRuns, styleStack, tag, characterIndex, backgroundRunIndex, backgroundTagReference, [](const Tag& tag, ColorRun& run) { ProcessBackground(tag, run); }); } + else if(TokenComparison(XHTML_SPAN_TAG, tag.buffer, tag.length)) + { + ProcessSpanForRun(tag, spanStack, markupProcessData.colorRuns, markupProcessData.fontRuns, colorRunIndex, fontRunIndex, characterIndex, spanTagReference); + } } // end if( IsTag() ) else if(markupStringBuffer < markupStringEndBuffer) { -- 2.7.4