From: adam.b Date: Fri, 8 Sep 2017 08:28:11 +0000 (+0100) Subject: [dali_1.2.56] Merge branch 'devel/master' X-Git-Tag: dali_1.9.8~5^2~131 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=refs%2Fchanges%2F63%2F148663%2F1;hp=b841244c9f5ca50f066d91b5b381044f33b2bdf6 [dali_1.2.56] Merge branch 'devel/master' Change-Id: I71175275e071110a665469362684c2b8ea997717 --- diff --git a/automated-tests/src/dali-toolkit-styling/default-theme.json b/automated-tests/src/dali-toolkit-styling/default-theme.json index 6b3ddd1..30edbfd 100644 --- a/automated-tests/src/dali-toolkit-styling/default-theme.json +++ b/automated-tests/src/dali-toolkit-styling/default-theme.json @@ -1,7 +1,8 @@ { "config": { - "alwaysShowFocus":false + "alwaysShowFocus":false, + "clearFocusOnEscape":true }, "constants": { diff --git a/automated-tests/src/dali-toolkit-styling/utc-Dali-StyleManager.cpp b/automated-tests/src/dali-toolkit-styling/utc-Dali-StyleManager.cpp index 20de8e8..e8348f1 100644 --- a/automated-tests/src/dali-toolkit-styling/utc-Dali-StyleManager.cpp +++ b/automated-tests/src/dali-toolkit-styling/utc-Dali-StyleManager.cpp @@ -33,6 +33,10 @@ #include #include #include +#include +#include +#include +#include using namespace Dali; using namespace Dali::Toolkit; @@ -1298,3 +1302,46 @@ int UtcDaliStyleManagerSetSubState02(void) END_TEST; } + + +int UtcDaliStyleManagerConfigSectionTest(void) +{ + tet_infoline("Test that the properties in config section are works" ); + + const char* defaultTheme = + "{\n" + " \"config\":\n" + " {\n" + " \"alwaysShowFocus\":false,\n" + " \"clearFocusOnEscape\":false\n" + " },\n" + " \"styles\":\n" + " {\n" + " }\n" + "}\n"; + + Test::StyleMonitor::SetThemeFileOutput( DALI_STYLE_DIR "dali-toolkit-default-theme.json", defaultTheme ); + + ToolkitTestApplication application; + + Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); + + Property::Map config = Toolkit::DevelStyleManager::GetConfigurations( styleManager ); + bool alwaysShowFocus = config["alwaysShowFocus"].Get(); + DALI_TEST_CHECK( !alwaysShowFocus ); + bool clearFocusOnEscape = config["clearFocusOnEscape"].Get(); + DALI_TEST_CHECK( !clearFocusOnEscape ); + + // For coverage + Toolkit::TextEditor editor = Toolkit::TextEditor::New(); + editor.SetKeyboardFocusable( true ); + Stage::GetCurrent().Add( editor ); + + Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor( editor ); + + application.ProcessEvent( Integration::KeyEvent( "", "", DALI_KEY_ESCAPE, 0, 0, Integration::KeyEvent::Down, "", DevelDevice::Class::NONE, DevelDevice::Subclass::NONE ) ); + application.SendNotification(); + application.Render(); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index 266b8e5..08b194f 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -2528,3 +2528,28 @@ int utcDaliTextFieldExtremlyLargePointSize(void) } END_TEST; } + +int UtcDaliTextFieldDefaultFontStylePropertyCoverage(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliTextFieldFontStylePorpertyCoverage"); + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + Stage::GetCurrent().Add( field ); + + Property::Map fontStyleMapGet; + + fontStyleMapGet = field.GetProperty( TextField::Property::FONT_STYLE ); + + Property::Value* weightValue = NULL; + Property::Value* widthValue = NULL; + Property::Value* slantValue = NULL; + weightValue = fontStyleMapGet.Find( "weight" ); + widthValue = fontStyleMapGet.Find( "width" ); + slantValue = fontStyleMapGet.Find( "slant" ); + DALI_TEST_CHECK( !weightValue ); + DALI_TEST_CHECK( !widthValue ); + DALI_TEST_CHECK( !slantValue ); + + END_TEST; +} diff --git a/build/tizen/Makefile.am b/build/tizen/Makefile.am index 89a5e28..3df2c08 100755 --- a/build/tizen/Makefile.am +++ b/build/tizen/Makefile.am @@ -28,6 +28,7 @@ endif SUBDIRS += docs pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = dali-toolkit.pc MAINTAINERCLEANFILES = \ @@ -56,8 +57,8 @@ rename_cov_data: @test -z $(COVERAGE_DIR) || mkdir -p $(COVERAGE_DIR) @rm -f $(COVERAGE_DIR)/* @cp dali-toolkit/.libs/*.gcda dali-toolkit/.libs/*.gcno $(COVERAGE_DIR) - @for i in `find $(COVERAGE_DIR) -name "libdali_toolkit_la-*.gcda" -o -name "libdali_toolkit_la-*.gcno"` ;\ - do mv $$i `echo $$i | sed s/libdali_toolkit_la-//` ; echo $$i ; done + @for i in `find $(COVERAGE_DIR) -name "libdali_toolkit*_la-*.gcda" -o -name "libdali_toolkit*_la-*.gcno"` ;\ + do mv $$i `echo $$i | sed s/libdali_toolkit*_la-//` ; echo $$i ; done cov_data: rename_cov_data @cd $(COVERAGE_DIR) ; lcov $(LCOV_OPTS) --base-directory . --directory . -c -o dali.info diff --git a/build/tizen/configure.ac b/build/tizen/configure.ac index 80e4a8f..26be349 100755 --- a/build/tizen/configure.ac +++ b/build/tizen/configure.ac @@ -28,7 +28,6 @@ LT_INIT DALI_TOOLKIT_VERSION=dali_version AC_SUBST(DALI_TOOLKIT_VERSION) -PKG_CHECK_MODULES(DALICORE, dali-core) DALI_TOOLKIT_CFLAGS=-DPLATFORM_TIZEN @@ -75,6 +74,25 @@ AC_ARG_ENABLE([csharp], [enable_csharp=$enableval], [enable_csharp=automatic]) +AC_ARG_ENABLE([cxx03_abi], + [AC_HELP_STRING([--enable-cxx03-abi], + [Specify abi for the build])], + [enable_cxx03_abi=$enableval], + [enable_cxx03_abi=no]) + +AC_ARG_ENABLE([rename_so], + [AC_HELP_STRING([--enable-rename-so], + [Specify whether so file is renamed or not])], + [enable_rename_so=$enableval], + [enable_rename_so=yes]) + +AM_CONDITIONAL([ENABLE_CXX03_ABI], [test x$enable_cxx03_abi = xyes]) +AM_CONDITIONAL([ENABLE_RENAME_SO], [test x$enable_rename_so = xyes]) + +if test "x$enable_cxx03_abi" = "xyes"; then + DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -D_GLIBCXX_USE_CXX11_ABI=0" +fi + if test "x$enable_debug" = "xyes"; then DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -DDEBUG_ENABLED" fi @@ -203,6 +221,12 @@ if test x$enable_csharp = xyes; then AC_SUBST(DALITOOLKIT_LIBS) fi +if test "x$enable_cxx03_abi" = "xyes"; then +PKG_CHECK_MODULES(DALICORE, dali-core-cxx03) +else +PKG_CHECK_MODULES(DALICORE, dali-core) +fi + #set a variable for the makefile to force compile the csharp plugin AM_CONDITIONAL([ENABLE_CSHARP_PLUGIN], [test x$build_csharp_plugin = xyes]) AM_CONDITIONAL([ENABLE_RUBY_FLAG], [test x$build_ruby_flag = xyes]) @@ -212,13 +236,16 @@ AC_CONFIG_FILES([ dali-toolkit/Makefile plugins/javascript/Makefile plugins/csharp/Makefile - dali-toolkit.pc docs/Makefile docs/dali.doxy docs-internal/dali-internal.doxy ../../automated-tests/CMakeLists.txt ]) +if test "x$enable_cxx03_abi" = "xno"; then +AC_CONFIG_FILES([dali-toolkit.pc]) +fi + AC_OUTPUT echo " diff --git a/build/tizen/dali-toolkit.pc.in b/build/tizen/dali-toolkit.pc.in index 87cbcc0..16eacc4 100644 --- a/build/tizen/dali-toolkit.pc.in +++ b/build/tizen/dali-toolkit.pc.in @@ -4,8 +4,8 @@ apiversion=@DALI_TOOLKIT_VERSION@ libdir=@libdir@ includedir=@devincludepath@ -Name: Samsung OpenGLES Toolkit (including Toolkit) -Description: 3D Canvas Toolkit using OpenGLES (with the toolkit) +Name: Dali 3D engine Toolkit +Description: Cross platform 3D Engine Toolkit Version: ${apiversion} Requires: dali-core Libs: -L${libdir} -ldali-toolkit diff --git a/build/tizen/dali-toolkit/Makefile.am b/build/tizen/dali-toolkit/Makefile.am index c2f73c3..25bdf75 100644 --- a/build/tizen/dali-toolkit/Makefile.am +++ b/build/tizen/dali-toolkit/Makefile.am @@ -53,10 +53,7 @@ dalisound_DATA = ${dali_toolkit_sound_files} package_doxy_dir = ../../../doc include ../../../doc/file.list -# The library -lib_LTLIBRARIES = libdali-toolkit.la - -libdali_toolkit_la_SOURCES = \ +LIBDALI_TOOLKIT_LA_SOURCES = \ $(toolkit_src_files) \ $(public_api_src_files) \ $(devel_api_src_files) \ @@ -70,7 +67,7 @@ dalistyleimages_DATA = ${dali_toolkit_style_images} libdali_toolkit_la_DEPENDENCIES = -libdali_toolkit_la_CXXFLAGS = -DDALI_COMPILATION \ +LIBDALI_TOOLKIT_LA_CXXFLAGS = -DDALI_COMPILATION \ -DDALI_IMAGE_DIR="\"${daliimagedir}\"" \ -DDALI_SOUND_DIR="\"${dalisounddir}\"" \ -DDALI_STYLE_DIR="\"${dalistyledir}\"" \ @@ -84,14 +81,49 @@ libdali_toolkit_la_CXXFLAGS = -DDALI_COMPILATION \ $(FRIBIDI_CFLAGS) \ $(HTMLCXX_CFLAGS) -libdali_toolkit_la_LIBADD = \ +LIBDALI_TOOLKIT_LA_LIBADD = \ $(DALICORE_LIBS) \ $(DLOG_LIBS) \ $(FRIBIDI_LIBS) \ $(HTMLCXX_LIBS) -# Install headers +# The library +if ENABLE_CXX03_ABI + +lib_LTLIBRARIES = libdali-toolkit.la +libdali_toolkit_la_SOURCES = $(LIBDALI_TOOLKIT_LA_SOURCES) +libdali_toolkit_la_LIBADD = $(LIBDALI_TOOLKIT_LA_LIBADD) +libdali_toolkit_la_CXXFLAGS = $(LIBDALI_TOOLKIT_LA_CXXFLAGS) +libdali_toolkit_la_CFLAGS = $(LIBDALI_TOOLKTI_LA_CFLAGS) + +if ENABLE_RENAME_SO +#rename +install: install-am + rm -rf $(libdir)/libdali-toolkit.so + rm -rf $(libdir)/libdali-toolkit-cxx03.so + ln -s $(libdir)/libdali-toolkit.so.0.0.* $(libdir)/libdali-toolkit-cxx03.so +endif + +else + +lib_LTLIBRARIES = libdali-toolkit-cxx11.la +libdali_toolkit_cxx11_la_SOURCES = $(LIBDALI_TOOLKIT_LA_SOURCES) +libdali_toolkit_cxx11_la_LIBADD = $(LIBDALI_TOOLKIT_LA_LIBADD) +libdali_toolkit_cxx11_la_CXXFLAGS = $(LIBDALI_TOOLKIT_LA_CXXFLAGS) +libdali_toolkit_cxx11_la_CFLAGS = $(LIBDALI_TOOLKTI_LA_CFLAGS) + +if ENABLE_RENAME_SO +#rename +install: install-am + rm -rf $(libdir)/libdali-toolkit-cxx11.so + rm -rf $(libdir)/libdali-toolkit.so + ln -s $(libdir)/libdali-toolkit-cxx11.so.0.0.* $(libdir)/libdali-toolkit.so +endif + +endif + +# Install headers topleveldir = $(devincludepath)/dali-toolkit toplevel_HEADERS = ../../../dali-toolkit/dali-toolkit.h diff --git a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp index 43c9307..703440a 100644 --- a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp +++ b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp @@ -135,8 +135,8 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cellPadding", VECTOR2, CELL_ DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layoutRows", MAP, LAYOUT_ROWS ) DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layoutColumns", MAP, LAYOUT_COLUMNS ) DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellIndex", VECTOR2, CELL_INDEX ) -DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "rowSpan", FLOAT, ROW_SPAN ) -DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "columnSpan", FLOAT, COLUMN_SPAN ) +DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "rowSpan", INTEGER, ROW_SPAN ) +DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "columnSpan", INTEGER, COLUMN_SPAN ) DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellHorizontalAlignment", STRING, CELL_HORIZONTAL_ALIGNMENT ) DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellVerticalAlignment", STRING, CELL_VERTICAL_ALIGNMENT ) @@ -996,12 +996,12 @@ void TableView::OnChildAdd( Actor& child ) Toolkit::TableView::CellPosition cellPosition; if( child.GetPropertyType( Toolkit::TableView::ChildProperty::ROW_SPAN ) != Property::NONE ) { - cellPosition.rowSpan = static_cast( child.GetProperty( Toolkit::TableView::ChildProperty::ROW_SPAN ).Get() ); + cellPosition.rowSpan = child.GetProperty( Toolkit::TableView::ChildProperty::ROW_SPAN ).Get< int >(); } if( child.GetPropertyType( Toolkit::TableView::ChildProperty::COLUMN_SPAN ) != Property::NONE ) { - cellPosition.columnSpan = static_cast( child.GetProperty( Toolkit::TableView::ChildProperty::COLUMN_SPAN ).Get() ); + cellPosition.columnSpan = child.GetProperty( Toolkit::TableView::ChildProperty::COLUMN_SPAN ).Get< int >(); } if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_INDEX ) != Property::NONE ) 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 d089d97..77005c0 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -1478,7 +1478,7 @@ bool TextEditor::OnKeyEvent( const KeyEvent& event ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode ); - if( Dali::DALI_KEY_ESCAPE == event.keyCode ) // Make a Dali key code for this + if( Dali::DALI_KEY_ESCAPE == event.keyCode && mController->ShouldClearFocusOnEscape() ) { // Make sure ClearKeyInputFocus when only key is up if( event.state == KeyEvent::Up ) 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 1ed87bd..d5ea993 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -1526,7 +1526,7 @@ bool TextField::OnKeyEvent( const KeyEvent& event ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode ); - if( Dali::DALI_KEY_ESCAPE == event.keyCode ) // Make a Dali key code for this + if( Dali::DALI_KEY_ESCAPE == event.keyCode && mController->ShouldClearFocusOnEscape() ) { // Make sure ClearKeyInputFocus when only key is up if( event.state == KeyEvent::Up ) 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 d92b1cd..e871db3 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -948,7 +948,7 @@ void TextLabel::SetUpAutoScrolling() // Create a texture of the text for scrolling Text::TypesetterPtr typesetter = Text::Typesetter::New( mController->GetTextModel() ); - PixelData data = typesetter->Render( textNaturalSize, Text::Typesetter::RENDER_TEXT_AND_STYLES, true ); // ignore the horizontal alignment + PixelData data = typesetter->Render( textNaturalSize, Text::Typesetter::RENDER_TEXT_AND_STYLES, true, Pixel::RGBA8888 ); // ignore the horizontal alignment Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), data.GetWidth(), diff --git a/dali-toolkit/internal/helpers/round-robin-container-view.h b/dali-toolkit/internal/helpers/round-robin-container-view.h new file mode 100644 index 0000000..c3619f9 --- /dev/null +++ b/dali-toolkit/internal/helpers/round-robin-container-view.h @@ -0,0 +1,124 @@ + +#ifndef DALI_TOOLKIT_INTERNAL_ROUND_ROBIN_CONTAINER_VIEW_H +#define DALI_TOOLKIT_INTERNAL_ROUND_ROBIN_CONTAINER_VIEW_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. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * @brief RoundRobinContainerView is a view to a container that allows iterating through the elements cyclically. + */ +template +class RoundRobinContainerView +{ +public: + using ContainerType = std::vector; + + /** + * @brief Constructs a new RoundRobinControlView with the given number elements using the provided factory. + * @param[in] numberOfElements The number of elements in the container + * @param[in] factory Factory function of functor that will be used to create instances of the elements + */ + template + RoundRobinContainerView(size_t numberOfElements, const FactoryType& factory) + : mElements(), + mNextIndex{} + { + mElements.reserve(numberOfElements); + for(unsigned i = {}; i < numberOfElements; ++i) + { + mElements.push_back(factory()); + } + } + + /** + * @brief Reset the position of the iterator returned by GetNext() to the first element. + */ + void Reset() + { + mNextIndex = 0u; + } + + /** + * @brief Returns the next element on the container. + * @return Iterator for the next element + */ + typename ContainerType::iterator GetNext() + { + SetValidNextIndex(); + + return mElements.begin() + mNextIndex++; + } + + /** + * @brief Returns the iterator to the end of the container. + * + * Can be used to compare against GetNext() to check if the container is empty. + * + * @return The container end() element + */ + typename ContainerType::const_iterator End() const + { + return mElements.cend(); + } + + // default members + ~RoundRobinContainerView() = default; + + RoundRobinContainerView(const RoundRobinContainerView&) = delete; + RoundRobinContainerView& operator=(const RoundRobinContainerView&) = delete; + RoundRobinContainerView(RoundRobinContainerView&&) = default; + RoundRobinContainerView& operator=(RoundRobinContainerView&&) = default; + +private: + /** + * @brief Check the current index and reset if necessary. + */ + void SetValidNextIndex() + { + if(mNextIndex >= mElements.size()) + { + Reset(); + } + } + +private: + ContainerType mElements; //< container of elements + size_t mNextIndex; //< index to the next element to be viewed +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + + +#endif // DALI_TOOLKIT_INTERNAL_ROUND_ROBIN_CONTAINER_VIEW_H diff --git a/dali-toolkit/internal/scripting/script-impl.cpp b/dali-toolkit/internal/scripting/script-impl.cpp index 9cc0d24..6c9191b 100644 --- a/dali-toolkit/internal/scripting/script-impl.cpp +++ b/dali-toolkit/internal/scripting/script-impl.cpp @@ -33,7 +33,11 @@ namespace Internal namespace { +#if _GLIBCXX_USE_CXX11_ABI +const char* PLUGIN_FILE = "libdali-script-plugin-v8-cxx11.so"; +#else const char* PLUGIN_FILE = "libdali-script-plugin-v8.so"; +#endif } Script::Script() diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index 1821db4..66bb797 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -59,11 +59,13 @@ struct GlyphData * @param[in] position The position of the glyph. * @param[in] color The color of the glyph. * @param[in] style The style of the text. + * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8). */ void TypesetGlyph( GlyphData& data, const Vector2* const position, const Vector4* const color, - Typesetter::Style style) + Typesetter::Style style, + Pixel::Format pixelFormat ) { if( ( 0u == data.glyphBitmap.width ) || ( 0u == data.glyphBitmap.height ) ) { @@ -74,81 +76,138 @@ void TypesetGlyph( GlyphData& data, const int widthMinusOne = static_cast( data.width - 1u ); const int heightMinusOne = static_cast( data.height - 1u ); - // Whether the given glyph is a color one. - const bool isColorGlyph = Pixel::BGRA8888 == data.glyphBitmap.format; - - // Pointer to the color glyph if there is one. - const uint32_t* const colorGlyphBuffer = isColorGlyph ? reinterpret_cast( data.glyphBitmap.buffer ) : NULL; + if ( Pixel::RGBA8888 == pixelFormat ) + { + // Whether the given glyph is a color one. + const bool isColorGlyph = Pixel::BGRA8888 == data.glyphBitmap.format; - // Pack the given color into a 32bit buffer. The alpha channel will be updated later for each pixel. - // The format is RGBA8888. - uint32_t packedColor = 0u; - uint8_t* packedColorBuffer = reinterpret_cast( &packedColor ); - *( packedColorBuffer + 2 ) = static_cast( color->b * 255.f ); - *( packedColorBuffer + 1 ) = static_cast( color->g * 255.f ); - *packedColorBuffer = static_cast( color->r * 255.f ); + // Pointer to the color glyph if there is one. + const uint32_t* const colorGlyphBuffer = isColorGlyph ? reinterpret_cast( data.glyphBitmap.buffer ) : NULL; - // Initial vertical offset. - const int yOffset = data.verticalOffset + position->y; + // Pack the given color into a 32bit buffer. The alpha channel will be updated later for each pixel. + // The format is RGBA8888. + uint32_t packedColor = 0u; + uint8_t* packedColorBuffer = reinterpret_cast( &packedColor ); + *( packedColorBuffer + 2 ) = static_cast( color->b * 255.f ); + *( packedColorBuffer + 1 ) = static_cast( color->g * 255.f ); + *packedColorBuffer = static_cast( color->r * 255.f ); - // Traverse the pixels of the glyph line per line. - for( int lineIndex = 0, glyphHeight = static_cast( data.glyphBitmap.height ); lineIndex < glyphHeight; ++lineIndex ) - { - const int yOffsetIndex = yOffset + lineIndex; - if( ( 0 > yOffsetIndex ) || ( yOffsetIndex > heightMinusOne ) ) - { - // Do not write out of bounds. - break; - } + // Initial vertical offset. + const int yOffset = data.verticalOffset + position->y; - const int verticalOffset = yOffsetIndex * data.width; - const int xOffset = data.horizontalOffset + position->x; - const int glyphBufferOffset = lineIndex * static_cast( data.glyphBitmap.width ); - for( int index = 0, glyphWidth = static_cast( data.glyphBitmap.width ); index < glyphWidth; ++index ) + // Traverse the pixels of the glyph line per line. + for( int lineIndex = 0, glyphHeight = static_cast( data.glyphBitmap.height ); lineIndex < glyphHeight; ++lineIndex ) { - const int xOffsetIndex = xOffset + index; - if( ( 0 > xOffsetIndex ) || ( xOffsetIndex > widthMinusOne ) ) + const int yOffsetIndex = yOffset + lineIndex; + if( ( 0 > yOffsetIndex ) || ( yOffsetIndex > heightMinusOne ) ) { - // Don't write out of bounds. + // Do not write out of bounds. break; } - uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( data.bitmapBuffer.GetBuffer() ); - - if( isColorGlyph ) + const int verticalOffset = yOffsetIndex * data.width; + const int xOffset = data.horizontalOffset + position->x; + const int glyphBufferOffset = lineIndex * static_cast( data.glyphBitmap.width ); + for( int index = 0, glyphWidth = static_cast( data.glyphBitmap.width ); index < glyphWidth; ++index ) { - // Retrieves the color from the color glyph. The format is BGRA8888. - uint32_t packedColorGlyph = *( colorGlyphBuffer + glyphBufferOffset + index ); - uint8_t* packedColorGlyphBuffer = reinterpret_cast( &packedColorGlyph ); - - if( Typesetter::STYLE_SHADOW == style ) + const int xOffsetIndex = xOffset + index; + if( ( 0 > xOffsetIndex ) || ( xOffsetIndex > widthMinusOne ) ) { - // The shadow of color glyph needs to have the shadow color. - *( packedColorGlyphBuffer + 2 ) = static_cast( color->b * 255.f ); - *( packedColorGlyphBuffer + 1 ) = static_cast( color->g * 255.f ); - *packedColorGlyphBuffer = static_cast( color->r * 255.f ); - } - else - { - std::swap( *packedColorGlyphBuffer, *( packedColorGlyphBuffer + 2u ) ); // Swap B and R. + // Don't write out of bounds. + break; } - // Update the alpha channel. - if( Typesetter::STYLE_MASK == style ) + uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( data.bitmapBuffer.GetBuffer() ); + + if( isColorGlyph ) { - // Create an alpha mask for color glyph. - *( packedColorGlyphBuffer + 3u ) = 0u; + // Retrieves the color from the color glyph. The format is BGRA8888. + uint32_t packedColorGlyph = *( colorGlyphBuffer + glyphBufferOffset + index ); + uint8_t* packedColorGlyphBuffer = reinterpret_cast( &packedColorGlyph ); + + if( Typesetter::STYLE_SHADOW == style ) + { + // The shadow of color glyph needs to have the shadow color. + *( packedColorGlyphBuffer + 2 ) = static_cast( color->b * 255.f ); + *( packedColorGlyphBuffer + 1 ) = static_cast( color->g * 255.f ); + *packedColorGlyphBuffer = static_cast( color->r * 255.f ); + } + else + { + std::swap( *packedColorGlyphBuffer, *( packedColorGlyphBuffer + 2u ) ); // Swap B and R. + } + + // Update the alpha channel. + if( Typesetter::STYLE_MASK == style ) + { + // Create an alpha mask for color glyph. + *( packedColorGlyphBuffer + 3u ) = 0u; + } + else + { + *( packedColorGlyphBuffer + 3u ) = static_cast( color->a * static_cast( *( packedColorGlyphBuffer + 3u ) ) ); + } + + // Set the color into the final pixel buffer. + *( bitmapBuffer + verticalOffset + xOffsetIndex ) = packedColorGlyph; } else { - *( packedColorGlyphBuffer + 3u ) = static_cast( color->a * static_cast( *( packedColorGlyphBuffer + 3u ) ) ); + // Update the alpha channel. + const uint8_t alpha = *( data.glyphBitmap.buffer + glyphBufferOffset + index ); + + // Copy non-transparent pixels only + if ( alpha > 0u ) + { + // Check alpha of overlapped pixels + uint32_t& currentColor = *( bitmapBuffer + verticalOffset + xOffsetIndex ); + uint8_t* packedCurrentColorBuffer = reinterpret_cast( ¤tColor ); + + uint8_t currentAlpha = *( packedCurrentColorBuffer + 3u ); + uint8_t newAlpha = static_cast( color->a * static_cast( alpha ) ); + + // For any pixel overlapped with the pixel in previous glyphs, make sure we don't + // overwrite a previous bigger alpha with a smaller alpha (in order to avoid + // semi-transparent gaps between joint glyphs with overlapped pixels, which could + // happen, for example, in the RTL text when we copy glyphs from right to left). + *( packedColorBuffer + 3u ) = std::max( currentAlpha, newAlpha ); + + // Set the color into the final pixel buffer. + currentColor = packedColor; + } } + } + } + } + else + { + // Initial vertical offset. + const int yOffset = data.verticalOffset + position->y; - // Set the color into the final pixel buffer. - *( bitmapBuffer + verticalOffset + xOffsetIndex ) = packedColorGlyph; + // Traverse the pixels of the glyph line per line. + for( int lineIndex = 0, glyphHeight = static_cast( data.glyphBitmap.height ); lineIndex < glyphHeight; ++lineIndex ) + { + const int yOffsetIndex = yOffset + lineIndex; + if( ( 0 > yOffsetIndex ) || ( yOffsetIndex > heightMinusOne ) ) + { + // Do not write out of bounds. + break; } - else + + const int verticalOffset = yOffsetIndex * data.width; + const int xOffset = data.horizontalOffset + position->x; + const int glyphBufferOffset = lineIndex * static_cast( data.glyphBitmap.width ); + for( int index = 0, glyphWidth = static_cast( data.glyphBitmap.width ); index < glyphWidth; ++index ) { + const int xOffsetIndex = xOffset + index; + if( ( 0 > xOffsetIndex ) || ( xOffsetIndex > widthMinusOne ) ) + { + // Don't write out of bounds. + break; + } + + uint8_t* bitmapBuffer = reinterpret_cast< uint8_t* >( data.bitmapBuffer.GetBuffer() ); + // Update the alpha channel. const uint8_t alpha = *( data.glyphBitmap.buffer + glyphBufferOffset + index ); @@ -156,20 +215,15 @@ void TypesetGlyph( GlyphData& data, if ( alpha > 0u ) { // Check alpha of overlapped pixels - uint32_t& currentColor = *( bitmapBuffer + verticalOffset + xOffsetIndex ); - uint8_t* packedCurrentColorBuffer = reinterpret_cast( ¤tColor ); - - uint8_t currentAlpha = *( packedCurrentColorBuffer + 3u ); + uint8_t& currentAlpha = *( bitmapBuffer + verticalOffset + xOffsetIndex ); uint8_t newAlpha = static_cast( color->a * static_cast( alpha ) ); +// printf("y: %d, x: %d: alpha: %u, currentAlpha: %u, newAlpha: %u, a: %u\n", yOffsetIndex, xOffsetIndex, alpha, currentAlpha, newAlpha, std::max( currentAlpha, newAlpha ) ); // For any pixel overlapped with the pixel in previous glyphs, make sure we don't // overwrite a previous bigger alpha with a smaller alpha (in order to avoid // semi-transparent gaps between joint glyphs with overlapped pixels, which could // happen, for example, in the RTL text when we copy glyphs from right to left). - *( packedColorBuffer + 3u ) = std::max( currentAlpha, newAlpha ); - - // Set the color into the final pixel buffer. - currentColor = packedColor; + *( bitmapBuffer + verticalOffset + xOffsetIndex ) = std::max( currentAlpha, newAlpha ); } } } @@ -207,7 +261,7 @@ ViewModel* Typesetter::GetViewModel() return mModel; } -PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bool ignoreHorizontalAlignment ) +PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat ) { // @todo. This initial implementation for a TextLabel has only one visible page. @@ -257,7 +311,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo if( RENDER_MASK == behaviour ) { // Generate the image buffer as an alpha mask for color glyphs. - imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_MASK, ignoreHorizontalAlignment, penY, 0u, numberOfGlyphs - 1 ); + imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_MASK, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); } else if( RENDER_NO_TEXT == behaviour ) { @@ -268,7 +322,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo else { // Generate the image buffer for the text with no style. - imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_NONE, ignoreHorizontalAlignment, penY, 0u, numberOfGlyphs -1 ); + imageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_NONE, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs -1 ); } if ( ( RENDER_NO_STYLES != behaviour ) && ( RENDER_MASK != behaviour ) ) @@ -280,7 +334,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 ) { // Create the image buffer for shadow - Devel::PixelBuffer shadowImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_SHADOW, ignoreHorizontalAlignment, penY, 0u, numberOfGlyphs - 1 ); + Devel::PixelBuffer shadowImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_SHADOW, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); // Combine the two buffers imageBuffer = CombineImageBuffer( imageBuffer, shadowImageBuffer, bufferWidth, bufferHeight ); @@ -291,7 +345,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo if ( underlineEnabled ) { // Create the image buffer for underline - Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, penY, 0u, numberOfGlyphs - 1 ); + Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, penY, 0u, numberOfGlyphs - 1 ); // Combine the two buffers imageBuffer = CombineImageBuffer( imageBuffer, underlineImageBuffer, bufferWidth, bufferHeight ); @@ -304,7 +358,7 @@ PixelData Typesetter::Render( const Vector2& size, RenderBehaviour behaviour, bo return pixelData; } -Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, int verticalOffset, GlyphIndex fromGlyphIndex, GlyphIndex toGlyphIndex ) +Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int verticalOffset, GlyphIndex fromGlyphIndex, GlyphIndex toGlyphIndex ) { // Retrieve lines, glyphs, positions and colors from the view model. const Length modelNumberOfLines = mModel->GetNumberOfLines(); @@ -322,13 +376,20 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth // Create and initialize the pixel buffer. GlyphData glyphData; glyphData.verticalOffset = verticalOffset; - glyphData.width = bufferWidth; glyphData.height = bufferHeight; - const unsigned int bufferSizeInt = bufferWidth * bufferHeight; - const unsigned int bufferSizeChar = 4u * bufferSizeInt; - glyphData.bitmapBuffer = Devel::PixelBuffer::New( bufferWidth, bufferHeight, Pixel::RGBA8888 ); - memset( glyphData.bitmapBuffer.GetBuffer(), 0u, bufferSizeChar ); + glyphData.bitmapBuffer = Devel::PixelBuffer::New( bufferWidth, bufferHeight, pixelFormat ); + + if ( Pixel::RGBA8888 == pixelFormat ) + { + const unsigned int bufferSizeInt = bufferWidth * bufferHeight; + const unsigned int bufferSizeChar = 4u * bufferSizeInt; + memset( glyphData.bitmapBuffer.GetBuffer(), 0u, bufferSizeChar ); + } + else + { + memset( glyphData.bitmapBuffer.GetBuffer(), 0, bufferWidth * bufferHeight ); + } // Get a handle of the font client. Used to retrieve the bitmaps of the glyphs. TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); @@ -490,7 +551,8 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth TypesetGlyph( glyphData, position, color, - style ); + style, + pixelFormat); // delete the glyphBitmap.buffer as it is now copied into glyphData.bitmapBuffer delete []glyphData.glyphBitmap.buffer; glyphData.glyphBitmap.buffer = NULL; @@ -518,6 +580,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth break; } + // Always RGBA image for text with styles uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( glyphData.bitmapBuffer.GetBuffer() ); uint32_t underlinePixel = *( bitmapBuffer + y * glyphData.width + x ); uint8_t* underlinePixelBuffer = reinterpret_cast( &underlinePixel ); @@ -565,6 +628,7 @@ Devel::PixelBuffer Typesetter::CombineImageBuffer( Devel::PixelBuffer topPixelBu return topPixelBuffer; } + // Always combine two RGBA images const unsigned int bufferSizeInt = bufferWidth * bufferHeight; const unsigned int bufferSizeChar = 4u * bufferSizeInt; diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.h b/dali-toolkit/internal/text/rendering/text-typesetter.h index c1408cc..285348e 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.h +++ b/dali-toolkit/internal/text/rendering/text-typesetter.h @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include #include #include #include @@ -103,10 +104,11 @@ public: * @param[in] size The renderer size. * @param[in] behaviour The behaviour of how to render the text (i.e. whether to render the text only or the styles only or both). * @param[in] ignoreHorizontalAlignment Whether to ignore the horizontal alignment (i.e. always render as if HORIZONTAL_ALIGN_BEGIN). + * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8). * * @return A pixel data with the text rendered. */ - PixelData Render( const Vector2& size, RenderBehaviour behaviour = RENDER_TEXT_AND_STYLES, bool ignoreHorizontalAlignment = false ); + PixelData Render( const Vector2& size, RenderBehaviour behaviour = RENDER_TEXT_AND_STYLES, bool ignoreHorizontalAlignment = false, Pixel::Format pixelFormat = Pixel::RGBA8888 ); private: /** @@ -134,16 +136,17 @@ private: * @param[in] bufferHeight The height of the image buffer. * @param[in] style The style of the text. * @param[in] ignoreHorizontalAlignment Whether to ignore the horizontal alignment, not ignored by default. + * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8). * @param[in] verticalOffset The vertical offset to be added to the glyph's position. * @param[in] fromGlyphIndex The index of the first glyph within the text to be drawn * @param[in] toGlyphIndex The index of the last glyph within the text to be drawn * * @return An image buffer with the text. */ - Devel::PixelBuffer CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, int verticalOffset, TextAbstraction::GlyphIndex fromGlyphIndex, TextAbstraction::GlyphIndex toGlyphIndex ); + Devel::PixelBuffer CreateImageBuffer( const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int verticalOffset, TextAbstraction::GlyphIndex fromGlyphIndex, TextAbstraction::GlyphIndex toGlyphIndex ); /** - * @brief Combine the two image buffers together. + * @brief Combine the two RGBA image buffers together. * * The top layer buffer will blend over the bottom layer buffer: * - If the pixel is not fully opaque from either buffer, it will be blended with @@ -159,7 +162,7 @@ private: * @return The combined image buffer with the text. * */ - Devel::PixelBuffer CombineImageBuffer( Devel::PixelBuffer topPixelBuffer, Devel::PixelBuffer bottomPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight ); + Devel::PixelBuffer CombineImageBuffer( Devel::PixelBuffer topPixelBuffer, Devel::PixelBuffer bottomPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeightbool ); protected: diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp index 3a0d319..1dcda36 100644 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -86,6 +86,16 @@ const LineRun* const ViewModel::GetLines() const return mModel->GetLines(); } +Length ViewModel::GetNumberOfScripts() const +{ + return mModel->GetNumberOfScripts(); +} + +const ScriptRun* const ViewModel::GetScriptRuns() const +{ + return mModel->GetScriptRuns(); +} + Length ViewModel::GetNumberOfGlyphs() const { if( mIsTextElided && mModel->IsTextElideEnabled() ) diff --git a/dali-toolkit/internal/text/rendering/view-model.h b/dali-toolkit/internal/text/rendering/view-model.h index df0e32c..e15fa9c 100644 --- a/dali-toolkit/internal/text/rendering/view-model.h +++ b/dali-toolkit/internal/text/rendering/view-model.h @@ -97,6 +97,16 @@ public: virtual const LineRun* const GetLines() const; /** + * @copydoc ModelInterface::GetNumberOfScripts() + */ + virtual Length GetNumberOfScripts() const; + + /** + * @copydoc ModelInterface::GetScriptRuns() + */ + virtual const ScriptRun* const GetScriptRuns() const; + + /** * @copydoc ModelInterface::GetNumberOfGlyphs() */ virtual Length GetNumberOfGlyphs() const; diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 054f4a7..898e2c6 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include namespace Dali { @@ -320,7 +322,8 @@ struct Controller::Impl mAutoScrollDirectionRTL( false ), mUnderlineSetByString( false ), mShadowSetByString( false ), - mFontStyleSetByString( false ) + mFontStyleSetByString( false ), + mShouldClearFocusOnEscape( true ) { mModel = Model::New(); @@ -336,6 +339,17 @@ struct Controller::Impl // Set the text properties to default mModel->mVisualModel->SetUnderlineEnabled( false ); mModel->mVisualModel->SetUnderlineHeight( 0.0f ); + + Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); + if( styleManager ) + { + bool temp; + Property::Map config = Toolkit::DevelStyleManager::GetConfigurations( styleManager ); + if( config["clearFocusOnEscape"].Get( temp ) ) + { + mShouldClearFocusOnEscape = temp; + } + } } ~Impl() @@ -730,6 +744,7 @@ public: bool mUnderlineSetByString:1; ///< Set when underline is set by string (legacy) instead of map bool mShadowSetByString:1; ///< Set when shadow is set by string (legacy) instead of map bool mFontStyleSetByString:1; ///< Set when font style is set by string (legacy) instead of map + bool mShouldClearFocusOnEscape:1; ///< Whether text control should clear key input focus }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 8b0ee5b..258fea7 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -686,7 +686,12 @@ void Controller::SetDefaultFontWeight( FontWeight weight ) bool Controller::IsDefaultFontWeightDefined() const { - return mImpl->mFontDefaults->weightDefined; + if( NULL != mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->weightDefined; + } + + return false; } FontWeight Controller::GetDefaultFontWeight() const @@ -752,7 +757,12 @@ void Controller::SetDefaultFontWidth( FontWidth width ) bool Controller::IsDefaultFontWidthDefined() const { - return mImpl->mFontDefaults->widthDefined; + if( NULL != mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->widthDefined; + } + + return false; } FontWidth Controller::GetDefaultFontWidth() const @@ -818,7 +828,11 @@ void Controller::SetDefaultFontSlant( FontSlant slant ) bool Controller::IsDefaultFontSlantDefined() const { - return mImpl->mFontDefaults->slantDefined; + if( NULL != mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->slantDefined; + } + return false; } FontSlant Controller::GetDefaultFontSlant() const @@ -2222,13 +2236,10 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) // Do nothing. return false; } - else if( Dali::DALI_KEY_ESCAPE == keyCode ) + else if( Dali::DALI_KEY_ESCAPE == keyCode || Dali::DALI_KEY_BACK == keyCode ) { - // Escape key is a special case which causes focus loss - KeyboardFocusLostEvent(); - - // Will request for relayout. - relayoutNeeded = true; + // Do nothing + return false; } else if( ( Dali::DALI_KEY_CURSOR_LEFT == keyCode ) || ( Dali::DALI_KEY_CURSOR_RIGHT == keyCode ) || @@ -3688,6 +3699,11 @@ void Controller::SetControlInterface( ControlInterface* controlInterface ) mImpl->mControlInterface = controlInterface; } +bool Controller::ShouldClearFocusOnEscape() const +{ + return mImpl->mShouldClearFocusOnEscape; +} + // private : Private contructors & copy operator. Controller::Controller() diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 5cb079c..9e193c7 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -1180,6 +1180,13 @@ public: // Text-input Event Queuing. */ void PasteClipboardItemEvent(); + /** + * @brief Return true when text control should clear key input focus when escape key is pressed. + * + * @return Whether text control should clear key input focus or not when escape key is pressed. + */ + bool ShouldClearFocusOnEscape() const; + protected: // Inherit from Text::Decorator::ControllerInterface. /** diff --git a/dali-toolkit/internal/text/text-model-interface.h b/dali-toolkit/internal/text/text-model-interface.h index d84b46a..38e1fa2 100644 --- a/dali-toolkit/internal/text/text-model-interface.h +++ b/dali-toolkit/internal/text/text-model-interface.h @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include #include +#include #include namespace Dali @@ -104,6 +105,20 @@ public: virtual const LineRun* const GetLines() const = 0; /** + * @brief Retrieves the number of script runs. + * + * @return The number of script runs. + */ + virtual Length GetNumberOfScripts() const = 0; + + /** + * @brief Retrieves the script runs. + * + * @return A pointer to the vector with the runs of characters with the same script.. + */ + virtual const ScriptRun* const GetScriptRuns() const = 0; + + /** * @brief Retrieves the number of laid-out glyphs. * * @return The number of laid-out glyphs. diff --git a/dali-toolkit/internal/text/text-model.cpp b/dali-toolkit/internal/text/text-model.cpp index 05cb405..2c00cf8 100644 --- a/dali-toolkit/internal/text/text-model.cpp +++ b/dali-toolkit/internal/text/text-model.cpp @@ -72,6 +72,16 @@ const LineRun* const Model::GetLines() const return mVisualModel->mLines.Begin(); } +Length Model::GetNumberOfScripts() const +{ + return mLogicalModel->mScriptRuns.Count(); +} + +const ScriptRun* const Model::GetScriptRuns() const +{ + return mLogicalModel->mScriptRuns.Begin(); +} + Length Model::GetNumberOfGlyphs() const { return mVisualModel->mGlyphs.Count(); diff --git a/dali-toolkit/internal/text/text-model.h b/dali-toolkit/internal/text/text-model.h index d8b08e9..a7b0bb8 100644 --- a/dali-toolkit/internal/text/text-model.h +++ b/dali-toolkit/internal/text/text-model.h @@ -100,6 +100,16 @@ public: virtual const LineRun* const GetLines() const; /** + * @copydoc ModelInterface::GetNumberOfScripts() + */ + virtual Length GetNumberOfScripts() const; + + /** + * @copydoc ModelInterface::GetScriptRuns() + */ + virtual const ScriptRun* const GetScriptRuns() const; + + /** * @copydoc ModelInterface::GetNumberOfGlyphs() */ virtual Length GetNumberOfGlyphs() const; diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp index be736e1..7c933ce 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -266,15 +266,26 @@ void AnimatedImageVisual::DoSetProperty( Property::Index index, case Toolkit::ImageVisual::Property::WRAP_MODE_U: { int wrapMode; - Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode ); - mWrapModeU = Dali::WrapMode::Type( wrapMode ); - break; + if(Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode )) + { + mWrapModeU = Dali::WrapMode::Type(wrapMode); + } + else + { + mWrapModeU = Dali::WrapMode::Type::DEFAULT; + } } case Toolkit::ImageVisual::Property::WRAP_MODE_V: { int wrapMode; - Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode ); - mWrapModeV = Dali::WrapMode::Type( wrapMode ); + if(Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode )) + { + mWrapModeV = Dali::WrapMode::Type(wrapMode); + } + else + { + mWrapModeV = Dali::WrapMode::Type::DEFAULT; + } break; } diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index 46cb2a1..2968f07 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL HEADER #include @@ -31,6 +32,7 @@ #include #include #include +#include namespace Dali { @@ -129,7 +131,7 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( }\n ); -const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER( +const char* FRAGMENT_SHADER_ATLAS_CLAMP_RGBA = DALI_COMPOSE_SHADER( varying mediump vec2 vTexCoord;\n uniform sampler2D sTexture;\n uniform sampler2D sStyle;\n @@ -160,6 +162,25 @@ const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER( }\n ); +const char* FRAGMENT_SHADER_ATLAS_CLAMP_L8 = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord;\n + uniform sampler2D sTexture;\n + uniform lowp vec4 uTextColorAnimatable;\n + uniform mediump vec4 uAtlasRect;\n + uniform lowp vec4 uColor;\n + uniform lowp vec3 mixColor;\n + uniform lowp float opacity;\n + \n + void main()\n + {\n + mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n + mediump float textTexture = texture2D( sTexture, texCoord ).r;\n + + // Set the color of the text to what it is animated to. + gl_FragColor = uTextColorAnimatable * textTexture * uColor * vec4( mixColor, opacity );\n + }\n +); + /** * Return Property index for the given string key * param[in] stringKey the string index key @@ -351,15 +372,7 @@ void TextVisual::DoSetOnStage( Actor& actor ) mControl = actor; Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - - Shader shader = mFactoryCache.GetShader( VisualFactoryCache::TEXT_SHADER ); - if( ! shader ) - { - shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP ); - shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); - - mFactoryCache.SaveShader( VisualFactoryCache::TEXT_SHADER, shader ); - } + Shader shader = GetTextShader(mFactoryCache, true); mImpl->mRenderer = Renderer::New( geometry, shader ); mImpl->mRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, Toolkit::DepthIndex::CONTENT ); @@ -545,66 +558,130 @@ void TextVisual::UpdateRenderer() if( ( relayoutSize.width > Math::MACHINE_EPSILON_1000 ) && ( relayoutSize.height > Math::MACHINE_EPSILON_1000 ) ) { - Vector4 atlasRect = FULL_TEXTURE_RECT; + // Check whether it is a markup text with multiple text colors + const Vector4* const colorsBuffer = mController->GetTextModel()->GetColors(); + bool hasMultipleTextColors = ( NULL != colorsBuffer ); + + // Check whether the text contains any emoji + bool containsEmoji = false; - // Create a texture for the text without any styles - PixelData data = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_NO_STYLES ); + Text::ScriptRunIndex numberOfScripts = mController->GetTextModel()->GetNumberOfScripts(); + const Text::ScriptRun* scripts = mController->GetTextModel()->GetScriptRuns(); + for ( Text::ScriptRunIndex scriptIndex = 0u; scriptIndex < numberOfScripts; scriptIndex++ ) + { + const Text::ScriptRun& scriptRun = *( scripts + scriptIndex ); + if( TextAbstraction::EMOJI == scriptRun.script ) + { + containsEmoji = true; + break; + } + } + + // Check whether the text contains any style colors (e.g. underline color, shadow color, etc.) + bool shadowEnabled = false; + const Vector2& shadowOffset = mController->GetTextModel()->GetShadowOffset(); + if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 ) + { + shadowEnabled = true; + } + + const bool underlineEnabled = mController->GetTextModel()->IsUnderlineEnabled(); + + if ( hasMultipleTextColors || containsEmoji || shadowEnabled || underlineEnabled ) + { + // Create RGBA textures if the text contains emojis or styles or multiple text colors - // It may happen the image atlas can't handle a pixel data it exceeds the maximum size. - // In that case, create a texture. TODO: should tile the text. + // Create a texture for the text without any styles + PixelData data = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_NO_STYLES ); - Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, - data.GetPixelFormat(), - data.GetWidth(), - data.GetHeight() ); + // It may happen the image atlas can't handle a pixel data it exceeds the maximum size. + // In that case, create a texture. TODO: should tile the text. - texture.Upload( data ); + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, + data.GetPixelFormat(), + data.GetWidth(), + data.GetHeight() ); - TextureSet textureSet = TextureSet::New(); - textureSet.SetTexture( 0u, texture ); + texture.Upload( data ); - // Create a texture for all the text styles (without the text itself) - PixelData styleData = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_NO_TEXT ); + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture( 0u, texture ); - Texture styleTexture = Texture::New( Dali::TextureType::TEXTURE_2D, - styleData.GetPixelFormat(), - styleData.GetWidth(), - styleData.GetHeight() ); + // Create a texture for all the text styles (without the text itself) + PixelData styleData = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_NO_TEXT ); - styleTexture.Upload( styleData ); + Texture styleTexture = Texture::New( Dali::TextureType::TEXTURE_2D, + styleData.GetPixelFormat(), + styleData.GetWidth(), + styleData.GetHeight() ); - textureSet.SetTexture( 1u, styleTexture ); + styleTexture.Upload( styleData ); - // Create a texture as a mask to avoid color glyphs (e.g. emojis) to be affected by text color animation - PixelData maskData = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_MASK ); + textureSet.SetTexture( 1u, styleTexture ); - Texture maskTexture = Texture::New( Dali::TextureType::TEXTURE_2D, - styleData.GetPixelFormat(), - styleData.GetWidth(), - styleData.GetHeight() ); + // Create a texture as a mask to avoid color glyphs (e.g. emojis) to be affected by text color animation + PixelData maskData = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_MASK ); - maskTexture.Upload( maskData ); + Texture maskTexture = Texture::New( Dali::TextureType::TEXTURE_2D, + styleData.GetPixelFormat(), + styleData.GetWidth(), + styleData.GetHeight() ); - textureSet.SetTexture( 2u, maskTexture ); + maskTexture.Upload( maskData ); - // Filter mode needs to be set to linear to produce better quality while scaling. - Sampler sampler = Sampler::New(); - sampler.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); - textureSet.SetSampler( 0u, sampler ); - textureSet.SetSampler( 1u, sampler ); - textureSet.SetSampler( 2u, sampler ); + textureSet.SetTexture( 2u, maskTexture ); - mImpl->mRenderer.SetTextures( textureSet ); + // Filter mode needs to be set to nearest to produce better quality while static. + Sampler sampler = Sampler::New(); + sampler.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); + textureSet.SetSampler( 0u, sampler ); + textureSet.SetSampler( 1u, sampler ); + textureSet.SetSampler( 2u, sampler ); + + mImpl->mRenderer.SetTextures( textureSet ); + + Shader shader = GetTextShader(mFactoryCache, true); // RGBA shader + mImpl->mRenderer.SetShader(shader); + } + else + { + // Create L8 texture if the text contains only single text color with no emoji and no style + + // Create a texture for the text without any styles + PixelData data = mTypesetter->Render( relayoutSize, Text::Typesetter::RENDER_NO_STYLES, false, Pixel::L8 ); + + // It may happen the image atlas can't handle a pixel data it exceeds the maximum size. + // In that case, create a texture. TODO: should tile the text. + + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, + data.GetPixelFormat(), + data.GetWidth(), + data.GetHeight() ); + + texture.Upload( data ); + + TextureSet textureSet = TextureSet::New(); + textureSet.SetTexture( 0u, texture ); + + // Filter mode needs to be set to nearest to produce better quality while static. + Sampler sampler = Sampler::New(); + sampler.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); + textureSet.SetSampler( 0u, sampler ); + + mImpl->mRenderer.SetTextures( textureSet ); + + Shader shader = GetTextShader(mFactoryCache, false); // L8 shader + mImpl->mRenderer.SetShader(shader); + } mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + Vector4 atlasRect = FULL_TEXTURE_RECT; mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, atlasRect ); - - // Check whether it is a markup text with multiple text colors - const Vector4* const colorsBuffer = mController->GetTextModel()->GetColors(); - bool hasMultipleTextColors = ( NULL != colorsBuffer ); mImpl->mRenderer.RegisterProperty( "uHasMultipleTextColors", static_cast( hasMultipleTextColors ) ); + mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON); + //Register transform properties mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); @@ -635,6 +712,33 @@ void TextVisual::RemoveTextureSet() } } +Shader TextVisual::GetTextShader( VisualFactoryCache& factoryCache, bool isRgbaTexture ) +{ + Shader shader; + if( isRgbaTexture ) + { + shader = factoryCache.GetShader( VisualFactoryCache::TEXT_SHADER_RGBA ); + if( !shader ) + { + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP_RGBA ); + shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); + factoryCache.SaveShader( VisualFactoryCache::TEXT_SHADER_RGBA, shader ); + } + } + else + { + shader = factoryCache.GetShader( VisualFactoryCache::TEXT_SHADER_L8 ); + if( !shader ) + { + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP_L8 ); + shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); + factoryCache.SaveShader( VisualFactoryCache::TEXT_SHADER_L8, shader ); + } + } + + return shader; +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/visuals/text/text-visual.h b/dali-toolkit/internal/visuals/text/text-visual.h index 2ed7bee..31353b9 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.h +++ b/dali-toolkit/internal/visuals/text/text-visual.h @@ -192,6 +192,13 @@ private: void RemoveTextureSet(); /** + * Get the text rendering shader. + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @param[in] isRgbaTexture Whether the texture is in RGBA format. + */ + Shader GetTextShader( VisualFactoryCache& factoryCache, bool isRgbaTexture ); + + /** * @brief Retrieve the text's controller. * @param[in] visual The text visual. * @return The text controller diff --git a/dali-toolkit/internal/visuals/texture-manager.cpp b/dali-toolkit/internal/visuals/texture-manager.cpp index 824213e..9468935 100644 --- a/dali-toolkit/internal/visuals/texture-manager.cpp +++ b/dali-toolkit/internal/visuals/texture-manager.cpp @@ -19,18 +19,45 @@ #include "texture-manager.h" // EXTERNAL HEADERS +#include +#include #include #include #include #include // INTERNAL HEADERS -#include -#include #include -#include #include +namespace +{ + +constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS = size_t{4u}; +constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS = size_t{8u}; + +constexpr auto NUMBER_OF_LOCAL_LOADER_THREADS_ENV = "DALI_TEXTURE_LOCAL_THREADS"; +constexpr auto NUMBER_OF_REMOTE_LOADER_THREADS_ENV = "DALI_TEXTURE_REMOTE_THREADS"; + +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; +} + +size_t GetNumberOfLocalLoaderThreads() +{ + return GetNumberOfThreads(NUMBER_OF_LOCAL_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS); +} + +size_t GetNumberOfRemoteLoaderThreads() +{ + return GetNumberOfThreads(NUMBER_OF_REMOTE_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS); +} + +} // namespace namespace Dali { @@ -58,12 +85,10 @@ const int INVALID_CACHE_INDEX( -1 ); ///< Invalid Cache index TextureManager::TextureManager() -: mAsyncLocalLoader( Toolkit::AsyncImageLoader::New() ), - mAsyncRemoteLoader( Toolkit::AsyncImageLoader::New() ), - mCurrentTextureId( 0 ) +: mCurrentTextureId( 0 ), + mAsyncLocalLoaders( GetNumberOfLocalLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); } ), + mAsyncRemoteLoaders( GetNumberOfRemoteLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); } ) { - DevelAsyncImageLoader::PixelBufferLoadedSignal(mAsyncLocalLoader).Connect( this, &TextureManager::AsyncLocalLoadComplete ); - DevelAsyncImageLoader::PixelBufferLoadedSignal(mAsyncRemoteLoader).Connect( this, &TextureManager::AsyncRemoteLoadComplete ); } TextureManager::TextureId TextureManager::RequestLoad( @@ -294,22 +319,12 @@ bool TextureManager::LoadTexture( TextureInfo& textureInfo ) if( !textureInfo.loadSynchronously ) { - if( textureInfo.url.IsLocal() ) - { - mAsyncLocalLoadingInfoContainer.push_back( AsyncLoadingInfo( textureInfo.textureId ) ); - mAsyncLocalLoadingInfoContainer.back().loadId = - GetImplementation(mAsyncLocalLoader).Load( textureInfo.url, textureInfo.desiredSize, - textureInfo.fittingMode, - textureInfo.samplingMode, true ); - } - else - { - mAsyncRemoteLoadingInfoContainer.push_back( AsyncLoadingInfo( textureInfo.textureId ) ); - mAsyncRemoteLoadingInfoContainer.back().loadId = - GetImplementation(mAsyncRemoteLoader).Load( textureInfo.url, textureInfo.desiredSize, - textureInfo.fittingMode, - textureInfo.samplingMode, true ); - } + auto& loadersContainer = textureInfo.url.IsLocal() ? mAsyncLocalLoaders : mAsyncRemoteLoaders; + auto loadingHelperIt = loadersContainer.GetNext(); + DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End()); + loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, + textureInfo.desiredSize, textureInfo.fittingMode, + textureInfo.samplingMode, true); } } @@ -326,16 +341,6 @@ void TextureManager::ObserveTexture( TextureInfo& textureInfo, } } -void TextureManager::AsyncLocalLoadComplete( uint32_t id, Devel::PixelBuffer pixelBuffer ) -{ - AsyncLoadComplete( mAsyncLocalLoadingInfoContainer, id, pixelBuffer ); -} - -void TextureManager::AsyncRemoteLoadComplete( uint32_t id, Devel::PixelBuffer pixelBuffer ) -{ - AsyncLoadComplete( mAsyncRemoteLoadingInfoContainer, id, pixelBuffer ); -} - void TextureManager::AsyncLoadComplete( AsyncLoadingInfoContainerType& loadingContainer, uint32_t id, Devel::PixelBuffer pixelBuffer ) { DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( id:%d )\n", id ); @@ -674,13 +679,48 @@ void TextureManager::ObserverDestroyed( TextureUploadObserver* observer ) TextureManager::~TextureManager() { - mTextureInfoContainer.clear(); - mAsyncLocalLoadingInfoContainer.clear(); - mAsyncRemoteLoadingInfoContainer.clear(); } +TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(TextureManager& textureManager) +: AsyncLoadingHelper(Toolkit::AsyncImageLoader::New(), textureManager, + AsyncLoadingInfoContainerType()) +{ +} +void TextureManager::AsyncLoadingHelper::Load(TextureId textureId, + const VisualUrl& url, + ImageDimensions desiredSize, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode, + bool orientationCorrection) +{ + mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId)); + auto id = mLoader.Load(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection); + mLoadingInfoContainer.back().loadId = id; +} +TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(AsyncLoadingHelper&& rhs) +: AsyncLoadingHelper(rhs.mLoader, rhs.mTextureManager, std::move(rhs.mLoadingInfoContainer)) +{ +} + +TextureManager::AsyncLoadingHelper::AsyncLoadingHelper( + Toolkit::AsyncImageLoader loader, + TextureManager& textureManager, + AsyncLoadingInfoContainerType&& loadingInfoContainer) +: mLoader(loader), + mTextureManager(textureManager), + mLoadingInfoContainer(std::move(loadingInfoContainer)) +{ + DevelAsyncImageLoader::PixelBufferLoadedSignal(mLoader).Connect( + this, &AsyncLoadingHelper::AsyncLoadComplete); +} + +void TextureManager::AsyncLoadingHelper::AsyncLoadComplete(uint32_t id, + Devel::PixelBuffer pixelBuffer) +{ + mTextureManager.AsyncLoadComplete(mLoadingInfoContainer, id, pixelBuffer); +} } // namespace Internal diff --git a/dali-toolkit/internal/visuals/texture-manager.h b/dali-toolkit/internal/visuals/texture-manager.h index 5e07735..090846e 100644 --- a/dali-toolkit/internal/visuals/texture-manager.h +++ b/dali-toolkit/internal/visuals/texture-manager.h @@ -18,19 +18,23 @@ */ // EXTERNAL INCLUDES +#include +#include #include #include #include #include #include #include -#include // INTERNAL INCLUDES +#include #include #include #include #include +#include +#include namespace Dali @@ -485,18 +489,75 @@ private: const bool useAtlas, TextureId maskTextureId ); +private: + + /** + * @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container + */ + class AsyncLoadingHelper : public ConnectionTracker + { + public: + /** + * @brief Create an AsyncLoadingHelper. + * @param[in] textureManager Reference to the texture manager + */ + AsyncLoadingHelper(TextureManager& textureManager); + + /** + * @brief Load a new texture. + * @param[in] textureId TextureId to reference the texture that will be loaded + * @param[in] url The URL of the image to load + * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic + * @param[in] fittingMode The FittingMode to use + * @param[in] samplingMode The SamplingMode to use + * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image, e.g., from portrait to landscape + */ + void Load(TextureId textureId, + const VisualUrl& url, + ImageDimensions desiredSize, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode, + bool orientationCorrection); + + public: + AsyncLoadingHelper(const AsyncLoadingHelper&) = delete; + AsyncLoadingHelper& operator=(const AsyncLoadingHelper&) = delete; + + AsyncLoadingHelper(AsyncLoadingHelper&& rhs); + AsyncLoadingHelper& operator=(AsyncLoadingHelper&&rhs) = delete; + + private: + /** + * @brief Main constructor that used by all other constructors + */ + AsyncLoadingHelper(Toolkit::AsyncImageLoader loader, + TextureManager& textureManager, + AsyncLoadingInfoContainerType&& loadingInfoContainer); + + /** + * @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager. + * @param[in] id Loader id + * @param[in] pixelBuffer Image data + */ + void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer); + + private: + Toolkit::AsyncImageLoader mLoader; + TextureManager& mTextureManager; + AsyncLoadingInfoContainerType mLoadingInfoContainer; + }; private: /** - * Undefined copy constructor. + * Deleted copy constructor. */ - TextureManager( const TextureManager& ); + TextureManager( const TextureManager& ) = delete; /** - * Undefined assignment operator. + * Deleted assignment operator. */ - TextureManager& operator=( const TextureManager& rhs ); + TextureManager& operator=( const TextureManager& rhs ) = delete; /** * This is called by the TextureManagerUploadObserver when an observer is destroyed. @@ -507,14 +568,12 @@ private: private: // Member Variables: - AsyncLoadingInfoContainerType mAsyncLocalLoadingInfoContainer; ///< Used to manage Asynchronous loads in progress - AsyncLoadingInfoContainerType mAsyncRemoteLoadingInfoContainer; ///< Used to manage Asynchronous loads in progress - AtlasInfoContainerType mAtlasContainer; ///< Used to manage Atlas creation and destruction - TextureInfoContainerType mTextureInfoContainer; ///< Used to manage the life-cycle and caching of Textures - Toolkit::AsyncImageLoader mAsyncLocalLoader; ///< The Asynchronous image loader used to provide all local async loads - Toolkit::AsyncImageLoader mAsyncRemoteLoader; ///< The Asynchronous image loader used to provide all remote async loads - TextureId mCurrentTextureId; ///< The current value used for the unique Texture Id generation + AtlasInfoContainerType mAtlasContainer; ///< Used to manage Atlas creation and destruction + TextureInfoContainerType mTextureInfoContainer; ///< Used to manage the life-cycle and caching of Textures + TextureId mCurrentTextureId; ///< The current value used for the unique Texture Id generation + RoundRobinContainerView mAsyncLocalLoaders; ///< The Asynchronous image loaders used to provide all local async loads + RoundRobinContainerView mAsyncRemoteLoaders; ///< The Asynchronous image loaders used to provide all remote async loads }; diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.h b/dali-toolkit/internal/visuals/visual-factory-cache.h index cc68e0f..17d2246 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.h +++ b/dali-toolkit/internal/visuals/visual-factory-cache.h @@ -69,7 +69,8 @@ public: IMAGE_SHADER_ATLAS_CUSTOM_WRAP, NINE_PATCH_SHADER, SVG_SHADER, - TEXT_SHADER, + TEXT_SHADER_RGBA, + TEXT_SHADER_L8, WIREFRAME_SHADER, SHADER_TYPE_MAX = WIREFRAME_SHADER }; diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 07f851c..8417ead 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 = 2; -const unsigned int TOOLKIT_MICRO_VERSION = 55; +const unsigned int TOOLKIT_MICRO_VERSION = 56; const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali-toolkit/public-api/visuals/image-visual-properties.h b/dali-toolkit/public-api/visuals/image-visual-properties.h index 44d5692..8eff9fa 100644 --- a/dali-toolkit/public-api/visuals/image-visual-properties.h +++ b/dali-toolkit/public-api/visuals/image-visual-properties.h @@ -56,6 +56,9 @@ enum * @brief The URL of the image. * @details Name "url", type Property::STRING or Property::ARRAY of Property::STRING * @note The array form is used for generating animated image visuals. + * @note The number of threads used for local and remote image loading can be controlled by the + * environment variables DALI_TEXTURE_LOCAL_THREADS and DALI_TEXTURE_REMOTE_THREADS respectively. + * The default values are 4 threads for local image loading and 8 threads for remote image loading. * @SINCE_1_1.45 * @note Mandatory. */ diff --git a/dali-toolkit/styles/1920x1080/dali-toolkit-default-theme.json b/dali-toolkit/styles/1920x1080/dali-toolkit-default-theme.json index dd06d35..7d78ed4 100644 --- a/dali-toolkit/styles/1920x1080/dali-toolkit-default-theme.json +++ b/dali-toolkit/styles/1920x1080/dali-toolkit-default-theme.json @@ -28,7 +28,8 @@ { "config": { - "alwaysShowFocus":false + "alwaysShowFocus":false, + "clearFocusOnEscape":false }, "styles": { diff --git a/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json b/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json index 8612b3c..460d0f8 100644 --- a/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json +++ b/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json @@ -28,7 +28,8 @@ { "config": { - "alwaysShowFocus":false + "alwaysShowFocus":false, + "clearFocusOnEscape":true }, "styles": { diff --git a/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json b/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json index 0c48655..9390546 100644 --- a/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json +++ b/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json @@ -28,7 +28,8 @@ { "config": { - "alwaysShowFocus":false + "alwaysShowFocus":false, + "clearFocusOnEscape":true }, "styles": { diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 09b9373..fc6b10e 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali-toolkit -Summary: The OpenGLES Canvas Core Library Toolkit -Version: 1.2.55 +Summary: Dali 3D engine Toolkit +Version: 1.2.56 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT @@ -10,15 +10,25 @@ Source0: %{name}-%{version}.tar.gz Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig +%if 0%{?tizen_version_major} < 4 +%define disable_cxx03_build 1 +%endif + BuildRequires: pkgconfig BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(dali-core) +%if !0%{?disable_cxx03_build} +BuildRequires: pkgconfig(dali-core-cxx03) +%endif BuildRequires: gettext # dali-toolkit only need to know the interfaces(APIs) of dali-adaptor(the devel package). # It doesn't need to know which adaptor will be used by applications. # Applications or dali-addon will decide which one they will use. BuildRequires: dali-adaptor-devel +%if !0%{?disable_cxx03_build} +BuildRequires: dali-adaptor-devel-cxx03 +%endif #need libtzplatform-config for directory if tizen version is 3.x @@ -35,7 +45,7 @@ BuildRequires: pkgconfig(libtzplatform-config) %endif %description -The OpenGLES Canvas Core Library Toolkit - a set of controls that provide +Dali 3D engine Toolkit - a set of controls that provide user interface functionality. ############################## @@ -68,16 +78,25 @@ Conflicts: %{name}-resources_720x1280 dali-toolkit default resource files for 1920x1080 Contain po / sounds / common images / style / style images +%if !0%{?disable_cxx03_build} +%package cxx03 +Summary: Dali 3D engine Toolkit with cxx03 +Provides: %{name}-cxx03 = %{version}-%{release} + +%description cxx03 +Dali 3D engine Toolkit with cxx03 +%endif + ############################## # devel ############################## %package devel -Summary: Application development package for the OpenGLES Canvas toolkit +Summary: Application development package for Dali 3D engine toolkit Group: Development/Building Requires: %{name} = %{version}-%{release} %description devel -Application development package for the OpenGLES Canvas toolkit - headers and package config +Application development package for Dali 3D engine toolkit - headers and package config ############################## # Preparation @@ -133,18 +152,52 @@ DALI_DATA_RO_DIR="%{dali_data_ro_dir}" ; export DALI_DATA_RO_DIR %if 0%{?enable_debug} --enable-debug \ %endif - --enable-i18n=yes + --enable-i18n=yes \ + --enable-rename-so=no make %{?jobs:-j%jobs} +pushd %{_builddir}/%{name}-%{version}/build/tizen +%make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}" +popd + +pushd %{buildroot}%{_libdir} +for FILE in libdali-toolkit-cxx11.so*; do mv "$FILE" "%{_builddir}/%{name}-%{version}/build/tizen/$FILE"; done +mv pkgconfig/dali-toolkit.pc %{_builddir}/%{name}-%{version}/build/tizen/dali-toolkit.pc +popd + +%if !0%{?disable_cxx03_build} +make clean + +libtoolize --force +cd %{_builddir}/dali-toolkit-%{version}/build/tizen +autoreconf --install + +DALI_DATA_RW_DIR="%{dali_data_rw_dir}" ; export DALI_DATA_RW_DIR +DALI_DATA_RO_DIR="%{dali_data_ro_dir}" ; export DALI_DATA_RO_DIR + +%configure --enable-profile=TIZEN \ + --enable-cxx03-abi=yes \ +%if 0%{?enable_debug} + --enable-debug \ +%endif + --enable-i18n=yes \ + --enable-rename-so=no + +make %{?jobs:-j%jobs} +%endif + ############################## # Installation ############################## %install rm -rf %{buildroot} -pushd build/tizen +pushd %{_builddir}/%{name}-%{version}/build/tizen %make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}" +for FILE in libdali-toolkit-cxx11.so*; do mv "$FILE" "%{buildroot}%{_libdir}/$FILE"; done +mv dali-toolkit.pc %{buildroot}%{_libdir}/pkgconfig/dali-toolkit.pc + # PO { cd %{_builddir}/dali-toolkit-%{version}/dali-toolkit/po @@ -157,6 +210,18 @@ done } &> /dev/null popd +############################# +#rename +############################# +pushd %{buildroot}%{_libdir} +rm -rf libdali-toolkit.so +rm -rf libdali-toolkit-cxx11.so +%if !0%{?disable_cxx03_build} +ln -s libdali-toolkit.so.0.0.* libdali-toolkit-cxx03.so +%endif +ln -s libdali-toolkit-cxx11.so.0.0.* libdali-toolkit.so +popd + # Remove default style and style images which are for Linux build rm -rf %{buildroot}%{dali_toolkit_style_files}/* @@ -279,13 +344,27 @@ popd %manifest dali-toolkit.manifest %endif %defattr(-,root,root,-) -%{_libdir}/lib%{name}.so* +%{_libdir}/libdali-toolkit-cxx11.so.* +%{_libdir}/libdali-toolkit.so +%license LICENSE + +%if !0%{?disable_cxx03_build} +%files cxx03 +%if 0%{?enable_dali_smack_rules} +%manifest dali-toolkit.manifest-smack +%else +%manifest dali-toolkit.manifest +%endif +%defattr(-,root,root,-) +%{_libdir}/libdali-toolkit.so.* +%{_libdir}/libdali-toolkit-cxx03.so %license LICENSE +%endif %files devel %defattr(-,root,root,-) -%{dev_include_path}/%{name}/* -%{_libdir}/pkgconfig/*.pc +%{dev_include_path}/dali-toolkit/* +%{_libdir}/pkgconfig/dali-toolkit.pc %files resources_480x800 %manifest dali-toolkit-resources.manifest