From: Paul Wisbey Date: Thu, 20 Oct 2016 09:06:39 +0000 (-0700) Subject: Merge "TextVisual implementation." into devel/master X-Git-Tag: dali_1.2.11~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=63f9b5207c2794cdc460d587723be89585872a51;hp=44835162f4c0107591223e60557ee62b79cab35a Merge "TextVisual implementation." into devel/master --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp index ae91f4c..f2e761f 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp @@ -19,12 +19,14 @@ #include #include +#include #include #include #include #include #include +#include using namespace Dali; using namespace Toolkit; @@ -42,6 +44,8 @@ const char* const OPTION_CLIPBOARD("optionClipboard"); // "Clipboard" popup const Size CONTROL_SIZE( 300.f, 60.f ); +const std::string DEFAULT_FONT_DIR( "/resources/fonts" ); + class ControlImpl : public ControlInterface, public Text::EditableControlInterface { public: @@ -364,3 +368,157 @@ int UtcDaliTextControllerGetInputUnderlineProperty(void) tet_result(TET_PASS); END_TEST; } + +int UtcDaliTextControllerSetGetAutoScrollEnabled(void) +{ + tet_infoline(" UtcDaliTextControllerSetGetAutoScrollEnabled"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + DALI_TEST_CHECK( !controller->IsAutoScrollEnabled() ); + + // The auto scrolling shouldn't be enabled if the multi-line is enabled. + + // Enable multi-line. + controller->SetMultiLineEnabled( true ); + + // Enable text scrolling. + controller->SetAutoScrollEnabled( true ); + + DALI_TEST_CHECK( !controller->IsAutoScrollEnabled() ); + + // Disable multi-line. + controller->SetMultiLineEnabled( false ); + + // Enable text scrolling. + controller->SetAutoScrollEnabled( true ); + + // Should be ebabled now. + DALI_TEST_CHECK( controller->IsAutoScrollEnabled() ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerSetGetAutoScrollSpeed(void) +{ + tet_infoline(" UtcDaliTextControllerSetGetAutoScrollSpeed"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + // Check the default value. + DALI_TEST_EQUALS( 0, controller->GetAutoScrollSpeed(), TEST_LOCATION ); + + // Set the auto scroll speed. + controller->SetAutoscrollSpeed( 10 ); + + DALI_TEST_EQUALS( 10, controller->GetAutoScrollSpeed(), TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerSetGetAutoScrollLoopCount(void) +{ + tet_infoline(" UtcDaliTextControllerSetGetAutoScrollLoopCount"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + // Check the default value. + DALI_TEST_EQUALS( 0, controller->GetAutoScrollLoopCount(), TEST_LOCATION ); + + // Set the auto scroll loop count. + controller->SetAutoScrollLoopCount( 5 ); + + DALI_TEST_EQUALS( 5, controller->GetAutoScrollLoopCount(), TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerSetGetAutoScrollWrapGap(void) +{ + tet_infoline(" UtcDaliTextControllerSetGetAutoScrollWrapGap"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + // Check the default value. + DALI_TEST_EQUALS( 0.f, controller->GetAutoScrollWrapGap(), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Set the auto scroll loop count. + controller->SetAutoScrollWrapGap( 25.f ); + + DALI_TEST_EQUALS( 25.f, controller->GetAutoScrollWrapGap(), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerGetAutoScrollData(void) +{ + tet_infoline(" UtcDaliTextControllerGetAutoScrollData"); + ToolkitTestApplication application; + + // Load some fonts to get the same metrics on different platforms. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.SetDpi( 96u, 96u ); + + char* pathNamePtr = get_current_dir_name(); + const std::string pathName( pathNamePtr ); + free( pathNamePtr ); + + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" ); + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + DALI_TEST_CHECK( NULL == controller->GetAutoScrollData() ); + + // Set and check some values. + controller->SetAutoscrollSpeed( 10 ); + controller->SetAutoScrollLoopCount( 5 ); + controller->SetAutoScrollWrapGap( 25.f ); + + const ScrollerData* scrollerData = controller->GetAutoScrollData(); + DALI_TEST_CHECK( NULL != controller->GetAutoScrollData() ); + + DALI_TEST_EQUALS( Size::ZERO, scrollerData->mControlSize, TEST_LOCATION ); + DALI_TEST_EQUALS( Size::ZERO, scrollerData->mOffscreenSize, TEST_LOCATION ); + DALI_TEST_EQUALS( 10, scrollerData->mScrollSpeed, TEST_LOCATION ); + DALI_TEST_EQUALS( 5, scrollerData->mLoopCount, TEST_LOCATION ); + DALI_TEST_EQUALS( 25.f, scrollerData->mWrapGap, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( 0.f, scrollerData->mAlignmentOffset, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_CHECK( !scrollerData->mAutoScrollDirectionRTL ); + + // Set some text and layout. + controller->SetMarkupProcessorEnabled( true ); + controller->SetHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_END ); + controller->SetText( "Hello world" ); + controller->Relayout( Size( 100.f, 20.f ) ); + + scrollerData = controller->GetAutoScrollData(); + DALI_TEST_EQUALS( Size( 100.f, 20.f ), scrollerData->mControlSize, TEST_LOCATION ); + DALI_TEST_EQUALS( Size( 80.f, 20.f ), scrollerData->mOffscreenSize, TEST_LOCATION ); + DALI_TEST_EQUALS( 20.f, scrollerData->mAlignmentOffset, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index c185ee2..0f0072e 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -403,14 +403,14 @@ int UtcDaliToolkitTextlabelScrollingP(void) Stage::GetCurrent().Add( label ); // Turn on all the effects label.SetProperty( TextLabel::Property::MULTI_LINE, false ); - label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, 50.0f ); - label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 3 ); - label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, 80.0f); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, 50.0f ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 3 ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, 80.0f ); try { // Render some text with the shared atlas backend - label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true ); + label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true ); application.SendNotification(); application.Render(); } @@ -422,6 +422,37 @@ int UtcDaliToolkitTextlabelScrollingP(void) END_TEST; } +int UtcDaliToolkitTextlabelScrollingN(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliToolkitTextlabelScrollingN"); + + TextLabel label = TextLabel::New("Some text to scroll"); + DALI_TEST_CHECK( label ); + + Stage::GetCurrent().Add( label ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // The text scrolling works only on single line text. + label.SetProperty( TextLabel::Property::MULTI_LINE, true ); + + // Turn on all the effects. + label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, 50.0f ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 3 ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, 80.0f ); + + // Enable the auto scrolling effect. + label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true ); + + // The auto scrolling shouldn't be enabled. + const bool enabled = label.GetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL ).Get(); + DALI_TEST_CHECK( !enabled ); + + END_TEST; +} + int UtcDaliToolkitTextlabelEllipsis(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index c329ccc..0b767d7 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -16,6 +16,8 @@ #include #include +#include + #include #include #include @@ -34,6 +36,8 @@ const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg"; const char* TEST_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube.obj"; const char* TEST_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal.mtl"; const char* TEST_RESOURCE_LOCATION = TEST_RESOURCE_DIR "/"; + +const std::string DEFAULT_FONT_DIR( "/resources/fonts" ); } void dali_visual_startup(void) @@ -205,6 +209,31 @@ int UtcDaliVisualSize(void) batchImageVisual.GetNaturalSize( naturalSize ); DALI_TEST_EQUALS( naturalSize, Vector2( 80.0f, 160.0f ), TEST_LOCATION ); + // Text visual. + + // Load some fonts to get the same metrics on different platforms. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.SetDpi( 96u, 96u ); + + char* pathNamePtr = get_current_dir_name(); + const std::string pathName( pathNamePtr ); + free( pathNamePtr ); + + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" ); + + propertyMap.Clear(); + propertyMap.Insert( Visual::Property::TYPE, Visual::TEXT ); + propertyMap.Insert( TextVisual::Property::ENABLE_MARKUP, true ); + propertyMap.Insert( TextVisual::Property::TEXT, "Hello world" ); + propertyMap.Insert( TextVisual::Property::MULTI_LINE, true ); + + Visual::Base textVisual = factory.CreateVisual( propertyMap ); + textVisual.GetNaturalSize( naturalSize ); + DALI_TEST_EQUALS( naturalSize, Size( 80.f, 20.f ), TEST_LOCATION ); + + const float height = textVisual.GetHeightForWidth( 40.f ); + DALI_TEST_EQUALS( height, 40.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + END_TEST; } @@ -898,6 +927,95 @@ int UtcDaliVisualGetPropertyMapBatchImageVisual(void) END_TEST; } +//Text shape visual +int UtcDaliVisualGetPropertyMap10(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualGetPropertyMap10: TextVisual" ); + + //Request PrimitiveVisual using a property map. + VisualFactory factory = VisualFactory::Get(); + + Property::Map propertyMap; + propertyMap.Insert( Visual::Property::TYPE, Visual::TEXT ); + propertyMap.Insert( "renderingBackend", static_cast( Toolkit::Text::DEFAULT_RENDERING_BACKEND ) ); + propertyMap.Insert( "text", "Hello world" ); + propertyMap.Insert( "fontFamily", "TizenSans" ); + propertyMap.Insert( "fontStyle", "{\"weight\":\"bold\"}" ); + propertyMap.Insert( "pointSize", 12.f ); + propertyMap.Insert( "multiLine", true ); + propertyMap.Insert( "horizontalAlignment", "CENTER" ); + propertyMap.Insert( "verticalAlignment", "CENTER" ); + propertyMap.Insert( "textColor", Color::RED ); + propertyMap.Insert( "enableMarkup", false ); + propertyMap.Insert( "enableAutoScroll", false ); + propertyMap.Insert( "lineSpacing", 0.f ); + propertyMap.Insert( "batchingEnabled", false ); + Visual::Base textVisual = factory.CreateVisual( propertyMap ); + + Property::Map resultMap; + textVisual.CreatePropertyMap( resultMap ); + + //Check values in the result map are identical to the initial map's values. + Property::Value* value = resultMap.Find( Visual::Property::TYPE, Property::INTEGER ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), (int)Visual::TEXT, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::RENDERING_BACKEND, Property::INTEGER ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Toolkit::Text::DEFAULT_RENDERING_BACKEND, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::TEXT, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "Hello world", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::FONT_FAMILY, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "TizenSans", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::FONT_STYLE, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "{\"weight\":\"bold\"}", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::POINT_SIZE, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 12.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::MULTI_LINE, Property::BOOLEAN ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() ); + + value = resultMap.Find( TextVisual::Property::HORIZONTAL_ALIGNMENT, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "CENTER", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::VERTICAL_ALIGNMENT, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "CENTER", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::TEXT_COLOR, Property::VECTOR4 ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Color::RED, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::ENABLE_MARKUP, Property::BOOLEAN ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( !value->Get() ); + + value = resultMap.Find( TextVisual::Property::ENABLE_AUTO_SCROLL, Property::BOOLEAN ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( !value->Get() ); + + value = resultMap.Find( TextVisual::Property::LINE_SPACING, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::BATCHING_ENABLED, Property::BOOLEAN ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( !value->Get() ); + + END_TEST; +} + int UtcDaliVisualGetPropertyMapBatchImageVisualNoAtlas(void) { ToolkitTestApplication application; diff --git a/dali-toolkit/dali-toolkit.h b/dali-toolkit/dali-toolkit.h index 4e39d12..be46ddd 100644 --- a/dali-toolkit/dali-toolkit.h +++ b/dali-toolkit/dali-toolkit.h @@ -61,6 +61,7 @@ #include #include #include +#include #include #include diff --git a/dali-toolkit/devel-api/visual-factory/visual-base.cpp b/dali-toolkit/devel-api/visual-factory/visual-base.cpp index 0c39ff5..52f7f3e 100644 --- a/dali-toolkit/devel-api/visual-factory/visual-base.cpp +++ b/dali-toolkit/devel-api/visual-factory/visual-base.cpp @@ -61,6 +61,11 @@ const Vector2& Visual::Base::GetSize() const return GetImplementation( *this ).GetSize(); } +float Visual::Base::GetHeightForWidth( float width ) const +{ + return GetImplementation( *this ).GetHeightForWidth( width ); +} + void Visual::Base::GetNaturalSize(Vector2& naturalSize ) const { GetImplementation( *this ).GetNaturalSize( naturalSize ); diff --git a/dali-toolkit/devel-api/visual-factory/visual-base.h b/dali-toolkit/devel-api/visual-factory/visual-base.h index 8429b41..075ef0f 100644 --- a/dali-toolkit/devel-api/visual-factory/visual-base.h +++ b/dali-toolkit/devel-api/visual-factory/visual-base.h @@ -90,6 +90,15 @@ public: const Vector2& GetSize() const; /** + * @brief Returns the height for a given width. + * + * @param[in] width Width to use. + * + * @return The height based on the width. + */ + float GetHeightForWidth( float width ) const; + + /** * @brief Return the natural size of the visual. * * Deriving classes stipulate the natural size and by default a visual has a ZERO natural size. 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 8e74c70..9d59568 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -949,6 +949,7 @@ void TextEditor::OnInitialize() // Disables the horizontal scrolling. mController->SetHorizontalScrollEnabled( false ); + // Sets the maximum number of characters. mController->SetMaximumNumberOfCharacters( std::numeric_limits::max() ); // Enable the smooth handle panning. 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 12bbe0d..2d7190b 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -28,9 +31,6 @@ #include #include -// EXTERNAL INCLUDES -#include - namespace Dali { diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index 4f8515f..6e679e3 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -1246,7 +1246,7 @@ void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container ) } } - void TextField::RenderText( Text::Controller::UpdateTextType updateTextType ) +void TextField::RenderText( Text::Controller::UpdateTextType updateTextType ) { Actor self = Self(); Actor renderableActor; diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h index 9762c70..e40c647 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -28,9 +31,6 @@ #include #include -// EXTERNAL INCLUDES -#include - namespace Dali { diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index 6fbe3b6..955e0f2 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -24,17 +24,11 @@ // INTERNAL INCLUDES #include -#include -#include -#include +#include #include -#include -#include -#include #include using Dali::Toolkit::Text::LayoutEngine; -using Dali::Toolkit::Text::Backend; namespace Dali { @@ -57,22 +51,6 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); #endif -const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] = -{ - { "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN }, - { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER }, - { "END", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END }, -}; -const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); - -const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] = -{ - { "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP }, - { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER }, - { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM }, -}; -const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); - // Type registration BaseHandle Create() { @@ -109,7 +87,33 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "outline", STRING, DALI_TYPE_REGISTRATION_END() - +const int TEXT_VISUAL_PROPERTY_TABLE[] = { + Dali::Toolkit::TextVisual::Property::RENDERING_BACKEND, + Dali::Toolkit::TextVisual::Property::TEXT, + Dali::Toolkit::TextVisual::Property::FONT_FAMILY, + Dali::Toolkit::TextVisual::Property::FONT_STYLE, + Dali::Toolkit::TextVisual::Property::POINT_SIZE, + Dali::Toolkit::TextVisual::Property::MULTI_LINE, + Dali::Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, + Dali::Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, + Dali::Toolkit::TextVisual::Property::TEXT_COLOR, + Dali::Toolkit::TextVisual::Property::SHADOW, + Dali::Toolkit::TextVisual::Property::SHADOW, + Dali::Toolkit::TextVisual::Property::UNDERLINE, + Dali::Toolkit::TextVisual::Property::UNDERLINE, + Dali::Toolkit::TextVisual::Property::UNDERLINE, + Dali::Toolkit::TextVisual::Property::ENABLE_MARKUP, + Dali::Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL, + Dali::Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED, + Dali::Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT, + Dali::Toolkit::TextVisual::Property::AUTO_SCROLL_GAP, + Dali::Toolkit::TextVisual::Property::LINE_SPACING, + Dali::Toolkit::TextVisual::Property::UNDERLINE, + Dali::Toolkit::TextVisual::Property::SHADOW, + Dali::Toolkit::TextVisual::Property::EMBOSS, + Dali::Toolkit::TextVisual::Property::OUTLINE, + Dali::Toolkit::TextVisual::Property::BATCHING_ENABLED +}; } // namespace @@ -134,298 +138,10 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr if( label ) { - TextLabel& impl( GetImpl( label ) ); - switch( index ) - { - case Toolkit::TextLabel::Property::RENDERING_BACKEND: - { - int backend = value.Get< int >(); - -#ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING - if( Text::RENDERING_VECTOR_BASED == backend ) - { - backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering - } -#endif - if( impl.mRenderingBackend != backend ) - { - impl.mRenderingBackend = backend; - impl.mRenderer.Reset(); - - if( impl.mController ) - { - // When using the vector-based rendering, the size of the GLyphs are different - TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; - impl.mController->SetGlyphType( glyphType ); - } - } - break; - } - case Toolkit::TextLabel::Property::TEXT: - { - if( impl.mController ) - { - impl.mController->SetText( value.Get< std::string >() ); - } - break; - } - case Toolkit::TextLabel::Property::FONT_FAMILY: - { - if( impl.mController ) - { - const std::string fontFamily = value.Get< std::string >(); - - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextLabel::SetProperty Property::FONT_FAMILY newFont(%s)\n", fontFamily.c_str() ); - impl.mController->SetDefaultFontFamily( fontFamily ); - } - break; - } - case Toolkit::TextLabel::Property::FONT_STYLE: - { - SetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::POINT_SIZE: - { - if( impl.mController ) - { - const float pointSize = value.Get< float >(); - - if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) ) - { - impl.mController->SetDefaultPointSize( pointSize ); - } - } - break; - } - case Toolkit::TextLabel::Property::MULTI_LINE: - { - if( impl.mController ) - { - impl.mController->SetMultiLineEnabled( value.Get< bool >() ); - } - break; - } - case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT: - { - if( impl.mController ) - { - LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ); - if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(), - HORIZONTAL_ALIGNMENT_STRING_TABLE, - HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT, - alignment ) ) - { - impl.mController->SetHorizontalAlignment( alignment ); - } - } - break; - } - case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT: - { - if( impl.mController ) - { - LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM ); - if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(), - VERTICAL_ALIGNMENT_STRING_TABLE, - VERTICAL_ALIGNMENT_STRING_TABLE_COUNT, - alignment ) ) - { - impl.mController->SetVerticalAlignment( alignment ); - } - } - break; - } - - case Toolkit::TextLabel::Property::TEXT_COLOR: - { - if( impl.mController ) - { - const Vector4 textColor = value.Get< Vector4 >(); - if( impl.mController->GetTextColor() != textColor ) - { - impl.mController->SetTextColor( textColor ); - impl.mRenderer.Reset(); - } - } - break; - } - - case Toolkit::TextLabel::Property::SHADOW_OFFSET: - { - if( impl.mController ) - { - const Vector2 shadowOffset = value.Get< Vector2 >(); - if ( impl.mController->GetShadowOffset() != shadowOffset ) - { - impl.mController->SetShadowOffset( shadowOffset ); - impl.mRenderer.Reset(); - } - } - break; - } - case Toolkit::TextLabel::Property::SHADOW_COLOR: - { - if( impl.mController ) - { - const Vector4 shadowColor = value.Get< Vector4 >(); - if ( impl.mController->GetShadowColor() != shadowColor ) - { - impl.mController->SetShadowColor( shadowColor ); - impl.mRenderer.Reset(); - } - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_COLOR: - { - if( impl.mController ) - { - const Vector4 color = value.Get< Vector4 >(); - if ( impl.mController->GetUnderlineColor() != color ) - { - impl.mController->SetUnderlineColor( color ); - impl.mRenderer.Reset(); - } - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: - { - if( impl.mController ) - { - const bool enabled = value.Get< bool >(); - if ( impl.mController->IsUnderlineEnabled() != enabled ) - { - impl.mController->SetUnderlineEnabled( enabled ); - impl.mRenderer.Reset(); - } - } - break; - } + TextLabel& impl = GetImpl( label ); - case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT: - { - if( impl.mController ) - { - float height = value.Get< float >(); - if( fabsf( impl.mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) - { - impl.mController->SetUnderlineHeight( height ); - impl.mRenderer.Reset(); - } - } - break; - } - case Toolkit::TextLabel::Property::ENABLE_MARKUP: - { - if( impl.mController ) - { - const bool enableMarkup = value.Get(); - impl.mController->SetMarkupProcessorEnabled( enableMarkup ); - } - break; - } - case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL: - { - if( impl.mController ) - { - const bool enableAutoScroll = value.Get(); - // If request to auto scroll is the same as current state then do nothing. - if ( enableAutoScroll != impl.mController->IsAutoScrollEnabled() ) - { - // If request is disable (false) and auto scrolling is enabled then need to stop it - if ( enableAutoScroll == false ) - { - if( impl.mTextScroller ) - { - impl.mTextScroller->SetLoopCount( 0 ); // Causes the current animation to finish playing (0) - } - } - // If request is enable (true) then start autoscroll as not already running - else - { - impl.mController->GetLayoutEngine().SetTextEllipsisEnabled( false ); - impl.mController->SetAutoScrollEnabled( enableAutoScroll ); - } - } - } - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED: - { - if( !impl.mTextScroller ) - { - impl.mTextScroller = Text::TextScroller::New( impl ); - } - impl.mTextScroller->SetSpeed( value.Get() ); - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT: - { - if( !impl.mTextScroller ) - { - impl.mTextScroller = Text::TextScroller::New( impl ); - } - impl.mTextScroller->SetLoopCount( value.Get() ); - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP: - { - if( !impl.mTextScroller ) - { - impl.mTextScroller = Text::TextScroller::New( impl ); - } - impl.mTextScroller->SetGap( value.Get() ); - break; - } - case Toolkit::TextLabel::Property::LINE_SPACING: - { - if( impl.mController ) - { - const float lineSpacing = value.Get(); - impl.mController->SetDefaultLineSpacing( lineSpacing ); - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE: - { - const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - if( update ) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextLabel::Property::SHADOW: - { - const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - if( update ) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextLabel::Property::EMBOSS: - { - const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - if( update ) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextLabel::Property::OUTLINE: - { - const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - if( update ) - { - impl.mRenderer.Reset(); - } - break; - } - } + // Sets the property to the to the text visual. + impl.mVisual.SetProperty( TEXT_VISUAL_PROPERTY_TABLE[index - Toolkit::TextLabel::PROPERTY_START_INDEX], value ); } } @@ -437,204 +153,127 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde if( label ) { - TextLabel& impl( GetImpl( label ) ); - switch( index ) + TextLabel& impl = GetImpl( label ); + + if( ( Toolkit::TextLabel::Property::SHADOW_OFFSET == index ) || + ( Toolkit::TextLabel::Property::SHADOW_COLOR == index ) || + ( Toolkit::TextLabel::Property::UNDERLINE_ENABLED == index ) || + ( Toolkit::TextLabel::Property::UNDERLINE_COLOR == index ) || + ( Toolkit::TextLabel::Property::UNDERLINE_HEIGHT == index ) ) { - case Toolkit::TextLabel::Property::RENDERING_BACKEND: - { - value = impl.mRenderingBackend; - break; - } - case Toolkit::TextLabel::Property::TEXT: - { - if( impl.mController ) - { - std::string text; - impl.mController->GetText( text ); - value = text; - } - break; - } - case Toolkit::TextLabel::Property::FONT_FAMILY: - { - if( impl.mController ) - { - value = impl.mController->GetDefaultFontFamily(); - } - break; - } - case Toolkit::TextLabel::Property::FONT_STYLE: - { - GetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::POINT_SIZE: - { - if( impl.mController ) - { - value = impl.mController->GetDefaultPointSize(); - } - break; - } - case Toolkit::TextLabel::Property::MULTI_LINE: - { - if( impl.mController ) - { - value = impl.mController->IsMultiLineEnabled(); - } - break; - } - case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT: + // TODO : Branch to be removed when the deprecated properties are finally removed. + value = impl.mVisual.GetProperty( TEXT_VISUAL_PROPERTY_TABLE[index - Toolkit::TextLabel::PROPERTY_START_INDEX] ); + + switch( index ) { - if( impl.mController ) + case Toolkit::TextLabel::Property::SHADOW_OFFSET: // Converts the deprecated property to the new one. { - const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(), - HORIZONTAL_ALIGNMENT_STRING_TABLE, - HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); - if( name ) + bool colorDefined = false; + Vector4 color; + bool offsetDefined = false; + Vector2 offset; + const bool empty = Text::ParseProperties( value.Get(), + colorDefined, + color, + offsetDefined, + offset ); + + if( !empty ) { - value = std::string( name ); + value = offset; } + break; } - break; - } - case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT: - { - if( impl.mController ) + case Toolkit::TextLabel::Property::SHADOW_COLOR: // Converts the deprecated property to the new one. { - const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(), - VERTICAL_ALIGNMENT_STRING_TABLE, - VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); - if( name ) + bool colorDefined = false; + Vector4 color; + bool offsetDefined = false; + Vector2 offset; + const bool empty = Text::ParseProperties( value.Get(), + colorDefined, + color, + offsetDefined, + offset ); + + if( !empty ) { - value = std::string( name ); + value = color; } - } - break; - } - case Toolkit::TextLabel::Property::TEXT_COLOR: - { - if ( impl.mController ) - { - value = impl.mController->GetTextColor(); - } - break; - } - case Toolkit::TextLabel::Property::SHADOW_OFFSET: - { - if ( impl.mController ) - { - value = impl.mController->GetShadowOffset(); - } - break; - } - case Toolkit::TextLabel::Property::SHADOW_COLOR: - { - if ( impl.mController ) - { - value = impl.mController->GetShadowColor(); - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_COLOR: - { - if ( impl.mController ) - { - value = impl.mController->GetUnderlineColor(); - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: - { - if ( impl.mController ) - { - value = impl.mController->IsUnderlineEnabled(); - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT: - { - if ( impl.mController ) - { - value = impl.mController->GetUnderlineHeight(); - } - break; - } - case Toolkit::TextLabel::Property::ENABLE_MARKUP: - { - if( impl.mController ) - { - value = impl.mController->IsMarkupProcessorEnabled(); - } - break; - } - case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL: - { - if( impl.mController ) - { - value = impl.mController->IsAutoScrollEnabled(); - } - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED: - { - TextLabel& impl( GetImpl( label ) ); - if ( impl.mTextScroller ) - { - value = impl.mTextScroller->GetSpeed(); - } - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT: - { - if( impl.mController ) - { - TextLabel& impl( GetImpl( label ) ); - if ( impl.mTextScroller ) + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: // Converts the deprecated property to the new one. + { + bool enabled = false; + bool colorDefined = false; + Vector4 color; + bool heightDefined = false; + float height = 0.f; + const bool empty = Text::ParseProperties( value.Get(), + enabled, + colorDefined, + color, + heightDefined, + height ); + + if( !empty ) { - value = impl.mTextScroller->GetLoopCount(); + value = enabled; } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_COLOR: // Converts the deprecated property to the new one. + { + bool enabled = false; + bool colorDefined = false; + Vector4 color; + bool heightDefined = false; + float height = 0.f; + const bool empty = Text::ParseProperties( value.Get(), + enabled, + colorDefined, + color, + heightDefined, + height ); + + if( !empty && colorDefined ) + { + value = color; + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT: // Converts the deprecated property to the new one. + { + bool enabled = false; + bool colorDefined = false; + Vector4 color; + bool heightDefined = false; + float height = 0.f; + const bool empty = Text::ParseProperties( value.Get(), + enabled, + colorDefined, + color, + heightDefined, + height ); + + if( !empty && heightDefined ) + { + value = height; + } + break; } - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP: - { - TextLabel& impl( GetImpl( label ) ); - if ( impl.mTextScroller ) - { - value = impl.mTextScroller->GetGap(); - } - break; - } - case Toolkit::TextLabel::Property::LINE_SPACING: - { - if( impl.mController ) + default: { - value = impl.mController->GetDefaultLineSpacing(); + // Nothing to do. + break; } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE: - { - GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::SHADOW: - { - GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::EMBOSS: - { - GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::OUTLINE: - { - GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - break; } } + else + { + // Retrieves the property from the text visual. + value = impl.mVisual.GetProperty( TEXT_VISUAL_PROPERTY_TABLE[index - Toolkit::TextLabel::PROPERTY_START_INDEX] ); + } } return value; @@ -644,23 +283,23 @@ void TextLabel::OnInitialize() { Actor self = Self(); - mController = Text::Controller::New( this ); + // Creates the text's visual. + Property::Map visualMap; + visualMap[Toolkit::Visual::Property::TYPE] = Toolkit::Visual::TEXT; + visualMap[Toolkit::TextVisual::Property::RENDERING_BACKEND] = static_cast( DEFAULT_RENDERING_BACKEND ); - // When using the vector-based rendering, the size of the GLyphs are different - TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; - mController->SetGlyphType( glyphType ); + mVisual = Toolkit::VisualFactory::Get().CreateVisual( visualMap ); + RegisterVisual( Toolkit::TextLabel::Property::TEXT, self, mVisual ); + + Internal::Visual::Base& visualBase = Toolkit::GetImplementation( mVisual ); + TextVisual* textVisual = static_cast( &visualBase ); + + // Sets the text's control interface. + textVisual->SetTextControlInterface( this ); // Use height-for-width negotiation by default self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); - - // Enable the text ellipsis. - LayoutEngine& engine = mController->GetLayoutEngine(); - - engine.SetTextEllipsisEnabled( true ); // If false then text larger than control will overflow - engine.SetCursorWidth( 0u ); // Do not layout space for the cursor. - - self.OnStageSignal().Connect( this, &TextLabel::OnStageConnect ); } void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change ) @@ -674,10 +313,11 @@ void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange:: // Property system did not set the font so should update it. const std::string& newFont = GetImpl( styleManager ).GetDefaultFontFamily(); DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnStyleChange StyleChange::DEFAULT_FONT_CHANGE newFont(%s)\n", newFont.c_str() ); - mController->UpdateAfterFontChange( newFont ); + + const std::string fontString = "{\"family\":\"" + newFont + "\",\"type\":\"system\"}"; + mVisual.SetProperty( Toolkit::TextVisual::Property::FONT_FAMILY, fontString ); break; } - case StyleChange::DEFAULT_FONT_SIZE_CHANGE: { GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); @@ -693,29 +333,22 @@ void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange:: Vector3 TextLabel::GetNaturalSize() { - return mController->GetNaturalSize(); + Vector2 naturalSize; + mVisual.GetNaturalSize( naturalSize ); + + return Vector3( naturalSize ); } float TextLabel::GetHeightForWidth( float width ) { - return mController->GetHeightForWidth( width ); + return mVisual.GetHeightForWidth( width ); } void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container ) { DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnRelayout\n" ); - const Text::Controller::UpdateTextType updateTextType = mController->Relayout( size ); - - if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) ) || - !mRenderer ) - { - if( !mRenderer ) - { - mRenderer = Backend::Get().NewRenderer( mRenderingBackend ); - } - RenderText(); - } + mVisual.SetSize( size ); } void TextLabel::RequestTextRelayout() @@ -723,95 +356,16 @@ void TextLabel::RequestTextRelayout() RelayoutRequest(); } -void TextLabel::RenderText() -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::RenderText IsAutoScrollEnabled[%s] [%p]\n", ( mController->IsAutoScrollEnabled())?"true":"false", this ); - - Actor self = Self(); - Actor renderableActor; - - if( mRenderer ) - { - renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT ); - } - - if( renderableActor != mRenderableActor ) - { - UnparentAndReset( mRenderableActor ); - - if( renderableActor ) - { - const Vector2& scrollOffset = mController->GetScrollPosition(); - renderableActor.SetPosition( scrollOffset.x, scrollOffset.y ); - - self.Add( renderableActor ); - } - mRenderableActor = renderableActor; - - if ( mController->IsAutoScrollEnabled() ) - { - SetUpAutoScrolling(); - } - } -} - -void TextLabel::SetUpAutoScrolling() -{ - const Size& controlSize = mController->GetView().GetControlSize(); - const Size offScreenSize = GetNaturalSize().GetVectorXY(); // As relayout of text may not be done at this point natural size is used to get size. Single line scrolling only. - const float alignmentOffset = mController->GetAutoScrollLineAlignment(); - const Text::CharacterDirection direction = mController->GetAutoScrollDirection(); - - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling alignmentOffset[%f] offScreenSize[%f,%f] controlSize[%f,%f]\n", - alignmentOffset, offScreenSize.x,offScreenSize.y , controlSize.x,controlSize.y ); - - if ( !mTextScroller ) - { - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling Creating default TextScoller\n" ); - - // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults - mTextScroller = Text::TextScroller::New( *this ); - } - mTextScroller->SetParameters( mRenderableActor, controlSize, offScreenSize, direction, alignmentOffset ); - - Actor self = Self(); - self.Add( mTextScroller->GetScrollingText() ); - self.Add( mTextScroller->GetSourceCamera() ); -} - -void TextLabel::OnStageConnect( Dali::Actor actor ) -{ - if ( mHasBeenStaged ) - { - RenderText(); - } - else - { - mHasBeenStaged = true; - } -} - void TextLabel::OnStageConnection( int depth ) { // Call the Control::OnStageConnection() to set the depth of the background. Control::OnStageConnection( depth ); - // The depth of the text renderer is set in the RenderText() called from OnRelayout(). -} - -void TextLabel::ScrollingFinished() -{ - // Pure Virtual from TextScroller Interface - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::ScrollingFinished\n"); - mController->SetAutoScrollEnabled( false ); - mController->GetLayoutEngine().SetTextEllipsisEnabled( true ); - RequestTextRelayout(); + // The depth of the text renderer is set by the text-visual called from OnRelayout(). } TextLabel::TextLabel() -: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), - mRenderingBackend( DEFAULT_RENDERING_BACKEND ), - mHasBeenStaged( false ) +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ) { } diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.h b/dali-toolkit/internal/controls/text-controls/text-label-impl.h index c928763..bdc587d 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -22,10 +22,7 @@ #include #include #include -#include -#include -#include -#include +#include namespace Dali { @@ -39,7 +36,7 @@ namespace Internal /** * @brief A control which renders a short text string. */ -class TextLabel : public Control, public Text::ControlInterface, public Text::ScrollerInterface +class TextLabel : public Control, public Text::ControlInterface { public: @@ -107,13 +104,6 @@ private: // From Control */ virtual void RequestTextRelayout(); -private: // from TextScroller - - /** - * @copydoc Text::ScrollerInterface::ScrollingFinished() - */ - virtual void ScrollingFinished(); - private: // Implementation /** @@ -132,27 +122,9 @@ private: TextLabel(const TextLabel&); TextLabel& operator=(const TextLabel& rhs); - // Connection needed to re-render text, when a Text Label returns to the stage - void OnStageConnect( Dali::Actor actor ); - - /** - * @brief Render view, create and attach actor(s) to this Text Label - */ - void RenderText(); - - /** - * @brief Set up Autoscrolling - */ - void SetUpAutoScrolling(); - private: // Data - Text::ControllerPtr mController; - Text::RendererPtr mRenderer; - Text::TextScrollerPtr mTextScroller; - Actor mRenderableActor; - int mRenderingBackend; - bool mHasBeenStaged:1; + Toolkit::Visual::Base mVisual; }; } // namespace Internal diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 6f9ab11..7514ea5 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -29,6 +29,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/visuals/primitive/primitive-visual.cpp \ $(toolkit_src_dir)/visuals/svg/svg-rasterize-thread.cpp \ $(toolkit_src_dir)/visuals/svg/svg-visual.cpp \ + $(toolkit_src_dir)/visuals/text/text-visual.cpp \ $(toolkit_src_dir)/visuals/wireframe/wireframe-visual.cpp \ $(toolkit_src_dir)/controls/alignment/alignment-impl.cpp \ $(toolkit_src_dir)/controls/bloom-view/bloom-view-impl.cpp \ @@ -112,6 +113,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/text/text-font-style.cpp \ $(toolkit_src_dir)/text/text-io.cpp \ $(toolkit_src_dir)/text/text-scroller.cpp \ + $(toolkit_src_dir)/text/text-scroller-data.cpp \ $(toolkit_src_dir)/text/text-scroller-interface.cpp \ $(toolkit_src_dir)/text/text-view.cpp \ $(toolkit_src_dir)/text/text-view-interface.cpp \ diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 399de3f..608ea7d 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -297,6 +298,7 @@ struct Controller::Impl mEmbossDefaults( NULL ), mOutlineDefaults( NULL ), mEventData( NULL ), + mAutoScrollData( NULL ), mFontClient(), mClipboard(), mView(), @@ -304,14 +306,14 @@ struct Controller::Impl mLayoutEngine(), mModifyEvents(), mTextColor( Color::BLACK ), + mScrollPosition(), mTextUpdateInfo(), mOperationsPending( NO_OPERATION ), mMaximumNumberOfCharacters( 50u ), mRecalculateNaturalSize( true ), mMarkupProcessorEnabled( false ), mClipboardHideEnabled( true ), - mAutoScrollEnabled( false ), - mAutoScrollDirectionRTL( false ) + mIsAutoScrollEnabled( false ) { mLogicalModel = LogicalModel::New(); mVisualModel = VisualModel::New(); @@ -338,10 +340,13 @@ struct Controller::Impl delete mEmbossDefaults; delete mOutlineDefaults; delete mEventData; + delete mAutoScrollData; } + // Text Controller Implementation. + /** - * @brief Request a relayout using the ControlInterface. + * @copydoc Text::Controller::RequestRelayout() */ void RequestRelayout(); @@ -698,6 +703,7 @@ public: EmbossDefaults* mEmbossDefaults; ///< Avoid allocating this when the user does not specify emboss parameters. OutlineDefaults* mOutlineDefaults; ///< Avoid allocating this when the user does not specify outline parameters. EventData* mEventData; ///< Avoid allocating everything for text input until EnableTextInput(). + ScrollerData* mAutoScrollData; ///< Avoid allocating this when the user does not specify the auto text scrolling feature. TextAbstraction::FontClient mFontClient; ///< Handle to the font client. Clipboard mClipboard; ///< Handle to the system clipboard View mView; ///< The view interface to the rendering back-end. @@ -716,10 +722,8 @@ public: bool mRecalculateNaturalSize:1; ///< Whether the natural size needs to be recalculated. bool mMarkupProcessorEnabled:1; ///< Whether the mark-up procesor is enabled. - bool mClipboardHideEnabled:1; ///< Whether the ClipboardHide function work or not - bool mAutoScrollEnabled:1; ///< Whether auto text scrolling is enabled. - CharacterDirection mAutoScrollDirectionRTL:1; ///< Direction of auto scrolling, true if rtl - + bool mClipboardHideEnabled:1; ///< Whether the ClipboardHide function work or not. + bool mIsAutoScrollEnabled:1; ///< Whether auto text scrolling is enabled. }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 59040fd..769d0e04 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -118,6 +118,11 @@ ControllerPtr Controller::New( ControlInterface* controlInterface, editableControlInterface ) ); } +void Controller::SetTextControlInterface( ControlInterface* controlInterface ) +{ + mImpl->mControlInterface = controlInterface; +} + // public : Configure the text controller. void Controller::EnableTextInput( DecoratorPtr decorator ) @@ -153,9 +158,9 @@ void Controller::SetAutoScrollEnabled( bool enable ) { DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable)?"true":"false", ( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX)?"true":"false", this ); - if ( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX ) + if( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX ) { - if ( enable ) + if( enable ) { DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n" ); mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | @@ -165,6 +170,10 @@ void Controller::SetAutoScrollEnabled( bool enable ) UPDATE_DIRECTION | REORDER ); + if( NULL == mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData = new ScrollerData(); + } } else { @@ -176,39 +185,104 @@ void Controller::SetAutoScrollEnabled( bool enable ) REORDER ); } - mImpl->mAutoScrollEnabled = enable; + mImpl->mIsAutoScrollEnabled = enable; mImpl->RequestRelayout(); } else { DALI_LOG_WARNING( "Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n" ); - mImpl->mAutoScrollEnabled = false; + mImpl->mIsAutoScrollEnabled = false; } } bool Controller::IsAutoScrollEnabled() const { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", (mImpl->mAutoScrollEnabled)?"true":"false" ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled?"true":"false" ); + + return mImpl->mIsAutoScrollEnabled; +} + +void Controller::SetAutoscrollSpeed( int scrollSpeed ) +{ + if( NULL == mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData = new ScrollerData(); + } + + mImpl->mAutoScrollData->mScrollSpeed = scrollSpeed; +} + +int Controller::GetAutoScrollSpeed() const +{ + if( NULL != mImpl->mAutoScrollData ) + { + return mImpl->mAutoScrollData->mScrollSpeed; + } + + return 0; +} + +void Controller::SetAutoScrollLoopCount( int loopCount ) +{ + if( NULL == mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData = new ScrollerData(); + } + + mImpl->mAutoScrollData->mLoopCount = loopCount; +} + +int Controller::GetAutoScrollLoopCount() const +{ + if( NULL != mImpl->mAutoScrollData ) + { + return mImpl->mAutoScrollData->mLoopCount; + } - return mImpl->mAutoScrollEnabled; + return 0; } -CharacterDirection Controller::GetAutoScrollDirection() const +void Controller::SetAutoScrollWrapGap( float wrapGap ) { - return mImpl->mAutoScrollDirectionRTL; + if( NULL == mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData = new ScrollerData(); + } + + mImpl->mAutoScrollData->mWrapGap = wrapGap; } -float Controller::GetAutoScrollLineAlignment() const +float Controller::GetAutoScrollWrapGap() const { - float offset = 0.f; + if( NULL != mImpl->mAutoScrollData ) + { + return mImpl->mAutoScrollData->mWrapGap; + } + + return 0.f; +} - if( mImpl->mVisualModel && - ( 0u != mImpl->mVisualModel->mLines.Count() ) ) +const ScrollerData* const Controller::GetAutoScrollData() +{ + if( NULL != mImpl->mAutoScrollData ) { - offset = ( *mImpl->mVisualModel->mLines.Begin() ).alignmentOffset; + // Need to update the data with the latest layout. + if( mImpl->mVisualModel ) + { + mImpl->mAutoScrollData->mControlSize = mImpl->mVisualModel->mControlSize; + mImpl->mAutoScrollData->mOffscreenSize = GetNaturalSize().GetVectorXY(); + + mImpl->mAutoScrollData->mAlignmentOffset = 0.f; + if( 0u != mImpl->mVisualModel->mLines.Count() ) + { + mImpl->mAutoScrollData->mAlignmentOffset = ( *mImpl->mVisualModel->mLines.Begin() ).alignmentOffset; + } + } + + return mImpl->mAutoScrollData; } - return offset; + return NULL; } void Controller::SetHorizontalScrollEnabled( bool enable ) @@ -1453,7 +1527,7 @@ float Controller::GetHeightForWidth( float width ) Controller::UpdateTextType Controller::Relayout( const Size& size ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, (mImpl->mAutoScrollEnabled)?"true":"false" ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, mImpl->mIsAutoScrollEnabled ?"true":"false" ); UpdateTextType updateTextType = NONE_UPDATED; @@ -1559,6 +1633,11 @@ Controller::UpdateTextType Controller::Relayout( const Size& size ) return updateTextType; } +void Controller::RequestRelayout() +{ + mImpl->RequestRelayout(); +} + // public : Input style change signals. bool Controller::IsInputStyleChangedSignalsQueueEmpty() @@ -2123,6 +2202,17 @@ void Controller::TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Butt } } +// private : Inherit from TextScroller. + +void Controller::ScrollingFinished() +{ + // Pure Virtual from TextScroller Interface + SetAutoScrollEnabled( false ); + GetLayoutEngine().SetTextEllipsisEnabled( true ); + + mImpl->RequestRelayout(); +} + // private : Update. void Controller::InsertText( const std::string& text, Controller::InsertType type ) @@ -2588,7 +2678,10 @@ bool Controller::DoRelayout( const Size& size, if ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) ) { - mImpl->mAutoScrollDirectionRTL = false; + if( NULL != mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData->mAutoScrollDirectionRTL = false; + } } // Reorder the lines @@ -2624,9 +2717,11 @@ bool Controller::DoRelayout( const Size& size, if ( ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) ) && ( numberOfLines > 0 ) ) { const LineRun* const firstline = mImpl->mVisualModel->mLines.Begin(); - if ( firstline ) + if( firstline && + mImpl->mIsAutoScrollEnabled && + ( NULL != mImpl->mAutoScrollData ) ) { - mImpl->mAutoScrollDirectionRTL = firstline->direction; + mImpl->mAutoScrollData->mAutoScrollDirectionRTL = firstline->direction; } } } @@ -2658,7 +2753,7 @@ bool Controller::DoRelayout( const Size& size, #if defined(DEBUG_ENABLED) std::string currentText; GetText( currentText ); - DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mAutoScrollDirectionRTL[%s] [%s]\n", this, (mImpl->mAutoScrollDirectionRTL)?"true":"false", currentText.c_str() ); + DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mAutoScrollDirectionRTL[%s] [%s]\n", this, ( ( NULL != mImpl->mAutoScrollData ) && mImpl->mAutoScrollData->mAutoScrollDirectionRTL)?"true":"false", currentText.c_str() ); #endif DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", ( viewUpdated ? "true" : "false" ) ); return viewUpdated; diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 26a0ccb..ce5c51a 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace Dali { @@ -40,6 +41,7 @@ class Controller; class ControlInterface; class EditableControlInterface; class View; +struct ScrollerData; typedef IntrusivePtr ControllerPtr; @@ -54,7 +56,7 @@ typedef IntrusivePtr ControllerPtr; * * The text selection popup button callbacks are as well handled via the TextSelectionPopupCallbackInterface interface. */ -class Controller : public RefObject, public Decorator::ControllerInterface, public TextSelectionPopupCallbackInterface +class Controller : public RefObject, public Decorator::ControllerInterface, public TextSelectionPopupCallbackInterface, public Text::ScrollerInterface { public: // Enumerated types. @@ -147,6 +149,13 @@ public: // Constructor. static ControllerPtr New( ControlInterface* controlInterface, EditableControlInterface* editableControlInterface ); + /** + * @brief Sets the text-control interface. + * + * @param[in] controlInterface The text-control interface. + */ + void SetTextControlInterface( ControlInterface* controlInterface ); + public: // Configure the text controller. /** @@ -201,17 +210,53 @@ public: // Configure the text controller. bool IsAutoScrollEnabled() const; /** - * @brief Get direction of the text from the first line of text, - * @return bool rtl (right to left) is true + * @brief Sets the speed the text should automatically scroll at. + * + * @param[in] scrollSpeed The speed of scrolling in pixels per second. + */ + void SetAutoscrollSpeed( int scrollSpeed ); + + /** + * @brief Retrieves the auto scroll speed. + * + * @return The auto scroll speed in pixels per second. + */ + int GetAutoScrollSpeed() const; + + /** + * @brief Sets the number of loops the text should scroll. + * + * @param[in] loopCount The number of loops. + */ + void SetAutoScrollLoopCount( int loopCount ); + + /** + * @brief Retrieves the number of loops the text should scroll. + * + * @return The numebr of loops. + */ + int GetAutoScrollLoopCount() const; + + /** + * @brief Sets the gap before text wraps around when scrolling. + * + * @param[in] wrapGap The gap in pixels. + */ + void SetAutoScrollWrapGap( float wrapGap ); + + /** + * @brief Retrieves the gap before text wraps around when scrolling. + * + * @return The gap in pixels. */ - CharacterDirection GetAutoScrollDirection() const; + float GetAutoScrollWrapGap() const; /** - * @brief Get the alignment offset of the first line of text. + * @brief Retrieves the text's autoscroll data. * - * @return The alignment offset. + * @return The text's autoscroll data. */ - float GetAutoScrollLineAlignment() const; + const ScrollerData* const GetAutoScrollData(); /** * @brief Enables the horizontal scrolling. @@ -808,6 +853,11 @@ public: // Relayout. */ UpdateTextType Relayout( const Size& size ); + /** + * @brief Request a relayout using the ControlInterface. + */ + void RequestRelayout(); + public: // Input style change signals. /** @@ -906,6 +956,13 @@ protected: // Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface. */ virtual void TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Buttons button ); +private: // Inherit from TextScroller + + /** + * @copydoc Text::ScrollerInterface::ScrollingFinished() + */ + virtual void ScrollingFinished(); + private: // Update. /** diff --git a/dali-toolkit/internal/text/text-effects-style.cpp b/dali-toolkit/internal/text/text-effects-style.cpp index 1578329..083cf47 100644 --- a/dali-toolkit/internal/text/text-effects-style.cpp +++ b/dali-toolkit/internal/text/text-effects-style.cpp @@ -40,55 +40,122 @@ const std::string ENABLE_KEY( "enable" ); const std::string TRUE_TOKEN( "true" ); } -bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type ) +bool ParseProperties( const std::string& shadowProperties, + bool& colorDefined, + Vector4& color, + bool& offsetDefined, + Vector2& offset ) { - bool update = false; + // Parses and applies the style. + Property::Map map; + Text::ParsePropertyString( shadowProperties, map ); - if( controller ) + const bool empty = map.Empty(); + + if( !empty ) { - const std::string properties = value.Get(); + /// Color key. + Property::Value* colorValue = map.Find( COLOR_KEY ); + + colorDefined = colorValue != NULL; + if( colorDefined ) + { + const std::string colorStr = colorValue->Get(); - // Parses and applies the style. - Property::Map map; - ParsePropertyString( properties, map ); + Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); + } - if( !map.Empty() ) + /// Offset key. + Property::Value* offsetValue = map.Find( OFFSET_KEY ); + + offsetDefined = offsetValue != NULL; + if( offsetDefined ) { - /// Enable key. - Property::Value* enableValue = map.Find( ENABLE_KEY ); + const std::string offsetStr = offsetValue->Get(); - bool enabled = false; - const bool enabledDefined = enableValue != NULL; - if( enabledDefined ) - { - const std::string enableStr = enableValue->Get(); - enabled = TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() ); - } + StringToVector2( offsetStr.c_str(), offsetStr.size(), offset ); + } + } - /// Color key. - Property::Value* colorValue = map.Find( COLOR_KEY ); + return empty; +} - Vector4 color; - const bool colorDefined = colorValue != NULL; - if( colorDefined ) - { - const std::string colorStr = colorValue->Get(); +bool ParseProperties( const std::string& underlineProperties, + bool& enabled, + bool& colorDefined, + Vector4& color, + bool& heightDefined, + float& height ) +{ + // Parses and applies the style. + Property::Map map; + Text::ParsePropertyString( underlineProperties, map ); - ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); - } + const bool empty = map.Empty(); - /// Height key. - Property::Value* heightValue = map.Find( HEIGHT_KEY ); + if( !empty ) + { + /// Enable key. + Property::Value* enableValue = map.Find( ENABLE_KEY ); - float height = 0.f; - const bool heightDefined = heightValue != NULL; - if( heightDefined ) - { - const std::string heightStr = heightValue->Get(); + enabled = false; + const bool enabledDefined = enableValue != NULL; + if( enabledDefined ) + { + const std::string enableStr = enableValue->Get(); + enabled = Text::TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() ); + } - height = StringToFloat( heightStr.c_str() ); - } + /// Color key. + Property::Value* colorValue = map.Find( COLOR_KEY ); + + colorDefined = colorValue != NULL; + if( colorDefined ) + { + const std::string colorStr = colorValue->Get(); + + Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); + } + + /// Height key. + Property::Value* heightValue = map.Find( HEIGHT_KEY ); + + height = 0.f; + heightDefined = heightValue != NULL; + if( heightDefined ) + { + const std::string heightStr = heightValue->Get(); + height = StringToFloat( heightStr.c_str() ); + } + } + + return empty; +} + +bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type ) +{ + bool update = false; + + if( controller ) + { + const std::string properties = value.Get(); + + bool enabled = false; + bool colorDefined = false; + Vector4 color; + bool heightDefined = false; + float height = 0.f; + + const bool empty = ParseProperties( properties, + enabled, + colorDefined, + color, + heightDefined, + height ); + + if( !empty ) + { switch( type ) { case EffectStyle::DEFAULT: @@ -98,6 +165,7 @@ bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& va controller->SetUnderlineEnabled( enabled ); update = true; } + // Sets the default underline values. if( colorDefined && ( controller->GetUnderlineColor() != color ) ) { @@ -105,7 +173,7 @@ bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& va update = true; } - if( heightDefined && fabsf( controller->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) + if( heightDefined && ( fabsf( controller->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) ) { controller->SetUnderlineHeight( height ); update = true; @@ -192,36 +260,19 @@ bool SetShadowProperties( ControllerPtr controller, const Property::Value& value { const std::string properties = value.Get< std::string >(); - // Parses and applies the style. - Property::Map map; - ParsePropertyString( properties, map ); - - if( !map.Empty() ) - { - /// Color key - Property::Value* colorValue = map.Find( COLOR_KEY ); - - Vector4 color; - const bool colorDefined = colorValue != NULL; - if( colorDefined ) - { - const std::string colorStr = colorValue->Get(); - - ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); - } - - /// Offset key - Property::Value* offsetValue = map.Find( OFFSET_KEY ); + bool colorDefined = false; + Vector4 color; + bool offsetDefined = false; + Vector2 offset; - Vector2 offset; - const bool offsetDefined = offsetValue != NULL; - if( offsetDefined ) - { - const std::string offsetStr = offsetValue->Get(); - - StringToVector2( offsetStr.c_str(), offsetStr.size(), offset ); - } + const bool empty = ParseProperties( properties, + colorDefined, + color, + offsetDefined, + offset ); + if( !empty ) + { switch( type ) { case EffectStyle::DEFAULT: diff --git a/dali-toolkit/internal/text/text-effects-style.h b/dali-toolkit/internal/text/text-effects-style.h index 9feb75c..fb21fe9 100644 --- a/dali-toolkit/internal/text/text-effects-style.h +++ b/dali-toolkit/internal/text/text-effects-style.h @@ -18,12 +18,8 @@ * */ -// EXTERNAL INCLUDES -#include - // INTERNAL INCLUDES #include -#include namespace Dali { @@ -44,6 +40,36 @@ namespace EffectStyle }; /** + * @brief Parses the shadow properties. + * + * @param[out] colorDefined Whether the shadow's color is defined. + * @param[out] color The shadow's color. + * @param[out] offsetDefined Whether the shadow's offset is defined. + * @param[out] offset The shadow's offset. + */ +bool ParseProperties( const std::string& shadowProperties, + bool& colorDefined, + Vector4& color, + bool& offsetDefined, + Vector2& offset ); + +/** + * @brief Parses the underline properties. + * + * @param[out] enabled Whether the underline is enabled. + * @param[out] colorDefined Whether the underline's color is defined. + * @param[out] color The underline's color. + * @param[out] heightDefined Whether the underline's height is defined. + * @param[out] height The underline's height. + */ +bool ParseProperties( const std::string& underlineProperties, + bool& enabled, + bool& colorDefined, + Vector4& color, + bool& heightDefined, + float& height ); + +/** * @brief Sets the underline properties. * * @param[in] controller The text's controller. diff --git a/dali-toolkit/internal/text/text-font-style.cpp b/dali-toolkit/internal/text/text-font-style.cpp index 6fff87e..b3b9e84 100644 --- a/dali-toolkit/internal/text/text-font-style.cpp +++ b/dali-toolkit/internal/text/text-font-style.cpp @@ -23,6 +23,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -39,6 +40,10 @@ const std::string STYLE_KEY( "style" ); const std::string WEIGHT_KEY( "weight" ); const std::string WIDTH_KEY( "width" ); const std::string SLANT_KEY( "slant" ); +const std::string FAMILY_KEY( "family" ); +const std::string TYPE_KEY( "type" ); + +const std::string SYSTEM_TOKEN( "system" ); #if defined(DEBUG_ENABLED) Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); @@ -46,6 +51,59 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_C } // namespace +void SetFontFamilyProperty( ControllerPtr controller, const Property::Value& value ) +{ + if( controller ) + { + const std::string fontFamilyValue = value.Get(); + + if( fontFamilyValue.empty() ) + { + // Resets the default's font family name. + controller->SetDefaultFontFamily( "" ); + return; + } + + Property::Map map; + ParsePropertyString( fontFamilyValue, map ); + + if( map.Empty() ) + { + // There is no map. The font has been passed as a font's family name with no format. + controller->SetDefaultFontFamily( fontFamilyValue ); + } + else + { + /// Family key + Property::Value* familyValue = map.Find( FAMILY_KEY ); + + std::string fontFamilyName; + if( NULL != familyValue ) + { + fontFamilyName = familyValue->Get(); + } + + /// Type key + Property::Value* typeValue = map.Find( TYPE_KEY ); + + std::string typeStr; + if( NULL != typeValue ) + { + typeStr = typeValue->Get(); + } + + if( TokenComparison( SYSTEM_TOKEN, typeStr.c_str(), typeStr.size() ) ) + { + controller->UpdateAfterFontChange( fontFamilyName ); + } + else + { + controller->SetDefaultFontFamily( fontFamilyName ); + } + } + } +} + void SetFontStyleProperty( ControllerPtr controller, const Property::Value& value, FontStyle::Type type ) { if( controller ) diff --git a/dali-toolkit/internal/text/text-font-style.h b/dali-toolkit/internal/text/text-font-style.h index 425131d..e74bcfb 100644 --- a/dali-toolkit/internal/text/text-font-style.h +++ b/dali-toolkit/internal/text/text-font-style.h @@ -23,7 +23,6 @@ // INTERNAL INCLUDES #include -#include namespace Dali { @@ -90,6 +89,14 @@ namespace FontStyle }; /** + * @brief Sets the font family property. + * + * @param[in] controller The text's controller. + * @param[in] value The value of the font's family. + */ +void SetFontFamilyProperty( ControllerPtr controller, const Property::Value& value ); + +/** * @brief Sets the font's style property. * * @param[in] controller The text's controller. diff --git a/dali-toolkit/internal/text/text-scroller-data.cpp b/dali-toolkit/internal/text/text-scroller-data.cpp new file mode 100644 index 0000000..d938911 --- /dev/null +++ b/dali-toolkit/internal/text/text-scroller-data.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +const int MINIMUM_SCROLL_SPEED = 1; + +ScrollerData::ScrollerData() +: mScrollSpeed( MINIMUM_SCROLL_SPEED ), + mLoopCount( 1 ), + mWrapGap( 0.f ), + mAlignmentOffset( 0.f ), + mAutoScrollDirectionRTL( false ) +{} + +ScrollerData::~ScrollerData() +{} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-scroller-data.h b/dali-toolkit/internal/text/text-scroller-data.h new file mode 100644 index 0000000..3ba08c9 --- /dev/null +++ b/dali-toolkit/internal/text/text-scroller-data.h @@ -0,0 +1,62 @@ +#ifndef DALI_TOOLKIT_TEXT_SCROLLER_DATA_H +#define DALI_TOOLKIT_TEXT_SCROLLER_DATA_H + +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +extern const int MINIMUM_SCROLL_SPEED; // Speed should be set by Property system. + +/** + * @brief Stores the autoscroll data. + */ +struct ScrollerData +{ + ScrollerData(); + ~ScrollerData(); + + Size mControlSize; ///< The size of the control to scroll within. + Size mOffscreenSize; ///< The size of the sourceActor. + int mScrollSpeed; ///< Speed which text should automatically scroll at. + int mLoopCount; ///< Number of time the text should scroll. + float mWrapGap; ///< Gap before text wraps around when scrolling. + float mAlignmentOffset; ///< The alignment offset of the first line of text to be scrolled. + CharacterDirection mAutoScrollDirectionRTL; ///< Direction of auto scrolling, true if rtl. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_SCROLLER_H + diff --git a/dali-toolkit/internal/text/text-scroller.cpp b/dali-toolkit/internal/text/text-scroller.cpp index d2f9348..ee1d241 100644 --- a/dali-toolkit/internal/text/text-scroller.cpp +++ b/dali-toolkit/internal/text/text-scroller.cpp @@ -31,6 +31,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -38,6 +39,11 @@ namespace Dali namespace Toolkit { +namespace Text +{ +extern const int MINIMUM_SCROLL_SPEED; +} // namespace + namespace { @@ -45,8 +51,6 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_SCROLLING"); #endif -const int MINIMUM_SCROLL_SPEED = 1; // Speed should be set by Property system. - const char* VERTEX_SHADER_SCROLL = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n varying highp vec2 vTexCoord;\n @@ -195,50 +199,6 @@ TextScrollerPtr TextScroller::New( ScrollerInterface& scrollerInterface ) return textScroller; } -void TextScroller::SetGap( int gap ) -{ - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetGap gap[%d]\n", gap ); - mWrapGap = static_cast(gap); -} - -int TextScroller::GetGap() const -{ - return static_cast(mWrapGap); -} - -void TextScroller::SetSpeed( int scrollSpeed ) -{ - mScrollSpeed = std::max( MINIMUM_SCROLL_SPEED, scrollSpeed ); -} - -int TextScroller::GetSpeed() const -{ - return mScrollSpeed; -} - -void TextScroller::SetLoopCount( int loopCount ) -{ - if ( loopCount > 0 ) - { - mLoopCount = loopCount; - } - - if ( mScrollAnimation && mScrollAnimation.GetState() == Animation::PLAYING ) - { - if ( loopCount == 0 ) // Request to stop looping - { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount Single loop forced\n" ); - mScrollAnimation.SetLoopCount( 1 ); // As animation already playing this allows the current animation to finish instead of trying to stop mid-way - } - } - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount [%d] Status[%s]\n", mLoopCount, (loopCount)?"looping":"stop" ); -} - -int TextScroller::GetLoopCount() const -{ - return mLoopCount; -} - Actor TextScroller::GetSourceCamera() const { return mOffscreenCameraActor; @@ -249,11 +209,9 @@ Actor TextScroller::GetScrollingText() const return mScrollingTextActor; } -TextScroller::TextScroller( ScrollerInterface& scrollerInterface ) : mScrollerInterface( scrollerInterface ), - mScrollDeltaIndex( Property::INVALID_INDEX ), - mScrollSpeed( MINIMUM_SCROLL_SPEED ), - mLoopCount( 1 ), - mWrapGap( 0.0f ) +TextScroller::TextScroller( ScrollerInterface& scrollerInterface ) +: mScrollerInterface( scrollerInterface ), + mScrollDeltaIndex( Property::INVALID_INDEX ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller Default Constructor\n" ); } @@ -263,49 +221,71 @@ TextScroller::~TextScroller() CleanUp(); } -void TextScroller::SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, float alignmentOffset ) +void TextScroller::StartScrolling( Actor sourceActor, + const ScrollerData& data ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] offscreenSize[%f,%f] direction[%d] alignmentOffset[%f]\n", - controlSize.x, controlSize.y, offScreenSize.x, offScreenSize.y, direction, alignmentOffset ); - - FrameBufferImage offscreenRenderTargetForText = FrameBufferImage::New( offScreenSize.width, offScreenSize.height, Pixel::RGBA8888 ); + DALI_LOG_INFO( gLogFilter, + Debug::Verbose, + "TextScroller::StartScrolling controlSize[%f,%f] offscreenSize[%f,%f] direction[%d] alignmentOffset[%f]\n", + data.mControlSize.x, data.mControlSize.y, + data.mOffscreenSize.x, data.mOffscreenSize.y, + data.mAutoScrollDirectionRTL, + data.mAlignmentOffset ); + + FrameBufferImage offscreenRenderTargetForText = FrameBufferImage::New( data.mOffscreenSize.width, data.mOffscreenSize.height, Pixel::RGBA8888 ); Renderer renderer; - CreateCameraActor( offScreenSize, mOffscreenCameraActor ); + CreateCameraActor( data.mOffscreenSize, mOffscreenCameraActor ); CreateRenderer( offscreenRenderTargetForText, renderer ); CreateRenderTask( sourceActor, mOffscreenCameraActor, offscreenRenderTargetForText, mRenderTask ); // Reposition camera to match alignment of target, RTL text has direction=true - if ( direction ) + if( data.mAutoScrollDirectionRTL ) { - mOffscreenCameraActor.SetX( alignmentOffset + offScreenSize.width*0.5f ); + mOffscreenCameraActor.SetX( data.mAlignmentOffset + data.mOffscreenSize.width * 0.5f ); } else { - mOffscreenCameraActor.SetX( offScreenSize.width * 0.5f ); + mOffscreenCameraActor.SetX( data.mOffscreenSize.width * 0.5f ); } - mOffscreenCameraActor.SetY( offScreenSize.height * 0.5f ); + mOffscreenCameraActor.SetY( data.mOffscreenSize.height * 0.5f ); - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters mWrapGap[%f]\n", mWrapGap ) + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters mWrapGap[%f]\n", data.mWrapGap ) mScrollingTextActor = Actor::New(); mScrollingTextActor.AddRenderer( renderer ); - mScrollingTextActor.RegisterProperty( "uTextureSize", offScreenSize ); - mScrollingTextActor.RegisterProperty( "uRtl", ((direction)?1.0f:0.0f) ); - mScrollingTextActor.RegisterProperty( "uGap", mWrapGap ); - mScrollingTextActor.SetSize( controlSize.width, std::min( offScreenSize.height, controlSize.height ) ); + mScrollingTextActor.RegisterProperty( "uTextureSize", data.mOffscreenSize ); + mScrollingTextActor.RegisterProperty( "uRtl", ( data.mAutoScrollDirectionRTL ? 1.f : 0.f ) ); + mScrollingTextActor.RegisterProperty( "uGap", data.mWrapGap ); + mScrollingTextActor.SetSize( data.mControlSize.width, std::min( data.mOffscreenSize.height, data.mControlSize.height ) ); mScrollDeltaIndex = mScrollingTextActor.RegisterProperty( "uDelta", 0.0f ); - float scrollAmount = std::max( offScreenSize.width + mWrapGap, controlSize.width ); - float scrollDuration = scrollAmount / mScrollSpeed; + float scrollAmount = std::max( data.mOffscreenSize.width + data.mWrapGap, data.mControlSize.width ); + float scrollSpeed = std::max( MINIMUM_SCROLL_SPEED, data.mScrollSpeed ); + float scrollDuration = scrollAmount / scrollSpeed; - if ( direction ) + if( data.mAutoScrollDirectionRTL ) { scrollAmount = -scrollAmount; // reverse direction of scrollung } - StartScrolling( scrollAmount, scrollDuration, mLoopCount ); + mScrollAnimation = Animation::New( scrollDuration ); + mScrollAnimation.AnimateTo( Property( mScrollingTextActor, mScrollDeltaIndex ), scrollAmount ); + mScrollAnimation.SetEndAction( Animation::Discard ); + mScrollAnimation.SetLoopCount( data.mLoopCount ); + mScrollAnimation.FinishedSignal().Connect( this, &TextScroller::AutoScrollAnimationFinished ); + mScrollAnimation.Play(); +} + +void TextScroller::StopScrolling() +{ + if( mScrollAnimation && + ( mScrollAnimation.GetState() == Animation::PLAYING ) ) + { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount Single loop forced\n" ); + mScrollAnimation.SetLoopCount( 1 ); // As animation already playing this allows the current animation to finish instead of trying to stop mid-way + } } void TextScroller::AutoScrollAnimationFinished( Dali::Animation& animation ) @@ -315,18 +295,6 @@ void TextScroller::AutoScrollAnimationFinished( Dali::Animation& animation ) mScrollerInterface.ScrollingFinished(); } -void TextScroller::StartScrolling( float scrollAmount, float scrollDuration, int loopCount ) -{ - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::StartScrolling scrollAmount[%f] scrollDuration[%f], loop[%d] speed[%d]\n", scrollAmount, scrollDuration, loopCount, mScrollSpeed ); - - mScrollAnimation = Animation::New( scrollDuration ); - mScrollAnimation.AnimateTo( Property( mScrollingTextActor, mScrollDeltaIndex ), scrollAmount ); - mScrollAnimation.SetEndAction( Animation::Discard ); - mScrollAnimation.SetLoopCount( loopCount ); - mScrollAnimation.FinishedSignal().Connect( this, &TextScroller::AutoScrollAnimationFinished ); - mScrollAnimation.Play(); -} - void TextScroller::CleanUp() { if ( Stage::IsInstalled() ) diff --git a/dali-toolkit/internal/text/text-scroller.h b/dali-toolkit/internal/text/text-scroller.h index 17824b6..a40be3f 100644 --- a/dali-toolkit/internal/text/text-scroller.h +++ b/dali-toolkit/internal/text/text-scroller.h @@ -37,6 +37,7 @@ namespace Text class TextScroller; class ScrollerInterface; +struct ScrollerData; typedef IntrusivePtr TextScrollerPtr; @@ -46,7 +47,6 @@ typedef IntrusivePtr TextScrollerPtr; class TextScroller : public RefObject, public ConnectionTracker { public: - /** * @brief Text Scrolling helper, used to automatically scroll text, SetParameters should be called before scrolling is needed. * CleanUp removes the Scrolling actors from stage whilst keeping the Scroller object alive and preserving Speed, Gap and Loop count. @@ -56,52 +56,19 @@ public: static TextScrollerPtr New( ScrollerInterface& scrollerInterface ); /** - * @brief Set parameters relating to source required for scrolling + * @brief Starts the text scrolling. * * @param[in] sourceActor source actor to be scrolled - * @param[in] controlSize size of the control to scroll within - * @param[in] offScreenSize size of the sourceActor - * @param[in] direction text direction true for right to left text - * @param[in] alignmentOffset alignment of source text + * @param[in] data Parameters needed to set up the text scrolling. * */ - void SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, float alignmentOffset ); - - /** - * @brief Set the gap distance to elapse before the text wraps around - * @param[in] gap distance to elapse - */ - void SetGap( int gap ); - - /** - * @brief Get the distance before scrolling wraps - * @return gap distance to elapse - */ - int GetGap() const; - - /** - * @brief Set speed the text should scroll - * @param[in] scrollSpeed pixels per second - */ - void SetSpeed( int scrollSpeed ); + void StartScrolling( Actor sourceActor, + const ScrollerData& data ); /** - * @brief Get the speed of text scrolling - * @return speed in pixels per second + * @brief Stops the text scrolling. */ - int GetSpeed() const; - - /** - * @brief Set the number of times the text scrolling should loop, can stop current scrolling by passing in 0; - * @param[in] loopCount number of times the scrolled text should loop, 0 to stop scrolling - */ - void SetLoopCount( int loopCount ); - - /** - * @brief Get the number of loops - * @return int number of loops - */ - int GetLoopCount() const; + void StopScrolling(); /** * @brief Get the camera used to look at source, should be added to the parent of target actor. @@ -140,14 +107,6 @@ private: // Implementation void AutoScrollAnimationFinished( Dali::Animation& animation ); /** - * @brief variables required to set up scrolling animation - * @param[in] scrollAmount distance to animate text for the given duration - * @param[in] scrollDuration duration of aninmation - * @param[in] loopCount number of times to loop the scrolling text - */ - void StartScrolling( float scrollAmount, float scrollDuration, int loopCount ); - - /** * @brief When scrolling ended, the actors are cleaned up so no longer staged. */ void CleanUp(); @@ -161,10 +120,6 @@ private: Property::Index mScrollDeltaIndex; // Property used by shader to represent distance to scroll Animation mScrollAnimation; // Animation used to update the mScrollDeltaIndex - int mScrollSpeed; ///< Speed which text should automatically scroll at - int mLoopCount; ///< Number of time the text should scroll - float mWrapGap; ///< Gap before text wraps around when scrolling - }; // TextScroller class } // namespace Text diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp new file mode 100644 index 0000000..e9278f9 --- /dev/null +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -0,0 +1,869 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL HEADER +#include +// #include + +// INTERNAL HEADER +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Dali::Toolkit::Text::LayoutEngine; + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + +// Property names. +const char * const RENDERING_BACKEND_PROPERTY( "renderingBackend" ); +const char * const TEXT_PROPERTY( "text" ); +const char * const FONT_FAMILY_PROPERTY( "fontFamily" ); +const char * const FONT_STYLE_PROPERTY( "fontStyle" ); +const char * const POINT_SIZE_PROPERTY( "pointSize" ); +const char * const MULTI_LINE_PROPERTY( "multiLine" ); +const char * const HORIZONTAL_ALIGNMENT_PROPERTY( "horizontalAlignment" ); +const char * const VERTICAL_ALIGNMENT_PROPERTY( "verticalAlignment" ); +const char * const TEXT_COLOR_PROPERTY( "textColor" ); +const char * const ENABLE_MARKUP_PROPERTY( "enableMarkup" ); +const char * const ENABLE_AUTO_SCROLL_PROPERTY( "enableAutoScroll" ); +const char * const AUTO_SCROLL_SPEED_PROPERTY( "autoScrollSpeed" ); +const char * const AUTO_SCROLL_LOOP_COUNT_PROPERTY( "autoScrollLoopCount" ); +const char * const AUTO_SCROLL_GAP_PROPERTY( "autoScrollGap" ); +const char * const LINE_SPACING_PROPERTY( "lineSpacing" ); +const char * const UNDERLINE_PROPERTY( "underline" ); +const char * const SHADOW_PROPERTY( "shadow" ); +const char * const OUTLINE_PROPERTY( "outline" ); +const char * const BATCHING_ENABLED_PROPERTY( "batchingEnabled" ); + +const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] = +{ + { "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN }, + { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER }, + { "END", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END }, +}; +const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); + +const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] = +{ + { "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP }, + { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER }, + { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM }, +}; +const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); + +std::string GetHorizontalAlignment( LayoutEngine::HorizontalAlignment alignment ) +{ + const char* name = Scripting::GetEnumerationName( alignment, + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); + + return std::string( name ); +} + +std::string GetVerticalAlignment( LayoutEngine::VerticalAlignment alignment ) +{ + const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( alignment, + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); + + return std::string( name ); +} + +const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( + attribute mediump vec2 aPosition;\n + uniform mediump mat4 uMvpMatrix;\n + uniform mediump vec3 uSize;\n + uniform mediump vec4 pixelArea; + varying mediump vec2 vTexCoord;\n + \n + void main()\n + {\n + mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n + vertexPosition.xyz *= uSize;\n + vertexPosition = uMvpMatrix * vertexPosition;\n + \n + vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n + gl_Position = vertexPosition;\n + }\n +); + +const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord;\n + uniform sampler2D sTexture;\n + uniform mediump vec4 uAtlasRect;\n + uniform lowp vec4 uColor;\n + \n + void main()\n + {\n + mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n + gl_FragColor = texture2D( sTexture, texCoord ) * uColor;\n + }\n +); + +Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridSize ) +{ + Geometry geometry; + + if( gridSize == ImageDimensions( 1, 1 ) ) + { + geometry = factoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); + if( !geometry ) + { + geometry = VisualFactoryCache::CreateQuadGeometry(); + factoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry ); + } + } + else + { + geometry = VisualFactoryCache::CreateGridGeometry( gridSize ); + } + + return geometry; +} + +} // namespace + +TextVisual::TextVisual( VisualFactoryCache& factoryCache ) +: Visual::Base( factoryCache ), + mController( Text::Controller::New() ), + mRenderingBackend( Toolkit::Text::DEFAULT_RENDERING_BACKEND ), + mHasBeenStaged( false ) +{ +} + +TextVisual::~TextVisual() +{ +} + +void TextVisual::SetTextControlInterface( Text::ControlInterface* controlInterface ) +{ + if( mController ) + { + mController->SetTextControlInterface( controlInterface ); + } +} + +void TextVisual::SetSize( const Vector2& size ) +{ + const Text::Controller::UpdateTextType updateTextType = mController->Relayout( size ); + + if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) ) || + !mRenderer ) + { + if( !mRenderer ) + { + mRenderer = Text::Backend::Get().NewRenderer( mRenderingBackend ); + } + + RenderText(); + } +} + +float TextVisual::GetHeightForWidth( float width ) const +{ + return mController->GetHeightForWidth( width ); +} + +void TextVisual::GetNaturalSize( Vector2& naturalSize ) const +{ + naturalSize = mController->GetNaturalSize().GetVectorXY(); +} + +void TextVisual::DoCreatePropertyMap( Property::Map& map ) const +{ + Property::Value value; + + map.Clear(); + map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT ); + + map.Insert( Toolkit::TextVisual::Property::RENDERING_BACKEND, mRenderingBackend ); + + std::string text; + mController->GetText( text ); + map.Insert( Toolkit::TextVisual::Property::TEXT, text ); + + map.Insert( Toolkit::TextVisual::Property::FONT_FAMILY, mController->GetDefaultFontFamily() ); + + GetFontStyleProperty( mController, value, Text::FontStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::FONT_STYLE, value ); + + map.Insert( Toolkit::TextVisual::Property::POINT_SIZE, mController->GetDefaultPointSize() ); + + map.Insert( Toolkit::TextVisual::Property::MULTI_LINE, mController->IsMultiLineEnabled() ); + + map.Insert( Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, GetHorizontalAlignment( mController->GetHorizontalAlignment() ) ); + + map.Insert( Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, GetVerticalAlignment( mController->GetVerticalAlignment() ) ); + + map.Insert( Toolkit::TextVisual::Property::TEXT_COLOR, mController->GetTextColor() ); + + map.Insert( Toolkit::TextVisual::Property::ENABLE_MARKUP, mController->IsMarkupProcessorEnabled() ); + + map.Insert( Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL, mController->IsAutoScrollEnabled() ); + + map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED, mController->GetAutoScrollSpeed() ); + + map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT, mController->GetAutoScrollLoopCount() ); + + map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_GAP, mController->GetAutoScrollWrapGap() ); + + map.Insert( Toolkit::TextVisual::Property::LINE_SPACING, mController->GetDefaultLineSpacing() ); + + GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::UNDERLINE, value ); + + GetShadowProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::SHADOW, value ); + + GetOutlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::OUTLINE, value ); + + map.Insert( Toolkit::TextVisual::Property::BATCHING_ENABLED, false ); // TODO +} + +void TextVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap ) +{ + mSelf = actor; + + for( Property::Map::SizeType index = 0u, count = propertyMap.Count(); index < count; ++index ) + { + const KeyValuePair& keyValue = propertyMap.GetKeyValue( index ); + + switch( keyValue.first.type ) + { + case Property::Key::INDEX: + { + if( Toolkit::Visual::Property::TYPE != keyValue.first.indexKey ) // Toolkit::Visual::Property::TYPE is not a TextVisual's property. + { + DoSetProperty( keyValue.first.indexKey, keyValue.second ); + } + break; + } + case Property::Key::STRING: + { + if( keyValue.first.stringKey == RENDERING_BACKEND_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::RENDERING_BACKEND, keyValue.second ); + } + else if( keyValue.first.stringKey == TEXT_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::TEXT, keyValue.second ); + } + else if( keyValue.first.stringKey == FONT_FAMILY_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::FONT_FAMILY, keyValue.second ); + } + else if( keyValue.first.stringKey == FONT_STYLE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::FONT_STYLE, keyValue.second ); + } + else if( keyValue.first.stringKey == POINT_SIZE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::POINT_SIZE, keyValue.second ); + } + else if( keyValue.first.stringKey == MULTI_LINE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::MULTI_LINE, keyValue.second ); + } + else if( keyValue.first.stringKey == HORIZONTAL_ALIGNMENT_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, keyValue.second ); + } + else if( keyValue.first.stringKey == VERTICAL_ALIGNMENT_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, keyValue.second ); + } + else if( keyValue.first.stringKey == TEXT_COLOR_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::TEXT_COLOR, keyValue.second ); + } + else if( keyValue.first.stringKey == ENABLE_MARKUP_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::ENABLE_MARKUP, keyValue.second ); + } + else if( keyValue.first.stringKey == ENABLE_AUTO_SCROLL_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL, keyValue.second ); + } + else if( keyValue.first.stringKey == AUTO_SCROLL_SPEED_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED, keyValue.second ); + } + else if( keyValue.first.stringKey == AUTO_SCROLL_LOOP_COUNT_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT, keyValue.second ); + } + else if( keyValue.first.stringKey == AUTO_SCROLL_GAP_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_GAP, keyValue.second ); + } + else if( keyValue.first.stringKey == LINE_SPACING_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::LINE_SPACING, keyValue.second ); + } + else if( keyValue.first.stringKey == UNDERLINE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::UNDERLINE, keyValue.second ); + } + else if( keyValue.first.stringKey == SHADOW_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::SHADOW, keyValue.second ); + } + else if( keyValue.first.stringKey == OUTLINE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::OUTLINE, keyValue.second ); + } + else if( keyValue.first.stringKey == BATCHING_ENABLED_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::BATCHING_ENABLED, keyValue.second ); + } + break; + } + } + } + + // Retrieve the layout engine to set whether to elide the text and set the cursor's width. + Text::LayoutEngine& engine = mController->GetLayoutEngine(); + + // Elide the text if it exceeds the boundaries. + engine.SetTextEllipsisEnabled( true ); + + // Sets 0 as cursor's width. + engine.SetCursorWidth( 0u ); // Do not layout space for the cursor. +} + +void TextVisual::DoSetOnStage( Actor& actor ) +{ + // TODO Create the actual renderer(s) for the text!!!! + // Will crash if no mImpl->mRenderer is set. + Geometry geometry; + Shader shader; + + geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) ); + + shader = mFactoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP ); + if( !shader ) + { + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP ); + mFactoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader ); + } + + mImpl->mRenderer = Renderer::New( geometry, shader ); + + mSelf = actor; + + if( mHasBeenStaged ) + { + RenderText(); + } + else + { + mHasBeenStaged = true; + } +} + +void TextVisual::DoSetOffStage( Actor& actor ) +{ + mSelf.Reset(); +} + +void TextVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue ) +{ + switch( index ) + { + case Toolkit::TextVisual::Property::RENDERING_BACKEND: + { + int backend = propertyValue.Get(); + +#ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING + if( Text::RENDERING_VECTOR_BASED == backend ) + { + backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering + } +#endif + if( mRenderingBackend != backend ) + { + mRenderingBackend = backend; + mRenderer.Reset(); + + // When using the vector-based rendering, the size of the GLyphs are different + TextAbstraction::GlyphType glyphType = ( Text::RENDERING_VECTOR_BASED == mRenderingBackend ) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; + mController->SetGlyphType( glyphType ); + } + break; + } + case Toolkit::TextVisual::Property::TEXT: + { + mController->SetText( propertyValue.Get() ); + break; + } + case Toolkit::TextVisual::Property::FONT_FAMILY: + { + SetFontFamilyProperty( mController, propertyValue ); + break; + } + case Toolkit::TextVisual::Property::FONT_STYLE: + { + SetFontStyleProperty( mController, propertyValue, Text::FontStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::POINT_SIZE: + { + const float pointSize = propertyValue.Get(); + + if( !Equals( mController->GetDefaultPointSize(), pointSize ) ) + { + mController->SetDefaultPointSize( pointSize ); + } + break; + } + case Toolkit::TextVisual::Property::MULTI_LINE: + { + mController->SetMultiLineEnabled( propertyValue.Get() ); + break; + } + case Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT: + { + LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ); + if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( propertyValue.Get< std::string >().c_str(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT, + alignment ) ) + { + mController->SetHorizontalAlignment( alignment ); + } + break; + } + case Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT: + { + LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM ); + if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( propertyValue.Get< std::string >().c_str(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT, + alignment ) ) + { + mController->SetVerticalAlignment( alignment ); + } + break; + } + case Toolkit::TextVisual::Property::TEXT_COLOR: + { + const Vector4 textColor = propertyValue.Get< Vector4 >(); + if( mController->GetTextColor() != textColor ) + { + mController->SetTextColor( textColor ); + mRenderer.Reset(); + } + break; + } + case Toolkit::TextVisual::Property::ENABLE_MARKUP: + { + const bool enableMarkup = propertyValue.Get(); + mController->SetMarkupProcessorEnabled( enableMarkup ); + break; + } + case Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL: + { + const bool enableAutoScroll = propertyValue.Get(); + + // If request to auto scroll is the same as current state then do nothing. + if( enableAutoScroll != mController->IsAutoScrollEnabled() ) + { + // If request is disable (false) and auto scrolling is enabled then need to stop it + if( !enableAutoScroll ) + { + StopTextAutoScrolling(); // Causes the current animation to finish playing. + } + // If request is enable (true) then start autoscroll as not already running + else + { + mController->GetLayoutEngine().SetTextEllipsisEnabled( false ); + mController->SetAutoScrollEnabled( enableAutoScroll ); + mController->RequestRelayout(); + } + } + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED: + { + mController->SetAutoscrollSpeed( propertyValue.Get() ); + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT: + { + const int loopCount = propertyValue.Get(); + if( loopCount > 0 ) + { + mController->SetAutoScrollLoopCount( loopCount ); + } + else + { + StopTextAutoScrolling(); // Causes the current animation to finish playing. + } + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_GAP: + { + mController->SetAutoScrollWrapGap( propertyValue.Get() ); + break; + } + case Toolkit::TextVisual::Property::LINE_SPACING: + { + const float lineSpacing = propertyValue.Get(); + mController->SetDefaultLineSpacing( lineSpacing ); + mRenderer.Reset(); + break; + } + case Toolkit::TextVisual::Property::UNDERLINE: + { + // TODO : This switch can be removed when the deprecated SHADOW_OFFSET and SHADOW_COLOR properties are finally removed. + // Only the code for the STRING case should be kept. + switch( propertyValue.GetType() ) + { + case Property::VECTOR4: + { + const Vector4 color = propertyValue.Get(); + if( mController->GetUnderlineColor() != color ) + { + mController->SetUnderlineColor( color ); + mRenderer.Reset(); + } + break; + } + case Property::FLOAT: + { + float height = propertyValue.Get(); + if( fabsf( mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) + { + mController->SetUnderlineHeight( height ); + mRenderer.Reset(); + } + break; + } + case Property::BOOLEAN: + { + const bool enabled = propertyValue.Get(); + if( mController->IsUnderlineEnabled() != enabled ) + { + mController->SetUnderlineEnabled( enabled ); + mRenderer.Reset(); + } + break; + } + case Property::STRING: + { + const bool update = SetUnderlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + if( update ) + { + mRenderer.Reset(); + } + break; + } + default: + { + // Nothing to do. + break; + } + } + + break; + } + case Toolkit::TextVisual::Property::SHADOW: + { + // TODO : This switch can be removed when the deprecated SHADOW_OFFSET and SHADOW_COLOR properties are finally removed. + // Only the code for the STRING case should be kept. + switch( propertyValue.GetType() ) + { + case Property::VECTOR2: + { + const Vector2 shadowOffset = propertyValue.Get(); + if( mController->GetShadowOffset() != shadowOffset ) + { + mController->SetShadowOffset( shadowOffset ); + mRenderer.Reset(); + } + break; + } + case Property::VECTOR4: + { + const Vector4 shadowColor = propertyValue.Get(); + if( mController->GetShadowColor() != shadowColor ) + { + mController->SetShadowColor( shadowColor ); + mRenderer.Reset(); + } + break; + } + case Property::STRING: + { + const bool update = SetShadowProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + if( update ) + { + mRenderer.Reset(); + } + break; + } + default: + { + // Nothing to do. + break; + } + } + break; + } + case Toolkit::TextVisual::Property::EMBOSS: + { + const bool update = SetEmbossProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + if( update ) + { + mRenderer.Reset(); + } + break; + } + case Toolkit::TextVisual::Property::OUTLINE: + { + const bool update = SetOutlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + if( update ) + { + mRenderer.Reset(); + } + break; + } + case Toolkit::TextVisual::Property::BATCHING_ENABLED: + { + // TODO + break; + } + default: + { + // Should not arrive here. + DALI_ASSERT_DEBUG( false ); + } + } +} + +Dali::Property::Value TextVisual::DoGetProperty( Dali::Property::Index index ) +{ + Dali::Property::Value value; + + switch( index ) + { + case Toolkit::TextVisual::Property::RENDERING_BACKEND: + { + value = mRenderingBackend; + break; + } + case Toolkit::TextVisual::Property::TEXT: + { + std::string text; + mController->GetText( text ); + value = text; + break; + } + case Toolkit::TextVisual::Property::FONT_FAMILY: + { + value = mController->GetDefaultFontFamily(); + break; + } + case Toolkit::TextVisual::Property::FONT_STYLE: + { + GetFontStyleProperty( mController, value, Text::FontStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::POINT_SIZE: + { + value = mController->GetDefaultPointSize(); + break; + } + case Toolkit::TextVisual::Property::MULTI_LINE: + { + value = mController->IsMultiLineEnabled(); + break; + } + case Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT: + { + const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( mController->GetHorizontalAlignment(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); + if( name ) + { + value = std::string( name ); + } + break; + } + case Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT: + { + const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( mController->GetVerticalAlignment(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); + if( name ) + { + value = std::string( name ); + } + break; + } + case Toolkit::TextVisual::Property::TEXT_COLOR: + { + value = mController->GetTextColor(); + break; + } + case Toolkit::TextVisual::Property::ENABLE_MARKUP: + { + value = mController->IsMarkupProcessorEnabled(); + break; + } + case Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL: + { + value = mController->IsAutoScrollEnabled(); + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED: + { + value = mController->GetAutoScrollSpeed(); + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT: + { + value = mController->GetAutoScrollLoopCount(); + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_GAP: + { + value = mController->GetAutoScrollWrapGap(); + break; + } + case Toolkit::TextVisual::Property::LINE_SPACING: + { + value = mController->GetDefaultLineSpacing(); + break; + } + case Toolkit::TextVisual::Property::UNDERLINE: + { + GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::SHADOW: + { + GetShadowProperties( mController, value, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::EMBOSS: + { + GetEmbossProperties( mController, value, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::OUTLINE: + { + GetOutlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::BATCHING_ENABLED: + { + // TODO + break; + } + default: + { + // Should not arrive here. + DALI_ASSERT_DEBUG( false ); + } + } + + return value; +} + +void TextVisual::RenderText() +{ + Actor renderableActor; + + if( mRenderer ) + { + renderableActor = mRenderer->Render( mController->GetView(), Toolkit::DepthIndex::TEXT ); + } + + if( renderableActor != mRenderableActor ) + { + UnparentAndReset( mRenderableActor ); + + if( renderableActor ) + { + const Vector2& scrollOffset = mController->GetScrollPosition(); + renderableActor.SetPosition( scrollOffset.x, scrollOffset.y ); + + mSelf.Add( renderableActor ); + } + mRenderableActor = renderableActor; + + if( mController->IsAutoScrollEnabled() ) + { + SetUpAutoScrolling(); + } + } +} + +void TextVisual::StopTextAutoScrolling() +{ + if( mTextScroller ) + { + mTextScroller->StopScrolling(); + } +} + +void TextVisual::SetUpAutoScrolling() +{ + const Text::ScrollerData* const data = mController->GetAutoScrollData(); + + if( NULL != data ) + { + if( !mTextScroller ) + { + // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults + mTextScroller = Text::TextScroller::New( *mController ); + } + + mTextScroller->StartScrolling( mRenderableActor, + *data ); + + mSelf.Add( mTextScroller->GetScrollingText() ); + mSelf.Add( mTextScroller->GetSourceCamera() ); + } +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/visuals/text/text-visual.h b/dali-toolkit/internal/visuals/text/text-visual.h new file mode 100644 index 0000000..9151ec7 --- /dev/null +++ b/dali-toolkit/internal/visuals/text/text-visual.h @@ -0,0 +1,172 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TEXT_VISUAL_H +#define DALI_TOOLKIT_INTERNAL_TEXT_VISUAL_H + +/* + * Copyright (c) 2016 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. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +class TextVisual; +typedef IntrusivePtr< TextVisual > TextVisualPtr; + +/** + * The visual which renders text + * + * The following properties are optional: + * + * | %Property Name | Type | + * |---------------------|---------| + * | renderingBackend | INTEGER | + * | text | STRING | + * | fontFamily | STRING | + * | fontStyle | STRING | + * | pointSize | FLOAT | + * | multiLine | BOOLEAN | + * | horizontalAlignment | STRING | + * | verticalAlignment | STRING | + * | textColor | VECTOR4 | + * | enableMarkup | BOOLEAN | + * | enableAutoScroll | BOOLEAN | + * | autoScrollSpeed | INTEGER | + * | autoScrollLoopCount | INTEGER | + * | autoScrollGap | INTEGER | + * | lineSpacing | FLOAT | + * | underline | STRING | + * | shadow | STRING | + * | outline | STRING | + * | batchingEnabled | BOOLEAN | + * + */ +class TextVisual : public Visual::Base +{ +public: + + /** + * @brief Constructor. + * + * @param[in] factoryCache The VisualFactoryCache object + */ + TextVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + ~TextVisual(); + + /** + * + */ + void SetTextControlInterface( Text::ControlInterface* controlInterface ); + +public: // from Visual::Base + + /** + * @copydoc Visual::Base::GetHeightForWidth() + */ + float GetHeightForWidth( float width ) const; + + /** + * @copydoc Visual::Base::GetNaturalSize() + */ + virtual void SetSize( const Vector2& size ); + + /** + * @copydoc Visual::Base::GetNaturalSize() + */ + virtual void GetNaturalSize( Vector2& naturalSize ) const; + + /** + * @copydoc Visual::Base::CreatePropertyMap() + */ + virtual void DoCreatePropertyMap( Property::Map& map ) const; + +protected: // from Visual::Base + /** + * @copydoc Visual::Base::DoInitialize() + */ + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); + + /** + * @copydoc Visual::Base::DoSetOnStage() + */ + virtual void DoSetOnStage( Actor& actor ); + + /** + * @copydoc Visual::Base::DoSetOffStage() + */ + virtual void DoSetOffStage( Actor& actor ); + + /** + *@copydoc Visual::Base::DoSetProperty + */ + virtual void DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue ); + + /** + * @copydoc Visual::Base::DoGetProperty + */ + virtual Dali::Property::Value DoGetProperty( Dali::Property::Index index ); + +private: + + /** + * @brief Render view, create and attach actor(s) to this TextView. + * @todo In a next patch a new text render back-end won't add extra actors. + */ + void RenderText(); + + /** + * @brief Stops the text auto scroll. + */ + void StopTextAutoScrolling(); + + /** + * @brief Set up Autoscrolling. + */ + void SetUpAutoScrolling(); + +private: + Text::ControllerPtr mController; ///< The text's controller. + Actor mSelf; + + Text::RendererPtr mRenderer; + Text::TextScrollerPtr mTextScroller; + Actor mRenderableActor; + + int mRenderingBackend; + bool mHasBeenStaged : 1; +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif /* DALI_TOOLKIT_INTERNAL_TEXT_VISUAL_H */ diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 4156d1a..86d2114 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -84,6 +84,11 @@ const Vector2& Visual::Base::GetSize() const return mImpl->mSize; } +float Visual::Base::GetHeightForWidth( float width ) const +{ + return 0.f; +} + void Visual::Base::GetNaturalSize( Vector2& naturalSize ) const { naturalSize = Vector2::ZERO; @@ -124,6 +129,16 @@ void Visual::Base::SetOffStage( Actor& actor ) } } +void Visual::Base::CreatePropertyMap( Property::Map& map ) const +{ + DoCreatePropertyMap( map ); + + if( mImpl->mCustomShader ) + { + mImpl->mCustomShader->CreatePropertyMap( map ); + } +} + void Visual::Base::EnablePreMultipliedAlpha( bool preMultipled ) { if(preMultipled) @@ -152,16 +167,6 @@ void Visual::Base::DoSetOffStage( Actor& actor ) mImpl->mRenderer.Reset(); } -void Visual::Base::CreatePropertyMap( Property::Map& map ) const -{ - DoCreatePropertyMap( map ); - - if( mImpl->mCustomShader ) - { - mImpl->mCustomShader->CreatePropertyMap( map ); - } -} - bool Visual::Base::IsOnStage() const { return mImpl->mFlags & Impl::IS_ON_STAGE; diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index c073518..3334842 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -85,6 +85,11 @@ public: const Vector2& GetSize() const; /** + * @copydoc Toolkit::Visual::Base::GetHeightForWidth + */ + virtual float GetHeightForWidth( float width ) const; + + /** * @copydoc Toolkit::Visual::Base::GetNaturalSize */ virtual void GetNaturalSize( Vector2& naturalSize ) const; @@ -120,7 +125,7 @@ public: * * @param[in] preMultipled whether alpha is pre-multiplied. */ - void EnablePreMultipliedAlpha( bool preMultipled ); + void EnablePreMultipliedAlpha( bool preMultipled ); /** * @brief Query whether alpha is pre-multiplied. diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.cpp b/dali-toolkit/internal/visuals/visual-factory-impl.cpp index f76aeed..76d0ba7 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-impl.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -189,6 +190,12 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property break; } + case Toolkit::Visual::TEXT: + { + visualPtr = new TextVisual( *( mFactoryCache.Get() ) ); + break; + } + } if( visualPtr ) diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.h b/dali-toolkit/internal/visuals/visual-factory-impl.h index 484a688..501a854 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.h +++ b/dali-toolkit/internal/visuals/visual-factory-impl.h @@ -65,7 +65,6 @@ public: */ Toolkit::Visual::Base CreateVisual( const std::string& image, ImageDimensions size ); - protected: /** diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.h b/dali-toolkit/public-api/controls/text-controls/text-label.h index c9322aa..9c216c2 100644 --- a/dali-toolkit/public-api/controls/text-controls/text-label.h +++ b/dali-toolkit/public-api/controls/text-controls/text-label.h @@ -122,7 +122,7 @@ public: /** * @brief The single-line or multi-line layout option - * @details name "multiLine", type FLOAT, default SINGLE_LINE_BOX + * @details name "multiLine", type BOOLEAN, default false * @SINCE_1_0.0 */ MULTI_LINE, @@ -150,7 +150,7 @@ public: /** * @brief The drop shadow offset 0 indicates no shadow - * @details name "shadowOffset", type VECTOR4 + * @details name "shadowOffset", type VECTOR2 * @DEPRECATED_1_1.37 Use SHADOW instead */ SHADOW_OFFSET, @@ -192,13 +192,13 @@ public: /** * @brief Start or stop auto scrolling, - * @details name "enableMarkup", type BOOLEAN, default is false + * @details name "enableAutoScroll", type BOOLEAN, default is false * @SINCE_1_1.35 */ ENABLE_AUTO_SCROLL, /** - * @brief Start or stop auto scrolling, + * @brief Sets the speed of scrolling in pixels per second, * @details name "autoScrollSpeed", type INT, default in style sheet * @SINCE_1_1.35 */ diff --git a/dali-toolkit/public-api/file.list b/dali-toolkit/public-api/file.list index de5e006..2439b45 100755 --- a/dali-toolkit/public-api/file.list +++ b/dali-toolkit/public-api/file.list @@ -113,4 +113,5 @@ public_api_visuals_header_files = \ $(public_api_src_dir)/visuals/image-visual-properties.h \ $(public_api_src_dir)/visuals/mesh-visual-properties.h \ $(public_api_src_dir)/visuals/primitive-visual-properties.h \ + $(public_api_src_dir)/visuals/text-visual-properties.h \ $(public_api_src_dir)/visuals/visual-properties.h diff --git a/dali-toolkit/public-api/visuals/text-visual-properties.h b/dali-toolkit/public-api/visuals/text-visual-properties.h new file mode 100644 index 0000000..39a5eb3 --- /dev/null +++ b/dali-toolkit/public-api/visuals/text-visual-properties.h @@ -0,0 +1,188 @@ +#ifndef DALI_TOOLKIT_TEXT_VISUAL_PROPERTIES_H +#define DALI_TOOLKIT_TEXT_VISUAL_PROPERTIES_H + +/* + * Copyright (c) 2016 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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace TextVisual +{ + +namespace Property +{ + +enum +{ + /** + * @brief The type of rendering e.g. bitmap-based + * @details name "renderingBackend", type INTEGER, default RENDERING_SHARED_ATLAS + * @SINCE_1_2.11 + */ + RENDERING_BACKEND = VISUAL_PROPERTY_START_INDEX, + + /** + * @brief The text to display in UTF-8 format, + * @details name "text", type STRING + * @SINCE_1_2.11 + */ + TEXT, + + /** + * @brief The requested font family to use, + * @details name "fontFamily", type STRING + * @SINCE_1_2.11 + */ + FONT_FAMILY, + + /** + * @brief The requested font style to use, + * @details name "fontStyle", type STRING + * @SINCE_1_2.11 + */ + FONT_STYLE, + + /** + * @brief The size of font in points + * @details name "pointSize", type FLOAT + * @SINCE_1_2.11 + */ + POINT_SIZE, + + /** + * @brief The single-line or multi-line layout option + * @details name "multiLine", type BOOLEAN, default false + * @SINCE_1_2.11 + */ + MULTI_LINE, + + /** + * @brief The line horizontal alignment + * @details name "horizontalAlignment", type STRING, values "BEGIN", "CENTER", "END", default BEGIN + * @SINCE_1_2.11 + */ + HORIZONTAL_ALIGNMENT, + + /** + * @brief The line vertical alignment + * @details name "verticalAlignment", type STRING, values "TOP", "CENTER", "BOTTOM", default TOP + * @SINCE_1_2.11 + */ + VERTICAL_ALIGNMENT, + + /** + * @brief The color of the text + * @details name "textColor", type VECTOR4 + * @SINCE_1_2.11 + */ + TEXT_COLOR, + + /** + * @brief Whether the mark-up processing is enabled + * @details name "enableMarkup", type BOOLEAN + * @SINCE_1_2.11 + */ + ENABLE_MARKUP, + + /** + * @brief Start or stop auto scrolling, + * @details name "enableAutoScroll", type BOOLEAN, default is false + * @SINCE_1_2.11 + */ + ENABLE_AUTO_SCROLL, + + /** + * @brief Sets the speed of scrolling in pixels per second, + * @details name "autoScrollSpeed", type INTEGER, default in style sheet + * @SINCE_1_2.11 + */ + AUTO_SCROLL_SPEED, + + /** + * @brief Number of complete loops when scrolling enabled + * @details name "autoScrollLoopCount", type INTEGER, default in style sheet + * @SINCE_1_2.11 + */ + AUTO_SCROLL_LOOP_COUNT, + + /** + * @brief Gap before before scrolling wraps + * @details name "autoScrollGap", type INTEGER, default in style sheet but can be overridden to prevent same text being show at start and end. + * @SINCE_1_2.11 + */ + AUTO_SCROLL_GAP, + + /** + * @brief The default extra space between lines in points. + * @details name "lineSpacing", type FLOAT. + * @SINCE_1_2.11 + */ + LINE_SPACING, + + /** + * @brief The default underline parameters. + * @details name "underline", type STRING. + * @SINCE_1_2.11 + */ + UNDERLINE, + + /** + * @brief The default shadow parameters. + * @details name "shadow", type STRING. + * @SINCE_1_2.11 + */ + SHADOW, + + /** + * @brief The default emboss parameters. + * @details name "emboss", type STRING. + * @SINCE_1_2.11 + */ + EMBOSS, + + /** + * @brief The default outline parameters. + * @details name "outline", type STRING. + * @SINCE_1_2.11 + */ + OUTLINE, + + /** + * @brief This enables Text visuals to automatically be converted to Batch-Text visuals. + * @details Name "batchingEnabled", type Property::BOOLEAN. + * @SINCE_1_2.11 + * @note Optional. If not specified, the default is false. + */ + BATCHING_ENABLED, +}; + +} // namespace Property + +} // namespace TextVisual + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_VISUAL_PROPERTIES_H diff --git a/dali-toolkit/public-api/visuals/visual-properties.h b/dali-toolkit/public-api/visuals/visual-properties.h index 989d938..c64a73c 100644 --- a/dali-toolkit/public-api/visuals/visual-properties.h +++ b/dali-toolkit/public-api/visuals/visual-properties.h @@ -43,6 +43,7 @@ enum Type MESH, ///< Renders a mesh using an "obj" file, optionally with textures provided by an "mtl" file. @SINCE_1_1.45 PRIMITIVE, ///< Renders a simple 3D shape, such as a cube or sphere. @SINCE_1_1.45 WIREFRAME, ///< Renders a simple wire-frame outlining a quad. @SINCE_1_2_2 + TEXT, ///< Renders text. @SINCE_1_2.11 }; namespace Property