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, "H<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ello</span> 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, "<span font-size='45'>H</span>ello <span text-color='red'>S</span>pan" );
+
+ 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
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, "H<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ello</span> 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, "<span font-size='45'>H</span>ello <span text-color='red'>S</span>pan" );
+
+ 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
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, "H<span font-size='45' font-family='DejaVu Sans' font-width='condensed' font-slant='italic' text-color='red'>ello</span> 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, "<span font-size='45'>H</span>ello <span text-color='red'>S</span>pan" );
+
+ 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
${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
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<Attribute>::ConstIterator it = tag.attributes.Begin(),
const Attribute& attribute(*it);
if(TokenComparison(XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
{
- ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
+ ProcessColor(attribute, colorRun);
}
}
}
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.
*/
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<PointSize26Dot6>(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<Attribute>::ConstIterator it = tag.attributes.Begin(),
++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<PointSize26Dot6>(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);
}
}
}
namespace Text
{
struct Tag;
+struct Attribute;
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
--- /dev/null
+/*
+ * 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 <dali-toolkit/internal/text/markup-processor-color.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/markup-processor-font.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+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<Attribute>::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
--- /dev/null
+#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
#include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
#include <dali-toolkit/internal/text/markup-processor-font.h>
#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor-span.h>
#include <dali-toolkit/internal/text/xhtml-entities.h>
namespace Dali
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 = '>';
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<typename StyleStackType>
struct StyleStack
{
- typedef VectorBase::SizeType RunIndex;
-
- Vector<RunIndex> 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<StyleStackType> stack; ///< Use a vector as a style stack.
+ unsigned int topIndex; ///< Points the top of the stack.
StyleStack()
: stack(),
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();
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;
};
/**
+ * @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.
}
/**
+ * @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.
template<typename RunType>
void ProcessTagForRun(
Vector<RunType>& runsContainer,
- StyleStack& styleStack,
+ StyleStack<RunIndex>& styleStack,
const Tag& tag,
const CharacterIndex characterIndex,
- StyleStack::RunIndex& runIndex,
+ RunIndex& runIndex,
int& tagReference,
std::function<void(const Tag&, RunType&)> parameterSettingFunction)
{
}
/**
+ * @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<Span>& spanStack,
+ Vector<ColorRun>& colorRuns,
+ Vector<FontDescriptionRun>& 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
* @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);
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<RunIndex> styleStack;
+
+ // Stores a struct with the index to the first character of the color run & color font for the span.
+ StyleStack<Span> 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;
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);
ProcessTagForRun<ColorRun>(
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)
{
{
namespace Text
{
-
Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask, bool restoreLinesAndGlyphPositions)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->CalculateLayoutSizeOnRequiredControllerSize\n");
// The number of lines and glyph-positions inside visualModel have been changed by calling DoRelayout with requestedControllerSize.
// Store the mLines and mGlyphPositions from visualModel so that they can be restored later on with no modifications made on them.
//TODO: Refactor "DoRelayout" and extract common code of size calculation without modifying attributes of mVisualModel, and then blah, blah, etc.
- Vector<LineRun> linesBackup = visualModel->mLines;
+ Vector<LineRun> linesBackup = visualModel->mLines;
Vector<Vector2> glyphPositionsBackup = visualModel->mGlyphPositions;
// Operations that can be done only once until the text changes.
const Size actualControlSize = visualModel->mControlSize;
DoRelayout(controller,
- requestedControllerSize,
- static_cast<OperationsMask>(onlyOnceOperations |
- requestedOperationsMask),
- calculatedLayoutSize);
-
+ requestedControllerSize,
+ static_cast<OperationsMask>(onlyOnceOperations |
+ requestedOperationsMask),
+ calculatedLayoutSize);
// Clear the update info. This info will be set the next time the text is updated.
textUpdateInfo.Clear();
// Restore the previously backed-up mLines and mGlyphPositions from visualModel.
if(restoreLinesAndGlyphPositions)
{
- visualModel->mLines = linesBackup;
+ visualModel->mLines = linesBackup;
visualModel->mGlyphPositions = glyphPositionsBackup;
}
return calculatedLayoutSize;
}
-
Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n");
// Make sure the model is up-to-date before layouting
controller.ProcessModifyEvents();
- Controller::Impl& impl = *controller.mImpl;
- ModelPtr& model = impl.mModel;
- VisualModelPtr& visualModel = model->mVisualModel;
+ Controller::Impl& impl = *controller.mImpl;
+ ModelPtr& model = impl.mModel;
+ VisualModelPtr& visualModel = model->mVisualModel;
if(impl.mRecalculateNaturalSize)
{
Size naturalSize;
// Layout the text for the new width.
- OperationsMask requestedOperationsMask = static_cast<OperationsMask>(LAYOUT | REORDER);
- Size sizeMaxWidthAndMaxHeight = Size(MAX_FLOAT, MAX_FLOAT);
+ OperationsMask requestedOperationsMask = static_cast<OperationsMask>(LAYOUT | REORDER);
+ Size sizeMaxWidthAndMaxHeight = Size(MAX_FLOAT, MAX_FLOAT);
naturalSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeMaxWidthAndMaxHeight, requestedOperationsMask, true);
textUpdateInfo.mFullRelayoutNeeded ||
textUpdateInfo.mClearAll)
{
-
// Layout the text for the new width.
- OperationsMask requestedOperationsMask = static_cast<OperationsMask>(LAYOUT);
- Size sizeRequestedWidthAndMaxHeight = Size(width, MAX_FLOAT);
+ OperationsMask requestedOperationsMask = static_cast<OperationsMask>(LAYOUT);
+ Size sizeRequestedWidthAndMaxHeight = Size(width, MAX_FLOAT);
// Skip restore, because if GetHeightForWidth called before rendering and layouting then visualModel->mControlSize will be zero which will make LineCount zero.
// The implementation of Get LineCount property depends on calling GetHeightForWidth then read mLines.Count() from visualModel direct.
// So we will not restore the previously backed-up mLines and mGlyphPositions from visualModel in such case.
// Another case to skip restore is when the requested width equals the Control's width which means the caller need to update the old values.
// For example, when the text is changed.
- bool restoreLinesAndGlyphPositions = (visualModel->mControlSize.width>0 && visualModel->mControlSize.height>0)
- && (visualModel->mControlSize.width != width);
+ bool restoreLinesAndGlyphPositions = (visualModel->mControlSize.width > 0 && visualModel->mControlSize.height > 0) && (visualModel->mControlSize.width != width);
layoutSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeRequestedWidthAndMaxHeight, requestedOperationsMask, restoreLinesAndGlyphPositions);
void Controller::Relayouter::CalculateVerticalOffset(Controller& controller, const Size& controlSize)
{
- Controller::Impl& impl = *controller.mImpl;
- ModelPtr& model = impl.mModel;
- VisualModelPtr& visualModel = model->mVisualModel;
- Size layoutSize = model->mVisualModel->GetLayoutSize();
- Size oldLayoutSize = layoutSize;
- float offsetY = 0.f;
- bool needRecalc = false;
+ Controller::Impl& impl = *controller.mImpl;
+ ModelPtr& model = impl.mModel;
+ VisualModelPtr& visualModel = model->mVisualModel;
+ Size layoutSize = model->mVisualModel->GetLayoutSize();
+ Size oldLayoutSize = layoutSize;
+ float offsetY = 0.f;
+ bool needRecalc = false;
float defaultFontLineHeight = impl.GetDefaultFontLineHeight();
if(fabsf(layoutSize.height) < Math::MACHINE_EPSILON_1000)
// Whether the text control is editable
const bool isEditable = NULL != impl.mEventData;
- if (isEditable && layoutSize.height != defaultFontLineHeight)
+ if(isEditable && layoutSize.height != defaultFontLineHeight && impl.IsShowingPlaceholderText())
{
// This code prevents the wrong positioning of cursor when the layout size is bigger/smaller than defaultFontLineHeight.
// This situation occurs when the size of placeholder text is different from the default text.
layoutSize.height = defaultFontLineHeight;
- needRecalc = true;
+ needRecalc = true;
}
switch(model->mVerticalAlignment)
case VerticalAlignment::TOP:
{
model->mScrollPosition.y = 0.f;
- offsetY = 0.f;
+ offsetY = 0.f;
break;
}
case VerticalAlignment::CENTER:
{
model->mScrollPosition.y = floorf(0.5f * (controlSize.height - layoutSize.height)); // try to avoid pixel alignment.
- if (needRecalc) offsetY = floorf(0.5f * (layoutSize.height - oldLayoutSize.height));
+ if(needRecalc) offsetY = floorf(0.5f * (layoutSize.height - oldLayoutSize.height));
break;
}
case VerticalAlignment::BOTTOM:
{
model->mScrollPosition.y = controlSize.height - layoutSize.height;
- if (needRecalc) offsetY = layoutSize.height - oldLayoutSize.height;
+ if(needRecalc) offsetY = layoutSize.height - oldLayoutSize.height;
break;
}
}
- if (needRecalc)
+ if(needRecalc)
{
// Update glyphPositions according to recalculation.
- const Length positionCount = visualModel->mGlyphPositions.Count();
+ const Length positionCount = visualModel->mGlyphPositions.Count();
Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
for(Length index = 0u; index < positionCount; index++)
{
glyphPositions[index].y += offsetY;
}
}
-
}
} // namespace Text