From 1bf8666355ccc3b6ca6dde1cf4be9f0bc6e35875 Mon Sep 17 00:00:00 2001 From: abdullah Date: Mon, 31 May 2021 17:38:06 +0300 Subject: [PATCH] add support for background markup tag 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, "Wood"); 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: Ib3259932cb1bf0efc3f8690e7bdcdd8ca37423fd --- .../dali-toolkit-test-utils/toolkit-text-utils.cpp | 3 +- .../dali-toolkit-internal/utc-Dali-Text-Markup.cpp | 5 +- .../utc-Dali-TextEditor-internal.cpp | 33 +++++- .../utc-Dali-TextField-internal.cpp | 33 +++++- .../utc-Dali-TextLabel-internal.cpp | 33 +++++- dali-toolkit/devel-api/text/text-utils-devel.cpp | 3 +- .../controls/text-controls/text-editor-impl.cpp | 57 ++++++++- .../controls/text-controls/text-editor-impl.h | 1 + dali-toolkit/internal/file.list | 1 + .../internal/text/markup-processor-background.cpp | 55 +++++++++ .../internal/text/markup-processor-background.h | 44 +++++++ dali-toolkit/internal/text/markup-processor.cpp | 36 ++++-- dali-toolkit/internal/text/markup-processor.h | 13 +- .../internal/text/rendering/text-typesetter.cpp | 131 ++++++++++++++++++++- .../internal/text/rendering/view-model.cpp | 5 + dali-toolkit/internal/text/rendering/view-model.h | 5 + .../internal/text/text-controller-impl.cpp | 87 ++++++++------ .../internal/text/text-controller-text-updater.cpp | 3 +- dali-toolkit/internal/text/text-model-interface.h | 7 ++ dali-toolkit/internal/text/text-model.cpp | 5 + dali-toolkit/internal/text/text-model.h | 5 + dali-toolkit/internal/text/text-view-interface.h | 7 ++ dali-toolkit/internal/text/text-view.cpp | 10 ++ dali-toolkit/internal/text/text-view.h | 5 + 24 files changed, 522 insertions(+), 65 deletions(-) create mode 100644 dali-toolkit/internal/text/markup-processor-background.cpp create mode 100644 dali-toolkit/internal/text/markup-processor-background.h diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp index 0a426b0..9f77f91 100755 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp @@ -112,7 +112,8 @@ void CreateTextModel( const std::string& text, logicalModel->mFontDescriptionRuns, logicalModel->mEmbeddedItems, logicalModel->mAnchors, - logicalModel->mUnderlinedCharacterRuns); + logicalModel->mUnderlinedCharacterRuns, + logicalModel->mBackgroundColorRuns); Length textSize = 0u; const uint8_t* utf8 = NULL; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp index f46c401..1a4b5e1 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * 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. @@ -186,7 +186,8 @@ namespace Vector items; Vector anchors; Vector underlinedCharacterRuns; - MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors, underlinedCharacterRuns ); + Vector backgroundColorRuns; + MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns ); ProcessMarkupString( data.xHTMLEntityString, markupProcessData ); for( Vector::Iterator it = items.Begin(), diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp index b19d653..73d9e12 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * 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. @@ -167,4 +167,35 @@ int UtcDaliTextEditorFontPointSizeLargerThanAtlasPlaceholderCase(void) DALI_TEST_EQUALS( countAtlas, 1, TEST_LOCATION ); END_TEST; +} + +int UtcDaliTextEditorBackgroundTag(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextEditorBackgroundTag\n"); + + TextEditor editor = TextEditor::New(); + DALI_TEST_CHECK( editor ); + + editor.SetProperty( TextEditor ::Property::ENABLE_MARKUP, true ); + editor.SetProperty( TextEditor::Property::TEXT, "He World" ); + application.GetScene().Add( editor ); + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextEditor& editorImpl = GetImpl( editor ); + const ColorIndex* const backgroundColorIndicesBuffer = editorImpl.getController()->GetTextModel()->GetBackgroundColorIndices(); + + DALI_TEST_CHECK( backgroundColorIndicesBuffer ); + + //default color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION); + + //red color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION); + + //yellow color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, 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 619e5f4..73fe7e2 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * 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. @@ -251,4 +251,35 @@ int UtcDaliTextFieldFontPointSizeLargerThanAtlasPlaceholderCase(void) END_TEST; +} + +int UtcDaliTextFieldBackgroundTag(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextFieldBackgroundTag\n"); + + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + field.SetProperty( TextField ::Property::ENABLE_MARKUP, true ); + field.SetProperty( TextField::Property::TEXT, "He World" ); + application.GetScene().Add( field ); + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextField& fieldImpl = GetImpl( field ); + const ColorIndex* const backgroundColorIndicesBuffer = fieldImpl.getController()->GetTextModel()->GetBackgroundColorIndices(); + + DALI_TEST_CHECK( backgroundColorIndicesBuffer ); + + //default color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION); + + //red color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION); + + //yellow color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, 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 e85ea21..f67d88a 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * 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. @@ -66,4 +66,35 @@ int UtcDaliTextLabelMarkupUnderline(void) END_TEST; +} + +int UtcDaliTextLabelBackgroundTag(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextLabelBackgroundTag\n"); + + TextLabel label = TextLabel::New(); + DALI_TEST_CHECK( label ); + + label.SetProperty( TextLabel ::Property::ENABLE_MARKUP, true ); + label.SetProperty( TextLabel::Property::TEXT, "He World" ); + application.GetScene().Add( label ); + application.SendNotification(); + application.Render(); + + Toolkit::Internal::TextLabel& labelImpl = GetImpl( label ); + const ColorIndex* const backgroundColorIndicesBuffer = labelImpl.getController()->GetTextModel()->GetBackgroundColorIndices(); + + DALI_TEST_CHECK( backgroundColorIndicesBuffer ); + + //default color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION); + + //red color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION); + + //yellow color + DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION); + + END_TEST; } \ No newline at end of file diff --git a/dali-toolkit/devel-api/text/text-utils-devel.cpp b/dali-toolkit/devel-api/text/text-utils-devel.cpp index a4dbce4..99ff139 100644 --- a/dali-toolkit/devel-api/text/text-utils-devel.cpp +++ b/dali-toolkit/devel-api/text/text-utils-devel.cpp @@ -174,7 +174,8 @@ void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstracti fontDescriptionRuns, textModel->mLogicalModel->mEmbeddedItems, textModel->mLogicalModel->mAnchors, - textModel->mLogicalModel->mUnderlinedCharacterRuns); + textModel->mLogicalModel->mUnderlinedCharacterRuns, + textModel->mLogicalModel->mBackgroundColorRuns); if(textParameters.markupEnabled) { diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp index 9b9e7d9..db7096a 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -1560,16 +1560,50 @@ void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType) if(renderableActor != mRenderableActor) { + UnparentAndReset(mBackgroundActor); UnparentAndReset(mRenderableActor); mRenderableActor = renderableActor; + + if(mRenderableActor) + { + mBackgroundActor = mController->CreateBackgroundActor(); + } } } if(mRenderableActor) { + const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition(); + + float renderableActorPositionX, renderableActorPositionY; + + if(mStencil) + { + renderableActorPositionX = scrollOffset.x + mAlignmentOffset; + renderableActorPositionY = scrollOffset.y; + } + else + { + Extents padding; + padding = Self().GetProperty(Toolkit::Control::Property::PADDING); + + // Support Right-To-Left of padding + Dali::LayoutDirection::Type layoutDirection = static_cast(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); + if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection) + { + std::swap(padding.start, padding.end); + } + + renderableActorPositionX = scrollOffset.x + mAlignmentOffset + padding.start; + renderableActorPositionY = scrollOffset.y + padding.top; + } + + mRenderableActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // Make sure the actors are parented correctly with/without clipping Actor self = mStencil ? mStencil : Self(); + Actor highlightActor; + for(std::vector::iterator it = mClippingDecorationActors.begin(), endIt = mClippingDecorationActors.end(); it != endIt; @@ -1577,11 +1611,32 @@ void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType) { self.Add(*it); it->LowerToBottom(); + + if(it->GetProperty(Dali::Actor::Property::NAME) == "HighlightActor") + { + highlightActor = *it; + } } mClippingDecorationActors.clear(); self.Add(mRenderableActor); + if(mBackgroundActor) + { + if(mDecorator && mDecorator->IsHighlightVisible()) + { + self.Add(mBackgroundActor); + mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // In text field's coords. + mBackgroundActor.LowerBelow(highlightActor); + } + else + { + mRenderableActor.Add(mBackgroundActor); + mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f)); // In renderable actor's coords. + mBackgroundActor.LowerToBottom(); + } + } + ApplyScrollPosition(); } UpdateScrollBar(); @@ -2323,7 +2378,7 @@ Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates() return states; } -bool TextEditor::AccessibleImpl::InsertText(size_t startPosition, +bool TextEditor::AccessibleImpl::InsertText(size_t startPosition, std::string text) { auto slf = Toolkit::TextEditor::DownCast(Self()); diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h index 9a06ea5..0286da2 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -413,6 +413,7 @@ private: // Data Actor mRenderableActor; Actor mActiveLayer; + Actor mBackgroundActor; CallbackBase* mIdleCallback; float mAlignmentOffset; diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index eca4322..f712e9f 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -136,6 +136,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/markup-processor-embedded-item.cpp ${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-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-background.cpp b/dali-toolkit/internal/text/markup-processor-background.cpp new file mode 100644 index 0000000..8a9910e --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-background.cpp @@ -0,0 +1,55 @@ +/* + * 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. + * + */ + +// FILE HEADER +#include + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +namespace +{ +const std::string XHTML_COLOR_ATTRIBUTE("color"); +} // namespace + +void ProcessBackground(const Tag& tag, ColorRun& colorRun) +{ + for(auto&& attribute : tag.attributes) + { + if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength)) + { + ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color); + } + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali \ No newline at end of file diff --git a/dali-toolkit/internal/text/markup-processor-background.h b/dali-toolkit/internal/text/markup-processor-background.h new file mode 100644 index 0000000..331d2c8 --- /dev/null +++ b/dali-toolkit/internal/text/markup-processor-background.h @@ -0,0 +1,44 @@ +#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H +#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_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 ColorRun; + +/** + * @brief Retrieves the @e background from the @p tag. + * + * @param[in] tag The background tag and its attributes. + * @param[in,out] colorRun The color run to be filled. + */ +void ProcessBackground(const Tag& tag, ColorRun& colorRun); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H \ No newline at end of file diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index ea7f869..6fef092 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -26,6 +26,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -53,6 +54,7 @@ const std::string XHTML_GLOW_TAG("glow"); 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 char LESS_THAN = '<'; const char GREATER_THAN = '>'; @@ -631,12 +633,14 @@ void ProcessAnchorTag( * @param[in] fontRunIndex The font run index * @param[in] colorRunIndex The color run index * @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) +void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex, const StyleStack::RunIndex backgroundRunIndex) { markupProcessData.fontRuns.Resize(fontRunIndex); markupProcessData.colorRuns.Resize(colorRunIndex); markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex); + markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex); #ifdef DEBUG_ENABLED for(unsigned int i = 0; i < colorRunIndex; ++i) @@ -753,21 +757,24 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar StyleStack styleStack; // Points the next free position in the vector of runs. - StyleStack::RunIndex colorRunIndex = 0u; - StyleStack::RunIndex fontRunIndex = 0u; - StyleStack::RunIndex underlinedCharacterRunIndex = 0u; + StyleStack::RunIndex colorRunIndex = 0u; + StyleStack::RunIndex fontRunIndex = 0u; + StyleStack::RunIndex underlinedCharacterRunIndex = 0u; + StyleStack::RunIndex backgroundRunIndex = 0u; // check tag reference - int colorTagReference = 0u; - int fontTagReference = 0u; - int iTagReference = 0u; - int bTagReference = 0u; - int uTagReference = 0u; + int colorTagReference = 0u; + int fontTagReference = 0u; + int iTagReference = 0u; + int bTagReference = 0u; + int uTagReference = 0u; + int backgroundTagReference = 0u; // Give an initial default value to the model's vectors. markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); + markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE); // Get the mark-up string buffer. const char* markupStringBuffer = markupString.c_str(); @@ -798,8 +805,8 @@ 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) {}); + } // else if(TokenComparison(XHTML_B_TAG, tag.buffer, tag.length)) { ProcessTagForRun( @@ -844,6 +851,11 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar { ProcessItemTag(markupProcessData, tag, characterIndex); } + else if(TokenComparison(XHTML_BACKGROUND_TAG, tag.buffer, tag.length)) + { + ProcessTagForRun( + markupProcessData.backgroundColorRuns, styleStack, tag, characterIndex, backgroundRunIndex, backgroundTagReference, [](const Tag& tag, ColorRun& run) { ProcessBackground(tag, run); }); + } } // end if( IsTag() ) else if(markupStringBuffer < markupStringEndBuffer) { @@ -852,7 +864,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar } // Resize the model's vectors. - ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex); + ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, backgroundRunIndex); } } // namespace Text diff --git a/dali-toolkit/internal/text/markup-processor.h b/dali-toolkit/internal/text/markup-processor.h index ec45957..e84b892 100644 --- a/dali-toolkit/internal/text/markup-processor.h +++ b/dali-toolkit/internal/text/markup-processor.h @@ -40,16 +40,18 @@ namespace Text */ struct MarkupProcessData { - MarkupProcessData(Vector& colorRuns, - Vector& fontRuns, - Vector& items, - Vector& anchors, - Vector& underlinedCharacterRuns) + MarkupProcessData(Vector& colorRuns, + Vector& fontRuns, + Vector& items, + Vector& anchors, + Vector& underlinedCharacterRuns, + Vector& backgroundColorRuns) : colorRuns(colorRuns), fontRuns(fontRuns), items(items), anchors(anchors), underlinedCharacterRuns(underlinedCharacterRuns), + backgroundColorRuns(backgroundColorRuns), markupProcessedText() { } @@ -59,6 +61,7 @@ struct MarkupProcessData Vector& items; ///< The embedded items. Vector& anchors; ///< The anchors. Vector& underlinedCharacterRuns; ///< The underlined character runs. + Vector& backgroundColorRuns; ///< The background color runs. std::string markupProcessedText; ///< The mark-up string. }; diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index 83d67d5..17a5c61 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -417,6 +417,116 @@ void DrawBackgroundColor( } } +Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuffer& buffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, int horizontalOffset, int verticalOffset) +{ + // Retrieve lines, glyphs, positions and colors from the view model. + const Length modelNumberOfLines = model->GetNumberOfLines(); + const LineRun* const modelLinesBuffer = model->GetLines(); + const Length numberOfGlyphs = model->GetNumberOfGlyphs(); + const GlyphInfo* const glyphsBuffer = model->GetGlyphs(); + const Vector2* const positionBuffer = model->GetLayout(); + const Vector4* const backgroundColorsBuffer = model->GetBackgroundColors(); + const ColorIndex* const backgroundColorIndicesBuffer = model->GetBackgroundColorIndices(); + + // Create and initialize the pixel buffer. + GlyphData glyphData; + glyphData.verticalOffset = verticalOffset; + glyphData.width = bufferWidth; + glyphData.height = bufferHeight; + glyphData.bitmapBuffer = buffer; + glyphData.horizontalOffset = 0; + + ColorIndex prevBackgroundColorIndex = 0; + ColorIndex backgroundColorIndex = 0; + + // Traverses the lines of the text. + for(LineIndex lineIndex = 0u; lineIndex < modelNumberOfLines; ++lineIndex) + { + const LineRun& line = *(modelLinesBuffer + lineIndex); + + // Sets the horizontal offset of the line. + glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast(line.alignmentOffset); + glyphData.horizontalOffset += horizontalOffset; + + // Increases the vertical offset with the line's ascender. + glyphData.verticalOffset += static_cast(line.ascender); + + // Include line spacing after first line + if(lineIndex > 0u) + { + glyphData.verticalOffset += static_cast(line.lineSpacing); + } + + float left = bufferWidth; + float right = 0.0f; + float baseline = 0.0f; + + // Traverses the glyphs of the line. + const GlyphIndex endGlyphIndex = std::min(numberOfGlyphs, line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs); + for(GlyphIndex glyphIndex = line.glyphRun.glyphIndex; glyphIndex < endGlyphIndex; ++glyphIndex) + { + // Retrieve the glyph's info. + const GlyphInfo* const glyphInfo = glyphsBuffer + glyphIndex; + + if((glyphInfo->width < Math::MACHINE_EPSILON_1000) || + (glyphInfo->height < Math::MACHINE_EPSILON_1000)) + { + // Nothing to do if default background color, the glyph's width or height is zero. + continue; + } + + backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + glyphIndex); + + if((backgroundColorIndex != prevBackgroundColorIndex) && + (prevBackgroundColorIndex != 0u)) + { + const Vector4& backgroundColor = *(backgroundColorsBuffer + prevBackgroundColorIndex - 1u); + DrawBackgroundColor(backgroundColor, bufferWidth, bufferHeight, glyphData, baseline, line, left, right); + } + + if(backgroundColorIndex == 0u) + { + prevBackgroundColorIndex = backgroundColorIndex; + //if background color is the default do nothing + continue; + } + + // Retrieves the glyph's position. + const Vector2* const position = positionBuffer + glyphIndex; + + if(baseline < position->y + glyphInfo->yBearing) + { + baseline = position->y + glyphInfo->yBearing; + } + + // Calculate the positions of leftmost and rightmost glyphs in the current line + if((position->x < left) || (backgroundColorIndex != prevBackgroundColorIndex)) + { + left = position->x - glyphInfo->xBearing; + } + + if(position->x + glyphInfo->width > right) + { + right = position->x - glyphInfo->xBearing + glyphInfo->advance; + } + + prevBackgroundColorIndex = backgroundColorIndex; + } + + //draw last background at line end if not default + if(backgroundColorIndex != 0u) + { + const Vector4& backgroundColor = *(backgroundColorsBuffer + backgroundColorIndex - 1u); + DrawBackgroundColor(backgroundColor, bufferWidth, bufferHeight, glyphData, baseline, line, left, right); + } + + // Increases the vertical offset with the line's descender. + glyphData.verticalOffset += static_cast(-line.descender); + } + + return glyphData.bitmapBuffer; +} + } // namespace TypesetterPtr Typesetter::New(const ModelInterface* const model) @@ -587,10 +697,25 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect } // Generate the background if enabled - const bool backgroundEnabled = mModel->IsBackgroundEnabled(); - if(backgroundEnabled) + const bool backgroundEnabled = mModel->IsBackgroundEnabled(); + const bool backgroundMarkupSet = mModel->IsMarkupBackgroundColorSet(); + if(backgroundEnabled || backgroundMarkupSet) { - Devel::PixelBuffer backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1); + Devel::PixelBuffer backgroundImageBuffer; + + if(backgroundEnabled) + { + backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1); + } + else + { + backgroundImageBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat); + } + + if(backgroundMarkupSet) + { + DrawGlyphsBackground(mModel, backgroundImageBuffer, bufferWidth, bufferHeight, ignoreHorizontalAlignment, penX, penY); + } // Combine the two buffers imageBuffer = CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight); diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp index f695cd2..4ad0b14 100644 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -160,6 +160,11 @@ const ColorIndex* const ViewModel::GetBackgroundColorIndices() const return mModel->GetBackgroundColorIndices(); } +bool const ViewModel::IsMarkupBackgroundColorSet() const +{ + return mModel->IsMarkupBackgroundColorSet(); +} + const Vector4& ViewModel::GetDefaultColor() const { return mModel->GetDefaultColor(); diff --git a/dali-toolkit/internal/text/rendering/view-model.h b/dali-toolkit/internal/text/rendering/view-model.h index 9272956..e51a075 100644 --- a/dali-toolkit/internal/text/rendering/view-model.h +++ b/dali-toolkit/internal/text/rendering/view-model.h @@ -146,6 +146,11 @@ public: const ColorIndex* const GetBackgroundColorIndices() const override; /** + * @copydoc ModelInterface::IsMarkupBackgroundColorSet() + */ + bool const IsMarkupBackgroundColorSet() const override; + + /** * @copydoc ModelInterface::GetDefaultColor() */ const Vector4& GetDefaultColor() const override; diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 417eaed..a513d70 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -847,7 +847,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); - updated = true; + updated = true; } const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs; @@ -1056,9 +1056,9 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) } if((NO_OPERATION != (SHAPE_TEXT & operations)) && - ! ((nullptr != mEventData) && - mEventData->mPreEditFlag && - (0u != mModel->mVisualModel->mCharactersToGlyph.Count()))) + !((nullptr != mEventData) && + mEventData->mPreEditFlag && + (0u != mModel->mVisualModel->mCharactersToGlyph.Count()))) { //Mark-up processor case if(mModel->mVisualModel->IsMarkupProcessorEnabled()) @@ -1069,7 +1069,6 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) updated = true; } - // The estimated number of lines. Used to avoid reallocations when layouting. mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count()); @@ -2018,8 +2017,7 @@ void Controller::Impl::RequestRelayout() Actor Controller::Impl::CreateBackgroundActor() { - // NOTE: Currently we only support background color for one line left-to-right text, - // so the following calculation is based on one line left-to-right text only! + // NOTE: Currently we only support background color for left-to-right text. Actor actor; @@ -2060,8 +2058,12 @@ Actor Controller::Impl::CreateBackgroundActor() const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices(); const Vector4& defaultBackgroundColor = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT; - Vector4 quad; - uint32_t numberOfQuads = 0u; + Vector4 quad; + uint32_t numberOfQuads = 0u; + Length yLineOffset = 0; + Length prevLineIndex = 0; + LineIndex lineIndex; + Length numberOfLines; for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i) { @@ -2072,6 +2074,14 @@ Actor Controller::Impl::CreateBackgroundActor() const ColorIndex backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + i); const Vector4& backgroundColor = (0u == backgroundColorIndex) ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u); + mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines); + Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing; + + if(lineIndex != prevLineIndex) + { + yLineOffset += lineHeight; + } + // Only create quads for glyphs with a background color if(backgroundColor != Color::TRANSPARENT) { @@ -2080,30 +2090,30 @@ Actor Controller::Impl::CreateBackgroundActor() if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text { quad.x = position.x; - quad.y = 0.0f; + quad.y = yLineOffset; quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width); - quad.w = textSize.height; + quad.w = lineHeight; } - else if(i == 0u) // The first glyph in the whole text + else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line { quad.x = position.x; - quad.y = 0.0f; + quad.y = yLineOffset; quad.z = quad.x - glyph.xBearing + glyph.advance; - quad.w = textSize.height; + quad.w = quad.y + lineHeight; } else if(i == glyphSize - 1u) // The last glyph in the whole text { quad.x = position.x - glyph.xBearing; - quad.y = 0.0f; + quad.y = yLineOffset; quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width); - quad.w = textSize.height; + quad.w = quad.y + lineHeight; } else // The glyph in the middle of the text { quad.x = position.x - glyph.xBearing; - quad.y = 0.0f; + quad.y = yLineOffset; quad.z = quad.x + glyph.advance; - quad.w = textSize.height; + quad.w = quad.y + lineHeight; } BackgroundVertex vertex; @@ -2142,6 +2152,11 @@ Actor Controller::Impl::CreateBackgroundActor() numberOfQuads++; } + + if(lineIndex != prevLineIndex) + { + prevLineIndex = lineIndex; + } } // Only create the background actor if there are glyphs with background color @@ -2182,28 +2197,28 @@ Actor Controller::Impl::CreateBackgroundActor() void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns) { - //Underlined character runs for markup-processor - const Vector& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns; - const Vector& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph; - const Vector& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter; + //Underlined character runs for markup-processor + const Vector& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns; + const Vector& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph; + const Vector& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter; - if(shouldClearPreUnderlineRuns) - { - mModel->mVisualModel->mUnderlineRuns.Clear(); - } + if(shouldClearPreUnderlineRuns) + { + mModel->mVisualModel->mUnderlineRuns.Clear(); + } - for(Vector::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it) + for(Vector::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it) + { + CharacterIndex characterIndex = it->characterRun.characterIndex; + Length numberOfCharacters = it->characterRun.numberOfCharacters; + for(Length index = 0u; index < numberOfCharacters; index++) { - CharacterIndex characterIndex = it->characterRun.characterIndex; - Length numberOfCharacters = it->characterRun.numberOfCharacters; - for(Length index=0u; indexmVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun); - } + GlyphRun underlineGlyphRun; + underlineGlyphRun.glyphIndex = charactersToGlyph[characterIndex + index]; + underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index]; + mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun); } + } } } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller-text-updater.cpp b/dali-toolkit/internal/text/text-controller-text-updater.cpp index 36a2133..d946365 100644 --- a/dali-toolkit/internal/text/text-controller-text-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-text-updater.cpp @@ -83,7 +83,8 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string& logicalModel->mFontDescriptionRuns, logicalModel->mEmbeddedItems, logicalModel->mAnchors, - logicalModel->mUnderlinedCharacterRuns); + logicalModel->mUnderlinedCharacterRuns, + logicalModel->mBackgroundColorRuns); Length textSize = 0u; const uint8_t* utf8 = NULL; diff --git a/dali-toolkit/internal/text/text-model-interface.h b/dali-toolkit/internal/text/text-model-interface.h index c116f8f..928c3f0 100644 --- a/dali-toolkit/internal/text/text-model-interface.h +++ b/dali-toolkit/internal/text/text-model-interface.h @@ -174,6 +174,13 @@ public: virtual const ColorIndex* const GetBackgroundColorIndices() const = 0; /** + * @brief checks if there is background colors set using markup. + * + * @return boolean if there is background colors set using markup . + */ + virtual bool const IsMarkupBackgroundColorSet() const = 0; + + /** * @brief Retrieves the text's default color. * * @return The default color. diff --git a/dali-toolkit/internal/text/text-model.cpp b/dali-toolkit/internal/text/text-model.cpp index 948044e..26a9be8 100644 --- a/dali-toolkit/internal/text/text-model.cpp +++ b/dali-toolkit/internal/text/text-model.cpp @@ -119,6 +119,11 @@ const ColorIndex* const Model::GetBackgroundColorIndices() const return mVisualModel->mBackgroundColorIndices.Begin(); } +bool const Model::IsMarkupBackgroundColorSet() const +{ + return (mVisualModel->mBackgroundColorIndices.Count() > 0); +} + const Vector4& Model::GetDefaultColor() const { return mVisualModel->mTextColor; diff --git a/dali-toolkit/internal/text/text-model.h b/dali-toolkit/internal/text/text-model.h index 4faa1bc..751f230 100644 --- a/dali-toolkit/internal/text/text-model.h +++ b/dali-toolkit/internal/text/text-model.h @@ -143,6 +143,11 @@ public: const ColorIndex* const GetBackgroundColorIndices() const override; /** + * @copydoc ModelInterface::IsMarkupBackgroundColorSet() + */ + bool const IsMarkupBackgroundColorSet() const override; + + /** * @copydoc ModelInterface::GetDefaultColor() */ const Vector4& GetDefaultColor() const override; diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index 63f7fd4..ee4c306 100644 --- a/dali-toolkit/internal/text/text-view-interface.h +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -124,6 +124,13 @@ public: virtual const ColorIndex* const GetBackgroundColorIndices() const = 0; /** + * @brief checks if there is background colors set using markup. + * + * @return boolean if there is background colors set using markup . + */ + virtual bool const IsMarkupBackgroundColorSet() const = 0; + + /** * @brief Retrieves the text color * * @return The text color diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index 2f74699..74a83f5 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -343,6 +343,16 @@ const ColorIndex* const View::GetBackgroundColorIndices() const return nullptr; } +bool const View::IsMarkupBackgroundColorSet() const +{ + if(mImpl->mVisualModel) + { + return (mImpl->mVisualModel->mBackgroundColorIndices.Count() > 0); + } + + return false; +} + const Vector4& View::GetTextColor() const { if(mImpl->mVisualModel) diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index 3790fd0..7c61275 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -96,6 +96,11 @@ public: const ColorIndex* const GetBackgroundColorIndices() const override; /** + * @copydoc Dali::Toolkit::Text::ViewInterface::IsMarkupBackgroundColorSet() + */ + bool const IsMarkupBackgroundColorSet() const; + + /** * @copydoc Dali::Toolkit::Text::ViewInterface::GetTextColor() */ const Vector4& GetTextColor() const override; -- 2.7.4