From: Francisco Santos Date: Fri, 15 Dec 2017 11:19:45 +0000 (+0000) Subject: [dali_1.3.4] Merge branch 'devel/master' X-Git-Tag: dali_1.9.8~5^2~117 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=refs%2Fchanges%2F39%2F164139%2F1;hp=841cec182d26fa3b89d7a353fb0b5dde194779d0 [dali_1.3.4] Merge branch 'devel/master' Change-Id: I10679ea694931c87d64accd9d6c67e31386393b6 --- 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 8d73622..02f2e66 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 @@ -184,9 +184,16 @@ int UtcDaliTextControllerImfEvent(void) // Enables the text input. controller->EnableTextInput( decorator ); + // Set the placeholder text. + controller->SetPlaceholderText( Controller::PLACEHOLDER_TYPE_INACTIVE, "Hello Dali" ); + // Creates an ImfManager. ImfManager imfManager = ImfManager::Get(); + // For coverage. + imfEvent = ImfManager::ImfEventData( ImfManager::GETSURROUNDING, "", 0, 0 ); + controller->OnImfEvent( imfManager, imfEvent ); + // Send VOID event. imfEvent = ImfManager::ImfEventData( ImfManager::VOID, "", 0, 0 ); controller->OnImfEvent( imfManager, imfEvent ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 487ae20..6f9784f 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -314,9 +314,38 @@ bool DaliTestCheckMaps( const Property::Map& fontStyleMapGet, const Property::Ma if( NULL != valueSet ) { - if( valueGet.second.Get() != valueSet->Get() ) + if( valueSet->GetType() == Dali::Property::STRING && ( valueGet.second.Get() != valueSet->Get() ) ) { - tet_printf( " Value got : [%s], expected : [%s]", valueGet.second.Get().c_str(), valueSet->Get().c_str() ); + tet_printf( "Value got : [%s], expected : [%s]", valueGet.second.Get().c_str(), valueSet->Get().c_str() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::BOOLEAN && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::INTEGER && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::FLOAT && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%f], expected : [%f]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::VECTOR2 && ( valueGet.second.Get() != valueSet->Get() ) ) + { + Vector2 vector2Get = valueGet.second.Get(); + Vector2 vector2Set = valueSet->Get(); + tet_printf( "Value got : [%f, %f], expected : [%f, %f]", vector2Get.x, vector2Get.y, vector2Set.x, vector2Set.y ); + return false; + } + else if( valueSet->GetType() == Dali::Property::VECTOR4 && ( valueGet.second.Get() != valueSet->Get() ) ) + { + Vector4 vector4Get = valueGet.second.Get(); + Vector4 vector4Set = valueSet->Get(); + tet_printf( "Value got : [%f, %f, %f, %f], expected : [%f, %f, %f, %f]", vector4Get.r, vector4Get.g, vector4Get.b, vector4Get.a, vector4Set.r, vector4Set.g, vector4Set.b, vector4Set.a ); return false; } } @@ -785,8 +814,6 @@ int UtcDaliTextEditorSetPropertyP(void) editor.SetProperty( TextEditor::Property::OUTLINE, outlineMapSet ); - outlineMapSet["color"] = "red"; - outlineMapSet["width"] = "2"; outlineMapGet = editor.GetProperty( TextEditor::Property::OUTLINE ); DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index 0074c78..633ff81 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -329,39 +329,65 @@ bool DaliTestCheckMaps( const Property::Map& fontStyleMapGet, const Property::Ma { const KeyValuePair& valueGet = fontStyleMapGet.GetKeyValue( index ); - if( valueGet.first.type == Property::Key::STRING ) + Property::Value* valueSet = NULL; + if ( valueGet.first.type == Property::Key::INDEX ) { - Property::Value* valueSet = fontStyleMapSet.Find( valueGet.first.stringKey ); - if( NULL != valueSet ) + valueSet = fontStyleMapSet.Find( valueGet.first.indexKey ); + } + else + { + // Get Key is a string so searching Set Map for a string key + valueSet = fontStyleMapSet.Find( valueGet.first.stringKey ); + } + + if( NULL != valueSet ) + { + if( valueSet->GetType() == Dali::Property::STRING && ( valueGet.second.Get() != valueSet->Get() ) ) { - if( valueGet.second.Get() != valueSet->Get() ) - { - tet_printf( " Value got : [%s], expected : [%s]", valueGet.second.Get().c_str(), valueSet->Get().c_str() ); - return false; - } + tet_printf( "Value got : [%s], expected : [%s]", valueGet.second.Get().c_str(), valueSet->Get().c_str() ); + return false; } - else + else if( valueSet->GetType() == Dali::Property::BOOLEAN && ( valueGet.second.Get() != valueSet->Get() ) ) { - tet_printf( " The key %s doesn't exist.", valueGet.first.stringKey.c_str() ); + tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::INTEGER && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::FLOAT && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%f], expected : [%f]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::VECTOR2 && ( valueGet.second.Get() != valueSet->Get() ) ) + { + Vector2 vector2Get = valueGet.second.Get(); + Vector2 vector2Set = valueSet->Get(); + tet_printf( "Value got : [%f, %f], expected : [%f, %f]", vector2Get.x, vector2Get.y, vector2Set.x, vector2Set.y ); + return false; + } + else if( valueSet->GetType() == Dali::Property::VECTOR4 && ( valueGet.second.Get() != valueSet->Get() ) ) + { + Vector4 vector4Get = valueGet.second.Get(); + Vector4 vector4Set = valueSet->Get(); + tet_printf( "Value got : [%f, %f, %f, %f], expected : [%f, %f, %f, %f]", vector4Get.r, vector4Get.g, vector4Get.b, vector4Get.a, vector4Set.r, vector4Set.g, vector4Set.b, vector4Set.a ); return false; } } else { - Property::Value* valueSet = fontStyleMapSet.Find( valueGet.first.indexKey ); - if( NULL != valueSet ) + if ( valueGet.first.type == Property::Key::INDEX ) { - if( valueGet.second.Get() != valueSet->Get() ) - { - tet_printf( " Integer Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); - return false; - } + tet_printf( " The key %d doesn't exist.", valueGet.first.indexKey ); } else { - tet_printf( " The Int key %d doesn't exist.", valueGet.first.indexKey ); - return false; + tet_printf( " The key %s doesn't exist.", valueGet.first.stringKey.c_str() ); } + return false; } } } @@ -843,8 +869,6 @@ int UtcDaliTextFieldSetPropertyP(void) field.SetProperty( TextField::Property::OUTLINE, outlineMapSet ); - outlineMapSet["color"] = "red"; - outlineMapSet["width"] = "2"; outlineMapGet = field.GetProperty( TextField::Property::OUTLINE ); DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index 45214f8..f8d7497 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -82,18 +82,64 @@ bool DaliTestCheckMaps( const Property::Map& fontStyleMapGet, const Property::Ma { const KeyValuePair& valueGet = fontStyleMapGet.GetKeyValue( index ); - Property::Value* valueSet = fontStyleMapSet.Find( valueGet.first.stringKey ); + Property::Value* valueSet = NULL; + if ( valueGet.first.type == Property::Key::INDEX ) + { + valueSet = fontStyleMapSet.Find( valueGet.first.indexKey ); + } + else + { + // Get Key is a string so searching Set Map for a string key + valueSet = fontStyleMapSet.Find( valueGet.first.stringKey ); + } + if( NULL != valueSet ) { - if( valueGet.second.Get() != valueSet->Get() ) + if( valueSet->GetType() == Dali::Property::STRING && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%s], expected : [%s]", valueGet.second.Get().c_str(), valueSet->Get().c_str() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::BOOLEAN && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::INTEGER && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::FLOAT && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%f], expected : [%f]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::VECTOR2 && ( valueGet.second.Get() != valueSet->Get() ) ) + { + Vector2 vector2Get = valueGet.second.Get(); + Vector2 vector2Set = valueSet->Get(); + tet_printf( "Value got : [%f, %f], expected : [%f, %f]", vector2Get.x, vector2Get.y, vector2Set.x, vector2Set.y ); + return false; + } + else if( valueSet->GetType() == Dali::Property::VECTOR4 && ( valueGet.second.Get() != valueSet->Get() ) ) { - tet_printf( " Value got : [%s], expected : [%s]", valueGet.second.Get().c_str(), valueSet->Get().c_str() ); + Vector4 vector4Get = valueGet.second.Get(); + Vector4 vector4Set = valueSet->Get(); + tet_printf( "Value got : [%f, %f, %f, %f], expected : [%f, %f, %f, %f]", vector4Get.r, vector4Get.g, vector4Get.b, vector4Get.a, vector4Set.r, vector4Set.g, vector4Set.b, vector4Set.a ); return false; } } else { - tet_printf( " The key %s doesn't exist.", valueGet.first.stringKey.c_str() ); + if ( valueGet.first.type == Property::Key::INDEX ) + { + tet_printf( " The key %d doesn't exist.", valueGet.first.indexKey ); + } + else + { + tet_printf( " The key %s doesn't exist.", valueGet.first.stringKey.c_str() ); + } return false; } } @@ -463,8 +509,6 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) outlineMapSet["width"] = 2.0f; label.SetProperty( TextLabel::Property::OUTLINE, outlineMapSet ); - outlineMapSet["color"] = "red"; - outlineMapSet["width"] = "2"; outlineMapGet = label.GetProperty( TextLabel::Property::OUTLINE ); DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); @@ -1163,18 +1207,15 @@ int UtcDaliToolkitTextlabelTextDirection(void) tet_infoline(" UtcDaliToolkitTextlabelTextDirection"); TextLabel label = TextLabel::New(); + DALI_TEST_EQUALS( label.GetProperty< int >( DevelTextLabel::Property::TEXT_DIRECTION ), static_cast< int >( Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ), TEST_LOCATION ); + label.SetProperty( TextLabel::Property::TEXT, "Hello world" ); label.SetProperty( TextLabel::Property::POINT_SIZE, 20 ); Stage::GetCurrent().Add( label ); - application.SendNotification(); - application.Render(); - DALI_TEST_EQUALS( label.GetProperty< int >( DevelTextLabel::Property::TEXT_DIRECTION ), static_cast< int >( Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ), TEST_LOCATION ); label.SetProperty( TextLabel::Property::TEXT, "ﻡﺮﺤﺑﺍ ﺏﺎﻠﻋﺎﻠﻣ ﻡﺮﺤﺑﺍ" ); - application.SendNotification(); - application.Render(); DALI_TEST_EQUALS( label.GetProperty< int >( DevelTextLabel::Property::TEXT_DIRECTION ), static_cast< int >( Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT ), TEST_LOCATION ); END_TEST; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index b1f2e2e..ab45fc0 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -68,18 +69,64 @@ bool DaliTestCheckMaps( const Property::Map& fontStyleMapGet, const Property::Ma { const KeyValuePair& valueGet = fontStyleMapGet.GetKeyValue( index ); - Property::Value* valueSet = fontStyleMapSet.Find( valueGet.first.stringKey ); + Property::Value* valueSet = NULL; + if ( valueGet.first.type == Property::Key::INDEX ) + { + valueSet = fontStyleMapSet.Find( valueGet.first.indexKey ); + } + else + { + // Get Key is a string so searching Set Map for a string key + valueSet = fontStyleMapSet.Find( valueGet.first.stringKey ); + } + if( NULL != valueSet ) { - if( valueGet.second.Get() != valueSet->Get() ) + if( valueSet->GetType() == Dali::Property::STRING && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%s], expected : [%s]", valueGet.second.Get().c_str(), valueSet->Get().c_str() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::BOOLEAN && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::INTEGER && ( valueGet.second.Get() != valueSet->Get() ) ) + { + tet_printf( "Value got : [%d], expected : [%d]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::FLOAT && ( valueGet.second.Get() != valueSet->Get() ) ) { - tet_printf( " Value got : [%s], expected : [%s]", valueGet.second.Get().c_str(), valueSet->Get().c_str() ); + tet_printf( "Value got : [%f], expected : [%f]", valueGet.second.Get(), valueSet->Get() ); + return false; + } + else if( valueSet->GetType() == Dali::Property::VECTOR2 && ( valueGet.second.Get() != valueSet->Get() ) ) + { + Vector2 vector2Get = valueGet.second.Get(); + Vector2 vector2Set = valueSet->Get(); + tet_printf( "Value got : [%f, %f], expected : [%f, %f]", vector2Get.x, vector2Get.y, vector2Set.x, vector2Set.y ); + return false; + } + else if( valueSet->GetType() == Dali::Property::VECTOR4 && ( valueGet.second.Get() != valueSet->Get() ) ) + { + Vector4 vector4Get = valueGet.second.Get(); + Vector4 vector4Set = valueSet->Get(); + tet_printf( "Value got : [%f, %f, %f, %f], expected : [%f, %f, %f, %f]", vector4Get.r, vector4Get.g, vector4Get.b, vector4Get.a, vector4Set.r, vector4Set.g, vector4Set.b, vector4Set.a ); return false; } } else { - tet_printf( " The key %s doesn't exist.", valueGet.first.stringKey.c_str() ); + if ( valueGet.first.type == Property::Key::INDEX ) + { + tet_printf( " The key %d doesn't exist.", valueGet.first.indexKey ); + } + else + { + tet_printf( " The key %s doesn't exist.", valueGet.first.stringKey.c_str() ); + } return false; } } @@ -1070,6 +1117,16 @@ int UtcDaliVisualGetPropertyMap10(void) propertyMap.Insert( "horizontalAlignment", "CENTER" ); propertyMap.Insert( "verticalAlignment", "CENTER" ); propertyMap.Insert( "textColor", Color::RED ); + + Property::Map shadowMapSet; + propertyMap.Insert( "shadow", shadowMapSet.Add("color", Color::RED).Add("offset", Vector2(2.0f, 2.0f)).Add("blurRadius", 3.0f) ); + + Property::Map underlineMapSet; + propertyMap.Insert( "underline", underlineMapSet.Add("enable", "true").Add("color", "green").Add("height", "1") ); + + Property::Map outlineMapSet; + propertyMap.Insert( "outline", outlineMapSet.Add("color", Color::YELLOW).Add("width", 1) ); + Visual::Base textVisual = factory.CreateVisual( propertyMap ); Property::Map resultMap; @@ -1123,6 +1180,27 @@ int UtcDaliVisualGetPropertyMap10(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( !value->Get() ); + value = resultMap.Find( TextVisual::Property::SHADOW, Property::MAP ); + DALI_TEST_CHECK( value ); + + Property::Map shadowMapGet = value->Get(); + DALI_TEST_EQUALS( shadowMapGet.Count(), shadowMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( shadowMapGet, shadowMapSet ), true, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::UNDERLINE, Property::MAP ); + DALI_TEST_CHECK( value ); + + Property::Map underlineMapGet = value->Get(); + DALI_TEST_EQUALS( underlineMapGet.Count(), underlineMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( underlineMapGet, underlineMapSet ), true, TEST_LOCATION ); + + value = resultMap.Find( DevelTextVisual::Property::OUTLINE, Property::MAP ); + DALI_TEST_CHECK( value ); + + Property::Map outlineMapGet = value->Get(); + DALI_TEST_EQUALS( outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( DaliTestCheckMaps( outlineMapGet, outlineMapSet ), true, TEST_LOCATION ); + END_TEST; } diff --git a/build/tizen/docs/dali.doxy.in b/build/tizen/docs/dali.doxy.in index ddcd598..5c5d44b 100644 --- a/build/tizen/docs/dali.doxy.in +++ b/build/tizen/docs/dali.doxy.in @@ -354,6 +354,9 @@ ALIASES += SINCE_1_2_10="@since 1.2.10" ALIASES += SINCE_1_2_14="@since 1.2.14" ALIASES += SINCE_1_2_32="@since 1.2.32" +# Extra tags for Tizen 4.0 +ALIASES += SINCE_1_3_4="@since 1.3.4" + ALIASES += DEPRECATED_1_0="@deprecated Deprecated since 1.0" ALIASES += DEPRECATED_1_1="@deprecated Deprecated since 1.1" ALIASES += DEPRECATED_1_2_8="@deprecated Deprecated since 1.2.8" @@ -384,6 +387,9 @@ ALIASES += REMARK_RAWVIDEO="" #ALIASES += SINCE_1_2_14="\par Since:\n 3.0, DALi version 1.2.14" #ALIASES += SINCE_1_2_32="\par Since:\n 3.0, DALi version 1.2.32" +## Extra tags for Tizen 4.0 +#ALIASES += SINCE_1_3_4="\par Since:\n 4.0, DALi version 1.3.4" + ## DALi has no deprecated API in Tizen 2.4 because it's DALi's first release. ## Thus deprecated APIs in DALi 1.0.xx will be deprecated in Tizen 3.0. #ALIASES += DEPRECATED_1_0="@deprecated Deprecated since 3.0, DALi version 1.0" diff --git a/dali-toolkit/devel-api/file.list b/dali-toolkit/devel-api/file.list index 3f114bb..a995986 100644 --- a/dali-toolkit/devel-api/file.list +++ b/dali-toolkit/devel-api/file.list @@ -94,6 +94,7 @@ devel_api_visuals_header_files = \ $(devel_api_src_dir)/visuals/image-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/image-visual-actions-devel.h \ $(devel_api_src_dir)/visuals/animated-gradient-visual-properties-devel.h \ + $(devel_api_src_dir)/visuals/text-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/visual-properties-devel.h devel_api_shadow_view_header_files = \ diff --git a/dali-toolkit/devel-api/visuals/text-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/text-visual-properties-devel.h new file mode 100644 index 0000000..ec80f49 --- /dev/null +++ b/dali-toolkit/devel-api/visuals/text-visual-properties-devel.h @@ -0,0 +1,69 @@ +#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_TEXT_VISUAL_PROPERTIES_DEVEL_H +#define DALI_TOOLKIT_DEVEL_API_VISUALS_TEXT_VISUAL_PROPERTIES_DEVEL_H + +/* + * Copyright (c) 2017 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 DevelTextVisual +{ + +namespace Property +{ + +/** + * @brief All the visual types. + */ +enum +{ + TEXT = Dali::Toolkit::TextVisual::Property::TEXT, + FONT_FAMILY = Dali::Toolkit::TextVisual::Property::FONT_FAMILY, + FONT_STYLE = Dali::Toolkit::TextVisual::Property::FONT_STYLE, + POINT_SIZE = Dali::Toolkit::TextVisual::Property::POINT_SIZE, + MULTI_LINE = Dali::Toolkit::TextVisual::Property::MULTI_LINE, + HORIZONTAL_ALIGNMENT = Dali::Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, + VERTICAL_ALIGNMENT = Dali::Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, + TEXT_COLOR = Dali::Toolkit::TextVisual::Property::TEXT_COLOR, + ENABLE_MARKUP = Dali::Toolkit::TextVisual::Property::ENABLE_MARKUP, + SHADOW = Dali::Toolkit::TextVisual::Property::SHADOW, + UNDERLINE = Dali::Toolkit::TextVisual::Property::UNDERLINE, + + /** + * @brief The default outline parameters. + * @details name "outline", type Property::MAP. + */ + OUTLINE = UNDERLINE + 1 +}; + + +} // namespace Property + +} // namespace DevelTextVisual + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_TEXT_VISUAL_PROPERTIES_DEVEL_H diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp index e9e0b1a..aa4d5c6 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.cpp +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -236,6 +236,9 @@ struct Decorator::Impl : public ConnectionTracker mBoundingBox(), mHighlightColor( LIGHT_BLUE ), mHighlightPosition( Vector2::ZERO ), + mHighlightSize( Vector2::ZERO ), + mControlSize( Vector2::ZERO ), + mHighlightOutlineOffset( 0.f ), mActiveCursor( ACTIVE_CURSOR_NONE ), mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ), mCursorBlinkDuration( 0.0f ), @@ -1163,8 +1166,8 @@ struct Decorator::Impl : public ConnectionTracker if ( mHighlightActor ) { // Sets the position of the highlight actor inside the decorator. - mHighlightActor.SetPosition( mHighlightPosition.x, - mHighlightPosition.y ); + mHighlightActor.SetPosition( mHighlightPosition.x + mHighlightOutlineOffset, + mHighlightPosition.y + mHighlightOutlineOffset ); const unsigned int numberOfQuads = mHighlightQuadList.Count(); if( 0u != numberOfQuads ) @@ -1912,6 +1915,7 @@ struct Decorator::Impl : public ConnectionTracker Vector2 mHighlightPosition; ///< The position of the highlight actor. Size mHighlightSize; ///< The size of the highlighted text. Size mControlSize; ///< The control's size. Set by the Relayout. + float mHighlightOutlineOffset; ///< The outline's offset. unsigned int mActiveCursor; unsigned int mCursorBlinkInterval; @@ -2199,16 +2203,18 @@ void Decorator::AddHighlight( unsigned int index, const Vector4& quad ) *( mImpl->mHighlightQuadList.Begin() + index ) = quad; } -void Decorator::SetHighLightBox( const Vector2& position, const Size& size ) +void Decorator::SetHighLightBox( const Vector2& position, const Size& size, float outlineOffset ) { mImpl->mHighlightPosition = position; mImpl->mHighlightSize = size; + mImpl->mHighlightOutlineOffset = outlineOffset; } void Decorator::ClearHighlights() { mImpl->mHighlightQuadList.Clear(); mImpl->mHighlightPosition = Vector2::ZERO; + mImpl->mHighlightOutlineOffset = 0.f; } void Decorator::ResizeHighlightQuads( unsigned int numberOfQuads ) diff --git a/dali-toolkit/internal/text/decorator/text-decorator.h b/dali-toolkit/internal/text/decorator/text-decorator.h index 8cff322..11f7062 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.h +++ b/dali-toolkit/internal/text/decorator/text-decorator.h @@ -468,9 +468,11 @@ public: * * @param[in] position The position of the highlighted text in decorator's coords. * @param[in] size The size of the highlighted text. + * @param[in] outlineOffset The outline's offset. */ void SetHighLightBox( const Vector2& position, - const Size& size ); + const Size& size, + float outlineOffset ); /** * @brief Removes all of the previously added highlights. diff --git a/dali-toolkit/internal/text/markup-processor-helper-functions.cpp b/dali-toolkit/internal/text/markup-processor-helper-functions.cpp index 8af6140..76d9a6a 100644 --- a/dali-toolkit/internal/text/markup-processor-helper-functions.cpp +++ b/dali-toolkit/internal/text/markup-processor-helper-functions.cpp @@ -109,6 +109,13 @@ void FloatToString( float value, std::string& floatStr ) floatStr = ss.str(); } +void UintToString( unsigned int value, std::string& uIntStr ) +{ + std::stringstream ss; + ss << value; + uIntStr = ss.str(); +} + void UintColorToVector4( unsigned int color, Vector4& retColor ) { retColor.a = static_cast( ( color & 0xFF000000 ) >> 24u ) / 255.f; diff --git a/dali-toolkit/internal/text/markup-processor-helper-functions.h b/dali-toolkit/internal/text/markup-processor-helper-functions.h index 45f586c..d1ecbc8 100644 --- a/dali-toolkit/internal/text/markup-processor-helper-functions.h +++ b/dali-toolkit/internal/text/markup-processor-helper-functions.h @@ -121,6 +121,14 @@ float StringToFloat( const char* const floatStr ); void FloatToString( float value, std::string& floatStr ); /** + * @brief Converts an unsigned int into a string. + * + * @param[in] value The unsigned int value. + * @param[out] uIntStr The string. + */ +void UintToString( unsigned int value, std::string& uIntStr ); + +/** * @brief Converts an ARGB color packed in 4 byte unsigned int into a Vector4 color used in Dali. * * @param[in] color An ARGB color packed in an unsigned int. diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp index 0d72be9..957fd8e 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp @@ -44,6 +44,7 @@ AtlasGlyphManager::AtlasGlyphManager() } void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph, + const uint32_t outlineWidth, const PixelData& bitmap, Dali::Toolkit::AtlasManager::AtlasSlot& slot ) { @@ -62,6 +63,7 @@ void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph, GlyphRecordEntry record; record.mIndex = glyph.index; + record.mOutlineWidth = outlineWidth; record.mImageId = slot.mImageId; record.mCount = 1; @@ -98,6 +100,7 @@ void AtlasGlyphManager::GenerateMeshData( uint32_t imageId, bool AtlasGlyphManager::IsCached( Text::FontId fontId, Text::GlyphIndex index, + uint32_t outlineWidth, Dali::Toolkit::AtlasManager::AtlasSlot& slot ) { for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin(); @@ -110,7 +113,7 @@ bool AtlasGlyphManager::IsCached( Text::FontId fontId, glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End(); ++glyphRecordIt ) { - if ( glyphRecordIt->mIndex == index ) + if ( glyphRecordIt->mIndex == index && glyphRecordIt->mOutlineWidth == outlineWidth ) { slot.mImageId = glyphRecordIt->mImageId; slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId ); @@ -171,7 +174,7 @@ const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics() return mMetrics; } -void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta ) +void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta ) { if( 0 != delta ) { @@ -187,7 +190,7 @@ void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIn glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End(); ++glyphRecordIt ) { - if ( glyphRecordIt->mIndex == index ) + if ( glyphRecordIt->mIndex == index && glyphRecordIt->mOutlineWidth == outlineWidth ) { glyphRecordIt->mCount += delta; DALI_ASSERT_DEBUG( glyphRecordIt->mCount >= 0 && "Glyph ref-count should not be negative" ); diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h index a2232f9..0d32834 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h @@ -51,6 +51,7 @@ public: struct GlyphRecordEntry { Text::GlyphIndex mIndex; + uint32_t mOutlineWidth; uint32_t mImageId; int32_t mCount; }; @@ -70,6 +71,7 @@ public: * @copydoc Toolkit::AtlasGlyphManager::Add */ void Add( const Text::GlyphInfo& glyph, + const uint32_t outlineWidth, const PixelData& bitmap, Dali::Toolkit::AtlasManager::AtlasSlot& slot ); @@ -85,6 +87,7 @@ public: */ bool IsCached( Text::FontId fontId, Text::GlyphIndex index, + uint32_t outlineWidth, Dali::Toolkit::AtlasManager::AtlasSlot& slot ); /** @@ -105,7 +108,7 @@ public: /** * @copydoc toolkit::AtlasGlyphManager::AdjustReferenceCount */ - void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta ); + void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta ); /** * @copydoc Toolkit::AtlasGlyphManager::GetTextures diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp index 743bc6c..bd6850d 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp @@ -69,10 +69,11 @@ AtlasGlyphManager::AtlasGlyphManager(Internal::AtlasGlyphManager *impl) } void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph, + const uint32_t outlineWidth, const PixelData& bitmap, AtlasManager::AtlasSlot& slot ) { - GetImplementation(*this).Add( glyph, bitmap, slot ); + GetImplementation(*this).Add( glyph, outlineWidth, bitmap, slot ); } void AtlasGlyphManager::GenerateMeshData( uint32_t imageId, @@ -86,9 +87,10 @@ void AtlasGlyphManager::GenerateMeshData( uint32_t imageId, bool AtlasGlyphManager::IsCached( Text::FontId fontId, Text::GlyphIndex index, + uint32_t outlineWidth, AtlasManager::AtlasSlot& slot ) { - return GetImplementation(*this).IsCached( fontId, index, slot ); + return GetImplementation(*this).IsCached( fontId, index, outlineWidth, slot ); } void AtlasGlyphManager::SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight ) @@ -116,9 +118,9 @@ const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics() return GetImplementation(*this).GetMetrics(); } -void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta ) +void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta ) { - GetImplementation(*this).AdjustReferenceCount( fontId, index, delta ); + GetImplementation(*this).AdjustReferenceCount( fontId, index, outlineWidth, delta ); } } // namespace Toolkit diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h index 1bc058b..c41415e 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h @@ -80,10 +80,12 @@ public: * @brief Ask Atlas Manager to add a glyph * * @param[in] glyph glyph to add to an atlas + * @param[in] outlineWidth the outline width of the glyph * @param[in] bitmap bitmap to use for glyph addition * @param[out] slot information returned by atlas manager for addition */ void Add( const Text::GlyphInfo& glyph, + const uint32_t outlineWidth, const PixelData& bitmap, AtlasManager::AtlasSlot& slot ); @@ -103,12 +105,14 @@ public: * * @param[in] fontId The font that this glyph comes from * @param[in] index The GlyphIndex of this glyph + * @param[in] outlineWidth The outline width of this glyph * @param[out] slot container holding information about the glyph( mImage = 0 indicates not being cached ) * * @return Whether glyph is cached or not ? */ bool IsCached( Text::FontId fontId, Text::GlyphIndex index, + uint32_t outlineWidth, AtlasManager::AtlasSlot& slot ); /** @@ -160,9 +164,10 @@ public: * * @param[in] fontId The font this image came from * @param[in] index The index of the glyph + * @param[in] outlineWidth The outline width of the glyph * @param[in] delta The adjustment to make to the reference count */ - void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta ); + void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta ); private: diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index 62865d6..03d02f5 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -94,7 +94,7 @@ const float HALF( 0.5f ); const float ONE( 1.0f ); const uint32_t DEFAULT_ATLAS_WIDTH = 512u; const uint32_t DEFAULT_ATLAS_HEIGHT = 512u; -const int NO_OUTLINE( 0 ); +const uint32_t NO_OUTLINE = 0; } struct AtlasRenderer::Impl @@ -172,12 +172,14 @@ struct AtlasRenderer::Impl TextCacheEntry() : mFontId( 0 ), mIndex( 0 ), + mOutlineWidth( 0 ), mImageId( 0 ) { } FontId mFontId; Text::GlyphIndex mIndex; + uint32_t mOutlineWidth; uint32_t mImageId; }; @@ -211,6 +213,207 @@ struct AtlasRenderer::Impl return false; } + void CacheGlyph( const GlyphInfo& glyph, FontId lastFontId, uint32_t outline, AtlasManager::AtlasSlot& slot ) + { + const bool glyphNotCached = !mGlyphManager.IsCached( glyph.fontId, glyph.index, outline, slot ); // Check FontGlyphRecord vector for entry with glyph index and fontId + + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "AddGlyphs fontID[%u] glyphIndex[%u] [%s]\n", glyph.fontId, glyph.index, (glyphNotCached)?"not cached":"cached" ); + + if( glyphNotCached ) + { + MaxBlockSize& blockSize = mBlockSizes[0u]; + + if ( lastFontId != glyph.fontId ) + { + uint32_t index = 0u; + // Looks through all stored block sizes until finds the one which mataches required glyph font it. Ensures new atlas block size will match existing for same font id. + // CalculateBlocksSize() above ensures a block size entry exists. + for( std::vector::const_iterator it = mBlockSizes.begin(), + endIt = mBlockSizes.end(); + it != endIt; + ++it, ++index ) + { + const MaxBlockSize& blockSizeEntry = *it; + if( blockSizeEntry.mFontId == glyph.fontId ) + { + blockSize = mBlockSizes[index]; + } + } + } + + // Create a new image for the glyph + PixelData bitmap; + + // Whether the glyph is an outline. + const bool isOutline = 0u != outline; + + // Whether the current glyph is a color one. + const bool isColorGlyph = mFontClient.IsColorGlyph( glyph.fontId, glyph.index ); + + if( !isOutline || ( isOutline && !isColorGlyph) ) + { + // Retrieve the emoji's bitmap. + TextAbstraction::FontClient::GlyphBufferData glyphBufferData; + glyphBufferData.width = isColorGlyph ? glyph.width : 0; // Desired width and height. + glyphBufferData.height = isColorGlyph ? glyph.height : 0; + + mFontClient.CreateBitmap( glyph.fontId, + glyph.index, + glyphBufferData, + outline ); + + // Create the pixel data. + bitmap = PixelData::New( glyphBufferData.buffer, + glyphBufferData.width * glyphBufferData.height * GetBytesPerPixel( glyphBufferData.format ), + glyphBufferData.width, + glyphBufferData.height, + glyphBufferData.format, + PixelData::DELETE_ARRAY ); + + if( bitmap ) + { + // Ensure that the next image will fit into the current block size + if( bitmap.GetWidth() > blockSize.mNeededBlockWidth ) + { + blockSize.mNeededBlockWidth = bitmap.GetWidth(); + } + + if( bitmap.GetHeight() > blockSize.mNeededBlockHeight ) + { + blockSize.mNeededBlockHeight = bitmap.GetHeight(); + } + + // If CheckAtlas in AtlasManager::Add can't fit the bitmap in the current atlas it will create a new atlas + + // Setting the block size and size of new atlas does not mean a new one will be created. An existing atlas may still surffice. + mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, + DEFAULT_ATLAS_HEIGHT, + blockSize.mNeededBlockWidth, + blockSize.mNeededBlockHeight ); + + // Locate a new slot for our glyph + mGlyphManager.Add( glyph, outline, bitmap, slot ); // slot will be 0 is glyph not added + } + } + } + else + { + // We have 2+ copies of the same glyph + mGlyphManager.AdjustReferenceCount( glyph.fontId, glyph.index, outline, 1 ); //increment + } + } + + void GenerateMesh( const GlyphInfo& glyph, + const Vector2& position, + const Vector4& color, + uint32_t outline, + AtlasManager::AtlasSlot& slot, + bool underlineGlyph, + float currentUnderlinePosition, + float currentUnderlineThickness, + std::vector& meshContainer, + Vector& newTextCache, + Vector& extents ) + { + // Generate mesh data for this quad, plugging in our supplied position + AtlasManager::Mesh2D newMesh; + mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh ); + + TextCacheEntry textCacheEntry; + textCacheEntry.mFontId = glyph.fontId; + textCacheEntry.mImageId = slot.mImageId; + textCacheEntry.mIndex = glyph.index; + textCacheEntry.mOutlineWidth = outline; + + newTextCache.PushBack( textCacheEntry ); + + AtlasManager::Vertex2D* verticesBuffer = newMesh.mVertices.Begin(); + + for( unsigned int index = 0u, size = newMesh.mVertices.Count(); + index < size; + ++index ) + { + AtlasManager::Vertex2D& vertex = *( verticesBuffer + index ); + + // Set the color of the vertex. + vertex.mColor = color; + } + + // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas) + StitchTextMesh( meshContainer, + newMesh, + extents, + position.y + glyph.yBearing, + underlineGlyph, + currentUnderlinePosition, + currentUnderlineThickness, + slot ); + } + + void CreateActors( const std::vector& meshContainer, + const Size& textSize, + const Vector4& color, + const Vector4& shadowColor, + const Vector2& shadowOffset, + Actor textControl, + Property::Index animatablePropertyIndex, + bool drawShadow ) + { + if( !mActor ) + { + // Create a container actor to act as a common parent for text and shadow, to avoid color inheritence issues. + mActor = Actor::New(); + mActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mActor.SetSize( textSize ); + mActor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + } + + for( std::vector< MeshRecord >::const_iterator it = meshContainer.begin(), + endIt = meshContainer.end(); + it != endIt; ++it ) + { + const MeshRecord& meshRecord = *it; + + Actor actor = CreateMeshActor( textControl, animatablePropertyIndex, color, meshRecord, textSize, STYLE_NORMAL ); + + // Whether the actor has renderers. + const bool hasRenderer = actor.GetRendererCount() > 0u; + + // Create an effect if necessary + if( hasRenderer && + drawShadow ) + { + // Change the color of the vertices. + for( Vector::Iterator vIt = meshRecord.mMesh.mVertices.Begin(), + vEndIt = meshRecord.mMesh.mVertices.End(); + vIt != vEndIt; + ++vIt ) + { + AtlasManager::Vertex2D& vertex = *vIt; + + vertex.mColor = shadowColor; + } + + Actor shadowActor = CreateMeshActor(textControl, animatablePropertyIndex, color, meshRecord, textSize, STYLE_DROP_SHADOW ); +#if defined(DEBUG_ENABLED) + shadowActor.SetName( "Text Shadow renderable actor" ); +#endif + // Offset shadow in x and y + shadowActor.RegisterProperty("uOffset", shadowOffset ); + Dali::Renderer renderer( shadowActor.GetRendererAt( 0 ) ); + int depthIndex = renderer.GetProperty(Dali::Renderer::Property::DEPTH_INDEX); + renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex - 1 ); + mActor.Add( shadowActor ); + } + + if( hasRenderer ) + { + mActor.Add( actor ); + } + } + } + void AddGlyphs( Text::ViewInterface& view, Actor textControl, Property::Index animatablePropertyIndex, @@ -223,18 +426,28 @@ struct AtlasRenderer::Impl float minLineOffset ) { AtlasManager::AtlasSlot slot; + slot.mImageId = 0u; + slot.mAtlasId = 0u; + + AtlasManager::AtlasSlot slotOutline; + slotOutline.mImageId = 0u; + slotOutline.mAtlasId = 0u; + std::vector< MeshRecord > meshContainer; + std::vector< MeshRecord > meshContainerOutline; Vector< Extent > extents; - TextCacheEntry textCacheEntry; mDepth = depth; const Vector2& textSize( view.GetLayoutSize() ); const Vector2 halfTextSize( textSize * 0.5f ); const Vector2& shadowOffset( view.GetShadowOffset() ); const Vector4& shadowColor( view.GetShadowColor() ); - const bool underlineEnabled( view.IsUnderlineEnabled() ); + const bool underlineEnabled = view.IsUnderlineEnabled(); const Vector4& underlineColor( view.GetUnderlineColor() ); - const float underlineHeight( view.GetUnderlineHeight() ); + const float underlineHeight = view.GetUnderlineHeight(); + const unsigned int outlineWidth = view.GetOutlineWidth(); + const Vector4& outlineColor( view.GetOutlineColor() ); + const bool isOutline = 0u != outlineWidth; const bool useDefaultColor = ( NULL == colorsBuffer ); @@ -250,7 +463,6 @@ struct AtlasRenderer::Impl float currentUnderlinePosition = ZERO; float currentUnderlineThickness = underlineHeight; - uint32_t currentBlockSize = 0; FontId lastFontId = 0; FontId lastUnderlinedFontId = 0; Style style = STYLE_NORMAL; @@ -271,14 +483,14 @@ struct AtlasRenderer::Impl for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i ) { const GlyphInfo& glyph = *( glyphsBuffer + i ); - const bool underlineGlyph = underlineEnabled || IsGlyphUnderlined( i, underlineRuns ); - thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph; + const bool isGlyphUnderlined = underlineEnabled || IsGlyphUnderlined( i, underlineRuns ); + thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || isGlyphUnderlined; // No operation for white space if( glyph.width && glyph.height ) { // Are we still using the same fontId as previous - if( underlineGlyph && ( glyph.fontId != lastUnderlinedFontId ) ) + if( isGlyphUnderlined && ( glyph.fontId != lastUnderlinedFontId ) ) { // We need to fetch fresh font underline metrics FontMetrics fontMetrics; @@ -316,85 +528,13 @@ struct AtlasRenderer::Impl lastUnderlinedFontId = glyph.fontId; } // underline - bool glyphNotCached = !mGlyphManager.IsCached( glyph.fontId, glyph.index, slot ); // Check FontGlyphRecord vector for entry with glyph index and fontId - - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "AddGlyphs fontID[%u] glyphIndex[%u] [%s]\n", glyph.fontId, glyph.index, (glyphNotCached)?"not cached":"cached" ); + // Retrieves and caches the glyph's bitmap. + CacheGlyph( glyph, lastFontId, NO_OUTLINE, slot ); - if( glyphNotCached ) + // Retrieves and caches the outline glyph's bitmap. + if( isOutline ) { - MaxBlockSize& blockSize = mBlockSizes[currentBlockSize]; - - if ( lastFontId != glyph.fontId ) - { - uint32_t index = 0u; - // Looks through all stored block sizes until finds the one which mataches required glyph font it. Ensures new atlas block size will match existing for same font id. - // CalculateBlocksSize() above ensures a block size entry exists. - for( std::vector::const_iterator it = mBlockSizes.begin(), - endIt = mBlockSizes.end(); - it != endIt; - ++it, ++index ) - { - const MaxBlockSize& blockSizeEntry = *it; - if( blockSizeEntry.mFontId == glyph.fontId ) - { - blockSize = mBlockSizes[index]; - } - } - } - - // Create a new image for the glyph - PixelData bitmap; - - // Whether the current glyph is a color one. - const bool isColorGlyph = mFontClient.IsColorGlyph( glyph.fontId, glyph.index ); - - // Retrieve the emoji's bitmap. - TextAbstraction::FontClient::GlyphBufferData glyphBufferData; - glyphBufferData.width = isColorGlyph ? glyph.width : 0; // Desired width and height. - glyphBufferData.height = isColorGlyph ? glyph.height : 0; - - mFontClient.CreateBitmap( glyph.fontId, - glyph.index, - glyphBufferData, - NO_OUTLINE ); - - // Create the pixel data. - bitmap = PixelData::New( glyphBufferData.buffer, - glyph.width * glyph.height * GetBytesPerPixel( glyphBufferData.format ), - glyph.width, - glyph.height, - glyphBufferData.format, - PixelData::DELETE_ARRAY ); - - if( bitmap ) - { - // Ensure that the next image will fit into the current block size - if( bitmap.GetWidth() > blockSize.mNeededBlockWidth ) - { - blockSize.mNeededBlockWidth = bitmap.GetWidth(); - } - - if( bitmap.GetHeight() > blockSize.mNeededBlockHeight ) - { - blockSize.mNeededBlockHeight = bitmap.GetHeight(); - } - - // If CheckAtlas in AtlasManager::Add can't fit the bitmap in the current atlas it will create a new atlas - - // Setting the block size and size of new atlas does not mean a new one will be created. An existing atlas may still surffice. - mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, - DEFAULT_ATLAS_HEIGHT, - blockSize.mNeededBlockWidth, - blockSize.mNeededBlockHeight ); - - // Locate a new slot for our glyph - mGlyphManager.Add( glyph, bitmap, slot ); // slot will be 0 is glyph not added - } - } - else - { - // We have 2+ copies of the same glyph - mGlyphManager.AdjustReferenceCount( glyph.fontId, glyph.index, 1/*increment*/ ); + CacheGlyph( glyph, lastFontId, outlineWidth, slotOutline ); } // Move the origin (0,0) of the mesh to the center of the actor @@ -402,42 +542,47 @@ struct AtlasRenderer::Impl if ( 0u != slot.mImageId ) // invalid slot id, glyph has failed to be added to atlas { - // Generate mesh data for this quad, plugging in our supplied position - AtlasManager::Mesh2D newMesh; - mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh ); - textCacheEntry.mFontId = glyph.fontId; - textCacheEntry.mImageId = slot.mImageId; - textCacheEntry.mIndex = glyph.index; - newTextCache.PushBack( textCacheEntry ); - - AtlasManager::Vertex2D* verticesBuffer = newMesh.mVertices.Begin(); + Vector2 positionPlusOutlineOffset = position; + if( isOutline ) + { + // Add an offset to the text. + const float outlineWidthOffset = static_cast( outlineWidth ); + positionPlusOutlineOffset += Vector2( outlineWidthOffset, outlineWidthOffset ); + } // Get the color of the character. const ColorIndex colorIndex = useDefaultColor ? 0u : *( colorIndicesBuffer + i ); const Vector4& color = ( useDefaultColor || ( 0u == colorIndex ) ) ? defaultColor : *( colorsBuffer + colorIndex - 1u ); - for( unsigned int index = 0u, size = newMesh.mVertices.Count(); - index < size; - ++index ) - { - AtlasManager::Vertex2D& vertex = *( verticesBuffer + index ); - - // Set the color of the vertex. - vertex.mColor = color; - } - - // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas) - StitchTextMesh( meshContainer, - newMesh, - extents, - position.y + glyph.yBearing, - underlineGlyph, - currentUnderlinePosition, - currentUnderlineThickness, - slot ); + GenerateMesh( glyph, + positionPlusOutlineOffset, + color, + NO_OUTLINE, + slot, + isGlyphUnderlined, + currentUnderlinePosition, + currentUnderlineThickness, + meshContainer, + newTextCache, + extents); lastFontId = glyph.fontId; // Prevents searching for existing blocksizes when string of the same fontId. } + + if( isOutline && ( 0u != slotOutline.mImageId ) ) // invalid slot id, glyph has failed to be added to atlas + { + GenerateMesh( glyph, + position, + outlineColor, + outlineWidth, + slotOutline, + false, + currentUnderlinePosition, + currentUnderlineThickness, + meshContainerOutline, + newTextCache, + extents); + } } } // glyphs @@ -452,62 +597,36 @@ struct AtlasRenderer::Impl } // For each MeshData object, create a mesh actor and add to the renderable actor - if( !meshContainer.empty() ) + bool isShadowDrawn = false; + if( !meshContainerOutline.empty() ) { - if( !mActor ) - { - // Create a container actor to act as a common parent for text and shadow, to avoid color inheritence issues. - mActor = Actor::New(); - mActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - mActor.SetSize( textSize ); - mActor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); - } - - for( std::vector< MeshRecord >::iterator it = meshContainer.begin(), - endIt = meshContainer.end(); - it != endIt; ++it ) - { - MeshRecord& meshRecord = *it; - - Actor actor = CreateMeshActor( textControl, animatablePropertyIndex, defaultColor, meshRecord, textSize, STYLE_NORMAL ); - - // Whether the actor has renderers. - const bool hasRenderer = actor.GetRendererCount() > 0u; - - // Create an effect if necessary - if( hasRenderer && - ( style == STYLE_DROP_SHADOW ) ) - { - // Change the color of the vertices. - for( Vector::Iterator vIt = meshRecord.mMesh.mVertices.Begin(), - vEndIt = meshRecord.mMesh.mVertices.End(); - vIt != vEndIt; - ++vIt ) - { - AtlasManager::Vertex2D& vertex = *vIt; - - vertex.mColor = shadowColor; - } - - Actor shadowActor = CreateMeshActor(textControl, animatablePropertyIndex, defaultColor, meshRecord, textSize, STYLE_DROP_SHADOW ); -#if defined(DEBUG_ENABLED) - shadowActor.SetName( "Text Shadow renderable actor" ); -#endif - // Offset shadow in x and y - shadowActor.RegisterProperty("uOffset", shadowOffset ); - Dali::Renderer renderer( shadowActor.GetRendererAt( 0 ) ); - int depthIndex = renderer.GetProperty(Dali::Renderer::Property::DEPTH_INDEX); - renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex - 1 ); - mActor.Add( shadowActor ); - } + const bool drawShadow = STYLE_DROP_SHADOW == style; + CreateActors( meshContainerOutline, + textSize, + outlineColor, + shadowColor, + shadowOffset, + textControl, + animatablePropertyIndex, + drawShadow ); + + isShadowDrawn = drawShadow; + } - if( hasRenderer ) - { - mActor.Add( actor ); - } - } + // For each MeshData object, create a mesh actor and add to the renderable actor + if( !meshContainer.empty() ) + { + const bool drawShadow = !isShadowDrawn && ( STYLE_DROP_SHADOW == style ); + CreateActors( meshContainer, + textSize, + defaultColor, + shadowColor, + shadowOffset, + textControl, + animatablePropertyIndex, + drawShadow ); } + #if defined(DEBUG_ENABLED) Toolkit::AtlasGlyphManager::Metrics metrics = mGlyphManager.GetMetrics(); DALI_LOG_INFO( gLogFilter, Debug::General, "TextAtlasRenderer::GlyphManager::GlyphCount: %i, AtlasCount: %i, TextureMemoryUse: %iK\n", @@ -536,7 +655,7 @@ struct AtlasRenderer::Impl { for( Vector< TextCacheEntry >::Iterator oldTextIter = mTextCache.Begin(); oldTextIter != mTextCache.End(); ++oldTextIter ) { - mGlyphManager.AdjustReferenceCount( oldTextIter->mFontId, oldTextIter->mIndex, -1/*decrement*/ ); + mGlyphManager.AdjustReferenceCount( oldTextIter->mFontId, oldTextIter->mIndex, oldTextIter->mOutlineWidth, -1/*decrement*/ ); } mTextCache.Resize( 0 ); } @@ -611,6 +730,7 @@ struct AtlasRenderer::Impl actor.SetSize( actorSize ); actor.RegisterProperty("uOffset", Vector2::ZERO ); actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + return actor; } diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 874503d..e2b482f 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -888,7 +888,7 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired ) TextAbstraction::FontDescription defaultFontDescription; TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE; - if( IsShowingPlaceholderText() && ( NULL != mEventData->mPlaceholderFont ) ) + if( IsShowingPlaceholderText() && mEventData && ( NULL != mEventData->mPlaceholderFont ) ) { // If the placeholder font is set specifically, only placeholder font is changed. defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription; @@ -1144,7 +1144,7 @@ float Controller::Impl::GetDefaultFontLineHeight() void Controller::Impl::OnCursorKeyEvent( const Event& event ) { - if( NULL == mEventData ) + if( NULL == mEventData || !IsShowingRealText() ) { // Nothing to do if there is no text input. return; @@ -2291,7 +2291,7 @@ void Controller::Impl::RepositionSelectionHandles() const SelectionBoxInfo& firstSelectionBoxLineInfo = *( selectionBoxLinesInfo.Begin() ); highLightPosition.y = firstSelectionBoxLineInfo.lineOffset; - mEventData->mDecorator->SetHighLightBox( highLightPosition, highLightSize ); + mEventData->mDecorator->SetHighLightBox( highLightPosition, highLightSize, static_cast( mModel->GetOutlineWidth() ) ); if( !mEventData->mDecorator->IsSmoothHandlePanEnabled() ) { @@ -2711,6 +2711,13 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical, Text::GetCursorPosition( parameters, cursorInfo ); + // Adds Outline offset. + const float outlineWidth = static_cast( mModel->GetOutlineWidth() ); + cursorInfo.primaryPosition.x += outlineWidth; + cursorInfo.primaryPosition.y += outlineWidth; + cursorInfo.secondaryPosition.x += outlineWidth; + cursorInfo.secondaryPosition.y += outlineWidth; + if( isMultiLine ) { // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control. diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index d054cbc..7a31d72 100755 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -1182,14 +1182,14 @@ const Vector4& Controller::GetOutlineColor() const return mImpl->mModel->mVisualModel->GetOutlineColor(); } -void Controller::SetOutlineWidth( float width ) +void Controller::SetOutlineWidth( unsigned int width ) { mImpl->mModel->mVisualModel->SetOutlineWidth( width ); mImpl->RequestRelayout(); } -float Controller::GetOutlineWidth() const +unsigned int Controller::GetOutlineWidth() const { return mImpl->mModel->mVisualModel->GetOutlineWidth(); } @@ -2105,8 +2105,15 @@ void Controller::GetPlaceholderProperty( Property::Map& map ) Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection() { - const LineRun* const firstline = mImpl->mModel->mVisualModel->mLines.Begin(); - if ( firstline && firstline->direction ) + if( ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) ) + { + return Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT; + } + + const Character character = mImpl->mModel->mLogicalModel->mText[0]; + Script script = TextAbstraction::GetCharacterScript( character ); + + if( TextAbstraction::IsRightToLeftScript( script ) ) { return Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT; } @@ -2737,7 +2744,17 @@ ImfManager::ImfCallbackData Controller::OnImfEvent( ImfManager& imfManager, cons if( retrieveText ) { - mImpl->GetText( numberOfWhiteSpaces, text ); + if( !mImpl->IsShowingPlaceholderText() ) + { + // Retrieves the normal text string. + mImpl->GetText( numberOfWhiteSpaces, text ); + } + else + { + // When the current text is Placeholder Text, the surrounding text should be empty string. + // It means DALi should send empty string ("") to IME. + text = ""; + } } ImfManager::ImfCallbackData callbackData( ( retrieveText || retrieveCursor ), cursorPosition, text, false ); @@ -3370,7 +3387,7 @@ bool Controller::DoRelayout( const Size& size, const Vector& glyphsToCharactersMap = mImpl->mModel->mVisualModel->mGlyphsToCharacters; const Vector& charactersPerGlyph = mImpl->mModel->mVisualModel->mCharactersPerGlyph; const Character* const textBuffer = mImpl->mModel->mLogicalModel->mText.Begin(); - float outlineWidth = mImpl->mModel->GetOutlineWidth(); + const float outlineWidth = static_cast( mImpl->mModel->GetOutlineWidth() ); // Set the layout parameters. Layout::Parameters layoutParameters( size, @@ -3697,7 +3714,7 @@ bool Controller::DeleteEvent( int keyCode ) 1, UPDATE_INPUT_STYLE ); } - else if( ( mImpl->mEventData->mPrimaryCursorPosition >= 0 ) && ( keyCode == Dali::DevelKey::DALI_KEY_DELETE ) ) + else if( keyCode == Dali::DevelKey::DALI_KEY_DELETE ) { // Remove the character after the current cursor position removed = RemoveText( 0, diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 07d91be..88831db 100755 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -834,14 +834,14 @@ public: // Default style & Input style * * @param[in] width The width in pixels of the outline, 0 indicates no outline */ - void SetOutlineWidth( float width ); + void SetOutlineWidth( unsigned int width ); /** * @brief Retrieves the width of an outline * * @return The width of the outline. */ - float GetOutlineWidth() const; + unsigned int GetOutlineWidth() const; /** * @brief Sets the emboss's properties string. diff --git a/dali-toolkit/internal/text/text-effects-style.cpp b/dali-toolkit/internal/text/text-effects-style.cpp index 7c08ebe..d8d35de 100755 --- a/dali-toolkit/internal/text/text-effects-style.cpp +++ b/dali-toolkit/internal/text/text-effects-style.cpp @@ -125,26 +125,45 @@ bool ParseUnderlineProperties( const Property::Map& underlinePropertiesMap, if( ENABLE_KEY == valueGet.first.stringKey ) { /// Enable key. - const std::string enableStr = valueGet.second.Get(); - enabled = Text::TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() ); + if( valueGet.second.GetType() == Dali::Property::STRING ) + { + const std::string enableStr = valueGet.second.Get(); + enabled = Text::TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() ); + } + else + { + enabled = valueGet.second.Get(); + } } else if( COLOR_KEY == valueGet.first.stringKey ) { /// Color key. colorDefined = true; - const std::string colorStr = valueGet.second.Get(); - - Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); + if( valueGet.second.GetType() == Dali::Property::STRING ) + { + const std::string colorStr = valueGet.second.Get(); + Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); + } + else + { + color = valueGet.second.Get(); + } } else if( HEIGHT_KEY == valueGet.first.stringKey ) { /// Height key. heightDefined = true; - const std::string heightStr = valueGet.second.Get(); - - height = StringToFloat( heightStr.c_str() ); + if( valueGet.second.GetType() == Dali::Property::STRING ) + { + const std::string heightStr = valueGet.second.Get(); + height = StringToFloat( heightStr.c_str() ); + } + else + { + height = valueGet.second.Get(); + } } } @@ -155,7 +174,7 @@ bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap, bool& colorDefined, Vector4& color, bool& widthDefined, - float& width ) + unsigned int& width ) { const unsigned int numberOfItems = underlinePropertiesMap.Count(); @@ -174,7 +193,7 @@ bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap, { /// Width key. widthDefined = true; - width = valueGet.second.Get(); + width = static_cast( valueGet.second.Get() ); } } @@ -218,7 +237,7 @@ bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& va heightDefined, height ); - controller->UnderlineSetByString( !empty); + controller->UnderlineSetByString( !empty ); } } else @@ -546,7 +565,7 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu bool colorDefined = false; Vector4 color; bool widthDefined = false; - float width = 0.f; + unsigned int width = 0u; bool empty = true; @@ -581,7 +600,7 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu update = true; } - if( widthDefined && ( fabsf( controller->GetOutlineWidth() - width ) > Math::MACHINE_EPSILON_1000 ) ) + if( widthDefined && ( controller->GetOutlineWidth() != width ) ) { controller->SetOutlineWidth( width ); update = true; @@ -590,9 +609,9 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu else { // Disable outline - if( fabsf( controller->GetOutlineWidth() ) > Math::MACHINE_EPSILON_1000 ) + if( 0u != controller->GetOutlineWidth() ) { - controller->SetOutlineWidth( 0.0f ); + controller->SetOutlineWidth( 0u ); update = true; } } @@ -627,17 +646,11 @@ void GetOutlineProperties( ControllerPtr controller, Property::Value& value, Eff else { const Vector4& color = controller->GetOutlineColor(); - const float width = controller->GetOutlineWidth(); + const unsigned int width = controller->GetOutlineWidth(); Property::Map map; - - std::string colorStr; - Vector4ToColorString( color, colorStr ); - map.Insert( COLOR_KEY, colorStr ); - - std::string widthStr; - FloatToString( width, widthStr ); - map.Insert( WIDTH_KEY, widthStr ); + map.Insert( COLOR_KEY, color ); + map.Insert( WIDTH_KEY, static_cast( width ) ); value = map; diff --git a/dali-toolkit/internal/text/text-effects-style.h b/dali-toolkit/internal/text/text-effects-style.h index 521f52c..e2b0f0c 100755 --- a/dali-toolkit/internal/text/text-effects-style.h +++ b/dali-toolkit/internal/text/text-effects-style.h @@ -84,7 +84,7 @@ bool ParseOutlineProperties( const Property::Map& outlineProperties, bool& colorDefined, Vector4& color, bool& widthDefined, - float& width ); + unsigned int& width ); /** * @brief Sets the underline properties. diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index efa88ad..96f9005 100644 --- a/dali-toolkit/internal/text/text-view-interface.h +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -172,6 +172,21 @@ public: virtual void GetUnderlineRuns( GlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns ) const = 0; + + /** + * @brief Retrieve the outline color. + * + * @return The outline color. + */ + virtual const Vector4& GetOutlineColor() const = 0; + + /** + * @brief Retrieves the width of an outline + * + * @return The width of the outline. + */ + virtual unsigned int GetOutlineWidth() const = 0; + }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index 9e8d0be..62c0008 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -402,6 +402,24 @@ void View::GetUnderlineRuns( GlyphRun* underlineRuns, } } +const Vector4& View::GetOutlineColor() const +{ + if( mImpl->mVisualModel ) + { + return mImpl->mVisualModel->GetOutlineColor(); + } + return Vector4::ZERO; +} + +unsigned int View::GetOutlineWidth() const +{ + if( mImpl->mVisualModel ) + { + return mImpl->mVisualModel->GetOutlineWidth(); + } + return 0u; +} + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index d494d2b..51426de 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -131,6 +131,16 @@ public: UnderlineRunIndex index, Length numberOfRuns ) const; + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineColor() + */ + virtual const Vector4& GetOutlineColor() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineWidth() + */ + virtual unsigned int GetOutlineWidth() const; + private: // Undefined diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index 9caa523..5373a6a 100755 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -370,7 +370,7 @@ void VisualModel::SetUnderlineHeight( float height ) mUnderlineHeight = height; } -void VisualModel::SetOutlineWidth( float width ) +void VisualModel::SetOutlineWidth( unsigned int width ) { mOutlineWidth = width; } @@ -415,7 +415,7 @@ float VisualModel::GetUnderlineHeight() const return mUnderlineHeight; } -float VisualModel::GetOutlineWidth() const +unsigned int VisualModel::GetOutlineWidth() const { return mOutlineWidth; } @@ -449,7 +449,7 @@ VisualModel::VisualModel() mControlSize(), mShadowOffset(), mUnderlineHeight( 0.0f ), - mOutlineWidth( 0.0f ), + mOutlineWidth( 0u ), mShadowBlurRadius( 0.0f ), mNaturalSize(), mLayoutSize(), diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index 28d2269..24be0c7 100755 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -320,14 +320,14 @@ public: * * @param[in] width The width in pixels of the outline, 0 indicates no outline */ - void SetOutlineWidth( float width ); + void SetOutlineWidth( unsigned int width ); /** * @brief Retrieves the width of an outline * * @return The width of the outline. */ - float GetOutlineWidth() const; + unsigned int GetOutlineWidth() const; protected: @@ -369,7 +369,7 @@ public: Size mControlSize; ///< The size of the UI control. Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow float mUnderlineHeight; ///< Fixed height for underline to override font metrics. - float mOutlineWidth; ///< Width of outline. + unsigned int mOutlineWidth; ///< Width of outline. float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur. private: diff --git a/dali-toolkit/internal/visuals/npatch-loader.cpp b/dali-toolkit/internal/visuals/npatch-loader.cpp index f23f1ca..8bc050f 100644 --- a/dali-toolkit/internal/visuals/npatch-loader.cpp +++ b/dali-toolkit/internal/visuals/npatch-loader.cpp @@ -79,10 +79,10 @@ std::size_t NPatchLoader::Load( const std::string& url, const Rect< int >& borde data->textureSet = mCache[ cachedIndex ]->textureSet; NinePatchImage::StretchRanges stretchRangesX; - stretchRangesX.PushBack( Uint16Pair( border.left, data->croppedWidth - border.right ) ); + stretchRangesX.PushBack( Uint16Pair( border.left, ( (data->croppedWidth >= static_cast< unsigned int >( border.right )) ? data->croppedWidth - border.right : 0 ) ) ); NinePatchImage::StretchRanges stretchRangesY; - stretchRangesY.PushBack( Uint16Pair( border.top, data->croppedHeight - border.bottom ) ); + stretchRangesY.PushBack( Uint16Pair( border.top, ( (data->croppedHeight >= static_cast< unsigned int >( border.bottom )) ? data->croppedHeight - border.bottom : 0 ) ) ); data->stretchPixelsX = stretchRangesX; data->stretchPixelsY = stretchRangesY; @@ -137,10 +137,10 @@ std::size_t NPatchLoader::Load( const std::string& url, const Rect< int >& borde data->textureSet.SetTexture( 0u, texture ); NinePatchImage::StretchRanges stretchRangesX; - stretchRangesX.PushBack( Uint16Pair( border.left, data->croppedWidth - border.right ) ); + stretchRangesX.PushBack( Uint16Pair( border.left, ( (data->croppedWidth >= static_cast< unsigned int >( border.right )) ? data->croppedWidth - border.right : 0 ) ) ); NinePatchImage::StretchRanges stretchRangesY; - stretchRangesY.PushBack( Uint16Pair( border.top, data->croppedHeight - border.bottom ) ); + stretchRangesY.PushBack( Uint16Pair( border.top, ( (data->croppedHeight >= static_cast< unsigned int >( border.bottom )) ? data->croppedHeight - border.bottom : 0 ) ) ); data->stretchPixelsX = stretchRangesX; data->stretchPixelsY = stretchRangesY; diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp index 33a4842..f61848c 100755 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp @@ -56,6 +56,7 @@ const char * const AUXILIARY_IMAGE_ALPHA_NAME( "auxiliaryImageAlpha" ); const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n varying mediump vec2 vTexCoord;\n + varying mediump vec2 vMaskTexCoord;\n uniform mediump mat4 uMvpMatrix;\n uniform mediump vec3 uSize;\n uniform mediump vec2 uNinePatchFactorsX[ FACTOR_SIZE_X ];\n @@ -83,7 +84,7 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( mediump vec4 gridPosition = vec4( fixedFactor + ( visualSize.xy - fixedTotal ) * stretch / stretchTotal, 0.0, 1.0 );\n mediump vec4 vertexPosition = gridPosition;\n vertexPosition.xy -= visualSize.xy * vec2( 0.5, 0.5 );\n - vertexPostion.xy += anchorPoint*visualSize + (visualOffset + origin)*uSize.xy;\n + vertexPosition.xy += anchorPoint*visualSize + (visualOffset + origin)*uSize.xy;\n vertexPosition = uMvpMatrix * vertexPosition;\n \n vTexCoord = ( fixedFactor + stretch ) / ( fixedTotal + stretchTotal );\n @@ -569,8 +570,8 @@ void NPatchVisual::ApplyTextureAndUniforms() Uint16Pair stretchX = data->stretchPixelsX[ 0 ]; Uint16Pair stretchY = data->stretchPixelsY[ 0 ]; - uint16_t stretchWidth = stretchX.GetY() - stretchX.GetX(); - uint16_t stretchHeight = stretchY.GetY() - stretchY.GetX(); + uint16_t stretchWidth = ( stretchX.GetY() >= stretchX.GetX() ) ? stretchX.GetY() - stretchX.GetX() : 0; + uint16_t stretchHeight = ( stretchY.GetY() >= stretchY.GetX() ) ? stretchY.GetY() - stretchY.GetX() : 0; mImpl->mRenderer.RegisterProperty( "uFixed[0]", Vector2::ZERO ); mImpl->mRenderer.RegisterProperty( "uFixed[1]", Vector2( stretchX.GetX(), stretchY.GetX()) ); diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index f5817ea..e44b005 100755 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -24,6 +24,7 @@ // INTERNAL HEADER #include +#include #include #include #include @@ -58,6 +59,7 @@ const char * const TEXT_COLOR_PROPERTY( "textColor" ); const char * const ENABLE_MARKUP_PROPERTY( "enableMarkup" ); const char * const SHADOW_PROPERTY( "shadow" ); const char * const UNDERLINE_PROPERTY( "underline" ); +const char * const OUTLINE_PROPERTY( "outline" ); const Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f ); @@ -328,6 +330,10 @@ Dali::Property::Index StringKeyToIndexKey( const std::string& stringKey ) { result = Toolkit::TextVisual::Property::UNDERLINE; } + else if( stringKey == OUTLINE_PROPERTY ) + { + result = Toolkit::DevelTextVisual::Property::OUTLINE; + } return result; } @@ -405,6 +411,9 @@ void TextVisual::DoCreatePropertyMap( Property::Map& map ) const GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT ); map.Insert( Toolkit::TextVisual::Property::UNDERLINE, value ); + + GetOutlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::DevelTextVisual::Property::OUTLINE, value ); } void TextVisual::DoCreateInstancePropertyMap( Property::Map& map ) const @@ -593,6 +602,11 @@ void TextVisual::DoSetProperty( Dali::Property::Index index, const Dali::Propert SetUnderlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); break; } + case Toolkit::DevelTextVisual::Property::OUTLINE: + { + SetOutlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + break; + } } } diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp index b2e0d03..11d3b0f 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.cpp +++ b/dali-toolkit/internal/visuals/texture-manager-impl.cpp @@ -47,8 +47,10 @@ size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue) { using Dali::EnvironmentVariable::GetEnvironmentVariable; auto numberString = GetEnvironmentVariable(environmentVariable); - auto numberOfThreads = numberString ? std::strtol(numberString, nullptr, 10) : 0; - return (numberOfThreads > 0) ? numberOfThreads : defaultValue; + auto numberOfThreads = numberString ? std::strtoul(numberString, nullptr, 10) : 0; + constexpr auto MAX_NUMBER_OF_THREADS = 100u; + DALI_ASSERT_DEBUG( numberOfThreads < MAX_NUMBER_OF_THREADS ); + return ( numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS ) ? numberOfThreads : defaultValue; } size_t GetNumberOfLocalLoaderThreads() diff --git a/dali-toolkit/public-api/controls/image-view/image-view.h b/dali-toolkit/public-api/controls/image-view/image-view.h index ac2befa..7c99a5f 100644 --- a/dali-toolkit/public-api/controls/image-view/image-view.h +++ b/dali-toolkit/public-api/controls/image-view/image-view.h @@ -48,7 +48,7 @@ class ImageView; * ResouceReadySignal is done after the resource is set then signal will be missed. * * To protect against this, IsResourceReady() can be checked before connecting to ResourceReadySignal, - * or the signal connection can be done before setting the resource" + * or the signal connection can be done before setting the resource. * * @code * auto myImageView = ImageView::New( resourceUrl ); diff --git a/dali-toolkit/public-api/controls/text-controls/text-editor.h b/dali-toolkit/public-api/controls/text-controls/text-editor.h index fdda010..f633f45 100644 --- a/dali-toolkit/public-api/controls/text-controls/text-editor.h +++ b/dali-toolkit/public-api/controls/text-controls/text-editor.h @@ -301,9 +301,7 @@ public: INPUT_LINE_SPACING, /** - * @brief The default underline parameters. - * @details Name "underline", type Property::MAP. - * @SINCE_1_2.13 + * @copydoc Dali::Toolkit::TextLabel::Property::UNDERLINE */ UNDERLINE, @@ -315,9 +313,7 @@ public: INPUT_UNDERLINE, /** - * @brief The default shadow parameters. - * @details Name "shadow", type Property::MAP. - * @SINCE_1_2.13 + * @copydoc Dali::Toolkit::TextLabel::Property::SHADOW */ SHADOW, @@ -343,9 +339,7 @@ public: INPUT_EMBOSS, /** - * @brief The default outline parameters. - * @details Name "outline", type Property::MAP. - * @SINCE_1_2.13 + * @copydoc Dali::Toolkit::TextLabel::Property::OUTLINE */ OUTLINE, diff --git a/dali-toolkit/public-api/controls/text-controls/text-field.h b/dali-toolkit/public-api/controls/text-controls/text-field.h index 0875753..5af78b2 100644 --- a/dali-toolkit/public-api/controls/text-controls/text-field.h +++ b/dali-toolkit/public-api/controls/text-controls/text-field.h @@ -353,9 +353,7 @@ public: INPUT_POINT_SIZE, /** - * @brief The default underline parameters. - * @details Name "underline", type Property::MAP. - * @SINCE_1_2.13 + * @copydoc Dali::Toolkit::TextLabel::Property::UNDERLINE */ UNDERLINE, @@ -367,9 +365,7 @@ public: INPUT_UNDERLINE, /** - * @brief The default shadow parameters. - * @details Name "shadow", type Property::MAP. - * @SINCE_1_2.13 + * @copydoc Dali::Toolkit::TextLabel::Property::SHADOW */ SHADOW, @@ -395,9 +391,7 @@ public: INPUT_EMBOSS, /** - * @brief The default outline parameters. - * @details Name "outline", type Property::MAP. - * @SINCE_1_2.13 + * @copydoc Dali::Toolkit::TextLabel::Property::OUTLINE */ OUTLINE, 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 ec6613c..106f234 100644 --- a/dali-toolkit/public-api/controls/text-controls/text-label.h +++ b/dali-toolkit/public-api/controls/text-controls/text-label.h @@ -254,6 +254,15 @@ public: /** * @brief The default underline parameters. * @details Name "underline", type Property::MAP. + * + * The underline map contains the following keys: + * + * | %Property Name | Type | Required | Description | + * |----------------------|----------|----------|--------------------------------------------------------------------------------------------------------------------| + * | enable | BOOLEAN | No | True to enable the underline or false to disable (the default value is false) | + * | color | VECTOR4 | No | The color of the underline (the default value is Color::BLACK) | + * | height | FLOAT | No | The height of the underline (the default value is 0) | + * * @SINCE_1_2.13 */ UNDERLINE, @@ -261,6 +270,15 @@ public: /** * @brief The default shadow parameters. * @details Name "shadow", type Property::MAP. + * + * The shadow map contains the following keys: + * + * | %Property Name | Type | Required | Description | + * |----------------------|----------|----------|--------------------------------------------------------------------------------------------------------------------| + * | color | VECTOR4 | No | The color of the shadow (the default value is Color::BLACK) | + * | offset | VECTOR2 | No | The offset from the text to draw the shadow in the X and Y axes (the default value is 0 which means no shadow) | + * | blurRadius | FLOAT | No | The radius of blur to be applied to the shadow (the default value is 0 which means no blur) | + * * @SINCE_1_2.13 */ SHADOW, @@ -275,6 +293,14 @@ public: /** * @brief The default outline parameters. * @details Name "outline", type Property::MAP. + * + * The outline map contains the following keys: + * + * | %Property Name | Type | Required | Description | + * |----------------------|----------|----------|--------------------------------------------------------------------------------------------------------------------| + * | color | VECTOR4 | No | The color of the outline (the default value is Color::WHITE) | + * | width | INTEGER | No | The width of the outline (the default value is 0 which means no outline) | + * * @SINCE_1_2.13 */ OUTLINE, diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 6ed8280..d417fe7 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -31,7 +31,7 @@ namespace Toolkit const unsigned int TOOLKIT_MAJOR_VERSION = 1; const unsigned int TOOLKIT_MINOR_VERSION = 3; -const unsigned int TOOLKIT_MICRO_VERSION = 3; +const unsigned int TOOLKIT_MICRO_VERSION = 4; const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index b1b4cef..981b30a 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali-toolkit Summary: Dali 3D engine Toolkit -Version: 1.3.3 +Version: 1.3.4 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT