From: Adeel Kazmi Date: Thu, 13 May 2021 12:01:21 +0000 (+0100) Subject: Merge branch 'devel/master' into devel/graphics X-Git-Tag: dali_2.0.28~3^2~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=9161d9828d1a5bb3c7eaf83002863de84b23b751;hp=68d3700c2fe64a0f09c654840672f6d93ae8f35f Merge branch 'devel/master' into devel/graphics Change-Id: Ie1526bf82b84f25cf1cfbd1ccf77d2033bd38190 --- diff --git a/automated-tests/.gitignore b/automated-tests/.gitignore index b12e784..17d54d9 100644 --- a/automated-tests/.gitignore +++ b/automated-tests/.gitignore @@ -2,5 +2,5 @@ build build.log tct*core.h -CMakeLists.txt +/CMakeLists.txt results_xml.* diff --git a/automated-tests/resources/shape.riv b/automated-tests/resources/shape.riv new file mode 100644 index 0000000..2450a94 Binary files /dev/null and b/automated-tests/resources/shape.riv differ diff --git a/automated-tests/src/dali-scene-loader/CMakeLists.txt b/automated-tests/src/dali-scene-loader/CMakeLists.txt index 108a3c4..7ac6035 100755 --- a/automated-tests/src/dali-scene-loader/CMakeLists.txt +++ b/automated-tests/src/dali-scene-loader/CMakeLists.txt @@ -16,6 +16,7 @@ SET(TC_SOURCES utc-Dali-Gltf2Loader.cpp utc-Dali-KtxLoader.cpp utc-Dali-MatrixStack.cpp + utc-Dali-MeshDefinition.cpp utc-Dali-NodeDefinition.cpp utc-Dali-RendererState.cpp utc-Dali-ResourceBundle.cpp diff --git a/automated-tests/src/dali-scene-loader/utc-Dali-MeshDefinition.cpp b/automated-tests/src/dali-scene-loader/utc-Dali-MeshDefinition.cpp new file mode 100644 index 0000000..37c170b --- /dev/null +++ b/automated-tests/src/dali-scene-loader/utc-Dali-MeshDefinition.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "dali-scene-loader/public-api/mesh-definition.h" +#include + +using namespace Dali; +using namespace Dali::SceneLoader; + +int UtcDaliMeshDefinitionBlobApplyMinMaxBothMinMaxApplied(void) +{ + using Container = std::vector; + + Container buffer = { 4.0f, 6.0f, 8.0f, 10.0f, 12.0f }; + Container minValues = { 5.0f }; + Container maxValues = { 10.0f }; + Container result = {5.0f, 6.0f, 8.0f, 10.0f, 10.0f}; + + MeshDefinition::Blob::ApplyMinMax(minValues, maxValues, 5, buffer.data()); + + for( auto i = 0u; i < result.size(); ++i) + { + DALI_TEST_EQUALS(buffer[i], result[i], TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliMeshDefinitionBlobApplyMinMaxOnlyMin(void) +{ + using Container = std::vector; + + Container buffer = { 4.0f, 6.0f, 8.0f, 10.0f, 12.0f }; + Container minValues = { 5.0f }; + Container maxValues = {}; + Container result = {5.0f, 6.0f, 8.0f, 10.0f, 12.0f}; + + MeshDefinition::Blob::ApplyMinMax(minValues, maxValues, 5, buffer.data()); + + for( auto i = 0u; i < result.size(); ++i) + { + DALI_TEST_EQUALS(buffer[i], result[i], TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliMeshDefinitionBlobApplyMinMaxOnlyMax(void) +{ + using Container = std::vector; + + Container buffer = { 4.0f, 6.0f, 8.0f, 10.0f, 12.0f }; + Container minValues = { }; + Container maxValues = { 10.0f }; + Container result = {4.0f, 6.0f, 8.0f, 10.0f, 10.0f}; + + MeshDefinition::Blob::ApplyMinMax(minValues, maxValues, 5, buffer.data()); + + for( auto i = 0u; i < result.size(); ++i) + { + DALI_TEST_EQUALS(buffer[i], result[i], TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliMeshDefinitionBlobApplyMinMaxBothEmpty(void) +{ + using Container = std::vector; + + Container buffer = { 4.0f, 6.0f, 8.0f, 10.0f, 12.0f }; + Container minValues; + Container maxValues; + Container result = {4.0f, 6.0f, 8.0f, 10.0f, 12.0f}; + + MeshDefinition::Blob::ApplyMinMax(minValues, maxValues, 5, buffer.data()); + + for( auto i = 0u; i < result.size(); ++i) + { + DALI_TEST_EQUALS(buffer[i], result[i], TEST_LOCATION); + } + + END_TEST; +} + diff --git a/automated-tests/src/dali-shader-generator/CMakeLists.txt b/automated-tests/src/dali-shader-generator/CMakeLists.txt new file mode 100644 index 0000000..4ef7ac6 --- /dev/null +++ b/automated-tests/src/dali-shader-generator/CMakeLists.txt @@ -0,0 +1,133 @@ +SET(PKG_NAME "dali-shader-generator") + +SET(EXEC_NAME "tct-${PKG_NAME}-core") +SET(EXEC_NAME "tct-${PKG_NAME}-core") + +SET(CAPI_LIB "dali-shader-generator") + +PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED + dali2-core + dali2-adaptor + dali2-toolkit +) + +SET(TC_SOURCES + utc-Dali-ShaderGenerator.cpp +) + +# List of test harness files (Won't get parsed for test cases) +SET(TEST_HARNESS_DIR "../dali-toolkit/dali-toolkit-test-utils") + +SET(TEST_HARNESS_SOURCES + ${TEST_HARNESS_DIR}/toolkit-adaptor.cpp + ${TEST_HARNESS_DIR}/toolkit-application.cpp + ${TEST_HARNESS_DIR}/toolkit-event-thread-callback.cpp + ${TEST_HARNESS_DIR}/toolkit-environment-variable.cpp + ${TEST_HARNESS_DIR}/toolkit-input-method-context.cpp + ${TEST_HARNESS_DIR}/toolkit-input-method-options.cpp + ${TEST_HARNESS_DIR}/toolkit-lifecycle-controller.cpp + ${TEST_HARNESS_DIR}/toolkit-orientation.cpp + ${TEST_HARNESS_DIR}/toolkit-style-monitor.cpp + ${TEST_HARNESS_DIR}/toolkit-test-application.cpp + ${TEST_HARNESS_DIR}/toolkit-timer.cpp + ${TEST_HARNESS_DIR}/toolkit-trigger-event-factory.cpp + ${TEST_HARNESS_DIR}/toolkit-window.cpp + ${TEST_HARNESS_DIR}/toolkit-scene-holder.cpp + ${TEST_HARNESS_DIR}/dali-test-suite-utils.cpp + ${TEST_HARNESS_DIR}/dali-toolkit-test-suite-utils.cpp + ${TEST_HARNESS_DIR}/dummy-control.cpp + ${TEST_HARNESS_DIR}/mesh-builder.cpp + ${TEST_HARNESS_DIR}/test-actor-utils.cpp + ${TEST_HARNESS_DIR}/test-animation-data.cpp + ${TEST_HARNESS_DIR}/test-application.cpp + ${TEST_HARNESS_DIR}/test-button.cpp + ${TEST_HARNESS_DIR}/test-harness.cpp + ${TEST_HARNESS_DIR}/test-gesture-generator.cpp + ${TEST_HARNESS_DIR}/test-gl-abstraction.cpp + ${TEST_HARNESS_DIR}/test-gl-sync-abstraction.cpp + ${TEST_HARNESS_DIR}/test-graphics-buffer.cpp + ${TEST_HARNESS_DIR}/test-graphics-command-buffer.cpp + ${TEST_HARNESS_DIR}/test-graphics-controller.cpp + ${TEST_HARNESS_DIR}/test-graphics-framebuffer.cpp + ${TEST_HARNESS_DIR}/test-graphics-texture.cpp + ${TEST_HARNESS_DIR}/test-graphics-sampler.cpp + ${TEST_HARNESS_DIR}/test-graphics-program.cpp + ${TEST_HARNESS_DIR}/test-graphics-pipeline.cpp + ${TEST_HARNESS_DIR}/test-graphics-shader.cpp + ${TEST_HARNESS_DIR}/test-graphics-reflection.cpp + ${TEST_HARNESS_DIR}/test-platform-abstraction.cpp + ${TEST_HARNESS_DIR}/test-render-controller.cpp + ${TEST_HARNESS_DIR}/test-trace-call-stack.cpp +) + +ADD_DEFINITIONS(-DTEST_RESOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../../resources\" ) + +FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS}) + SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -L${directory}") +ENDFOREACH(directory ${CAPI_LIB_LIBRARY_DIRS}) + +INCLUDE_DIRECTORIES( + ../../../ + ${${CAPI_LIB}_INCLUDE_DIRS} + ../dali-toolkit/dali-toolkit-test-utils +) + +ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror -DDEBUG_ENABLED) +ADD_COMPILE_OPTIONS( ${${CAPI_LIB}_CFLAGS_OTHER} ) + +ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.h ${EXEC_NAME}.cpp ${TC_SOURCES} ${TEST_HARNESS_SOURCES}) + +TARGET_LINK_LIBRARIES(${EXEC_NAME} + ${${CAPI_LIB}_LIBRARIES} + -lpthread --coverage +) + +ADD_CUSTOM_COMMAND( + COMMAND ${SCRIPT_DIR}/tcheadgen.sh ${EXEC_NAME}.h ${TC_SOURCES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT ${EXEC_NAME}.h + COMMENT "Generating test tables" +) + +INSTALL(PROGRAMS ${EXEC_NAME} + DESTINATION ${BIN_DIR}/${EXEC_NAME} +) + +SET(SHADER_GENERATOR dali-shader-generator) +SET(GENERATED_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/shader/generated) +SET(SHADER_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/shader) + +# All the shader generator execution tests are below + +ADD_CUSTOM_TARGET(test_help ALL COMMAND ${SHADER_GENERATOR} -h | grep "DALi Shader Generator" > /dev/null 2>&1 && echo "test_help Succeeded" VERBATIM) +ADD_CUSTOM_TARGET(test_no_params ALL COMMAND ${SHADER_GENERATOR} > /dev/null 2>&1 || echo "test_no_params Succeeded" VERBATIM) +ADD_CUSTOM_TARGET(test_version ALL COMMAND ${SHADER_GENERATOR} -v | wc -l | grep 1 > /dev/null 2>&1 && echo "test_version Succeeded" VERBATIM) +ADD_CUSTOM_TARGET(test_invalid_option ALL COMMAND ${SHADER_GENERATOR} --undeclared > /dev/null 2>&1 || echo "test_invalid_option Succeeded" VERBATIM) +ADD_CUSTOM_TARGET(test_too_many_params ALL COMMAND ${SHADER_GENERATOR} ONE TWO THREE > /dev/null 2>&1 || echo "test_too_many_params Succeeded" VERBATIM) +ADD_CUSTOM_TARGET(test_invalid_indir ALL COMMAND ${SHADER_GENERATOR} ONE TWO > /dev/null 2>&1 || echo "test_invalid_indir Succeeded" VERBATIM) +ADD_CUSTOM_TARGET( + test_check_built_in_created + ALL + COMMAND ${SHADER_GENERATOR} . ${GENERATED_FOLDER} | grep builtin-shader | wc -l | grep 2 > /dev/null 2>&1 && echo "test_check_built_in_created Succeeded" + VERBATIM) +ADD_CUSTOM_TARGET( + test_check_built_in_not_created + ALL + COMMAND ${SHADER_GENERATOR} --skip . ${GENERATED_FOLDER} | grep builtin-shader > /dev/null 2>&1 || echo "test_check_built_in_not_created Succeeded" + VERBATIM) +ADD_CUSTOM_TARGET( + test_frag_correct + ALL + COMMAND ${SHADER_GENERATOR} ${SHADER_FOLDER} ${GENERATED_FOLDER} | grep "SHADER_FRAGMENT_SHADER_FRAG" | grep "fragment-shader-frag.h" > /dev/null 2>&1 && echo "test_frag_correct Succeeded" + VERBATIM) +ADD_CUSTOM_TARGET( + test_vert_correct + ALL + COMMAND ${SHADER_GENERATOR} ${SHADER_FOLDER} ${GENERATED_FOLDER} | grep "SHADER_VERTEX_SHADER_VERT" | grep "vertex-shader-vert.h" > /dev/null 2>&1 && echo "test_vert_correct Succeeded" + VERBATIM) +ADD_CUSTOM_TARGET( + test_def_correct + ALL + COMMAND ${SHADER_GENERATOR} ${SHADER_FOLDER} ${GENERATED_FOLDER} | grep "SHADER_SHADER_DEFINE_DEF" | grep "shader-define-def.h" > /dev/null 2>&1 && echo "test_def_correct Succeeded" + VERBATIM) + diff --git a/automated-tests/src/dali-shader-generator/shader/fragment-shader.frag b/automated-tests/src/dali-shader-generator/shader/fragment-shader.frag new file mode 100644 index 0000000..d9b3d5a --- /dev/null +++ b/automated-tests/src/dali-shader-generator/shader/fragment-shader.frag @@ -0,0 +1,14 @@ +varying mediump vec2 vTexCoord; + +uniform sampler2D sTexture; +uniform lowp vec4 uColor; + +void main() +{ + mediump vec4 color = texture2D( sTexture, vTexCoord ); + if(color.a <= 0.0001) + { + discard; + } + gl_FragColor = color * uColor; +} diff --git a/automated-tests/src/dali-shader-generator/shader/shader-define.def b/automated-tests/src/dali-shader-generator/shader/shader-define.def new file mode 100644 index 0000000..c6e148b --- /dev/null +++ b/automated-tests/src/dali-shader-generator/shader/shader-define.def @@ -0,0 +1,2 @@ +#version 300 es +precision highp float; diff --git a/automated-tests/src/dali-shader-generator/shader/vertex-shader.vert b/automated-tests/src/dali-shader-generator/shader/vertex-shader.vert new file mode 100644 index 0000000..e5cbaa7 --- /dev/null +++ b/automated-tests/src/dali-shader-generator/shader/vertex-shader.vert @@ -0,0 +1,59 @@ +attribute mediump vec2 aPosition; +uniform highp mat4 uMvpMatrix; +uniform highp vec3 uSize; + +uniform mediump vec2 start_point; +uniform mediump vec2 end_point; +uniform mediump vec2 rotate_center; +uniform mediump float rotate_angle; + +varying mediump vec2 vTexCoord; +varying mediump vec2 vStart; +varying mediump vec2 vEnd; + +vec2 rotate(vec2 x, vec2 c, float a) +{ + vec2 d = x - c; + vec2 r = vec2(d.x * cos(a) - d.y * sin(a), d.x * sin(a) + d.y * cos(a)); + +#ifdef UNIT_TYPE_BOUNDING_BOX + return r + c; +#endif + + /* UnitType::OBJECT_BOUNDING_BOX */ +#ifdef UNIT_TYPE_USER + return (r + c) / uSize.x; +#endif + /* UnitType::USER_SPACE*/ +} + +//Visual size and offset +uniform mediump vec2 offset; +uniform highp vec2 size; +uniform mediump vec4 offsetSizeMode; +uniform mediump vec2 origin; +uniform mediump vec2 anchorPoint; + +vec4 ComputeVertexPosition() +{ + vec2 visualSize = mix( uSize.xy*size, size, offsetSizeMode.zw ); + vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy ); + return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 ); +} + +void main() +{ + vStart = rotate( start_point, rotate_center, rotate_angle ); + vEnd = rotate( end_point, rotate_center, rotate_angle ); + gl_Position = uMvpMatrix * ComputeVertexPosition(); + +#ifdef UNIT_TYPE_BOUNDING_BOX + vTexCoord = vec2(aPosition.x, -aPosition.y); +#endif +/* UnitType::OBJECT_BOUNDING_BOX */ + +#ifdef UNIT_TYPE_USER + vTexCoord = vec2(aPosition.x, -aPosition.y * uSize.y / uSize.x); +#endif +/* UnitType::USER_SPACE*/ +} diff --git a/automated-tests/src/dali-shader-generator/tct-dali-shader-generator-core.cpp b/automated-tests/src/dali-shader-generator/tct-dali-shader-generator-core.cpp new file mode 100644 index 0000000..539d80c --- /dev/null +++ b/automated-tests/src/dali-shader-generator/tct-dali-shader-generator-core.cpp @@ -0,0 +1,7 @@ +#include +#include "tct-dali-shader-generator-core.h" + +int main(int argc, char * const argv[]) +{ + return TestHarness::RunTests(argc, argv, tc_array); +} diff --git a/automated-tests/src/dali-shader-generator/utc-Dali-ShaderGenerator.cpp b/automated-tests/src/dali-shader-generator/utc-Dali-ShaderGenerator.cpp new file mode 100644 index 0000000..68fc2ab --- /dev/null +++ b/automated-tests/src/dali-shader-generator/utc-Dali-ShaderGenerator.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +void utc_dali_shader_generator_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_shader_generator_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliShaderGenerator(void) +{ + tet_infoline("All tests run as part of cmake build"); + DALI_TEST_CHECK(true); + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index e90e147..b914f96 100755 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -30,11 +30,13 @@ SET(TC_SOURCES utc-Dali-Text-ViewModel.cpp utc-Dali-TextField-internal.cpp utc-Dali-TextEditor-internal.cpp + utc-Dali-TextLabel-internal.cpp utc-Dali-TextSelectionPopup-internal.cpp utc-Dali-TextureManager.cpp utc-Dali-Visuals-internal.cpp utc-Dali-VisualModel.cpp utc-Dali-VisualUrl.cpp + utc-Dali-Text-Hyphen-Wrapping.cpp ) IF(ELDBUS_AVAILABLE) diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp index d98f397..0a426b0 100755 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ #include #include #include +#include namespace Dali { @@ -100,7 +101,8 @@ void CreateTextModel( const std::string& text, Size& layoutSize, ModelPtr& textModel, MetricsPtr& metrics, - bool markupProcessorEnabled ) + bool markupProcessorEnabled, + LineWrap::Mode wrapMode ) { textModel = Model::New(); ///< Pointer to the text's model. LogicalModelPtr logicalModel = textModel->mLogicalModel; @@ -109,7 +111,8 @@ void CreateTextModel( const std::string& text, MarkupProcessData markupProcessData( logicalModel->mColorRuns, logicalModel->mFontDescriptionRuns, logicalModel->mEmbeddedItems, - logicalModel->mAnchors ); + logicalModel->mAnchors, + logicalModel->mUnderlinedCharacterRuns); Length textSize = 0u; const uint8_t* utf8 = NULL; @@ -153,6 +156,41 @@ void CreateTextModel( const std::string& text, return; } + textModel->mLineWrapMode = wrapMode; + + if(textModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || + textModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) + { + CharacterIndex end = characterCount; + LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + + for(CharacterIndex index = 0; index < end; index++) + { + CharacterIndex wordEnd = index; + while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK)) + { + wordEnd++; + } + + if((wordEnd + 1) == end) // add last char + { + wordEnd++; + } + + Vector hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr); + + for(CharacterIndex i = 0; i < (wordEnd - index); i++) + { + if(hyphens[i]) + { + *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK; + } + } + + index = wordEnd; + } + } + // 3) Set the script info. MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get(); @@ -283,7 +321,6 @@ void CreateTextModel( const std::string& text, // Set the layout parameters. textModel->mHorizontalAlignment = Text::HorizontalAlignment::BEGIN; - textModel->mLineWrapMode = LineWrap::WORD; textModel->mIgnoreSpacesAfterText = true; textModel->mMatchSystemLanguageDirection = false; Layout::Parameters layoutParameters( textArea, diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h index eb0dd40..6e30bbb 100644 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_TEXT_UTILS_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,7 +64,8 @@ void CreateTextModel( const std::string& text, Size& layoutSize, ModelPtr& textModel, MetricsPtr& metrics, - bool markupProcessorEnabled ); + bool markupProcessorEnabled, + LineWrap::Mode wrapMode ); /** * @brief Configures the text @p controller similarly to the one configured by the text-label. diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp index c68e84f..fdd8f10 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp @@ -460,6 +460,22 @@ int UtcDaliControlReadingInfoType(void) auto control = Control::New(); auto reading_info_type = DevelControl::GetAccessibilityReadingInfoType(control); + + for ( auto i = 0u; i < 4; ++i) + DALI_TEST_CHECK ( reading_info_type[ static_cast< Dali::Accessibility::ReadingInfoType >( i ) ]); + + reading_info_type[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = false; + reading_info_type[Dali::Accessibility::ReadingInfoType::STATE] = false; + reading_info_type[Dali::Accessibility::ReadingInfoType::NAME] = false; + reading_info_type[Dali::Accessibility::ReadingInfoType::ROLE] = false; + + DevelControl::SetAccessibilityReadingInfoType(control, reading_info_type); + + reading_info_type = DevelControl::GetAccessibilityReadingInfoType(control); + + for ( auto i = 0u; i < 4; ++i) + DALI_TEST_CHECK ( false == reading_info_type[ static_cast< Dali::Accessibility::ReadingInfoType >( i ) ]); + reading_info_type[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true; reading_info_type[Dali::Accessibility::ReadingInfoType::STATE] = true; reading_info_type[Dali::Accessibility::ReadingInfoType::NAME] = true; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp index bd8f3a4..f3d97a9 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp @@ -98,6 +98,9 @@ int UtcDaliAccessibilityPushButtonStates(void) Dali::Accessibility::TestEnableSC( true ); + /* add to scene and remove from scene to touch AccessibilityDeregister */ + application.GetScene().Add( pushbutton ); + auto states = accessible->GetStates(); DALI_TEST_EQUALS( static_cast< unsigned int >( states[ Accessibility::State::PRESSED ] ), false, TEST_LOCATION ); @@ -108,6 +111,9 @@ int UtcDaliAccessibilityPushButtonStates(void) states = accessible->GetStates(); DALI_TEST_EQUALS( static_cast< unsigned int >( states[ Accessibility::State::PRESSED ] ), true, TEST_LOCATION ); + /* add to scene and remove from scene to touch AccessibilityDeregister */ + application.GetScene().Remove( pushbutton ); + Dali::Accessibility::TestEnableSC( false ); END_TEST; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp index e056f73..de772f3 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -111,7 +111,8 @@ bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -196,7 +197,8 @@ bool GetMirroredTextTest( const GetMirroredTextData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -272,7 +274,8 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data ) layoutSize, textModel, metrics, - data.markupProcessorEnabled ); + data.markupProcessorEnabled, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp index 7cbbe90..8515172 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -118,7 +118,8 @@ bool CreateParagraphTest( const CreateParagraphData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -180,7 +181,8 @@ bool FindParagraphTest( const FindParagraphData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -231,7 +233,8 @@ bool FetchBidirectionalLineInfoTest( const FetchBidirectionalLineInfoData& data layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -277,7 +280,8 @@ bool GetLogicalCharacterIndexTest( const GetLogicalCharacterIndexData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -340,7 +344,8 @@ bool GetLogicalCursorIndexTest( const GetLogicalCursorIndexData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp index 2ab84e7..78d7cf8 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -111,7 +111,8 @@ bool GetClosestLineTest( const GetClosestLineData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -157,7 +158,8 @@ bool GetClosestCursorIndexTest( const GetClosestCursorIndexData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -207,7 +209,8 @@ bool GetCursorPositionTest( const GetCursorPositionData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -260,7 +263,8 @@ bool FindSelectionIndicesTest( const FindSelectionIndicesData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Hyphen-Wrapping.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Hyphen-Wrapping.cpp new file mode 100755 index 0000000..ccc8463 --- /dev/null +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Hyphen-Wrapping.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Toolkit; +using namespace Text; + + +namespace +{ + +const std::string DEFAULT_FONT_DIR( "/resources/fonts" ); + +struct LayoutTextData +{ + std::string text; + Size textArea; + unsigned int numberOfFonts; + FontDescriptionRun *fontDescriptions; + unsigned int numberOfLines; + LineRun* lines; + Layout::Engine::Type layout; + unsigned int startIndex; + unsigned int numberOfGlyphs; + Text::LineWrap::Mode wrapMode; +}; + +void Print( const LineRun& line ) +{ + std::cout << " glyph run, index : " << line.glyphRun.glyphIndex << ", num glyphs : " << line.glyphRun.numberOfGlyphs << std::endl; + std::cout << " character run, index : " << line.characterRun.characterIndex << ", num chars : " << line.characterRun.numberOfCharacters << std::endl; +} + +bool LayoutTextTest( const LayoutTextData& data ) +{ + // Load some fonts. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.SetDpi( 96u, 96u ); + + char* pathNamePtr = get_current_dir_name(); + const std::string pathName( pathNamePtr ); + free( pathNamePtr ); + + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" ); + + // 1) Create the model. + ModelPtr textModel; + MetricsPtr metrics; + Size layoutSize; + + Vector fontDescriptionRuns; + if( 0u != data.numberOfFonts ) + { + fontDescriptionRuns.Insert( fontDescriptionRuns.End(), + data.fontDescriptions, + data.fontDescriptions + data.numberOfFonts ); + } + + LayoutOptions options; + options.align = false; + CreateTextModel( data.text, + data.textArea, + fontDescriptionRuns, + options, + layoutSize, + textModel, + metrics, + false, + data.wrapMode ); + + Vector& lines = textModel->mVisualModel->mLines; + + // 4) Compare the results. + + if( lines.Count() != data.numberOfLines ) + { + std::cout << " Different number of lines : " << lines.Count() << ", expected : " << data.numberOfLines << std::endl; + return false; + } + + for( unsigned int index = 0u; index < data.numberOfLines; ++index ) + { + const LineRun& line = *( lines.Begin() + index ); + const LineRun& expectedLine = *( data.lines + index ); + + if( line.characterRun.characterIndex != expectedLine.characterRun.characterIndex ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + if( line.characterRun.numberOfCharacters != expectedLine.characterRun.numberOfCharacters ) + { + std::cout << " Different line info for line : " << index << std::endl; + Print( line ); + std::cout << " expected" << std::endl; + Print( expectedLine ); + return false; + } + } + + return true; +} + +} // namespace + + +int UtcDaliTextHyphenWrapping(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextHyphenWrapping"); + + // Layout some lines of left to right text. + + const std::string fontFamily( "TizenSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun1; + fontDescriptionRun1.characterRun.characterIndex = 0u; + fontDescriptionRun1.characterRun.numberOfCharacters = 13u; + fontDescriptionRun1.familyLength = fontFamily.size(); + fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength]; + memcpy( fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength ); + fontDescriptionRun1.familyDefined = true; + fontDescriptionRun1.weightDefined = false; + fontDescriptionRun1.widthDefined = false; + fontDescriptionRun1.slantDefined = false; + fontDescriptionRun1.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun1 ); + Size textArea(65.0f, 200.f); + + LineRun line1 = + { + { 0u, 5u }, + { 0u, 5u }, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + false, + false + }; + LineRun line2 = + { + { 5u, 8u }, + { 5u, 8u }, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + false, + false + }; + + Vector lines; + lines.PushBack( line1 ); + lines.PushBack( line2 ); + + LayoutTextData data = + { + "Hi Experiment", + textArea, + 1u, + fontDescriptionRuns.Begin(), + 2u, + lines.Begin(), + Layout::Engine::MULTI_LINE_BOX, + 0u, + 13u, + (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextMixedWrapping(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextMixedWrapping"); + + // Layout some lines of left to right text. + + const std::string fontFamily( "DejaVuSans" ); + + // Set a known font description + FontDescriptionRun fontDescriptionRun1; + fontDescriptionRun1.characterRun.characterIndex = 0u; + fontDescriptionRun1.characterRun.numberOfCharacters = 13u; + fontDescriptionRun1.familyLength = fontFamily.size(); + fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength]; + memcpy( fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength ); + fontDescriptionRun1.familyDefined = true; + fontDescriptionRun1.weightDefined = false; + fontDescriptionRun1.widthDefined = false; + fontDescriptionRun1.slantDefined = false; + fontDescriptionRun1.sizeDefined = false; + + Vector fontDescriptionRuns; + fontDescriptionRuns.PushBack( fontDescriptionRun1 ); + Size textArea(72.0f, 200.f); + + LineRun line1 = + { + { 0u, 3u }, + { 0u, 3u }, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + false, + false + }; + LineRun line2 = + { + { 3u, 6u }, + { 3u, 6u }, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + false, + false + }; + LineRun line3 = + { + { 9u, 4u }, + { 9u, 4u }, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + false, + false + }; + + Vector lines; + lines.PushBack( line1 ); + lines.PushBack( line2 ); + lines.PushBack( line3 ); + + LayoutTextData data = + { + "Hi Experiment", + textArea, + 1u, + fontDescriptionRuns.Begin(), + 3u, + lines.Begin(), + Layout::Engine::MULTI_LINE_BOX, + 0u, + 13u, + (Text::LineWrap::Mode)DevelText::LineWrap::MIXED + }; + + if( !LayoutTextTest( data ) ) + { + tet_result(TET_FAIL); + } + + tet_result(TET_PASS); + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp index 05226d4..8bdecaa 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -108,7 +108,8 @@ bool LayoutTextTest( const LayoutTextData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -363,7 +364,8 @@ bool AlignTest( const AlignData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp index 6e2d632..f46c401 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp @@ -185,7 +185,8 @@ namespace Vector fontRuns; Vector items; Vector anchors; - MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors ); + Vector underlinedCharacterRuns; + MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors, underlinedCharacterRuns ); ProcessMarkupString( data.xHTMLEntityString, markupProcessData ); for( Vector::Iterator it = items.Begin(), diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp index a7534f9..52c8808 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -140,7 +140,8 @@ bool ShapeInfoTest( const ShapeInfoData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp index 9445be6..b19d653 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -70,3 +71,100 @@ int UtcDaliTextEditorSelectText(void) END_TEST; } + +int UtcDaliTextEditorMarkupUnderline(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMarkupUnderline "); + + TextEditor textEditor = TextEditor::New(); + + application.GetScene().Add( textEditor ); + + textEditor.SetProperty( TextEditor::Property::TEXT, "ABCEFGH" ); + textEditor.SetProperty( TextEditor ::Property::ENABLE_MARKUP, true ); + + application.SendNotification(); + application.Render(); + + uint32_t expectedNumberOfUnderlinedGlyphs = 5u; + + Toolkit::Internal::TextEditor& textEditorImpl = GetImpl( textEditor ); + const Text::Length numberOfUnderlineRuns = textEditorImpl.getController()->GetTextModel()->GetNumberOfUnderlineRuns(); + + DALI_TEST_EQUALS( numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION ); + + Vector underlineRuns; + underlineRuns.Resize(numberOfUnderlineRuns); + textEditorImpl.getController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); + + //ABC are underlined + DALI_TEST_EQUALS( underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[1u].glyphIndex, 1u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[2u].glyphIndex, 2u, TEST_LOCATION); + + //GH are underlined + DALI_TEST_EQUALS( underlineRuns[3u].glyphIndex, 5u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[4u].glyphIndex, 6u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTextEditorFontPointSizeLargerThanAtlas(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorFontPointSizeLargerThanAtlas "); + + // Create a text editor + TextEditor textEditor = TextEditor::New(); + //Set size to avoid automatic eliding + textEditor.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + //Set very large font-size using point-size + textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 1000); + //Specify font-family + textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans"); + //Set text to check if appear or not + textEditor.SetProperty(TextEditor::Property::TEXT, "A"); + + application.GetScene().Add( textEditor ); + + application.SendNotification(); + application.Render(); + + //Check if Glyph is added to AtlasGlyphManger or not + int countAtlas = AtlasGlyphManager::Get().GetMetrics().mAtlasMetrics.mAtlasCount; + DALI_TEST_EQUALS( countAtlas, 1, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliTextEditorFontPointSizeLargerThanAtlasPlaceholderCase(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorFontPointSizeLargerThanAtlasPlaceholderCase "); + + //Set Map of placeholder: text, font-family and point-size + Property::Map placeholderMapSet; + placeholderMapSet["text"] = "A"; + placeholderMapSet["fontFamily"] = "DejaVu Sans"; + placeholderMapSet["pixelSize"] = 1000.0f; + + // Create a text editor + TextEditor textEditor = TextEditor::New(); + //Set size to avoid automatic eliding + textEditor.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + //Set placeholder + textEditor.SetProperty( TextEditor::Property::PLACEHOLDER, placeholderMapSet) ; + + application.GetScene().Add( textEditor ); + + application.SendNotification(); + application.Render(); + + //Check if Glyph is added to AtlasGlyphManger or not + int countAtlas = AtlasGlyphManager::Get().GetMetrics().mAtlasMetrics.mAtlasCount; + DALI_TEST_EQUALS( countAtlas, 1, TEST_LOCATION ); + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp index 37d54e1..619e5f4 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -152,3 +153,102 @@ int UtcDaliTextFieldSelectText(void) END_TEST; } + +int UtcDaliTextFieldMarkupUnderline(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldMarkupUnderline "); + + TextField textField = TextField::New(); + + application.GetScene().Add( textField ); + + textField.SetProperty( TextField::Property::TEXT, "ABCEFGH" ); + textField.SetProperty( TextField ::Property::ENABLE_MARKUP, true ); + + application.SendNotification(); + application.Render(); + + uint32_t expectedNumberOfUnderlinedGlyphs = 5u; + + Toolkit::Internal::TextField& textFieldImpl = GetImpl( textField ); + const Text::Length numberOfUnderlineRuns = textFieldImpl.getController()->GetTextModel()->GetNumberOfUnderlineRuns(); + + DALI_TEST_EQUALS( numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION ); + + Vector underlineRuns; + underlineRuns.Resize(numberOfUnderlineRuns); + textFieldImpl.getController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); + + //ABC are underlined + DALI_TEST_EQUALS( underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[1u].glyphIndex, 1u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[2u].glyphIndex, 2u, TEST_LOCATION); + + //GH are underlined + DALI_TEST_EQUALS( underlineRuns[3u].glyphIndex, 5u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[4u].glyphIndex, 6u, TEST_LOCATION); + + END_TEST; + +} + +int UtcDaliTextFieldFontPointSizeLargerThanAtlas(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldFontPointSizeLargerThanAtlas "); + + // Create a Text field + TextField textField = TextField::New(); + //Set size to avoid automatic eliding + textField.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + //Set very large font-size using point-size + textField.SetProperty( TextField::Property::POINT_SIZE, 1000) ; + //Specify font-family + textField.SetProperty( TextField::Property::FONT_FAMILY, "DejaVu Sans"); + //Set text to check if appear or not + textField.SetProperty( TextField::Property::TEXT, "A"); + + application.GetScene().Add( textField ); + + application.SendNotification(); + application.Render(); + + //Check if Glyph is added to AtlasGlyphManger or not + int countAtlas = AtlasGlyphManager::Get().GetMetrics().mAtlasMetrics.mAtlasCount; + DALI_TEST_EQUALS( countAtlas, 1, TEST_LOCATION ); + + + END_TEST; +} + +int UtcDaliTextFieldFontPointSizeLargerThanAtlasPlaceholderCase(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldFontPointSizeLargerThanAtlasPlaceholderCase "); + + //Set Map of placeholder: text, font-family and point-size + Property::Map placeholderMapSet; + placeholderMapSet["text"] = "A"; + placeholderMapSet["fontFamily"] = "DejaVu Sans"; + placeholderMapSet["pixelSize"] = 1000.0f; + + // Create a text editor + TextField textField = TextField::New(); + //Set size to avoid automatic eliding + textField.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + //Set placeholder + textField.SetProperty( TextField::Property::PLACEHOLDER, placeholderMapSet) ; + + application.GetScene().Add( textField ); + + application.SendNotification(); + application.Render(); + + //Check if Glyph is added to AtlasGlyphManger or not + int countAtlas = AtlasGlyphManager::Get().GetMetrics().mAtlasMetrics.mAtlasCount; + DALI_TEST_EQUALS( countAtlas, 1, TEST_LOCATION ); + + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp new file mode 100755 index 0000000..e85ea21 --- /dev/null +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 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. + * + */ + +#include +#include + +#include +#include + +#include +#include +#include + +using namespace Dali; +using namespace Toolkit; +using namespace Text; + +int UtcDaliTextLabelMarkupUnderline(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelMarkupUnderline "); + + TextLabel textLabel = TextLabel::New(); + + application.GetScene().Add( textLabel ); + + textLabel.SetProperty( TextLabel::Property::TEXT, "ABCEFGH" ); + textLabel.SetProperty( TextLabel ::Property::ENABLE_MARKUP, true ); + + application.SendNotification(); + application.Render(); + + uint32_t expectedNumberOfUnderlinedGlyphs = 5u; + + Toolkit::Internal::TextLabel& textLabelImpl = GetImpl( textLabel ); + const Text::Length numberOfUnderlineRuns = textLabelImpl.getController()->GetTextModel()->GetNumberOfUnderlineRuns(); + + DALI_TEST_EQUALS( numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION ); + + Vector underlineRuns; + underlineRuns.Resize(numberOfUnderlineRuns); + textLabelImpl.getController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); + + //ABC are underlined + DALI_TEST_EQUALS( underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[1u].glyphIndex, 1u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[2u].glyphIndex, 2u, TEST_LOCATION); + + //GH are underlined + DALI_TEST_EQUALS( underlineRuns[3u].glyphIndex, 5u, TEST_LOCATION); + DALI_TEST_EQUALS( underlineRuns[4u].glyphIndex, 6u, TEST_LOCATION); + + END_TEST; + +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp index df247e0..43157ff 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,7 +79,8 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; @@ -163,7 +164,8 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data ) layoutSize, textModel, metrics, - false ); + false, + LineWrap::WORD ); LogicalModelPtr logicalModel = textModel->mLogicalModel; VisualModelPtr visualModel = textModel->mVisualModel; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h index c3616b2..4970dc4 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_ADAPTOR_IMPL_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,8 +84,8 @@ public: void AddWindow( Internal::Adaptor::SceneHolder* window ); void RemoveWindow( Internal::Adaptor::SceneHolder* window ); - void RegisterProcessor( Integration::Processor& processor ); - void UnregisterProcessor( Integration::Processor& processor ); + void RegisterProcessor( Integration::Processor& processor, bool postProcessor = false); + void UnregisterProcessor( Integration::Processor& processor, bool postProcessor = false); void SetApplication( Dali::TestApplication& testApplication ); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp index 1fe86c3..8f3095f 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -172,16 +172,16 @@ void Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* window ) } } -void Adaptor::RegisterProcessor( Integration::Processor& processor ) +void Adaptor::RegisterProcessor( Integration::Processor& processor, bool postProcessor ) { Integration::Core& core = mTestApplication->GetCore(); - core.RegisterProcessor( processor ); + core.RegisterProcessor( processor, postProcessor ); } -void Adaptor::UnregisterProcessor( Integration::Processor& processor ) +void Adaptor::UnregisterProcessor( Integration::Processor& processor, bool postProcessor ) { Integration::Core& core = mTestApplication->GetCore(); - core.UnregisterProcessor( processor ); + core.UnregisterProcessor( processor, postProcessor ); } void Adaptor::SetApplication( Dali::TestApplication& testApplication ) @@ -368,14 +368,14 @@ const LogFactoryInterface& Adaptor::GetLogFactory() return *gLogFactory; } -void Adaptor::RegisterProcessor( Integration::Processor& processor ) +void Adaptor::RegisterProcessor( Integration::Processor& processor, bool postProcessor) { - mImpl->RegisterProcessor( processor ); + mImpl->RegisterProcessor( processor, postProcessor ); } -void Adaptor::UnregisterProcessor( Integration::Processor& processor ) +void Adaptor::UnregisterProcessor( Integration::Processor& processor, bool postProcessor) { - mImpl->UnregisterProcessor( processor ); + mImpl->UnregisterProcessor( processor, postProcessor ); } } // namespace Dali diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp index 18ce2ef..474706f 100755 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,8 @@ #include #include #include +#include +#include namespace Dali { @@ -31,6 +33,11 @@ namespace Internal namespace Adaptor { +namespace +{ +Dali::Internal::Adaptor::VectorAnimationRenderer* gVectorAnimationRenderer = nullptr; +} + class VectorAnimationRenderer: public Dali::BaseObject { public: @@ -40,8 +47,12 @@ public: mRenderer(), mWidth( 0 ), mHeight( 0 ), + mTotalFrameNumber(VECTOR_ANIMATION_TOTAL_FRAME_NUMBER), mPreviousFrame( 0 ), + mDelayTime(0), + mDroppedFrames(0), mFrameRate( 60.0f ), + mNeedDroppedFrames(false), mEventThreadCallback( new EventThreadCallback( MakeCallback( this, &VectorAnimationRenderer::OnTriggered ) ) ) { mCount++; @@ -60,10 +71,15 @@ public: bool Load(const std::string& url) { mUrl = url; - if(mUrl == "invalid.json") + if(mUrl == "invalid.json" || mUrl == "invalid.riv") { return false; } + else if(mUrl == "framedrop.json") + { + // Change total frame number for test + mTotalFrameNumber = 200; + } return true; } @@ -96,6 +112,19 @@ public: bool Render( uint32_t frameNumber ) { + if(mDelayTime != 0) + { + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(mDelayTime))); + mDelayTime = 0; + mNeedDroppedFrames = true; + } + else if(mNeedDroppedFrames) + { + mDroppedFrames = (frameNumber > mPreviousFrame) ? frameNumber - mPreviousFrame - 1: frameNumber + (mTotalFrameNumber - mPreviousFrame) - 1; + mNeedTrigger = true; + mNeedDroppedFrames = false; + } + if( mNeedTrigger ) { mEventThreadCallback->Trigger(); @@ -114,7 +143,7 @@ public: uint32_t GetTotalFrameNumber() const { - return VECTOR_ANIMATION_TOTAL_FRAME_NUMBER; + return mTotalFrameNumber; } float GetFrameRate() const @@ -165,8 +194,12 @@ public: Dali::Renderer mRenderer; uint32_t mWidth; uint32_t mHeight; + uint32_t mTotalFrameNumber; uint32_t mPreviousFrame; + uint32_t mDelayTime; + uint32_t mDroppedFrames; float mFrameRate; + bool mNeedDroppedFrames; Dali::VectorAnimationRenderer::UploadCompletedSignalType mUploadCompletedSignal; std::unique_ptr< EventThreadCallback > mEventThreadCallback; }; @@ -201,6 +234,8 @@ VectorAnimationRenderer VectorAnimationRenderer::New() { Internal::Adaptor::VectorAnimationRenderer* animationRenderer = new Internal::Adaptor::VectorAnimationRenderer(); + Internal::Adaptor::gVectorAnimationRenderer = animationRenderer; + return VectorAnimationRenderer( animationRenderer ); } @@ -293,6 +328,16 @@ void RequestTrigger() Dali::Internal::Adaptor::VectorAnimationRenderer::mNeedTrigger = true; } +void DelayRendering(uint32_t delay) +{ + Dali::Internal::Adaptor::gVectorAnimationRenderer->mDelayTime = delay; +} + +uint32_t GetDroppedFrames() +{ + return Dali::Internal::Adaptor::gVectorAnimationRenderer->mDroppedFrames; +} + } // VectorAnimationRenderer } // Test diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h index 2213465..a1ea51b 100755 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_TEST_VECTOR_ANIMATION_RENDERER_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,8 @@ namespace VectorAnimationRenderer #define VECTOR_ANIMATION_MARKER_END_FRAME_2 3 void RequestTrigger(); +void DelayRendering(uint32_t delay); +uint32_t GetDroppedFrames(); } // VectorAnimationRenderer } // Test diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp index 430615d..b30d3b6 100755 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp @@ -83,6 +83,7 @@ bool OnStorageUsageAcquired(); bool OnFormPasswordAcquired(); bool OnDownloadStarted(); bool OnMimeOverridden(); +bool OnChangesWatch(); static void ConnectToGlobalSignal( bool ( *func )() ) { @@ -170,7 +171,7 @@ public: { } - bool DeleteWebStorageOrigin(Dali::WebEngineSecurityOrigin& origin) + bool DeleteWebStorage(Dali::WebEngineSecurityOrigin& origin) { return true; } @@ -179,10 +180,6 @@ public: { } - void DisableCache( bool cacheDisabled ) override - { - } - void ClearCache() override { } @@ -219,6 +216,99 @@ public: } } + void EnableCache( bool cacheEnabled ) override + { + } + + bool IsCacheEnabled() const override + { + return true; + } + + std::string GetContextCertificateFile() const override + { + return "test"; + } + + void SetContextAppId(const std::string& appID) override + { + } + + bool SetContextAppVersion(const std::string& appVersion) override + { + return true; + } + + void SetContextApplicationType(const Dali::WebEngineContext::ApplicationType applicationType) override + { + } + + void SetContextTimeOffset(float timeOffset) override + { + } + + void SetContextTimeZoneOffset(float timeZoneOffset, float daylightSavingTime) override + { + } + + void RegisterUrlSchemesAsCorsEnabled(const std::vector& schemes) override + { + } + + void RegisterJsPluginMimeTypes(const std::vector& mimeTypes) override + { + } + + void SetDefaultZoomFactor(float zoomFactor) override + { + } + + float GetContextDefaultZoomFactor() const override + { + return 0; + } + + bool DeleteAllApplicationCache() override + { + return true; + } + + bool DeleteAllWebIndexedDatabase() override + { + return true; + } + + void DeleteFormPasswordDataList(const std::vector& list) override + { + } + + void DeleteAllFormPasswordData() override + { + } + + void DeleteAllFormCandidateData() override + { + } + + std::string GetContextProxy() const override + { + return "test"; + } + + void SetContextProxy(const std::string& proxy, const std::string& bypass) override + { + } + + std::string GetProxyBypassRule() const override + { + return "test"; + } + + bool FreeUnusedMemory() override + { + return true; + } + public: Dali::WebEngineContext::WebEngineSecurityOriginAcquiredCallback mSecurityOriginAcquiredCallback; Dali::WebEngineContext::WebEngineStorageUsageAcquiredCallback mStorageUsageAcquiredCallback; @@ -256,6 +346,18 @@ public: { } + void ChangesWatch( Dali::WebEngineCookieManager::WebEngineCookieManagerChangesWatchCallback callback ) override + { + if ( callback ) + { + ConnectToGlobalSignal( &OnChangesWatch ); + mChangesWatchCallback = callback; + } + } + +public: + Dali::WebEngineCookieManager::WebEngineCookieManagerChangesWatchCallback mChangesWatchCallback; + private: Dali::WebEngineCookieManager::CookieAcceptPolicy mockCookieAcceptPolicy; }; @@ -739,11 +841,11 @@ public: Dali::PixelData GetImageBuffer() override { - uint8_t* faviconData = new uint8_t[ 16 ]; - memset(faviconData, 0xff, 16); - return Dali::PixelData::New( faviconData, 16, 2, 2, - Dali::Pixel::Format::RGBA8888, - Dali::PixelData::ReleaseFunction::DELETE_ARRAY ); + uint8_t* imageData = new uint8_t[16]; + memset(imageData, 0xff, 16); + return Dali::PixelData::New(imageData, 16, 2, 2, + Dali::Pixel::Format::RGBA8888, + Dali::PixelData::ReleaseFunction::DELETE_ARRAY); } private: @@ -1127,28 +1229,20 @@ public: Dali::PixelData GetFavicon() const { - uint8_t* faviconData = new uint8_t[ 16 ]; - - faviconData[ 0 ] = 0xff; - faviconData[ 1 ] = 0x00; - faviconData[ 2 ] = 0x00; - faviconData[ 3 ] = 0xff; - faviconData[ 4 ] = 0xff; - faviconData[ 5 ] = 0x00; - faviconData[ 6 ] = 0x00; - faviconData[ 7 ] = 0xff; - faviconData[ 8 ] = 0xff; - faviconData[ 9 ] = 0x00; - faviconData[ 10 ] = 0x00; - faviconData[ 11 ] = 0xff; - faviconData[ 12 ] = 0xff; - faviconData[ 13 ] = 0x00; - faviconData[ 14 ] = 0x00; - faviconData[ 15 ] = 0xff; - - return Dali::PixelData::New( faviconData, 16, 2, 2, - Dali::Pixel::Format::RGBA8888, - Dali::PixelData::ReleaseFunction::DELETE_ARRAY ); + static int testGetFaviconCount = 0; + if (testGetFaviconCount == 0) + { + testGetFaviconCount++; + uint8_t* faviconData = new uint8_t[16]; + memset(faviconData, 0xff, 16); + return Dali::PixelData::New(faviconData, 16, 2, 2, + Dali::Pixel::Format::RGBA8888, + Dali::PixelData::ReleaseFunction::DELETE_ARRAY); + } + else + { + return Dali::PixelData(); + } } bool CanGoForward() const @@ -1405,9 +1499,9 @@ public: return mConsoleMessageSignal; } - Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& PolicyDecisionSignal() + Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal() { - return mPolicyDecisionSignal; + return mResponsePolicyDecisionSignal; } Dali::WebEnginePlugin::WebEngineCertificateSignalType& CertificateConfirmSignal() @@ -1450,7 +1544,7 @@ public: Dali::WebEnginePlugin::WebEngineFrameRenderedSignalType mFrameRenderedSignal; Dali::WebEnginePlugin::WebEngineRequestInterceptorSignalType mRequestInterceptorSignal; Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType mConsoleMessageSignal; - Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType mPolicyDecisionSignal; + Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType mResponsePolicyDecisionSignal; Dali::WebEnginePlugin::WebEngineCertificateSignalType mCertificateConfirmSignal; Dali::WebEnginePlugin::WebEngineCertificateSignalType mSslCertificateChangedSignal; Dali::WebEnginePlugin::WebEngineHttpAuthHandlerSignalType mHttpAuthHandlerSignal; @@ -1534,7 +1628,7 @@ bool OnLoadUrl() std::shared_ptr message(new MockWebEngineConsoleMessage()); gInstance->mConsoleMessageSignal.Emit(std::move(message)); std::shared_ptr policyDecision(new MockWebEnginePolicyDecision()); - gInstance->mPolicyDecisionSignal.Emit(std::move(policyDecision)); + gInstance->mResponsePolicyDecisionSignal.Emit(std::move(policyDecision)); std::shared_ptr certificate(new MockWebEngineCertificate()); gInstance->mCertificateConfirmSignal.Emit(std::move(certificate)); @@ -1727,6 +1821,22 @@ bool OnMimeOverridden() return false; } +bool OnChangesWatch() +{ + DisconnectFromGlobalSignal( &OnChangesWatch ); + + if ( gInstance ) + { + MockWebEngineCookieManager* temp = (MockWebEngineCookieManager *)(&(gInstance->GetCookieManager())); + if ( temp ) + { + temp->mChangesWatchCallback(); + } + } + + return false; +} + } // namespace inline WebEngine& GetImplementation( Dali::WebEngine& webEngine ) @@ -2204,9 +2314,9 @@ Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType& WebEngine::ConsoleMess return Internal::Adaptor::GetImplementation(*this).ConsoleMessageSignal(); } -Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& WebEngine::PolicyDecisionSignal() +Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& WebEngine::ResponsePolicyDecisionSignal() { - return Internal::Adaptor::GetImplementation(*this).PolicyDecisionSignal(); + return Internal::Adaptor::GetImplementation(*this).ResponsePolicyDecisionSignal(); } Dali::WebEnginePlugin::WebEngineCertificateSignalType& WebEngine::CertificateConfirmSignal() diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index dfd0b72..83c6a09 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,8 +50,12 @@ namespace { const char* TEST_VECTOR_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/insta_camera.json"; +const char* TEST_VECTOR_IMAGE_FILE_NAME_FRAME_DROP = "framedrop.json"; const char* TEST_VECTOR_IMAGE_INVALID_FILE_NAME = "invalid.json"; +const char* TEST_VECTOR_IMAGE_RIVE_FILE_NAME = TEST_RESOURCE_DIR "/shape.riv"; +const char* TEST_VECTOR_IMAGE_INVALID_RIVE_FILE_NAME = "invalid.riv"; + bool gAnimationFinishedSignalFired = false; void VisualEventSignal( Control control, Dali::Property::Index visualIndex, Dali::Property::Index signalId ) @@ -1530,3 +1534,244 @@ int UtcDaliAnimatedVectorImageVisualInvalidFile(void) END_TEST; } + +int UtcDaliAnimatedVectorImageVisualFrameDrops(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliAnimatedVectorImageVisualFrameDrops"); + + Property::Map propertyMap; + propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE) + .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME_FRAME_DROP); + + Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap); + DALI_TEST_CHECK(visual); + + DummyControl actor = DummyControl::New(true); + DummyControlImpl& dummyImpl = static_cast(actor.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual); + + Vector2 controlSize(20.f, 30.f); + actor.SetProperty(Actor::Property::SIZE, controlSize); + + application.GetScene().Add(actor); + + application.SendNotification(); + application.Render(); + + Property::Map attributes; + DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes); + + application.SendNotification(); + application.Render(); + + // Trigger count is 1 - render the first frame + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + // Make delay to drop frames + Test::VectorAnimationRenderer::DelayRendering(170); // longer than 16.6 * 10frames + + // Check dropped frame + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + uint32_t frames = Test::VectorAnimationRenderer::GetDroppedFrames(); + DALI_TEST_CHECK(frames >= 9); + + END_TEST; +} + +int UtcDaliAnimatedVectorImageVisualLoadRiveFileP(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliAnimatedVectorImageVisualLoadRiveFile: Request animated vector image visual with a rive url" ); + + VisualFactory factory = VisualFactory::Get(); + Visual::Base visual = factory.CreateVisual( TEST_VECTOR_IMAGE_RIVE_FILE_NAME, ImageDimensions() ); + DALI_TEST_CHECK( visual ); + + DummyControl actor = DummyControl::New( true ); + DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >( actor.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + actor.SetProperty( Actor::Property::SIZE, Vector2( 200.0f, 200.0f ) ); + application.GetScene().Add( actor ); + + application.SendNotification(); + application.Render(); + + // renderer is added to actor + DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); + Renderer renderer = actor.GetRendererAt( 0u ); + DALI_TEST_CHECK( renderer ); + + // Test SetOffScene(). + actor.Unparent(); + DALI_TEST_CHECK( actor.GetRendererCount() == 0u ); + + END_TEST; +} + +int UtcDaliAnimatedVectorImageVisualLoadRiveFileN(void) +{ + ToolkitTestApplication application; + tet_infoline("Request loading with invalid rive file - should draw broken image"); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable(true); + + Property::Map propertyMap; + propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE) + .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_INVALID_RIVE_FILE_NAME); + + Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap); + DALI_TEST_CHECK(visual); + + DummyControl actor = DummyControl::New(true); + DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >(actor.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual); + + actor.SetProperty(Actor::Property::SIZE, Vector2(20.0f, 20.0f)); + + application.GetScene().Add(actor); + + application.SendNotification(); + application.Render(); + + // Check resource status + Visual::ResourceStatus status = actor.GetVisualResourceStatus(DummyControl::Property::TEST_VISUAL); + DALI_TEST_EQUALS(status, Visual::ResourceStatus::FAILED, TEST_LOCATION); + + // The broken image should be shown. + DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAnimatedVectorImageVisualPlaybackRiveFile(void) +{ + ToolkitTestApplication application; + + tet_infoline( "UtcDaliAnimatedVectorImageVisualPlaybackRiveFile" ); + + { + // request AnimatedVectorImageVisual for Rive with a property map + VisualFactory factory = VisualFactory::Get(); + Visual::Base visual = factory.CreateVisual( + Property::Map() + .Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE ) + .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_RIVE_FILE_NAME ) ); + + DummyControl dummyControl = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummyControl.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + dummyControl.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); + + Property::Map attributes; + tet_infoline( "Test Play action" ); + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); + + application.GetScene().Add( dummyControl ); + application.SendNotification(); + application.Render( 16 ); + + Property::Map map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + Property::Value* value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::PLAYING ); + + tet_infoline( "Test Pause action" ); + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PAUSE, attributes ); + + application.SendNotification(); + application.Render(16); + + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::PAUSED ); + + tet_infoline( "Test Play action" ); + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); + + application.SendNotification(); + application.Render(16); + + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::PLAYING ); + + tet_infoline( "Test Stop action" ); + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::STOP, attributes ); + + application.SendNotification(); + application.Render(16); + + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::STOPPED ); + + tet_infoline( "Test Stop action again" ); + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::STOP, attributes ); + + application.SendNotification(); + application.Render(16); + + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::STOPPED ); + + tet_infoline( "Test Play action" ); + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); + + application.SendNotification(); + application.Render(16); + + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::PLAYING ); + + tet_infoline( "Off stage" ); + dummyControl.Unparent(); + + application.SendNotification(); + application.Render(16); + + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::STOPPED ); + + tet_infoline( "On stage again" ); + application.GetScene().Add( dummyControl ); + + application.SendNotification(); + application.Render(16); + + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::STOPPED ); + + tet_infoline( "Test Play action" ); + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); + + application.SendNotification(); + application.Render(16); + + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::PLAYING ); + + // Change Size + Vector3 newSize( 100.0f, 100.0f, 0.0f ); + dummyControl.SetProperty( Actor::Property::SIZE, newSize ); + + application.SendNotification(); + application.Render(16); + + // Size should be changed + Vector3 naturalSize = dummyControl.GetNaturalSize(); + DALI_TEST_CHECK( naturalSize == newSize ); + + dummyControl.Unparent(); + } + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp index e9bd76e..fdf1697 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "dummy-control.h" @@ -416,6 +417,51 @@ int UtcDaliImageVisualRemoteImageLoad(void) END_TEST; } + +int UtcDaliImageVisualWithNativeImage(void) +{ + ToolkitTestApplication application; + tet_infoline( "Use Native Image as url" ); + + NativeImageSourcePtr nativeImageSource = NativeImageSource::New(500, 500, NativeImageSource::COLOR_DEPTH_DEFAULT); + std::string url = Dali::Toolkit::Image::GenerateUrl(nativeImageSource); + + VisualFactory factory = VisualFactory::Get(); + DALI_TEST_CHECK( factory ); + + Property::Map propertyMap; + propertyMap.Insert( Toolkit::Visual::Property::TYPE, Visual::IMAGE ); + propertyMap.Insert( ImageVisual::Property::URL, url ); + + Visual::Base visual = factory.CreateVisual( propertyMap ); + DALI_TEST_CHECK( visual ); + + DummyControl actor = DummyControl::New(); + DummyControlImpl& dummyImpl = static_cast(actor.GetImplementation()); + dummyImpl.RegisterVisual( Control::CONTROL_PROPERTY_END_INDEX + 1, visual ); + + DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION ); + + application.GetScene().Add( actor ); + + DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION ); + + Renderer renderer = actor.GetRendererAt(0); + Shader shader = renderer.GetShader(); + + Property::Value value = shader.GetProperty(Shader::Property::PROGRAM); + DALI_TEST_CHECK(value.GetType() == Property::MAP); + const Property::Map* outMap = value.GetMap(); + std::string fragmentShader = (*outMap)["fragment"].Get(); + + const char* fragmentPrefix = nativeImageSource->GetCustomFragmentPrefix(); + size_t pos = fragmentShader.find(fragmentPrefix); + + DALI_TEST_EQUALS( pos != std::string::npos, true, TEST_LOCATION ); + + END_TEST; +} + int UtcDaliImageVisualTextureReuse1(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 12d8805..626432e 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -28,6 +28,7 @@ #include #include #include +#include using namespace Dali; using namespace Toolkit; @@ -3386,3 +3387,306 @@ int UtcDaliTextEditorLineCountAfterGetNaturalSize(void) END_TEST; } + + +int utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountScrollingCase(void) +{ + ToolkitTestApplication application; + + tet_infoline(" utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountScrollingCase "); + + int lineCountBefore =0 ; + int lineCountAfter =0 ; + + // Create a text editor + TextEditor textEditor = TextEditor::New(); + //Set very large font-size using point-size + textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ; + //Specify font-family + textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans"); + //Specify size + textEditor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 100.f ) ); + //Set text longer than width of textEditor + textEditor.SetProperty( TextEditor::Property::TEXT, "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST "); + + application.GetScene().Add( textEditor ); + + application.SendNotification(); + application.Render(); + + //Failed case is the GetHeightForWidth change LineCount then the scrollor will not arrive to latest line + //GetHeightForWidth is a retrieval method which should not modify object + lineCountBefore = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + textEditor.GetHeightForWidth(200.f); + + //This is to simulate focus into text editor after calling GetHeightForWidth + //Create a tap event to touch the text editor. + TestGenerateTap( application, 18.0f, 25.0f ); + + application.SendNotification(); + application.Render(); + + lineCountAfter = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + + //The LineCount must not be changed when calling GetHeightForWidth. + DALI_TEST_EQUALS( lineCountAfter , lineCountBefore, TEST_LOCATION ); + + END_TEST; +} + +int utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountLineWrapCharCase(void) +{ + ToolkitTestApplication application; + + tet_infoline(" utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountLineWrapCharCase "); + + int lineCountBefore =0 ; + int lineCountAfter =0 ; + + // Create a text editor + TextEditor textEditor = TextEditor::New(); + //Set very large font-size using point-size + textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ; + //Specify font-family + textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans"); + //Specify size + textEditor.SetProperty( Actor::Property::SIZE, Vector2( 50.f, 100.f ) ); + //Set text longer than width of textEditor + textEditor.SetProperty( TextEditor::Property::TEXT, "qwertyuiopasdfghjklzxcvbnm\n"); + //Set line wrap mode Character + textEditor.SetProperty(TextEditor::Property::LINE_WRAP_MODE, "CHARACTER"); + + application.GetScene().Add( textEditor ); + + application.SendNotification(); + application.Render(); + + //Failed case is the GetHeightForWidth change LineCount which make position of cursor invalid in TextEditor + //GetHeightForWidth is a retrieval method which should not modify object + lineCountBefore = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + textEditor.GetHeightForWidth(200.f); + + //This is to simulate focus into text editor after calling GetHeightForWidth + //Create a tap event to touch the text editor. + TestGenerateTap( application, 18.0f, 25.0f ); + + application.SendNotification(); + application.Render(); + + lineCountAfter = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + + //The LineCount must not be changed when calling GetHeightForWidth. + DALI_TEST_EQUALS( lineCountAfter , lineCountBefore, TEST_LOCATION ); + + END_TEST; +} + +int utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountScrollingCase(void) +{ + ToolkitTestApplication application; + + tet_infoline(" utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountScrollingCase "); + + int lineCountBefore =0 ; + int lineCountAfter =0 ; + + // Create a text editor + TextEditor textEditor = TextEditor::New(); + //Set very large font-size using point-size + textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ; + //Specify font-family + textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans"); + //Specify size + textEditor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 100.f ) ); + //Set text longer than width of textEditor + textEditor.SetProperty( TextEditor::Property::TEXT, "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST "); + + application.GetScene().Add( textEditor ); + + application.SendNotification(); + application.Render(); + + //Failed case is the GetNaturalSize change LineCount then the scrollor will not arrive to latest line + //GetNaturalSize is a retrieval method which should not modify object + lineCountBefore = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + textEditor.GetNaturalSize(); + + //This is to simulate focus into text editor after calling GetNaturalSize + //Create a tap event to touch the text editor. + TestGenerateTap( application, 18.0f, 25.0f ); + + application.SendNotification(); + application.Render(); + + lineCountAfter = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + + //The LineCount must not be changed when calling GetNaturalSize. + DALI_TEST_EQUALS( lineCountAfter , lineCountBefore, TEST_LOCATION ); + + END_TEST; +} + +int utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountLineWrapCharCase(void) +{ + ToolkitTestApplication application; + + tet_infoline(" utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountLineWrapCharCase "); + + int lineCountBefore =0 ; + int lineCountAfter =0 ; + + // Create a text editor + TextEditor textEditor = TextEditor::New(); + //Set very large font-size using point-size + textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ; + //Specify font-family + textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans"); + //Specify size + textEditor.SetProperty( Actor::Property::SIZE, Vector2( 50.f, 100.f ) ); + //Set text longer than width of textEditor + textEditor.SetProperty( TextEditor::Property::TEXT, "qwertyuiopasdfghjklzxcvbnm\n"); + //Set line wrap mode Character + textEditor.SetProperty(TextEditor::Property::LINE_WRAP_MODE, "CHARACTER"); + + application.GetScene().Add( textEditor ); + + application.SendNotification(); + application.Render(); + + //Failed case is the GetNaturalSize change LineCount which make position of cursor invalid in TextEditor + //GetNaturalSize is a retrieval method which should not modify object + lineCountBefore = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + textEditor.GetNaturalSize( ); + + //This is to simulate focus into text editor after calling GetNaturalSize + //Create a tap event to touch the text editor. + TestGenerateTap( application, 18.0f, 25.0f ); + + application.SendNotification(); + application.Render(); + + lineCountAfter = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + + //The LineCount must not be changed when calling GetNaturalSize. + DALI_TEST_EQUALS( lineCountAfter , lineCountBefore, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTextEditorAtlasLimitationIsEnabledForLargeFontPointSize(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorAtlasLimitationIsEnabledForLargeFontPointSize "); + + // +2: First one to handle the equal case. Second one to handle odd to even case of GetNaturalSize + const uint32_t lessThanWidth = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + const uint32_t lessThanHeight = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + + // Create a text editor + TextEditor textEditor = TextEditor::New(); + + //Set size to avoid automatic eliding + textEditor.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + //Set very large font-size using point-size + textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 1000) ; + //Specify font-family + textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans"); + //Set text to check if appear or not + textEditor.SetProperty( TextEditor::Property::TEXT, "A"); + + application.GetScene().Add( textEditor ); + + application.SendNotification(); + application.Render(); + //Use GetNaturalSize to verify that size of block does not exceed Atlas size + Vector3 naturalSize = textEditor.GetNaturalSize(); + + DALI_TEST_GREATER( lessThanWidth, static_cast(naturalSize.width), TEST_LOCATION ); + DALI_TEST_GREATER( lessThanHeight, static_cast(naturalSize.height), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTextEditorAtlasLimitationIsEnabledPerformanceCases(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorAtlasLimitationIsEnabledPerformanceCases "); + + // +2: First one to handle the equal case. Second one to handle odd to even case of GetNaturalSize + const uint32_t lessThanWidth = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + const uint32_t lessThanHeight = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + + Vector3 naturalSize; //Use GetNaturalSize to verify that size of block does not exceed Atlas size + // Create a text editor + TextEditor textEditor = TextEditor::New(); + //Set size to avoid automatic eliding + textEditor.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans"); + textEditor.SetProperty( TextEditor::Property::TEXT, "A"); + + const int numberOfCases = 6; + int arrayCases[numberOfCases] = {323, 326, 330, 600, 1630, 2500}; + + for (int index=0; index < numberOfCases; index++) + { + tet_printf(" UtcDaliTextEditorAtlasLimitationIsEnabledPerformanceCases point-size= %d \n", arrayCases[index]); + textEditor.SetProperty( TextEditor::Property::POINT_SIZE, arrayCases[index]) ; + application.GetScene().Add( textEditor ); + application.SendNotification(); + application.Render(); + naturalSize = textEditor.GetNaturalSize(); + DALI_TEST_GREATER( lessThanWidth, static_cast(naturalSize.width), TEST_LOCATION ); + DALI_TEST_GREATER( lessThanHeight, static_cast(naturalSize.height), TEST_LOCATION ); + + } + + END_TEST; +} + +int UtcDaliTextEditorHyphenWrapMode(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorHyphenWrapMode "); + + int lineCount =0; + TextEditor textEditor = TextEditor::New(); + + textEditor.SetProperty( Actor::Property::SIZE, Vector2( 150.0f, 300.f ) ); + + application.GetScene().Add( textEditor ); + application.SendNotification(); + application.Render(); + + textEditor.SetProperty( TextEditor::Property::TEXT, "Hi Experimen" ); + textEditor.SetProperty(TextEditor::Property::LINE_WRAP_MODE, DevelText::LineWrap::HYPHENATION); + DALI_TEST_EQUALS( textEditor.GetProperty< int >( TextEditor::Property::LINE_WRAP_MODE ), static_cast< int >( DevelText::LineWrap::HYPHENATION ), TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + lineCount = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + /* + text will be : + Hi Exp- + erimen + */ + DALI_TEST_EQUALS( lineCount, 2, TEST_LOCATION ); + + textEditor.SetProperty( TextEditor::Property::TEXT, "Hi Experimen" ); + textEditor.SetProperty(TextEditor::Property::LINE_WRAP_MODE, DevelText::LineWrap::MIXED); + DALI_TEST_EQUALS( textEditor.GetProperty< int >( TextEditor::Property::LINE_WRAP_MODE ), static_cast< int >( DevelText::LineWrap::MIXED ), TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + lineCount = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + /* + text will be : + Hi + Experi- + men + */ + DALI_TEST_EQUALS( lineCount, 3, TEST_LOCATION ); + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index aa25cf2..c615774 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -3524,3 +3524,108 @@ int UtcDaliTextFieldPrimaryCursorPosition(void) END_TEST; } + +// test max length when set after setting long text +int utcDaliTextFieldMaxCharactersReachedAfterSetText(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldMaxCharactersReachedAfterSetText"); + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + application.GetScene().Add( field ); + + field.SetProperty(TextField::Property::TEXT, "123456789"); + + const int maxNumberOfCharacters = 3; + field.SetProperty( TextField::Property::MAX_LENGTH, maxNumberOfCharacters ); + + field.SetKeyInputFocus(); + + // connect to the text max lengh reached signal. + ConnectionTracker* testTracker = new ConnectionTracker(); + bool maxLengthReachedSignal = false; + field.ConnectSignal( testTracker, "maxLengthReached", CallbackFunctor(&maxLengthReachedSignal) ); + + application.ProcessEvent( GenerateKey( "a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + DALI_TEST_CHECK( maxLengthReachedSignal ); + + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::TEXT ).Get(), "123456789", TEST_LOCATION ); + + END_TEST; +} + + + +int UtcDaliTextFieldAtlasLimitationIsEnabledForLargeFontPointSize(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldAtlasLimitationIsEnabledForLargeFontPointSize "); + + // +2: First one to handle the equal case. Second one to handle odd to even case of GetNaturalSize + const uint32_t lessThanWidth = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + const uint32_t lessThanHeight = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + + // Create a text field + TextField textField = TextField::New(); + + //Set size to avoid automatic eliding + textField.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + //Set very large font-size using point-size + textField.SetProperty( TextField::Property::POINT_SIZE, 1000) ; + //Specify font-family + textField.SetProperty( TextField::Property::FONT_FAMILY, "DejaVu Sans"); + //Set text to check if appear or not + textField.SetProperty( TextField::Property::TEXT, "A"); + + application.GetScene().Add( textField ); + + application.SendNotification(); + application.Render(); + //Use GetNaturalSize to verify that size of block does not exceed Atlas size + Vector3 naturalSize = textField.GetNaturalSize(); + + DALI_TEST_GREATER( lessThanWidth, static_cast(naturalSize.width), TEST_LOCATION ); + DALI_TEST_GREATER( lessThanHeight, static_cast(naturalSize.height), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTextFieldAtlasLimitationIsEnabledPerformanceCases(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldAtlasLimitationIsEnabledPerformanceCases "); + + // +2: First one to handle the equal case. Second one to handle odd to even case of GetNaturalSize + const uint32_t lessThanWidth = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + const uint32_t lessThanHeight = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + + Vector3 naturalSize; //Use GetNaturalSize to verify that size of block does not exceed Atlas size + // Create a text editor + TextField textField = TextField::New(); + + //Set size to avoid automatic eliding + textField.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + textField.SetProperty( TextField::Property::FONT_FAMILY, "DejaVu Sans"); + textField.SetProperty( TextField::Property::TEXT, "A"); + + const int numberOfCases = 6; + int arrayCases[numberOfCases] = {323, 326, 330, 600, 1630, 2500}; + + for (int index=0; index < numberOfCases; index++) + { + tet_printf(" UtcDaliTextFieldAtlasLimitationIsEnabledPerformanceCases point-size= %d \n", arrayCases[index]); + textField.SetProperty( TextField::Property::POINT_SIZE, arrayCases[index]) ; + application.GetScene().Add( textField ); + application.SendNotification(); + application.Render(); + naturalSize = textField.GetNaturalSize(); + DALI_TEST_GREATER( lessThanWidth, static_cast(naturalSize.width), TEST_LOCATION ); + DALI_TEST_GREATER( lessThanHeight, static_cast(naturalSize.height), TEST_LOCATION ); + + } + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index ecefef7..ac7403b 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -1802,3 +1802,86 @@ int UtcDaliToolkitTextlabelAnchorClicked(void) END_TEST; } + +int UtcDaliTextLabelAtlasLimitationIsEnabledForLargeFontPointSize(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelAtlasLimitationIsEnabledForLargeFontPointSize "); + + //TextLabel is not using Atlas but this is to unify font-size on text-controllers + + // +2: First one to handle the equal case. Second one to handle odd to even case of GetNaturalSize + const uint32_t lessThanWidth = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + const uint32_t lessThanHeight = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK + 2; + + // Create a text editor + TextLabel textLabel = TextLabel::New(); + //Set size to avoid automatic eliding + textLabel.SetProperty( Actor::Property::SIZE, Vector2(1025, 1025)); + //Set very large font-size using point-size + textLabel.SetProperty( TextLabel::Property::POINT_SIZE, 1000); + //Specify font-family + textLabel.SetProperty( TextLabel::Property::FONT_FAMILY, "DejaVu Sans"); + //Set text to check if appear or not + textLabel.SetProperty( TextLabel::Property::TEXT, "A"); + + application.GetScene().Add( textLabel ); + + application.SendNotification(); + application.Render(); + //Use GetNaturalSize to verify that size of block does not exceed Atlas size + Vector3 naturalSize = textLabel.GetNaturalSize(); + + DALI_TEST_GREATER( lessThanWidth, static_cast(naturalSize.width), TEST_LOCATION ); + DALI_TEST_GREATER( lessThanHeight, static_cast(naturalSize.height), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTextLabelHyphenWrapMode(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextLabelHyphenWrapMode "); + + int lineCount =0; + TextLabel label = TextLabel::New(); + label.SetProperty( Actor::Property::SIZE, Vector2( 150.0f, 300.f )); + label.SetProperty( TextLabel::Property::POINT_SIZE, 12.f ); + label.SetProperty( TextLabel::Property::MULTI_LINE, true); + application.GetScene().Add( label ); + application.SendNotification(); + application.Render(); + + label.SetProperty( TextLabel::Property::TEXT, "Hi Experimen" ); + label.SetProperty(TextLabel::Property::LINE_WRAP_MODE,DevelText::LineWrap::HYPHENATION); + DALI_TEST_EQUALS( label.GetProperty< int >( TextLabel::Property::LINE_WRAP_MODE ), static_cast< int >( DevelText::LineWrap::HYPHENATION ), TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + lineCount = label.GetProperty( TextLabel::Property::LINE_COUNT ); + /* + text will be : + Hi Exp- + erimen + */ + DALI_TEST_EQUALS( lineCount, 2, TEST_LOCATION ); + + label.SetProperty( TextLabel::Property::TEXT, "Hi Experimen" ); + label.SetProperty(TextLabel::Property::LINE_WRAP_MODE,DevelText::LineWrap::MIXED); + DALI_TEST_EQUALS( label.GetProperty< int >( TextLabel::Property::LINE_WRAP_MODE ), static_cast< int >( DevelText::LineWrap::MIXED ), TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + lineCount = label.GetProperty( TextLabel::Property::LINE_COUNT ); + /* + text will be : + Hi + Experi- + men + */ + DALI_TEST_EQUALS( lineCount, 3, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-VideoView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-VideoView.cpp index 9a77bba..de842bf 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-VideoView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-VideoView.cpp @@ -458,6 +458,36 @@ int UtcDaliVideoViewMethodsForCoverage2(void) END_TEST; } +int UtcDaliVideoViewCustomShaderForCoverage3(void) +{ + ToolkitTestApplication application; + VideoView videoView = VideoView::New(); + DALI_TEST_CHECK( videoView ); + + ToolkitApplication::DECODED_IMAGES_SUPPORTED = true; + + videoView.SetProperty( Toolkit::VideoView::Property::UNDERLAY, false ); + bool isUnderlay = videoView.GetProperty( Toolkit::VideoView::Property::UNDERLAY ).Get< bool >(); + DALI_TEST_CHECK( !isUnderlay ); + + application.GetScene().Add( videoView ); + videoView.SetProperty( VideoView::Property::VIDEO, "testvideo" ); + + Property::Map customShader; + customShader.Insert( "vertexShader", VERTEX_SHADER ); + + Property::Map map; + map.Insert( "shader", customShader ); + + videoView.SetProperty( VideoView::Property::VIDEO, map ); + + Property::Map map2; + Property::Value value = videoView.GetProperty( VideoView::Property::VIDEO ); + + DALI_TEST_CHECK( !value.Get( map2 ) ); + END_TEST; +} + int UtcDaliVideoViewPropertyUnderlay(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-WebView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-WebView.cpp index 39ebd29..4fbe8c1 100755 --- a/automated-tests/src/dali-toolkit/utc-Dali-WebView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-WebView.cpp @@ -81,8 +81,8 @@ static int gRequestInterceptorCallbackCalled = 0; static std::shared_ptr gRequestInterceptorInstance = nullptr; static int gConsoleMessageCallbackCalled = 0; static std::shared_ptr gConsoleMessageInstance = nullptr; -static int gPolicyDecisionCallbackCalled = 0; -static std::shared_ptr gPolicyDecisionInstance = nullptr; +static int gResponsePolicyDecidedCallbackCalled = 0; +static std::shared_ptr gResponsePolicyDecisionInstance = nullptr; static int gCertificateConfirmCallbackCalled = 0; static std::shared_ptr gCertificateConfirmInstance = nullptr; static int gSslCertificateChangedCallbackCalled = 0; @@ -101,6 +101,7 @@ static std::shared_ptr gContextMenuInstance = nullpt static int gContextMenuItemSelectedCallbackCalled = 0; static std::shared_ptr gContextMenuItemInstance = nullptr; static int gHitTestCreatedCallbackCalled = 0; +static int gCookieManagerChangsWatchCallbackCalled = 0; struct CallbackFunctor { @@ -136,10 +137,10 @@ static void OnScrollEdgeReached( WebView view, Dali::WebEnginePlugin::ScrollEdge gScrollEdgeReachedCallbackCalled++; } -static void OnPolicyDecisionRequest(WebView view, std::shared_ptr decision) +static void OnResponsePolicyDecided(WebView view, std::shared_ptr decision) { - gPolicyDecisionCallbackCalled++; - gPolicyDecisionInstance = std::move(decision); + gResponsePolicyDecidedCallbackCalled++; + gResponsePolicyDecisionInstance = std::move(decision); } static void OnUrlChanged( WebView view, const std::string& url ) @@ -204,6 +205,11 @@ static bool OnTouched( Actor actor, const Dali::TouchEvent& touch ) return true; } +static void OnChangesWatch() +{ + gCookieManagerChangsWatchCallbackCalled++; +} + static bool OnHovered( Actor actor, const Dali::HoverEvent& hover ) { gHovered = true; @@ -1053,12 +1059,16 @@ int UtcDaliWebViewPropertyTitleFavicon(void) view.GetProperty( WebView::Property::TITLE ).Get( output ); DALI_TEST_EQUALS( output, testValue, TEST_LOCATION ); - // Check default value of favicon - Dali::Toolkit::ImageView* favicon = &view.GetFavicon(); + // Check the case that favicon is not null. + Dali::Toolkit::ImageView favicon = view.GetFavicon(); DALI_TEST_CHECK( favicon ); - Dali::Vector3 iconsize = favicon->GetProperty< Vector3 >( Dali::Actor::Property::SIZE ); + Dali::Vector3 iconsize = favicon.GetProperty< Vector3 >( Dali::Actor::Property::SIZE ); DALI_TEST_CHECK( ( int )iconsize.width == 2 && ( int )iconsize.height == 2 ); + // Check the case that favicon is null. + favicon = view.GetFavicon(); + DALI_TEST_CHECK( !favicon ); + END_TEST; } @@ -1294,7 +1304,7 @@ int UtcDaliWebViewHttpRequestInterceptor(void) END_TEST; } -int UtcDaliWebViewPolicyDecisionRequest(void) +int UtcDaliWebViewResponsePolicyDecisionRequest(void) { ToolkitTestApplication application; @@ -1303,42 +1313,42 @@ int UtcDaliWebViewPolicyDecisionRequest(void) // load url. ConnectionTracker* testTracker = new ConnectionTracker(); - view.PolicyDecisionSignal().Connect( &OnPolicyDecisionRequest ); + view.ResponsePolicyDecisionSignal().Connect( &OnResponsePolicyDecided ); bool signal1 = false; - view.ConnectSignal( testTracker, "policyDecision", CallbackFunctor(&signal1) ); - DALI_TEST_EQUALS( gPolicyDecisionCallbackCalled, 0, TEST_LOCATION ); - DALI_TEST_CHECK(gPolicyDecisionInstance == 0); + view.ConnectSignal( testTracker, "responsePolicyDecided", CallbackFunctor(&signal1) ); + DALI_TEST_EQUALS( gResponsePolicyDecidedCallbackCalled, 0, TEST_LOCATION ); + DALI_TEST_CHECK(gResponsePolicyDecisionInstance == 0); view.LoadUrl( TEST_URL1 ); Test::EmitGlobalTimerSignal(); - DALI_TEST_EQUALS( gPolicyDecisionCallbackCalled, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( gResponsePolicyDecidedCallbackCalled, 1, TEST_LOCATION ); DALI_TEST_CHECK( signal1 ); - // check policy decision & its frame. - DALI_TEST_CHECK(gPolicyDecisionInstance != 0); + // check response policy decision & its frame. + DALI_TEST_CHECK(gResponsePolicyDecisionInstance != 0); std::string testUrl("http://test.html"); - DALI_TEST_EQUALS(gPolicyDecisionInstance->GetUrl(), testUrl, TEST_LOCATION); + DALI_TEST_EQUALS(gResponsePolicyDecisionInstance->GetUrl(), testUrl, TEST_LOCATION); std::string testCookie("test:abc"); - DALI_TEST_EQUALS(gPolicyDecisionInstance->GetCookie(), testCookie, TEST_LOCATION); + DALI_TEST_EQUALS(gResponsePolicyDecisionInstance->GetCookie(), testCookie, TEST_LOCATION); Dali::WebEnginePolicyDecision::DecisionType testDecisionType = Dali::WebEnginePolicyDecision::DecisionType::USE; - DALI_TEST_EQUALS(gPolicyDecisionInstance->GetDecisionType(), testDecisionType, TEST_LOCATION); + DALI_TEST_EQUALS(gResponsePolicyDecisionInstance->GetDecisionType(), testDecisionType, TEST_LOCATION); std::string testResponseMime("txt/xml"); - DALI_TEST_EQUALS(gPolicyDecisionInstance->GetResponseMime(), testResponseMime, TEST_LOCATION); + DALI_TEST_EQUALS(gResponsePolicyDecisionInstance->GetResponseMime(), testResponseMime, TEST_LOCATION); int32_t ResponseStatusCode = 500; - DALI_TEST_EQUALS(gPolicyDecisionInstance->GetResponseStatusCode(), ResponseStatusCode, TEST_LOCATION); + DALI_TEST_EQUALS(gResponsePolicyDecisionInstance->GetResponseStatusCode(), ResponseStatusCode, TEST_LOCATION); Dali::WebEnginePolicyDecision::NavigationType testNavigationType = Dali::WebEnginePolicyDecision::NavigationType::LINK_CLICKED; - DALI_TEST_EQUALS(gPolicyDecisionInstance->GetNavigationType(), testNavigationType, TEST_LOCATION); + DALI_TEST_EQUALS(gResponsePolicyDecisionInstance->GetNavigationType(), testNavigationType, TEST_LOCATION); std::string testScheme("test"); - DALI_TEST_EQUALS(gPolicyDecisionInstance->GetScheme(), testScheme, TEST_LOCATION); - DALI_TEST_CHECK(gPolicyDecisionInstance->Use()); - DALI_TEST_CHECK(gPolicyDecisionInstance->Ignore()); - DALI_TEST_CHECK(gPolicyDecisionInstance->Suspend()); + DALI_TEST_EQUALS(gResponsePolicyDecisionInstance->GetScheme(), testScheme, TEST_LOCATION); + DALI_TEST_CHECK(gResponsePolicyDecisionInstance->Use()); + DALI_TEST_CHECK(gResponsePolicyDecisionInstance->Ignore()); + DALI_TEST_CHECK(gResponsePolicyDecisionInstance->Suspend()); - Dali::WebEngineFrame* webFrame = &(gPolicyDecisionInstance->GetFrame()); + Dali::WebEngineFrame* webFrame = &(gResponsePolicyDecisionInstance->GetFrame()); DALI_TEST_CHECK(webFrame); DALI_TEST_CHECK(webFrame->IsMainFrame()); - gPolicyDecisionInstance = nullptr; + gResponsePolicyDecisionInstance = nullptr; END_TEST; } @@ -1577,12 +1587,19 @@ int UtcDaliWebContextGetSetCacheModel(void) // Reset something context->SetProxyUri( kDefaultValue ); context->SetCertificateFilePath( kDefaultValue ); - context->DisableCache( false ); + context->EnableCache( true ); context->SetDefaultProxyAuth( kDefaultValue, kDefaultValue ); context->DeleteAllWebDatabase(); context->DeleteAllWebStorage(); context->DeleteLocalFileSystem(); context->ClearCache(); + context->SetContextAppId( "id" ); + context->SetContextApplicationType( Dali::WebEngineContext::ApplicationType::OTHER ); + context->SetContextTimeOffset( 0 ); + context->SetContextTimeZoneOffset( 0, 0 ); + context->SetDefaultZoomFactor( 0 ); + context->DeleteAllFormPasswordData(); + context->DeleteAllFormCandidateData(); // Check default value Dali::WebEngineContext::CacheModel value = context->GetCacheModel(); @@ -1593,6 +1610,37 @@ int UtcDaliWebContextGetSetCacheModel(void) value = context->GetCacheModel(); DALI_TEST_CHECK( value == Dali::WebEngineContext::CacheModel::DOCUMENT_BROWSER ); + // Get cache enabled + DALI_TEST_CHECK( context->IsCacheEnabled() ); + + // Get certificate + std::string str = context->GetContextCertificateFile(); + DALI_TEST_EQUALS( str, "test", TEST_LOCATION ); + + // Set version + DALI_TEST_CHECK( context->SetContextAppVersion( "test" ) ); + + // Register + std::vector temp; + context->RegisterUrlSchemesAsCorsEnabled( temp ); + context->RegisterJsPluginMimeTypes( temp ); + context->DeleteFormPasswordDataList( temp ); + + // Get zoom + DALI_TEST_EQUALS( context->GetContextDefaultZoomFactor(), float( 0 ), TEST_LOCATION ); + + // Delete cache and database + DALI_TEST_CHECK( context->DeleteAllApplicationCache() ); + DALI_TEST_CHECK( context->DeleteAllWebIndexedDatabase() ); + + // Get contextProxy + context->SetContextProxy("", ""); + DALI_TEST_EQUALS( context->GetContextProxy(), "test", TEST_LOCATION ); + DALI_TEST_EQUALS( context->GetProxyBypassRule(), "test", TEST_LOCATION ); + + //Notify low memory + DALI_TEST_CHECK( context->FreeUnusedMemory() ); + END_TEST; } @@ -1638,7 +1686,7 @@ int UtcDaliWebContextGetWebDatabaseStorageOrigins(void) Test::EmitGlobalTimerSignal(); DALI_TEST_EQUALS( gStorageUsageAcquiredCallbackCalled, 1, TEST_LOCATION ); - result = context->DeleteWebStorageOrigin(*origin); + result = context->DeleteWebStorage(*origin); DALI_TEST_CHECK( result ); result = context->DeleteApplicationCache(*origin); @@ -1696,6 +1744,23 @@ int UtcDaliWebCookieManagerGetSetCookieAcceptPolicy(void) END_TEST; } +int UtcDaliWebCookieManagerChangesWatch(void) +{ + ToolkitTestApplication application; + + WebView view = WebView::New(); + DALI_TEST_CHECK( view ); + + Dali::Toolkit::WebCookieManager* cookieManager = view.GetCookieManager(); + DALI_TEST_CHECK( cookieManager != 0 ) + + cookieManager->ChangesWatch(&OnChangesWatch); + Test::EmitGlobalTimerSignal(); + DALI_TEST_EQUALS( gCookieManagerChangsWatchCallbackCalled, 1, TEST_LOCATION ); + + END_TEST; +} + // test cases for web settings. int UtcDaliWebSettingsGetSetDefaultFontSize(void) diff --git a/build/tizen/.gitignore b/build/tizen/.gitignore index e59a17f..2d253c9 100644 --- a/build/tizen/.gitignore +++ b/build/tizen/.gitignore @@ -2,4 +2,5 @@ build dali.info *.dylib dali2-*-config.cmake -libdali2-scene-loader.so* \ No newline at end of file +libdali2-scene-loader.so* +dali-shader-generator diff --git a/build/tizen/CMakeLists.txt b/build/tizen/CMakeLists.txt index 8be2625..cd463b5 100644 --- a/build/tizen/CMakeLists.txt +++ b/build/tizen/CMakeLists.txt @@ -286,13 +286,51 @@ ENDIF() # Generate source files for shaders SET(SHADER_SOURCE_DIR "${ROOT_SRC_DIR}/dali-toolkit/internal/graphics/shaders/") SET(SHADER_GENERATED_DIR "${ROOT_SRC_DIR}/dali-toolkit/internal/graphics/generated") -EXECUTE_PROCESS( COMMAND bash -c "${CMAKE_CURRENT_SOURCE_DIR}/shader-generator.sh ${SHADER_SOURCE_DIR} ${SHADER_GENERATED_DIR}" ) SET(GENERATED_SHADER_DIR ${ROOT_SRC_DIR}/dali-toolkit/internal/graphics/) SET_PROPERTY(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${GENERATED_SHADER_DIR}/generated/" "${GENERATED_SHADER_DIR}/builtin-shader-extern-gen.h") +SET(SHADER_GENERATOR_NAME dali-shader-generator) +SET(SHADER_GENERATOR_SOURCES ${ROOT_SRC_DIR}/dali-toolkit/shader-generator/shader-generator.cpp) + +IF( WIN32) + # When Using VCPKG, the default is always set to Debug if CMAKE_BUILD_TYPE is not set + IF( NOT CMAKE_BUILD_TYPE ) + SET(SHADER_GENERATOR_BINARY ${CMAKE_CURRENT_BINARY_DIR}/Debug/${SHADER_GENERATOR_NAME}) + ELSE() + SET(SHADER_GENERATOR_BINARY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${SHADER_GENERATOR_NAME}) + ENDIF() +ELSE() + SET(SHADER_GENERATOR_BINARY ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_GENERATOR_NAME}) +ENDIF() + +IF(NOT ANDROID) + ADD_EXECUTABLE(${SHADER_GENERATOR_NAME} ${SHADER_GENERATOR_SOURCES}) + INSTALL(TARGETS ${SHADER_GENERATOR_NAME} RUNTIME DESTINATION bin) +ELSE() + # Need to build dali-shader-generator using the host compiler, not the android cross-compiler so + # that it can be run on the host machine + OPTION(ANDROID_HOST_COMPILER "Provide the host compiler used by Android (Mandatory)") + IF(${ANDROID_HOST_COMPILER} STREQUAL "OFF") + MESSAGE(FATAL_ERROR "-DANDROID_HOST_COMPILER=\"Compiler\" must be set") + ENDIF() + + ADD_CUSTOM_COMMAND(OUTPUT ${SHADER_GENERATOR_NAME} + COMMAND ${ANDROID_HOST_COMPILER} -o ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_GENERATOR_NAME} -std=c++17 ${SHADER_GENERATOR_SOURCES}) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_GENERATOR_NAME} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + DESTINATION bin) +ENDIF() + +SET(BUILT_IN_SHADER_GEN_CPP "${GENERATED_SHADER_DIR}/generated/builtin-shader-gen.cpp") +ADD_CUSTOM_COMMAND(OUTPUT ${BUILT_IN_SHADER_GEN_CPP} + DEPENDS ${SHADER_GENERATOR_NAME} + COMMAND ${SHADER_GENERATOR_BINARY} ${SHADER_SOURCE_DIR} ${SHADER_GENERATED_DIR}) + +SET(SOURCES ${SOURCES} ${BUILT_IN_SHADER_GEN_CPP}) + IF( WIN32 OR APPLE ) SET( DALICORE_LDFLAGS "${DALICORE_LDFLAGS}" diff --git a/build/tizen/dali-scene-loader/CMakeLists.txt b/build/tizen/dali-scene-loader/CMakeLists.txt index ae7fea2..8891e9d 100644 --- a/build/tizen/dali-scene-loader/CMakeLists.txt +++ b/build/tizen/dali-scene-loader/CMakeLists.txt @@ -14,6 +14,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) add_definitions("-DDEBUG_ENABLED") endif() +ADD_DEFINITIONS( "-DBUILDING_DALI_SCENE_LOADER" ) + foreach(flag ${PKGS_CFLAGS}) set(extra_flags "${extra_flags} ${flag}") endforeach(flag) @@ -77,6 +79,33 @@ include_directories(${repo_root_dir} ${prefix_include_dir} ) +# Generate source files for shaders +SET(SHADER_SOURCE_DIR "${scene_loader_dir}/internal/graphics/shaders/") +SET(SHADER_GENERATED_DIR "${scene_loader_dir}/internal/graphics/generated") + +SET(GENERATED_SHADER_DIR ${scene_loader_dir}/internal/graphics/) +SET_PROPERTY(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + "${GENERATED_SHADER_DIR}/generated/" + "${GENERATED_SHADER_DIR}/builtin-shader-extern-gen.h") + +IF( WIN32) + # When Using VCPKG, the default is always set to Debug if CMAKE_BUILD_TYPE is not set + IF( NOT CMAKE_BUILD_TYPE ) + SET(SHADER_GENERATOR_BINARY ${CMAKE_CURRENT_BINARY_DIR}/../Debug/${SHADER_GENERATOR_NAME}) + ELSE() + SET(SHADER_GENERATOR_BINARY ${CMAKE_CURRENT_BINARY_DIR}/../${CMAKE_BUILD_TYPE}/${SHADER_GENERATOR_NAME}) + ENDIF() +ELSE() + SET(SHADER_GENERATOR_BINARY ${CMAKE_CURRENT_BINARY_DIR}/../${SHADER_GENERATOR_NAME}) +ENDIF() + +SET( BUILT_IN_SHADER_GEN_CPP "${GENERATED_SHADER_DIR}/generated/builtin-shader-gen.cpp") +ADD_CUSTOM_COMMAND(OUTPUT ${BUILT_IN_SHADER_GEN_CPP} + DEPENDS ${SHADER_GENERATOR_BINARY} + COMMAND ${SHADER_GENERATOR_BINARY} ${SHADER_SOURCE_DIR} ${SHADER_GENERATED_DIR}) + +SET( scene_loader_src_files ${scene_loader_src_files} ${BUILT_IN_SHADER_GEN_CPP} ) + add_library(${name} SHARED ${scene_loader_src_files}) target_link_libraries(${name} ${DALICORE_LDFLAGS} ${DALIADAPTOR_LDFLAGS} @@ -87,16 +116,6 @@ if( ANDROID ) target_link_libraries(${name} log) endif() -# Generate source files for shaders -SET(SHADER_SOURCE_DIR "${scene_loader_dir}/internal/graphics/shaders/") -SET(SHADER_GENERATED_DIR "${scene_loader_dir}/internal/graphics/generated") -EXECUTE_PROCESS( COMMAND bash -c "${repo_root_dir}/build/tizen/shader-generator.sh ${SHADER_SOURCE_DIR} ${SHADER_GENERATED_DIR}" ) - -SET(GENERATED_SHADER_DIR ${scene_loader_dir}/internal/graphics/) -SET_PROPERTY(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES - "${GENERATED_SHADER_DIR}/generated/" - "${GENERATED_SHADER_DIR}/builtin-shader-extern-gen.h") - IF( INSTALL_CMAKE_MODULES ) SET_TARGET_PROPERTIES( ${name} PROPERTIES diff --git a/build/tizen/shader-generator.sh b/build/tizen/shader-generator.sh deleted file mode 100755 index 7b6b2fc..0000000 --- a/build/tizen/shader-generator.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -indir=$1 -outdir=$2 - -mkdir -p $outdir - -if [ ! -e $indir ] ; then - echo "Error! "$indir" not found!" - exit 0 -fi - -cd $indir -all_shaders=$(ls -1 *.{vert,frag,def}) -cd $OLDPWD - -# Generate one header file per shader which is defined as a const std::string_view -for name in $all_shaders ; do - echo "Generating header files for $name..." - varname=$(echo "SHADER_$name" | tr [a-z] [A-Z] | sed -e 's/-/_/g;s/\./_/g;') - - newname=$(echo ${name} | sed -e 's/\./-/;')".h" - echo Writing $newname - - shader_fullpath=$(echo ${indir})$name - - header_name="${varname}_GEN_H" - echo "const std::string_view" "$varname""{" > $outdir/$newname - cat $shader_fullpath | sed -e 's/^..*$/"&\\n"/' >> $outdir/$newname - echo "};" >> $outdir/$newname -done - -# Generate one cpp file that includes all the previously generated string_views for shaders -echo "Generating cpp file..." -echo -e "#include \"../builtin-shader-extern-gen.h\"\n" > $outdir/builtin-shader-gen.cpp - -varnames= -for name in $all_shaders ; do - varname=$(echo "SHADER_$name" | tr [a-z] [A-Z] | sed -e 's/-/_/g;s/\./_/g;') - newname=$(echo ${name} | sed -e 's/\./-/;')".h" - varnames="${varnames} $varname" - echo "#include \"$newname\"" >> $outdir/builtin-shader-gen.cpp -done - -# Generate one header file that defines all the shader string_views as extern variables -echo "Generating extern header file ( for external use )..." -echo "#ifndef GRAPHICS_BUILTIN_SHADER_EXTERN_GEN_H" > $outdir/../builtin-shader-extern-gen.h -echo -e "#define GRAPHICS_BUILTIN_SHADER_EXTERN_GEN_H\n" >> $outdir/../builtin-shader-extern-gen.h - -echo "#include " >> $outdir/../builtin-shader-extern-gen.h -echo "" >> $outdir/../builtin-shader-extern-gen.h - -for name in $all_shaders ; do - varname=$(echo "SHADER_$name" | tr [a-z] [A-Z] | sed -e 's/-/_/g;s/\./_/g;') - newname=$(echo ${name} | sed -e 's/\./-/;')".h" - echo "extern const std::string_view $varname;" >> $outdir/../builtin-shader-extern-gen.h -done -cat >> $outdir/../builtin-shader-extern-gen.h << EOF - -#endif // GRAPHICS_BUILTIN_SHADER_EXTERN_GEN_H -EOF - diff --git a/dali-scene-loader/public-api/mesh-definition.cpp b/dali-scene-loader/public-api/mesh-definition.cpp index 8317803..de37e30 100644 --- a/dali-scene-loader/public-api/mesh-definition.cpp +++ b/dali-scene-loader/public-api/mesh-definition.cpp @@ -466,9 +466,9 @@ void MeshDefinition::Blob::ApplyMinMax(const std::vector& min, const std: : (max.empty() ? [](const float* min, const float* max, uint32_t i, float& value) { value = std::max(min[i], value); } - : [](const float* min, const float* max, uint32_t i, float& value) { + : static_cast([](const float* min, const float* max, uint32_t i, float& value) { value = std::min(std::max(min[i], value), max[i]); - }); + })); if(!clampFn) { diff --git a/dali-toolkit/devel-api/controls/web-view/web-context.cpp b/dali-toolkit/devel-api/controls/web-view/web-context.cpp old mode 100644 new mode 100755 index 413f5ca..2a7090b --- a/dali-toolkit/devel-api/controls/web-view/web-context.cpp +++ b/dali-toolkit/devel-api/controls/web-view/web-context.cpp @@ -54,11 +54,6 @@ void WebContext::SetCertificateFilePath(const std::string& certificatePath) mWebEngineContext.SetCertificateFilePath(certificatePath); } -void WebContext::DisableCache(bool cacheDisabled) -{ - mWebEngineContext.DisableCache(cacheDisabled); -} - void WebContext::SetDefaultProxyAuth(const std::string& username, const std::string& password) { mWebEngineContext.SetDefaultProxyAuth(username, password); @@ -94,9 +89,9 @@ void WebContext::DeleteAllWebStorage() mWebEngineContext.DeleteAllWebStorage(); } -bool WebContext::DeleteWebStorageOrigin(Dali::WebEngineSecurityOrigin& origin) +bool WebContext::DeleteWebStorage(Dali::WebEngineSecurityOrigin& origin) { - return mWebEngineContext.DeleteWebStorageOrigin(origin); + return mWebEngineContext.DeleteWebStorage(origin); } void WebContext::DeleteLocalFileSystem() @@ -129,5 +124,110 @@ void WebContext::RegisterMimeOverriddenCallback(Dali::WebEngineContext::WebEngin mWebEngineContext.RegisterMimeOverriddenCallback(callback); } +void WebContext::EnableCache(bool cacheEnabled) +{ + mWebEngineContext.EnableCache(cacheEnabled); +} + +bool WebContext::IsCacheEnabled() const +{ + return mWebEngineContext.IsCacheEnabled(); +} + +std::string WebContext::GetContextCertificateFile() const +{ + return mWebEngineContext.GetContextCertificateFile(); +} + +void WebContext::SetContextAppId(const std::string& appID) +{ + mWebEngineContext.SetContextAppId(appID); +} + +bool WebContext::SetContextAppVersion(const std::string& appVersion) +{ + return mWebEngineContext.SetContextAppVersion(appVersion); +} + +void WebContext::SetContextApplicationType(const Dali::WebEngineContext::ApplicationType applicationType) +{ + mWebEngineContext.SetContextApplicationType(applicationType); +} + +void WebContext::SetContextTimeOffset(float timeOffset) +{ + mWebEngineContext.SetContextTimeOffset(timeOffset); +} + +void WebContext::SetContextTimeZoneOffset(float timeZoneOffset, float daylightSavingTime) +{ + mWebEngineContext.SetContextTimeZoneOffset(timeZoneOffset, daylightSavingTime); +} + +void WebContext::RegisterUrlSchemesAsCorsEnabled(const std::vector& schemes) +{ + mWebEngineContext.RegisterUrlSchemesAsCorsEnabled(schemes); +} + +void WebContext::RegisterJsPluginMimeTypes(const std::vector& mimeTypes) +{ + mWebEngineContext.RegisterJsPluginMimeTypes(mimeTypes); +} + +void WebContext::SetDefaultZoomFactor(float zoomFactor) +{ + mWebEngineContext.SetDefaultZoomFactor(zoomFactor); +} + +float WebContext::GetContextDefaultZoomFactor() const +{ + return mWebEngineContext.GetContextDefaultZoomFactor(); +} + +bool WebContext::DeleteAllApplicationCache() +{ + return mWebEngineContext.DeleteAllApplicationCache(); +} + +bool WebContext::DeleteAllWebIndexedDatabase() +{ + return mWebEngineContext.DeleteAllWebIndexedDatabase(); +} + +void WebContext::DeleteFormPasswordDataList(const std::vector& list) +{ + mWebEngineContext.DeleteFormPasswordDataList(list); +} + +void WebContext::DeleteAllFormPasswordData() +{ + mWebEngineContext.DeleteAllFormPasswordData(); +} + +void WebContext::DeleteAllFormCandidateData() +{ + mWebEngineContext.DeleteAllFormCandidateData(); +} + +std::string WebContext::GetContextProxy() const +{ + return mWebEngineContext.GetContextProxy(); +} + +void WebContext::SetContextProxy(const std::string& proxy, const std::string& bypass) +{ + mWebEngineContext.SetContextProxy(proxy, bypass); +} + +std::string WebContext::GetProxyBypassRule() const +{ + return mWebEngineContext.GetProxyBypassRule(); +} + +bool WebContext::FreeUnusedMemory() +{ + return mWebEngineContext.FreeUnusedMemory(); +} + } // namespace Toolkit } // namespace Dali diff --git a/dali-toolkit/devel-api/controls/web-view/web-context.h b/dali-toolkit/devel-api/controls/web-view/web-context.h index cdf7f0e..531ec00 100755 --- a/dali-toolkit/devel-api/controls/web-view/web-context.h +++ b/dali-toolkit/devel-api/controls/web-view/web-context.h @@ -91,16 +91,6 @@ public: void SetCertificateFilePath(const std::string& certificatePath); /** - * @brief Toggle the cache to be enabled or disabled - * - * Function works asynchronously. - * By default the cache is disabled resulting in not storing network data on disk. - * - * @param[in] cacheDisabled enable or disable cache - */ - void DisableCache(bool cacheDisabled); - - /** * @brief Set a proxy auth credential to network backend of specific context. * * @param[in] username username to set @@ -159,13 +149,13 @@ public: void DeleteAllWebStorage(); /** - * @brief Delete origin that is stored in web storage db. + * @brief Delete web storage db. * * @param[in] origin origin of db * * @return true if succeeded, false otherwise */ - bool DeleteWebStorageOrigin(Dali::WebEngineSecurityOrigin& origin); + bool DeleteWebStorage(Dali::WebEngineSecurityOrigin& origin); /** * @brief Request for deleting all local file systems. @@ -207,6 +197,160 @@ public: */ void RegisterMimeOverriddenCallback(Dali::WebEngineContext::WebEngineMimeOverriddenCallback callback); + /** + * @brief Toggle the cache to be enabled or disabled + * + * @param[in] cacheEnabled enable or disable cache + */ + void EnableCache(bool cacheEnabled); + + /** + * @brief Query if the cache is enabled + * + * @return @c true is cache is enabled or @c false otherwise + */ + bool IsCacheEnabled() const; + + /** + * @brief Get CA certifcate file path + * + * It returns an internal string and should not be modified. + * + * @return @c certificate_file is path which is set during ewk_context_certificate_file_set or @c null string otherwise + */ + std::string GetContextCertificateFile() const; + + /** + * @brief Set application id for @a context. + * + * @param[in] appID application id + */ + void SetContextAppId(const std::string& appID); + + /** + * @brief Set application version for @a context. + * + * @param[in] appVersion application version + * + * @return @c true if successful, @c false otherwise + */ + bool SetContextAppVersion(const std::string& appVersion); + + /** + * @brief To declare application type + * + * @param[in] applicationType The Application_Type enum + * + */ + void SetContextApplicationType(const Dali::WebEngineContext::ApplicationType applicationType); + + /** + * @brief Set time offset + * + * @param[in] timeOffset The value will be added to system time as offset + */ + void SetContextTimeOffset(float timeOffset); + + /** + * @brief Set timezone offset + * + * @param[in] timeZoneOffset offset for time zone. + * @param[in] daylightSavingTime The value is for daylight saving time use. + */ + void SetContextTimeZoneOffset(float timeZoneOffset, float daylightSavingTime); + + /** + * @brief Register url schemes as CORS enabled + * + * @param[in] schemes The URL schemes list which will be added to web security policy + * + */ + void RegisterUrlSchemesAsCorsEnabled(const std::vector& schemes); + + /** + * @brief Register JS plugin mime types. + * + * @param[in] mimeTypes The MIME types will be checked by the renderer frame loader + * to skip creating default frame for the object tags with the registered MIME type. + */ + void RegisterJsPluginMimeTypes(const std::vector& mimeTypes); + + /** + * @brief Set default zoom factor + * + * @param[in] zoomFactor default zoom factor + */ + void SetDefaultZoomFactor(float zoomFactor); + + /** + * @brief Get default zoom factor + * + * Gets default zoom factor for all pages opened with this context. + * + * @return @c default zoom factor or negative value on error + */ + float GetContextDefaultZoomFactor() const; + + /** + * @brief Request for deleting all web application caches. + * + * @return @c true on success, otherwise @c false + */ + bool DeleteAllApplicationCache(); + + /** + * @brief Request for deleting all web indexed databases. + * + * @return @c true on success, otherwise @c false + */ + bool DeleteAllWebIndexedDatabase(); + + /** + * @brief Delete a given password data list + * + * @param[in] list List with Ewk_Password_Data + */ + void DeleteFormPasswordDataList(const std::vector& list); + + /** + * @brief Delete whole password data from DB + */ + void DeleteAllFormPasswordData(); + + /** + * @brief Delete all candidate form data from DB + */ + void DeleteAllFormCandidateData(); + + /** + * @brief Get the proxy URI from the network backend of specific context. + * + * @return current proxy URI or @c null string if it's not set + */ + std::string GetContextProxy() const; + + /** + * @brief Set the given proxy to network backend of specific context. + * + * @param[in] proxy URI to set + * @param[in] bypass rule to set + */ + void SetContextProxy(const std::string& proxy, const std::string& bypass); + + /** + * @brief Get the proxy bypass rule from the network backend of specific context. + * + * @return current proxy bypass rule or @c null string if it's not set + */ + std::string GetProxyBypassRule() const; + + /** + * @brief Notify low memory to free unused memory. + * + * @return @c true on success or @c false otherwise. + */ + bool FreeUnusedMemory(); + private: Dali::WebEngineContext& mWebEngineContext; }; diff --git a/dali-toolkit/devel-api/controls/web-view/web-cookie-manager.cpp b/dali-toolkit/devel-api/controls/web-view/web-cookie-manager.cpp old mode 100644 new mode 100755 index fba924a..61529a8 --- a/dali-toolkit/devel-api/controls/web-view/web-cookie-manager.cpp +++ b/dali-toolkit/devel-api/controls/web-view/web-cookie-manager.cpp @@ -51,6 +51,11 @@ void WebCookieManager::SetPersistentStorage(const std::string& path, Dali::WebEn mWebEngineCookieManager.SetPersistentStorage(path, storage); } +void WebCookieManager::ChangesWatch(Dali::WebEngineCookieManager::WebEngineCookieManagerChangesWatchCallback callback) +{ + mWebEngineCookieManager.ChangesWatch(callback); +} + } // namespace Toolkit } // namespace Dali diff --git a/dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h b/dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h index adb133a..421db32 100755 --- a/dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h +++ b/dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h @@ -93,6 +93,13 @@ public: */ void SetPersistentStorage(const std::string& path, Dali::WebEngineCookieManager::CookiePersistentStorage storage); + /** + * @brief Watch for cookies' changes in @a manager. + * + * @param[in] callback cookies are added, removed or modified. + */ + void ChangesWatch(Dali::WebEngineCookieManager::WebEngineCookieManagerChangesWatchCallback callback); + private: Dali::WebEngineCookieManager& mWebEngineCookieManager; }; diff --git a/dali-toolkit/devel-api/controls/web-view/web-view.cpp b/dali-toolkit/devel-api/controls/web-view/web-view.cpp index d3c201a..5cac9f4 100755 --- a/dali-toolkit/devel-api/controls/web-view/web-view.cpp +++ b/dali-toolkit/devel-api/controls/web-view/web-view.cpp @@ -89,7 +89,7 @@ Dali::Toolkit::WebBackForwardList* WebView::GetBackForwardList() const return Dali::Toolkit::GetImpl(*this).GetBackForwardList(); } -Dali::Toolkit::ImageView& WebView::GetFavicon() +Dali::Toolkit::ImageView WebView::GetFavicon() const { return Dali::Toolkit::GetImpl(*this).GetFavicon(); } @@ -359,9 +359,9 @@ WebView::WebViewConsoleMessageSignalType& WebView::ConsoleMessageSignal() return Dali::Toolkit::GetImpl(*this).ConsoleMessageSignal(); } -WebView::WebViewPolicyDecisionSignalType& WebView::PolicyDecisionSignal() +WebView::WebViewResponsePolicyDecisionSignalType& WebView::ResponsePolicyDecisionSignal() { - return Dali::Toolkit::GetImpl(*this).PolicyDecisionSignal(); + return Dali::Toolkit::GetImpl(*this).ResponsePolicyDecisionSignal(); } WebView::WebViewCertificateSignalType& WebView::CertificateConfirmSignal() diff --git a/dali-toolkit/devel-api/controls/web-view/web-view.h b/dali-toolkit/devel-api/controls/web-view/web-view.h index 4f9159d..b290bfd 100755 --- a/dali-toolkit/devel-api/controls/web-view/web-view.h +++ b/dali-toolkit/devel-api/controls/web-view/web-view.h @@ -234,9 +234,9 @@ public: using WebViewConsoleMessageSignalType = Signal)>; /** - * @brief WebView signal type related with policy decision. + * @brief WebView signal type related with response policy decision. */ - using WebViewPolicyDecisionSignalType = Signal)>; + using WebViewResponsePolicyDecisionSignalType = Signal)>; /** * @brief WebView signal type related with certificate changed. @@ -342,11 +342,11 @@ public: Dali::Toolkit::WebBackForwardList* GetBackForwardList() const; /** - * @brief Get Favicon of web page. + * @brief Get favicon of web page. * - * @return Handle to a fav icon + * @return Handle to a favicon */ - Dali::Toolkit::ImageView& GetFavicon(); + Dali::Toolkit::ImageView GetFavicon() const; /** * @brief Load a web page based on a given URL. @@ -753,11 +753,11 @@ public: WebViewConsoleMessageSignalType& ConsoleMessageSignal(); /** - * @brief Connect to this signal to be notified when new policy would be decided. + * @brief Connect to this signal to be notified when response policy would be decided. * * @return A signal object to connect with. */ - WebViewPolicyDecisionSignalType& PolicyDecisionSignal(); + WebViewResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal(); /** * @brief Connect to this signal to be notified when certificate need be confirmed. diff --git a/dali-toolkit/devel-api/text/text-enumerations-devel.h b/dali-toolkit/devel-api/text/text-enumerations-devel.h index 0163cc6..a74af43 100644 --- a/dali-toolkit/devel-api/text/text-enumerations-devel.h +++ b/dali-toolkit/devel-api/text/text-enumerations-devel.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_TEXT_ENUMERATIONS_DEVEL_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,17 @@ enum Type }; } // namespace VerticalLineAlignment +namespace LineWrap +{ +enum Mode +{ + WORD, + CHARACTER, + HYPHENATION, // HYPHENATION mode will add hyphen and move part of the word to the next line. + MIXED // MIXEd mode will apply WORD mode, if failed try HYPHENATION mode, if failed try CHARACTER. +}; + +} // namespace LineWrap } // namespace DevelText diff --git a/dali-toolkit/devel-api/text/text-utils-devel.cpp b/dali-toolkit/devel-api/text/text-utils-devel.cpp index 1441dc4..a4dbce4 100644 --- a/dali-toolkit/devel-api/text/text-utils-devel.cpp +++ b/dali-toolkit/devel-api/text/text-utils-devel.cpp @@ -173,7 +173,8 @@ void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstracti MarkupProcessData markupProcessData(colorRuns, fontDescriptionRuns, textModel->mLogicalModel->mEmbeddedItems, - textModel->mLogicalModel->mAnchors); + textModel->mLogicalModel->mAnchors, + textModel->mLogicalModel->mUnderlinedCharacterRuns); if(textParameters.markupEnabled) { @@ -1029,7 +1030,7 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR // Resize the vector of positions to have the same size than the vector of glyphs. rendererParameters.positions.Resize(numberOfGlyphs); - textModel->mLineWrapMode = LineWrap::WORD; + textModel->mLineWrapMode = Text::LineWrap::WORD; textModel->mIgnoreSpacesAfterText = false; textModel->mMatchSystemLanguageDirection = false; Text::Layout::Parameters layoutParameters(internalDataModel.textLayoutArea, diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp index 07c77d9..342784a 100644 --- a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp @@ -120,7 +120,7 @@ void CanvasView::OnSizeSet(const Vector3& targetSize) mChanged = true; } -void CanvasView::Process() +void CanvasView::Process(bool postProcessor) { if(!mCanvasRenderer) { diff --git a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h index bc5c708..b2d5775 100644 --- a/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h +++ b/dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h @@ -82,7 +82,7 @@ protected: // Implementation of Processor /** * @copydoc Dali::Integration::Processor::Process() */ - void Process() override; + void Process(bool postProcessor) override; private: /** diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index 1c48bc1..9e69f95 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -487,7 +487,6 @@ Control::Impl::~Impl() StopObservingVisual(iter->visual); } - AccessibilityDeregister(); // All gesture detectors will be destroyed so no need to disconnect. delete mStartingPinchScale; @@ -1471,6 +1470,15 @@ Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfo { place->Get(value); } + else + { + Dali::Accessibility::ReadingInfoTypes types; + types[Dali::Accessibility::ReadingInfoType::NAME] = true; + types[Dali::Accessibility::ReadingInfoType::ROLE] = true; + types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true; + types[Dali::Accessibility::ReadingInfoType::STATE] = true; + return types; + } if(value.empty()) { @@ -1942,12 +1950,32 @@ void Control::Impl::AccessibilityRegister() } } -void Control::Impl::AccessibilityDeregister() +void Control::Impl::AccessibilityDeregister(bool remove) { if(accessibilityNotificationSet) { + accessibilityNotificationPosition.NotifySignal().Disconnect(&Control::Impl::PositionOrSizeChangedCallback); + if(remove) + { + mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationPosition); + } + accessibilityNotificationPosition.Reset(); accessibilityNotificationPosition = {}; + + accessibilityNotificationSize.NotifySignal().Disconnect(&Control::Impl::PositionOrSizeChangedCallback); + if(remove) + { + mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationSize); + } + accessibilityNotificationSize.Reset(); accessibilityNotificationSize = {}; + + accessibilityNotificationCulled.NotifySignal().Disconnect(&Control::Impl::CulledChangedCallback); + if(remove) + { + mControlImpl.Self().RemovePropertyNotification(accessibilityNotificationCulled); + } + accessibilityNotificationCulled.Reset(); accessibilityNotificationCulled = {}; accessibilityNotificationSet = false; } diff --git a/dali-toolkit/internal/controls/control/control-data-impl.h b/dali-toolkit/internal/controls/control/control-data-impl.h index 492461e..a3ab6c0 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.h +++ b/dali-toolkit/internal/controls/control/control-data-impl.h @@ -544,7 +544,7 @@ public: Dali::Accessibility::Accessible* GetAccessibilityObject(); void AccessibilityRegister(); - void AccessibilityDeregister(); + void AccessibilityDeregister(bool remove); std::function(Actor)> accessibilityConstructor; std::unique_ptr accessibilityObject; diff --git a/dali-toolkit/internal/controls/video-view/video-view-impl.cpp b/dali-toolkit/internal/controls/video-view/video-view-impl.cpp index 85b219e..509426e 100644 --- a/dali-toolkit/internal/controls/video-view/video-view-impl.cpp +++ b/dali-toolkit/internal/controls/video-view/video-view-impl.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include // INTERNAL INCLUDES @@ -869,7 +870,7 @@ void VideoView::PlayAnimation(Dali::Animation animation) Dali::Shader VideoView::CreateShader() { - std::string fragmentShader = "#extension GL_OES_EGL_image_external:require\n"; + std::string fragmentShader; std::string vertexShader; std::string customFragmentShader; bool checkShader = false; @@ -900,13 +901,15 @@ Dali::Shader VideoView::CreateShader() if(!fragmentShaderValue || !checkShader) { - fragmentShader += SHADER_VIDEO_VIEW_TEXTURE_FRAG.data(); + fragmentShader = SHADER_VIDEO_VIEW_TEXTURE_FRAG.data(); + DevelTexture::ApplyNativeFragmentShader(mNativeTexture, fragmentShader); } } else { - vertexShader = SHADER_VIDEO_VIEW_TEXTURE_VERT.data(); - fragmentShader += SHADER_VIDEO_VIEW_TEXTURE_FRAG.data(); + vertexShader = SHADER_VIDEO_VIEW_TEXTURE_VERT.data(); + fragmentShader = SHADER_VIDEO_VIEW_TEXTURE_FRAG.data(); + DevelTexture::ApplyNativeFragmentShader(mNativeTexture, fragmentShader); } return Dali::Shader::New(vertexShader, fragmentShader); diff --git a/dali-toolkit/internal/controls/web-view/web-view-impl.cpp b/dali-toolkit/internal/controls/web-view/web-view-impl.cpp old mode 100644 new mode 100755 index 6a3af8d..3342374 --- a/dali-toolkit/internal/controls/web-view/web-view-impl.cpp +++ b/dali-toolkit/internal/controls/web-view/web-view-impl.cpp @@ -97,7 +97,7 @@ DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "formRepostDecision", FORM_REPOS DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "frameRendered", FRAME_RENDERED_SIGNAL ) DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "requestInterceptor", REQUEST_INTERCEPTOR_SIGNAL ) DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "consoleMessage", CONSOLE_MESSAGE_SIGNAL ) -DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "policyDecision", POLICY_DECISION ) +DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "responsePolicyDecided", POLICY_DECISION ) DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "certificateConfirm", CERTIFICATE_CONFIRM_SIGNAL ) DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "sslCertificateChanged", SSL_CERTIFICATE_CHANGED_SIGNAL ) DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "httpAuthRequest", HTTP_AUTH_REQUEST_SIGNAL ) @@ -234,7 +234,7 @@ void WebView::OnInitialize() mWebEngine.FrameRenderedSignal().Connect(this, &WebView::OnFrameRendered); mWebEngine.RequestInterceptorSignal().Connect(this, &WebView::OnInterceptRequest); mWebEngine.ConsoleMessageSignal().Connect(this, &WebView::OnConsoleMessage); - mWebEngine.PolicyDecisionSignal().Connect(this, &WebView::OnPolicyDecisionRequest); + mWebEngine.ResponsePolicyDecisionSignal().Connect(this, &WebView::OnResponsePolicyDecided); mWebEngine.CertificateConfirmSignal().Connect(this, &WebView::OnCertificateConfirm); mWebEngine.SslCertificateChangedSignal().Connect(this, &WebView::OnSslCertificateChanged); mWebEngine.HttpAuthHandlerSignal().Connect(this, &WebView::OnHttpAuthenticationRequest); @@ -268,14 +268,15 @@ Dali::Toolkit::WebBackForwardList* WebView::GetBackForwardList() const return mWebBackForwardList.get(); } -Dali::Toolkit::ImageView& WebView::GetFavicon() +Dali::Toolkit::ImageView WebView::GetFavicon() const { + Dali::Toolkit::ImageView faviconView; if(mWebEngine) { Dali::PixelData pixelData = mWebEngine.GetFavicon(); - mFaviconView = CreateImageView(pixelData); + faviconView = CreateImageView(pixelData); } - return mFaviconView; + return faviconView; } void WebView::LoadUrl(const std::string& url) @@ -706,8 +707,13 @@ void WebView::EnableBlendMode(bool blendEnabled) } } -Dali::Toolkit::ImageView WebView::CreateImageView(Dali::PixelData pixel) +Dali::Toolkit::ImageView WebView::CreateImageView(Dali::PixelData pixel) const { + if(!pixel) + { + return Dali::Toolkit::ImageView(); + } + std::string url = Dali::Toolkit::Image::GenerateUrl(pixel); Dali::Toolkit::ImageView imageView = Dali::Toolkit::ImageView::New(url); imageView.SetProperty(Dali::Actor::Property::SIZE, Vector2(pixel.GetWidth(), pixel.GetHeight())); @@ -764,9 +770,9 @@ Dali::Toolkit::WebView::WebViewConsoleMessageSignalType& WebView::ConsoleMessage return mConsoleMessageSignal; } -Dali::Toolkit::WebView::WebViewPolicyDecisionSignalType& WebView::PolicyDecisionSignal() +Dali::Toolkit::WebView::WebViewResponsePolicyDecisionSignalType& WebView::ResponsePolicyDecisionSignal() { - return mPolicyDecisionSignal; + return mResponsePolicyDecisionSignal; } Dali::Toolkit::WebView::WebViewCertificateSignalType& WebView::CertificateConfirmSignal() @@ -901,12 +907,12 @@ void WebView::OnConsoleMessage(std::shared_ptr me } } -void WebView::OnPolicyDecisionRequest(std::shared_ptr decision) +void WebView::OnResponsePolicyDecided(std::shared_ptr decision) { - if(!mPolicyDecisionSignal.Empty()) + if(!mResponsePolicyDecisionSignal.Empty()) { Dali::Toolkit::WebView handle(GetOwner()); - mPolicyDecisionSignal.Emit(handle, std::move(decision)); + mResponsePolicyDecisionSignal.Emit(handle, std::move(decision)); } } @@ -1014,7 +1020,7 @@ bool WebView::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tr } else if(0 == strcmp(signalName.c_str(), POLICY_DECISION)) { - webView.PolicyDecisionSignal().Connect(tracker, functor); + webView.ResponsePolicyDecisionSignal().Connect(tracker, functor); connected = true; } else if(0 == strcmp(signalName.c_str(), CERTIFICATE_CONFIRM_SIGNAL)) diff --git a/dali-toolkit/internal/controls/web-view/web-view-impl.h b/dali-toolkit/internal/controls/web-view/web-view-impl.h index 4031ee6..a5cefa4 100755 --- a/dali-toolkit/internal/controls/web-view/web-view-impl.h +++ b/dali-toolkit/internal/controls/web-view/web-view-impl.h @@ -95,7 +95,7 @@ public: /** * @copydoc Dali::Toolkit::WebView::GetFavicon() */ - Dali::Toolkit::ImageView& GetFavicon(); + Dali::Toolkit::ImageView GetFavicon() const; /** * @copydoc Dali::Toolkit::WebView::LoadUrl() @@ -358,9 +358,9 @@ public: Dali::Toolkit::WebView::WebViewConsoleMessageSignalType& ConsoleMessageSignal(); /** - * @copydoc Dali::Toolkit::WebView::PolicyDecisionSignal() + * @copydoc Dali::Toolkit::WebView::ResponsePolicyDecisionSignal() */ - Dali::Toolkit::WebView::WebViewPolicyDecisionSignalType& PolicyDecisionSignal(); + Dali::Toolkit::WebView::WebViewResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal(); /** * @copydoc Dali::Toolkit::WebView::CertificateConfirmSignal() @@ -608,7 +608,7 @@ private: * @param[in] pixel Pixel data * @return The new image view */ - Dali::Toolkit::ImageView CreateImageView(Dali::PixelData pixel); + Dali::Toolkit::ImageView CreateImageView(Dali::PixelData pixel) const; /** * @brief Callback function to be called when page load started. @@ -709,10 +709,10 @@ private: void OnConsoleMessage(std::shared_ptr message); /** - * @brief Callback function to be called when policy need be decided. + * @brief Callback function to be called when response policy need be decided. * @param[in] decision The policy decided. */ - void OnPolicyDecisionRequest(std::shared_ptr decision); + void OnResponsePolicyDecided(std::shared_ptr decision); /** * @brief Callback function to be called when certificate need be confirmed. @@ -760,7 +760,7 @@ private: Dali::Toolkit::WebView::WebViewFrameRenderedSignalType mFrameRenderedSignal; Dali::Toolkit::WebView::WebViewRequestInterceptorSignalType mRequestInterceptorSignal; Dali::Toolkit::WebView::WebViewConsoleMessageSignalType mConsoleMessageSignal; - Dali::Toolkit::WebView::WebViewPolicyDecisionSignalType mPolicyDecisionSignal; + Dali::Toolkit::WebView::WebViewResponsePolicyDecisionSignalType mResponsePolicyDecisionSignal; Dali::Toolkit::WebView::WebViewCertificateSignalType mCertificateConfirmSignal; Dali::Toolkit::WebView::WebViewCertificateSignalType mSslCertificateChangedSignal; Dali::Toolkit::WebView::WebViewHttpAuthHandlerSignalType mHttpAuthHandlerSignal; @@ -772,8 +772,6 @@ private: std::unique_ptr mWebSettings; std::unique_ptr mWebBackForwardList; - Dali::Toolkit::ImageView mFaviconView; - Dali::PropertyNotification mPositionUpdateNotification; Dali::PropertyNotification mSizeUpdateNotification; Dali::PropertyNotification mScaleUpdateNotification; diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index ede26c1..395dfc8 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -142,6 +142,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/property-string-parser.cpp ${toolkit_src_dir}/text/segmentation.cpp ${toolkit_src_dir}/text/shaper.cpp + ${toolkit_src_dir}/text/hyphenator.cpp ${toolkit_src_dir}/text/text-enumerations-impl.cpp ${toolkit_src_dir}/text/text-controller.cpp ${toolkit_src_dir}/text/text-controller-event-handler.cpp @@ -182,7 +183,6 @@ SET( toolkit_src_files ${toolkit_src_dir}/transition-effects/cube-transition-wave-effect-impl.cpp ${toolkit_src_dir}/text/xhtml-entities.cpp ${toolkit_src_dir}/drag-drop-detector/drag-and-drop-detector-impl.cpp - ${toolkit_src_dir}/graphics/generated/builtin-shader-gen.cpp ) SET( SOURCES ${SOURCES} diff --git a/dali-toolkit/internal/graphics/shaders/glyphy-common-glsl-shader.def b/dali-toolkit/internal/graphics/shaders/glyphy-common-glsl-shader.def new file mode 100644 index 0000000..f044a16 --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/glyphy-common-glsl-shader.def @@ -0,0 +1,211 @@ +/* + * Copyright 2012 Google, Inc. All Rights Reserved. + * + * 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. + * + * Google Author(s): Behdad Esfahbod, Maysum Panju + */ + + +#ifndef GLYPHY_INFINITY +#define GLYPHY_INFINITY 1e9 +#endif +#ifndef GLYPHY_EPSILON +#define GLYPHY_EPSILON 1e-5 +#endif + +#ifndef GLYPHY_RGBA +#ifdef GLYPHY_BGRA +#define GLYPHY_RGBA(v) glyphy_bgra (v) +#else +#define GLYPHY_RGBA(v) glyphy_rgba (v) +#endif +#endif + +vec4 glyphy_rgba (const vec4 v) +{ + return v.rgba; +} + +vec4 glyphy_bgra (const vec4 v) +{ + return v.bgra; +} + +struct glyphy_arc_t +{ + vec2 p0; + vec2 p1; + float d; +}; + +struct glyphy_arc_endpoint_t +{ + /* Second arc endpoint */ + vec2 p; + /* Infinity if this endpoint does not form an arc with the previous + * endpoint. Ie. a \"move_to\". Test with glyphy_isinf(). + * Arc depth otherwise. */ + float d; +}; + +struct glyphy_arc_list_t +{ + /* Number of endpoints in the list. + * Will be zero if we're far away inside or outside, in which case side is set. + * Will be -1 if this arc-list encodes a single line, in which case line_* are set. */ + int num_endpoints; + + /* If num_endpoints is zero, this specifies whether we are inside (-1) + * or outside (+1). Otherwise we're unsure (0). */ + int side; + /* Offset to the arc-endpoints from the beginning of the glyph blob */ + int offset; + + /* A single line is all we care about. It's right here. */ + float line_angle; + float line_distance; /* From nominal glyph center */ +}; + +bool glyphy_isinf (const float v) +{ + return abs (v) >= GLYPHY_INFINITY * .5; +} + +bool glyphy_iszero (const float v) +{ + return abs (v) <= GLYPHY_EPSILON * 2.; +} + +vec2 glyphy_ortho (const vec2 v) +{ + return vec2 (-v.y, v.x); +} + +int glyphy_float_to_byte (const float v) +{ + return int (v * (256. - GLYPHY_EPSILON)); +} + +ivec4 glyphy_vec4_to_bytes (const vec4 v) +{ + return ivec4 (v * (256. - GLYPHY_EPSILON)); +} + +ivec2 glyphy_float_to_two_nimbles (const float v) +{ + int f = glyphy_float_to_byte (v); + return ivec2 (f / 16, int(mod (float(f), 16.))); +} + +/* returns tan (2 * atan (d)) */ +float glyphy_tan2atan (const float d) +{ + return 2. * d / (1. - d * d); +} + +glyphy_arc_endpoint_t glyphy_arc_endpoint_decode(const vec4 v, const ivec2 nominal_size) +{ + vec2 p = (vec2 (glyphy_float_to_two_nimbles (v.a)) + v.gb) / 16.; + float d = v.r; + if (d == 0.) + d = GLYPHY_INFINITY; + else +#define GLYPHY_MAX_D .5 + d = float(glyphy_float_to_byte (d) - 128) * GLYPHY_MAX_D / 127.; +#undef GLYPHY_MAX_D + return glyphy_arc_endpoint_t (p * vec2(nominal_size), d); +} + +vec2 glyphy_arc_center (const glyphy_arc_t a) +{ + return mix (a.p0, a.p1, .5) + + glyphy_ortho (a.p1 - a.p0) / (2. * glyphy_tan2atan (a.d)); +} + +bool glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p) +{ + float d2 = glyphy_tan2atan (a.d); + return dot (p - a.p0, (a.p1 - a.p0) * mat2(1, d2, -d2, 1)) >= 0. && + dot (p - a.p1, (a.p1 - a.p0) * mat2(1, -d2, d2, 1)) <= 0.; +} + +float glyphy_arc_wedge_signed_dist_shallow (const glyphy_arc_t a, const vec2 p) +{ + vec2 v = normalize (a.p1 - a.p0); + float line_d = dot (p - a.p0, glyphy_ortho (v)); + if (a.d == 0.) + return line_d; + + float d0 = dot ((p - a.p0), v); + if (d0 < 0.) + return sign (line_d) * distance (p, a.p0); + float d1 = dot ((a.p1 - p), v); + if (d1 < 0.) + return sign (line_d) * distance (p, a.p1); + float r = 2. * a.d * (d0 * d1) / (d0 + d1); + if (r * line_d > 0.) + return sign (line_d) * min (abs (line_d + r), min (distance (p, a.p0), distance (p, a.p1))); + return line_d + r; +} + +float glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p) +{ + if (abs (a.d) <= .03) + return glyphy_arc_wedge_signed_dist_shallow (a, p); + vec2 c = glyphy_arc_center (a); + return sign (a.d) * (distance (a.p0, c) - distance (p, c)); +} + +float glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p) +{ + /* Note: this doesn't handle points inside the wedge. */ + vec2 m = mix (a.p0, a.p1, .5); + float d2 = glyphy_tan2atan (a.d); + if (dot (p - m, a.p1 - m) < 0.) + return dot (p - a.p0, normalize ((a.p1 - a.p0) * mat2(+d2, -1, +1, +d2))); + else + return dot (p - a.p1, normalize ((a.p1 - a.p0) * mat2(-d2, -1, +1, -d2))); +} + +int glyphy_arc_list_offset (const vec2 p, const ivec2 nominal_size) +{ + ivec2 cell = ivec2 (clamp (floor (p), vec2 (0.,0.), vec2(nominal_size - 1))); + return cell.y * nominal_size.x + cell.x; +} + +glyphy_arc_list_t glyphy_arc_list_decode (const vec4 v, const ivec2 nominal_size) +{ + glyphy_arc_list_t l; + ivec4 iv = glyphy_vec4_to_bytes (v); + l.side = 0; /* unsure */ + if (iv.r == 0) + { /* arc-list encoded */ + l.offset = (iv.g * 256) + iv.b; + l.num_endpoints = iv.a; + if (l.num_endpoints == 255) + { + l.num_endpoints = 0; + l.side = -1; + } + else if (l.num_endpoints == 0) + l.side = +1; + } + else + { /* single line encoded */ + l.num_endpoints = -1; + l.line_distance = ( float(iv.r)/32. + 0.01*float(iv.g)/82.0 - 6.) * max (float (nominal_size.x), float (nominal_size.y)); + l.line_angle = ( -float(iv.b)/40.74 - float( iv.a )*0.0001 )-3.142; + } + return l; +} diff --git a/dali-toolkit/internal/graphics/shaders/glyphy-sdf-glsl-shader.def b/dali-toolkit/internal/graphics/shaders/glyphy-sdf-glsl-shader.def new file mode 100644 index 0000000..2b5accd --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/glyphy-sdf-glsl-shader.def @@ -0,0 +1,160 @@ +/* + * Copyright 2012 Google, Inc. All Rights Reserved. + * + * 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. + * + * Google Author(s): Behdad Esfahbod, Maysum Panju + */ + +#ifndef GLYPHY_TEXTURE1D_FUNC +#define GLYPHY_TEXTURE1D_FUNC glyphy_texture1D_func +#endif +#ifndef GLYPHY_TEXTURE1D_EXTRA_DECLS +#define GLYPHY_TEXTURE1D_EXTRA_DECLS +#endif +#ifndef GLYPHY_TEXTURE1D_EXTRA_ARGS +#define GLYPHY_TEXTURE1D_EXTRA_ARGS +#endif + +#ifndef GLYPHY_SDF_TEXTURE1D_FUNC +#define GLYPHY_SDF_TEXTURE1D_FUNC GLYPHY_TEXTURE1D_FUNC +#endif +#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS +#define GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS GLYPHY_TEXTURE1D_EXTRA_DECLS +#endif +#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS +#define GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS GLYPHY_TEXTURE1D_EXTRA_ARGS +#endif +#ifndef GLYPHY_SDF_TEXTURE1D +#define GLYPHY_SDF_TEXTURE1D(offset) GLYPHY_RGBA(GLYPHY_SDF_TEXTURE1D_FUNC (offset GLYPHY_TEXTURE1D_EXTRA_ARGS)) +#endif + +#ifndef GLYPHY_MAX_NUM_ENDPOINTS +#define GLYPHY_MAX_NUM_ENDPOINTS 32 +#endif + +glyphy_arc_list_t glyphy_arc_list (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) +{ + int cell_offset = glyphy_arc_list_offset (p, nominal_size); + vec4 arc_list_data = GLYPHY_SDF_TEXTURE1D (cell_offset); + return glyphy_arc_list_decode (arc_list_data, nominal_size); +} + +float glyphy_sdf (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) +{ + glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + + /* Short-circuits */ + if (arc_list.num_endpoints == 0) + { + /* far-away cell */ + return GLYPHY_INFINITY * float(arc_list.side); + } + if (arc_list.num_endpoints == -1) + { + /* single-line */ + float angle = arc_list.line_angle; + vec2 n = vec2 (cos (angle), sin (angle)); + return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance; + } + + float side = float(arc_list.side); + float min_dist = GLYPHY_INFINITY; + glyphy_arc_t closest_arc; + + glyphy_arc_endpoint_t endpoint_prev, endpoint; + endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size); + for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) + { + if (i >= arc_list.num_endpoints) + { + break; + } + endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size); + glyphy_arc_t a = glyphy_arc_t (endpoint_prev.p, endpoint.p, endpoint.d); + endpoint_prev = endpoint; + if (glyphy_isinf (a.d)) continue; + + if (glyphy_arc_wedge_contains (a, p)) + { + float sdist = glyphy_arc_wedge_signed_dist (a, p); + float udist = abs (sdist) * (1. - GLYPHY_EPSILON); + if (udist <= min_dist) + { + min_dist = udist; + side = sign (sdist); + } + } + else + { + float udist = min (distance (p, a.p0), distance (p, a.p1)); + if (udist < min_dist) + { + min_dist = udist; + side = 0.; /* unsure */ + closest_arc = a; + } + else if (side == 0. && udist == min_dist) + { + /* If this new distance is the same as the current minimum, + * compare extended distances. Take the sign from the arc + * with larger extended distance. */ + float old_ext_dist = glyphy_arc_extended_dist (closest_arc, p); + float new_ext_dist = glyphy_arc_extended_dist (a, p); + + float ext_dist = abs (new_ext_dist) <= abs (old_ext_dist) ? + old_ext_dist : new_ext_dist; + +#ifdef GLYPHY_SDF_PSEUDO_DISTANCE + /* For emboldening and stuff: */ + min_dist = abs (ext_dist); +#endif + side = sign (ext_dist); + } + } + } + + if (side == 0.) + { + // Technically speaking this should not happen, but it does. So try to fix it. + float ext_dist = glyphy_arc_extended_dist (closest_arc, p); + side = sign (ext_dist); + } + + return min_dist * side; +} + +float glyphy_point_dist (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) +{ + glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + + float side = float(arc_list.side); + float min_dist = GLYPHY_INFINITY; + + if (arc_list.num_endpoints == 0) + return min_dist; + + glyphy_arc_endpoint_t endpoint; + for (int i = 0; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) + { + if (i >= arc_list.num_endpoints) + { + break; + } + endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size); + if (glyphy_isinf (endpoint.d)) continue; + min_dist = min (min_dist, distance (p, endpoint.p)); + } + + return min_dist; +} diff --git a/dali-toolkit/internal/graphics/shaders/glyphy-shader-extention-prefix.def b/dali-toolkit/internal/graphics/shaders/glyphy-shader-extention-prefix.def new file mode 100644 index 0000000..3f7237d --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/glyphy-shader-extention-prefix.def @@ -0,0 +1,3 @@ +#extension GL_OES_standard_derivatives : enable +precision highp float; +precision highp int; diff --git a/dali-toolkit/internal/graphics/shaders/glyphy-shader-fragment-prefix.frag b/dali-toolkit/internal/graphics/shaders/glyphy-shader-fragment-prefix.frag new file mode 100644 index 0000000..4cb1423 --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/glyphy-shader-fragment-prefix.frag @@ -0,0 +1,34 @@ +struct Material +{ + mediump float mOpacity; + mediump float mShininess; + lowp vec4 mAmbient; + lowp vec4 mDiffuse; + lowp vec4 mSpecular; + lowp vec4 mEmissive; +}; + +uniform sampler2D sTexture; +uniform sampler2D sOpacityTexture; +uniform sampler2D sNormalMapTexture; +uniform sampler2D sEffect; +varying mediump vec2 vTexCoord; +uniform Material uMaterial; +uniform lowp vec4 uColor; +varying highp vec4 vVertex; +varying highp vec3 vNormal; +varying mediump vec4 vColor; +uniform vec4 u_atlas_info; + +#define GLYPHY_TEXTURE1D_EXTRA_DECLS , sampler2D _tex, ivec4 _atlas_info, ivec2 _atlas_pos +#define GLYPHY_TEXTURE1D_EXTRA_ARGS , _tex, _atlas_info, _atlas_pos +#define GLYPHY_DEMO_EXTRA_ARGS , sTexture, uu_atlas_info, gi.atlas_pos + +vec4 glyphy_texture1D_func (int offset GLYPHY_TEXTURE1D_EXTRA_DECLS) +{ + ivec2 item_geom = _atlas_info.zw; + vec2 pos = (vec2 (_atlas_pos.xy * item_geom + + ivec2 (mod (float (offset), float (item_geom.x)), offset / item_geom.x)) + + + vec2 (.5, .5)) / vec2(_atlas_info.xy); + return texture2D (_tex, pos); +} diff --git a/dali-toolkit/internal/graphics/shaders/glyphy-shader-main.frag b/dali-toolkit/internal/graphics/shaders/glyphy-shader-main.frag new file mode 100644 index 0000000..4fc43da --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/glyphy-shader-main.frag @@ -0,0 +1,66 @@ +uniform float u_contrast; +uniform float u_gamma_adjust; +uniform float u_outline_thickness; +uniform float u_outline; +uniform float u_boldness; + +varying vec4 v_glyph; + +#define SQRT2_2 0.70711 /* 1 / sqrt(2.) */ +#define SQRT2 1.41421 + +struct glyph_info_t +{ + ivec2 nominal_size; + ivec2 atlas_pos; +}; + +glyph_info_t glyph_info_decode (vec4 v) +{ + glyph_info_t gi; + gi.nominal_size = (ivec2 (mod (v.zw, 256.)) + 2) / 4; + gi.atlas_pos = ivec2 (v_glyph.zw) / 256; + return gi; +} + + +float antialias (float d) +{ + return smoothstep (-.75, +.75, d); +} + +vec4 source_over (const vec4 src, const vec4 dst) +{ + // http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators_srcover + float alpha = src.a + (dst.a * (1. - src.a)); + return vec4 (((src.rgb * src.a) + (dst.rgb * dst.a * (1. - src.a))) / alpha, alpha); +} + +void main() +{ + vec2 p = v_glyph.xy; + glyph_info_t gi = glyph_info_decode (v_glyph); + + /* isotropic antialiasing */ + vec2 dpdx = dFdx (p); + vec2 dpdy = dFdy (p); + float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_2; + + vec4 color = vec4( vColor.rgb * uColor.rgb, vColor.a * uColor.a ); + + ivec4 uu_atlas_info = ivec4( u_atlas_info ); + float gsdist = glyphy_sdf (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); + float sdist = gsdist / m * u_contrast; + + sdist -= u_boldness * 10.; + if ( glyphy_iszero( u_outline ) ) + sdist = abs (sdist) - u_outline_thickness * .5; + if (sdist > 1.) + discard; + float alpha = antialias (-sdist); + if (u_gamma_adjust != 1.) + alpha = pow (alpha, 1./u_gamma_adjust); + color = vec4 (color.rgb,color.a * alpha); + + gl_FragColor = color; +} diff --git a/dali-toolkit/internal/graphics/shaders/glyphy-shader-main.vert b/dali-toolkit/internal/graphics/shaders/glyphy-shader-main.vert new file mode 100644 index 0000000..9b0f342 --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/glyphy-shader-main.vert @@ -0,0 +1,31 @@ +uniform mediump mat4 uProjection; +uniform mediump mat4 uModelView; +uniform mediump mat4 uMvpMatrix; +uniform bool uTextureMapped; +uniform mediump vec4 uCustomTextureCoords; +attribute highp vec2 aTexCoord; +varying mediump vec2 vTexCoord; +uniform mat3 uModelViewIT; +attribute mediump vec3 aNormal; +varying mediump vec3 vNormal; +attribute mediump vec2 aPosition; +varying mediump vec4 vVertex; +attribute mediump vec4 aColor; +varying mediump vec4 vColor; +varying vec4 v_glyph; + +vec4 glyph_vertex_transcode (vec2 v) +{ + ivec2 g = ivec2 (v); + ivec2 corner = ivec2 (mod (v, 2.)); + g /= 2; + ivec2 nominal_size = ivec2 (mod (vec2(g), 64.)); + return vec4 (corner * nominal_size, g * 4); +} + +void main() +{ + gl_Position = uMvpMatrix * vec4 (aPosition, 0.0, 1.0); + v_glyph = glyph_vertex_transcode (aTexCoord); + vColor = aColor; +} \ No newline at end of file diff --git a/dali-toolkit/internal/text/hyphenator.cpp b/dali-toolkit/internal/text/hyphenator.cpp new file mode 100644 index 0000000..66f99a3 --- /dev/null +++ b/dali-toolkit/internal/text/hyphenator.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +#include // for strcmp + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +const char* UTF8 = "UTF-8"; + +Vector GetWordHyphens(const Character* word, + Length wordSize, + const char* lang) +{ + Vector hyphens; + + if(0u == wordSize || word == nullptr) + { + // Nothing to do if there are no characters. + return hyphens; + } + + TextAbstraction::Hyphenation hyphenation = TextAbstraction::Hyphenation::Get(); + + // first get the needed encoding + std::string text; + if(strcmp(hyphenation.GetDictionaryEncoding(lang), UTF8) == 0) + { + Utf32ToUtf8(word, wordSize, text); + } + else + { + text = std::string((char*)word, (size_t)(wordSize * sizeof(Character))); + } + + return hyphenation.GetWordHyphens(text.c_str(), (int)text.length(), lang); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/hyphenator.h b/dali-toolkit/internal/text/hyphenator.h new file mode 100644 index 0000000..eef2246 --- /dev/null +++ b/dali-toolkit/internal/text/hyphenator.h @@ -0,0 +1,53 @@ +#ifndef DALI_TOOLKIT_TEXT_HYPHENATOR_H +#define DALI_TOOLKIT_TEXT_HYPHENATOR_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * Gets a vector booleans that indicates possible hyphen locations. + * + * @param[in] word the word to get possible hyphens for. + * @param[in] wordSize the word size in bytes. + * @param[in] lang the language for the word + * + * @return vector of boolean, true if possible to hyphenate at this character position. + */ +Vector GetWordHyphens(const Character* word, + Length wordSize, + const char* lang); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_HYPHENATOR_H diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index fcf5f5e..25f83d1 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -44,11 +44,12 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_LAYOUT"); #endif -const float MAX_FLOAT = std::numeric_limits::max(); -const CharacterDirection LTR = false; -const CharacterDirection RTL = !LTR; -const float LINE_SPACING = 0.f; -const float MIN_LINE_SIZE = 0.f; +const float MAX_FLOAT = std::numeric_limits::max(); +const CharacterDirection LTR = false; +const CharacterDirection RTL = !LTR; +const float LINE_SPACING = 0.f; +const float MIN_LINE_SIZE = 0.f; +const Character HYPHEN_UNICODE = 0x002D; inline bool isEmptyLineAtLast(const Vector& lines, const Vector::Iterator& line) { @@ -448,7 +449,11 @@ struct Engine::Impl const Length totalNumberOfGlyphs = parameters.textModel->mVisualModel->mGlyphs.Count(); const bool isMultiline = mLayout == MULTI_LINE_BOX; - const bool isWordLaidOut = parameters.textModel->mLineWrapMode == Text::LineWrap::WORD; + const bool isWordLaidOut = parameters.textModel->mLineWrapMode == Text::LineWrap::WORD || + (parameters.textModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || + (parameters.textModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED); + const bool isHyphenMode = parameters.textModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION; + const bool isMixedMode = parameters.textModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED; // The last glyph to be laid-out. const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs; @@ -486,7 +491,10 @@ struct Engine::Impl FontId lastFontId = glyphMetrics.fontId; UpdateLineHeight(glyphMetrics, tmpLineLayout); - bool oneWordLaidOut = false; + bool oneWordLaidOut = false; + bool oneHyphenLaidOut = false; + GlyphIndex hyphenIndex = 0; + GlyphInfo hyphenGlyph; for(GlyphIndex glyphIndex = lineLayout.glyphIndex; glyphIndex < lastGlyphOfParagraphPlusOne;) @@ -565,7 +573,15 @@ struct Engine::Impl (tmpLineLayout.length > parameters.boundingBox.width)) { // Current word does not fit in the box's width. - if(!oneWordLaidOut || completelyFill) + if(((oneHyphenLaidOut && isHyphenMode) || + (!oneWordLaidOut && isMixedMode && oneHyphenLaidOut)) && + !completelyFill) + { + parameters.textModel->mVisualModel->mHyphen.glyph.PushBack(hyphenGlyph); + parameters.textModel->mVisualModel->mHyphen.index.PushBack(hyphenIndex + 1); + } + + if((!oneWordLaidOut && !oneHyphenLaidOut) || completelyFill) { DALI_LOG_INFO(gLogFilter, Debug::Verbose, " Break the word by character\n"); @@ -608,7 +624,7 @@ struct Engine::Impl (TextAbstraction::LINE_MUST_BREAK == lineBreakInfo)) { LineLayout currentLineLayout = lineLayout; - + oneHyphenLaidOut = false; // Must break the line. Update the line layout and return. MergeLineLayout(lineLayout, tmpLineLayout); @@ -631,7 +647,8 @@ struct Engine::Impl if(isMultiline && (TextAbstraction::LINE_ALLOW_BREAK == lineBreakInfo)) { - oneWordLaidOut = isWordLaidOut; + oneHyphenLaidOut = false; + oneWordLaidOut = isWordLaidOut; DALI_LOG_INFO(gLogFilter, Debug::Verbose, " One word laid-out\n"); // Current glyph is the last one of the current word. @@ -641,6 +658,33 @@ struct Engine::Impl tmpLineLayout.Clear(); } + if(isMultiline && + ((isHyphenMode || (!oneWordLaidOut && isMixedMode))) && + (TextAbstraction::LINE_HYPHENATION_BREAK == lineBreakInfo)) + { + hyphenGlyph = GlyphInfo(); + hyphenGlyph.fontId = glyphsBuffer[glyphIndex].fontId; + + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + hyphenGlyph.index = fontClient.GetGlyphIndex(hyphenGlyph.fontId, HYPHEN_UNICODE); + + mMetrics->GetGlyphMetrics(&hyphenGlyph, 1); + + if((tmpLineLayout.length + hyphenGlyph.width) <= parameters.boundingBox.width) + { + hyphenIndex = glyphIndex; + oneHyphenLaidOut = true; + + DALI_LOG_INFO(gLogFilter, Debug::Verbose, " One hyphen laid-out\n"); + + // Current glyph is the last one of the current word hyphen. + // Add the temporal layout to the current one. + MergeLineLayout(lineLayout, tmpLineLayout); + + tmpLineLayout.Clear(); + } + } + glyphIndex += numberOfGLyphsInGroup; } @@ -1059,6 +1103,9 @@ struct Engine::Impl DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->LayoutText\n"); DALI_LOG_INFO(gLogFilter, Debug::Verbose, " box size %f, %f\n", layoutParameters.boundingBox.width, layoutParameters.boundingBox.height); + layoutParameters.textModel->mVisualModel->mHyphen.glyph.Clear(); + layoutParameters.textModel->mVisualModel->mHyphen.index.Clear(); + Vector& lines = layoutParameters.textModel->mVisualModel->mLines; if(0u == layoutParameters.numberOfGlyphs) @@ -1271,6 +1318,17 @@ struct Engine::Impl if(ellipsis) { + //clear hyphen from ellipsis line + const Length* hyphenIndices = layoutParameters.textModel->mVisualModel->mHyphen.index.Begin(); + Length hyphensCount = layoutParameters.textModel->mVisualModel->mHyphen.glyph.Size(); + + while(hyphenIndices && hyphensCount > 0 && hyphenIndices[hyphensCount - 1] >= layout.glyphIndex) + { + layoutParameters.textModel->mVisualModel->mHyphen.index.Remove(layoutParameters.textModel->mVisualModel->mHyphen.index.Begin() + hyphensCount - 1); + layoutParameters.textModel->mVisualModel->mHyphen.glyph.Remove(layoutParameters.textModel->mVisualModel->mHyphen.glyph.Begin() + hyphensCount - 1); + hyphensCount--; + } + // No more lines to layout. break; } diff --git a/dali-toolkit/internal/text/logical-model-impl.cpp b/dali-toolkit/internal/text/logical-model-impl.cpp index 12929fc..0de63d5 100644 --- a/dali-toolkit/internal/text/logical-model-impl.cpp +++ b/dali-toolkit/internal/text/logical-model-impl.cpp @@ -296,6 +296,15 @@ void LogicalModel::UpdateTextStyleRuns(CharacterIndex index, int numberOfCharact mColorRuns, removedColorRuns); + // This is needed until now for underline tag in mark-up processor + // Process the underlined runs. + Vector removedUnderlinedCharacterRuns; + UpdateCharacterRuns(index, + numberOfCharacters, + totalNumberOfCharacters, + mUnderlinedCharacterRuns, + removedUnderlinedCharacterRuns); + // Process the background color runs. Vector removedBackgroundColorRuns; UpdateCharacterRuns(index, diff --git a/dali-toolkit/internal/text/logical-model-impl.h b/dali-toolkit/internal/text/logical-model-impl.h index 921d911..80a1285 100644 --- a/dali-toolkit/internal/text/logical-model-impl.h +++ b/dali-toolkit/internal/text/logical-model-impl.h @@ -33,6 +33,7 @@ #include #include #include +#include namespace Dali { @@ -219,6 +220,7 @@ public: Vector mBidirectionalLineInfo; Vector mEmbeddedItems; Vector mAnchors; + Vector mUnderlinedCharacterRuns; ///< The underlined character run from markup-processor BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info. }; diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp index a8a6ecc..ea7f869 100644 --- a/dali-toolkit/internal/text/markup-processor.cpp +++ b/dali-toolkit/internal/text/markup-processor.cpp @@ -156,6 +156,17 @@ void Initialize(ColorRun& colorRun) } /** + * @brief Initializes a underlined character run to its defaults. + * + * @param[in,out] underlinedCharacterRun The underelined character run to initialize. + */ +void Initialize(UnderlinedCharacterRun& underlinedCharacterRun) +{ + underlinedCharacterRun.characterRun.characterIndex = 0u; + underlinedCharacterRun.characterRun.numberOfCharacters = 0u; +} + +/** * @brief Splits the tag string into the tag name and its attributes. * * The attributes are stored in a vector in the tag. @@ -498,9 +509,9 @@ bool XHTMLNumericEntityToUtf8(const char* markupText, char* utf8) } /** - * @brief Processes a particular tag for the required run (color-run or font-run). + * @brief Processes a particular tag for the required run (color-run, font-run or underlined-character-run). * - * @tparam RunType Whether ColorRun or FontDescriptionRun + * @tparam RunType Whether ColorRun , FontDescriptionRun or UnderlinedCharacterRun * * @param[in/out] runsContainer The container containing all the runs * @param[in/out] styleStack The style stack @@ -619,11 +630,13 @@ void ProcessAnchorTag( * @param[in/out] markupProcessData The markup process data * @param[in] fontRunIndex The font run index * @param[in] colorRunIndex The color run index + * @param[in] underlinedCharacterRunIndex The underlined character run index */ -void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex) +void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex) { markupProcessData.fontRuns.Resize(fontRunIndex); markupProcessData.colorRuns.Resize(colorRunIndex); + markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex); #ifdef DEBUG_ENABLED for(unsigned int i = 0; i < colorRunIndex; ++i) @@ -740,18 +753,21 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar StyleStack styleStack; // Points the next free position in the vector of runs. - StyleStack::RunIndex colorRunIndex = 0u; - StyleStack::RunIndex fontRunIndex = 0u; + StyleStack::RunIndex colorRunIndex = 0u; + StyleStack::RunIndex fontRunIndex = 0u; + StyleStack::RunIndex underlinedCharacterRunIndex = 0u; // check tag reference int colorTagReference = 0u; int fontTagReference = 0u; int iTagReference = 0u; int bTagReference = 0u; + int uTagReference = 0u; // Give an initial default value to the model's vectors. markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE); markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE); + markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE); // Get the mark-up string buffer. const char* markupStringBuffer = markupString.c_str(); @@ -781,9 +797,9 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar } // else if(TokenComparison(XHTML_U_TAG, tag.buffer, tag.length)) { - // TODO: If !tag.isEndTag, then create a new underline run. - // else Pop the top of the stack and set the number of characters of the run. - } // + ProcessTagForRun( + markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) { }); + } // else if(TokenComparison(XHTML_B_TAG, tag.buffer, tag.length)) { ProcessTagForRun( @@ -836,7 +852,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar } // Resize the model's vectors. - ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex); + ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex); } } // namespace Text diff --git a/dali-toolkit/internal/text/markup-processor.h b/dali-toolkit/internal/text/markup-processor.h index c75ca0c..ec45957 100644 --- a/dali-toolkit/internal/text/markup-processor.h +++ b/dali-toolkit/internal/text/markup-processor.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace Dali { @@ -42,20 +43,23 @@ struct MarkupProcessData MarkupProcessData(Vector& colorRuns, Vector& fontRuns, Vector& items, - Vector& anchors) + Vector& anchors, + Vector& underlinedCharacterRuns) : colorRuns(colorRuns), fontRuns(fontRuns), items(items), anchors(anchors), + underlinedCharacterRuns(underlinedCharacterRuns), markupProcessedText() { } - Vector& colorRuns; ///< The color runs. - Vector& fontRuns; ///< The font description runs. - Vector& items; ///< The embedded items. - Vector& anchors; ///< The anchors. - std::string markupProcessedText; ///< The mark-up string. + Vector& colorRuns; ///< The color runs. + Vector& fontRuns; ///< The font description runs. + Vector& items; ///< The embedded items. + Vector& anchors; ///< The anchors. + Vector& underlinedCharacterRuns; ///< The underlined character runs. + std::string markupProcessedText; ///< The mark-up string. }; /** 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 208460c..1023dc4 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -46,10 +46,6 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT const float ZERO(0.0f); 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 uint32_t MAX_ATLAS_WIDTH = 1024u; -const uint32_t MAX_ATLAS_HEIGHT = 1024u; const uint32_t DOUBLE_PIXEL_PADDING = 4u;//Padding will be added twice to Atlas const uint16_t NO_OUTLINE = 0u; } // namespace @@ -85,7 +81,8 @@ struct AtlasRenderer::Impl mRight(0.0f), mUnderlinePosition(0.0f), mUnderlineThickness(0.0f), - mMeshRecordIndex(0u) + mMeshRecordIndex(0u), + mUnderlineChunkId(0u) { } @@ -95,6 +92,7 @@ struct AtlasRenderer::Impl float mUnderlinePosition; float mUnderlineThickness; uint32_t mMeshRecordIndex; + uint32_t mUnderlineChunkId; }; struct MaxBlockSize @@ -175,6 +173,9 @@ struct AtlasRenderer::Impl void CacheGlyph(const GlyphInfo& glyph, FontId lastFontId, const AtlasGlyphManager::GlyphStyle& style, AtlasManager::AtlasSlot& slot) { + const Size& defaultTextAtlasSize = mFontClient.GetDefaultTextAtlasSize(); //Retrieve default size of text-atlas-block from font-client. + const Size& maximumTextAtlasSize = mFontClient.GetMaximumTextAtlasSize(); //Retrieve maximum size of text-atlas-block from font-client. + const bool glyphNotCached = !mGlyphManager.IsCached(glyph.fontId, glyph.index, style, 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"); @@ -248,15 +249,15 @@ struct AtlasRenderer::Impl // 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. - uint32_t default_width = DEFAULT_ATLAS_WIDTH; - uint32_t default_height = DEFAULT_ATLAS_HEIGHT; + uint32_t default_width = defaultTextAtlasSize.width; + uint32_t default_height = defaultTextAtlasSize.height; while ( (blockSize.mNeededBlockWidth >= (default_width - (DOUBLE_PIXEL_PADDING + 1u)) || blockSize.mNeededBlockHeight >= (default_height - (DOUBLE_PIXEL_PADDING + 1u))) && - (default_width < MAX_ATLAS_WIDTH && - default_height < MAX_ATLAS_HEIGHT)) + (default_width < maximumTextAtlasSize.width && + default_height < maximumTextAtlasSize.height)) { default_width <<= 1u; default_height <<= 1u; @@ -288,7 +289,8 @@ struct AtlasRenderer::Impl float currentUnderlineThickness, std::vector& meshContainer, Vector& newTextCache, - Vector& extents) + Vector& extents, + uint32_t underlineChunkId) { // Generate mesh data for this quad, plugging in our supplied position AtlasManager::Mesh2D newMesh; @@ -324,7 +326,8 @@ struct AtlasRenderer::Impl underlineGlyph, currentUnderlinePosition, currentUnderlineThickness, - slot); + slot, + underlineChunkId); } void CreateActors(const std::vector& meshContainer, @@ -416,16 +419,19 @@ struct AtlasRenderer::Impl Vector extents; 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 Vector4& underlineColor(view.GetUnderlineColor()); - const float underlineHeight = view.GetUnderlineHeight(); - const uint16_t outlineWidth = view.GetOutlineWidth(); - const Vector4& outlineColor(view.GetOutlineColor()); - const bool isOutline = 0u != outlineWidth; + 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 Vector4& underlineColor(view.GetUnderlineColor()); + const float underlineHeight = view.GetUnderlineHeight(); + const uint16_t outlineWidth = view.GetOutlineWidth(); + const Vector4& outlineColor(view.GetOutlineColor()); + const bool isOutline = 0u != outlineWidth; + const GlyphInfo* hyphens = view.GetHyphens(); + const Length* hyphenIndices = view.GetHyphenIndices(); + const Length hyphensCount = view.GetHyphensCount(); const bool useDefaultColor = (NULL == colorsBuffer); @@ -457,12 +463,28 @@ struct AtlasRenderer::Impl const GlyphInfo* const glyphsBuffer = glyphs.Begin(); const Vector2* const positionsBuffer = positions.Begin(); const Vector2 lineOffsetPosition(minLineOffset, 0.f); + uint32_t hyphenIndex = 0; + + //For septated underlined chunks. (this is for Markup case) + uint32_t underlineChunkId = 0u; // give id for each chunk. + bool isPreUnderlined = false; // status of underlined for previous glyph. for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i) { - const GlyphInfo& glyph = *(glyphsBuffer + i); - const bool isGlyphUnderlined = underlineEnabled || IsGlyphUnderlined(i, underlineRuns); - thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || isGlyphUnderlined; + GlyphInfo glyph; + bool addHyphen = ((hyphenIndex < hyphensCount) && hyphenIndices && (i == hyphenIndices[hyphenIndex])); + if(addHyphen && hyphens) + { + glyph = hyphens[hyphenIndex]; + i--; + } + else + { + glyph = *(glyphsBuffer + i); + } + + const bool isGlyphUnderlined = underlineEnabled || IsGlyphUnderlined(i, underlineRuns); + thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || isGlyphUnderlined; // No operation for white space if(glyph.width && glyph.height) @@ -504,6 +526,7 @@ struct AtlasRenderer::Impl } lastUnderlinedFontId = glyph.fontId; + } // underline AtlasGlyphManager::GlyphStyle style; @@ -521,8 +544,16 @@ struct AtlasRenderer::Impl } // Move the origin (0,0) of the mesh to the center of the actor - const Vector2& temp = *(positionsBuffer + i); - const Vector2 position = Vector2(roundf(temp.x), temp.y) - halfTextSize - lineOffsetPosition; // roundf() avoids pixel alignment issues. + Vector2 position = *(positionsBuffer + i); + + if(addHyphen) + { + GlyphInfo tempInfo = *(glyphsBuffer + i); + position.x = position.x + tempInfo.advance - tempInfo.xBearing + glyph.xBearing; + position.y += tempInfo.yBearing - glyph.yBearing; + } + + position = Vector2(roundf(position.x), position.y) - halfTextSize - lineOffsetPosition; // roundf() avoids pixel alignment issues. if(0u != slot.mImageId) // invalid slot id, glyph has failed to be added to atlas { @@ -548,7 +579,8 @@ struct AtlasRenderer::Impl currentUnderlineThickness, meshContainer, newTextCache, - extents); + extents, + underlineChunkId); lastFontId = glyph.fontId; // Prevents searching for existing blocksizes when string of the same fontId. } @@ -565,8 +597,24 @@ struct AtlasRenderer::Impl currentUnderlineThickness, meshContainerOutline, newTextCache, - extents); + extents, + 0u); } + + + //The new underlined chunk. Add new id if they are not consecutive indices (this is for Markup case) + // Examples: "Hello World Hello World", "World Hello World", " World Hello World" + if( isPreUnderlined && (isPreUnderlined != isGlyphUnderlined)) + { + underlineChunkId++; + } + //Keep status of underlined for previous glyph to check consecutive indices + isPreUnderlined = isGlyphUnderlined; + } + + if(addHyphen) + { + hyphenIndex++; } } // glyphs @@ -717,7 +765,8 @@ struct AtlasRenderer::Impl bool underlineGlyph, float underlinePosition, float underlineThickness, - AtlasManager::AtlasSlot& slot) + AtlasManager::AtlasSlot& slot, + uint32_t underlineChunkId) { if(slot.mImageId) { @@ -745,7 +794,8 @@ struct AtlasRenderer::Impl right, baseLine, underlinePosition, - underlineThickness); + underlineThickness, + underlineChunkId); } return; @@ -768,7 +818,8 @@ struct AtlasRenderer::Impl right, baseLine, underlinePosition, - underlineThickness); + underlineThickness, + underlineChunkId); } } } @@ -780,7 +831,8 @@ struct AtlasRenderer::Impl float right, float baseLine, float underlinePosition, - float underlineThickness) + float underlineThickness, + uint32_t underlineChunkId) { bool foundExtent = false; for(Vector::Iterator eIt = extents.Begin(), @@ -788,7 +840,7 @@ struct AtlasRenderer::Impl eIt != eEndIt; ++eIt) { - if(Equals(baseLine, eIt->mBaseLine)) + if(Equals(baseLine, eIt->mBaseLine) && underlineChunkId == eIt->mUnderlineChunkId) { foundExtent = true; if(left < eIt->mLeft) @@ -819,6 +871,7 @@ struct AtlasRenderer::Impl extent.mUnderlinePosition = underlinePosition; extent.mUnderlineThickness = underlineThickness; extent.mMeshRecordIndex = index; + extent.mUnderlineChunkId = underlineChunkId; extents.PushBack(extent); } } diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index abf7325..83d67d5 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -595,6 +595,10 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect // Combine the two buffers imageBuffer = CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight); } + + // Markup-Processor + + imageBuffer = ApplyMarkupProcessorOnPixelBuffer(imageBuffer, bufferWidth, bufferHeight, ignoreHorizontalAlignment, pixelFormat, penX, penY); } // Create the final PixelData for the combined image buffer @@ -613,6 +617,9 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, const Vector2* const positionBuffer = mModel->GetLayout(); const Vector4* const colorsBuffer = mModel->GetColors(); const ColorIndex* const colorIndexBuffer = mModel->GetColorIndices(); + const GlyphInfo* hyphens = mModel->GetHyphens(); + const Length* hyphenIndices = mModel->GetHyphenIndices(); + const Length hyphensCount = mModel->GetHyphensCount(); // Whether to use the default color. const bool useDefaultColor = (NULL == colorsBuffer); @@ -638,7 +645,8 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, } // Get a handle of the font client. Used to retrieve the bitmaps of the glyphs. - TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + Length hyphenIndex = 0; // Traverses the lines of the text. for(LineIndex lineIndex = 0u; lineIndex < modelNumberOfLines; ++lineIndex) @@ -703,6 +711,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, float lineExtentLeft = bufferWidth; float lineExtentRight = 0.0f; float baseline = 0.0f; + bool addHyphen = false; // Traverses the glyphs of the line. const GlyphIndex endGlyphIndex = std::min(numberOfGlyphs, line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs); @@ -715,7 +724,17 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, } // Retrieve the glyph's info. - const GlyphInfo* const glyphInfo = glyphsBuffer + glyphIndex; + const GlyphInfo* glyphInfo; + + if(addHyphen && hyphens) + { + glyphInfo = hyphens + hyphenIndex; + hyphenIndex++; + } + else + { + glyphInfo = glyphsBuffer + glyphIndex; + } if((glyphInfo->width < Math::MACHINE_EPSILON_1000) || (glyphInfo->height < Math::MACHINE_EPSILON_1000)) @@ -735,21 +754,29 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, } // underline // Retrieves the glyph's position. - const Vector2* const position = positionBuffer + glyphIndex; - if(baseline < position->y + glyphInfo->yBearing) + Vector2 position = *(positionBuffer + glyphIndex); + + if(addHyphen) + { + GlyphInfo tempInfo = *(glyphsBuffer + glyphIndex); + position.x = position.x + tempInfo.advance - tempInfo.xBearing + glyphInfo->xBearing; + position.y = -glyphInfo->yBearing; + } + + if(baseline < position.y + glyphInfo->yBearing) { - baseline = position->y + glyphInfo->yBearing; + baseline = position.y + glyphInfo->yBearing; } // Calculate the positions of leftmost and rightmost glyphs in the current line - if(position->x < lineExtentLeft) + if(position.x < lineExtentLeft) { - lineExtentLeft = position->x; + lineExtentLeft = position.x; } - if(position->x + glyphInfo->width > lineExtentRight) + if(position.x + glyphInfo->width > lineExtentRight) { - lineExtentRight = position->x + glyphInfo->width; + lineExtentRight = position.x + glyphInfo->width; } // Retrieves the glyph's color. @@ -807,7 +834,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, // Set the buffer of the glyph's bitmap into the final bitmap's buffer TypesetGlyph(glyphData, - position, + &position, &color, style, pixelFormat); @@ -823,6 +850,20 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, delete[] glyphData.glyphBitmap.buffer; glyphData.glyphBitmap.buffer = NULL; } + + if(hyphenIndices) + { + while((hyphenIndex < hyphensCount) && (glyphIndex > hyphenIndices[hyphenIndex])) + { + hyphenIndex++; + } + + addHyphen = ((hyphenIndex < hyphensCount) && ((glyphIndex + 1) == hyphenIndices[hyphenIndex])); + if(addHyphen) + { + glyphIndex--; + } + } } // Draw the underline from the leftmost glyph to the rightmost glyph @@ -906,6 +947,48 @@ Devel::PixelBuffer Typesetter::CombineImageBuffer(Devel::PixelBuffer topPixelBuf return combinedPixelBuffer; } +Devel::PixelBuffer Typesetter::ApplyMarkupProcessorOnPixelBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset) +{ + // Apply the markup-Processor if enabled + const bool markupProcessorEnabled = mModel->IsMarkupProcessorEnabled(); + if(markupProcessorEnabled) + { + // Underline-tags (this is for Markup case) + // Get the underline runs. + const Length numberOfUnderlineRuns = mModel->GetNumberOfUnderlineRuns(); + Vector underlineRuns; + underlineRuns.Resize(numberOfUnderlineRuns); + mModel->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); + + // Iterate on the consecutive underlined glyph run and connect them into one chunk of underlined characters. + Vector::ConstIterator itGlyphRun = underlineRuns.Begin(); + Vector::ConstIterator endItGlyphRun = underlineRuns.End(); + GlyphIndex startGlyphIndex, endGlyphIndex; + + //The outer loop to iterate on the separated chunks of underlined glyph runs + while(itGlyphRun != endItGlyphRun) + { + startGlyphIndex = itGlyphRun->glyphIndex; + endGlyphIndex = startGlyphIndex; + //The inner loop to make a connected underline for the consecutive characters + do + { + endGlyphIndex += itGlyphRun->numberOfGlyphs; + itGlyphRun++; + } while(itGlyphRun != endItGlyphRun && itGlyphRun->glyphIndex == endGlyphIndex); + + endGlyphIndex--; + + // Create the image buffer for underline + Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, horizontalOffset, verticalOffset, startGlyphIndex, endGlyphIndex); + // Combine the two buffers + topPixelBuffer = CombineImageBuffer(topPixelBuffer, underlineImageBuffer, bufferWidth, bufferHeight); + } + } + + return topPixelBuffer; +} + Typesetter::Typesetter(const ModelInterface* const model) : mModel(new ViewModel(model)) { diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.h b/dali-toolkit/internal/text/rendering/text-typesetter.h index 2f29a47..c9cd4cc 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.h +++ b/dali-toolkit/internal/text/rendering/text-typesetter.h @@ -163,6 +163,27 @@ private: */ Devel::PixelBuffer CombineImageBuffer(Devel::PixelBuffer topPixelBuffer, Devel::PixelBuffer bottomPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeightbool); + /** + * @brief Apply behaviour of tags if the markup-processor is enabled. + * + * The properties on TextLabel override the behavior of Markup. + * Because the markup will be the bottom layer buffer + * - i.e: If you set property UNDERLINE to enabled and blue. + * And the TEXT is "Hello World Hello World". + * Then the output of the whole text is underlined by blue line. + * + * @param[in] topPixelBuffer The top layer buffer. + * @param[in] bufferWidth The width of the image buffer. + * @param[in] bufferHeight The height of the image buffer. + * @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] horizontalOffset The horizontal offset to be added to the glyph's position. + * @param[in] verticalOffset The vertical offset to be added to the glyph's position. + * + * @return The image buffer with the markup. + */ + Devel::PixelBuffer ApplyMarkupProcessorOnPixelBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset); + protected: /** * @brief A reference counted object may only be deleted by calling Unreference(). diff --git a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h b/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h deleted file mode 100644 index 48a8335..0000000 --- a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h +++ /dev/null @@ -1,229 +0,0 @@ -static const char* glyphy_common_glsl = - "/*\n" - " * Copyright 2012 Google, Inc. All Rights Reserved.\n" - " *\n" - " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" - " * you may not use this file except in compliance with the License.\n" - " * You may obtain a copy of the License at\n" - " *\n" - " * http://www.apache.org/licenses/LICENSE-2.0\n" - " *\n" - " * Unless required by applicable law or agreed to in writing, software\n" - " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" - " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" - " * See the License for the specific language governing permissions and\n" - " * limitations under the License.\n" - " *\n" - " * Google Author(s): Behdad Esfahbod, Maysum Panju\n" - " */\n" - "\n" - "\n" - "#ifndef GLYPHY_INFINITY\n" - "# define GLYPHY_INFINITY 1e9\n" - "#endif\n" - "#ifndef GLYPHY_EPSILON\n" - "# define GLYPHY_EPSILON 1e-5\n" - "#endif\n" - "\n" - "#ifndef GLYPHY_RGBA\n" - "# ifdef GLYPHY_BGRA\n" - "# define GLYPHY_RGBA(v) glyphy_bgra (v)\n" - "# else\n" - "# define GLYPHY_RGBA(v) glyphy_rgba (v)\n" - "# endif\n" - "#endif\n" - "\n" - "vec4\n" - "glyphy_rgba (const vec4 v)\n" - "{\n" - " return v.rgba;\n" - "}\n" - "\n" - "vec4\n" - "glyphy_bgra (const vec4 v)\n" - "{\n" - " return v.bgra;\n" - "}\n" - "\n" - "\n" - "struct glyphy_arc_t {\n" - " vec2 p0;\n" - " vec2 p1;\n" - " float d;\n" - "};\n" - "\n" - "struct glyphy_arc_endpoint_t {\n" - " /* Second arc endpoint */\n" - " vec2 p;\n" - " /* Infinity if this endpoint does not form an arc with the previous\n" - " * endpoint. Ie. a \"move_to\". Test with glyphy_isinf().\n" - " * Arc depth otherwise. */\n" - " float d;\n" - "};\n" - "\n" - "struct glyphy_arc_list_t {\n" - " /* Number of endpoints in the list.\n" - " * Will be zero if we're far away inside or outside, in which case side is set.\n" - " * Will be -1 if this arc-list encodes a single line, in which case line_* are set. */\n" - " int num_endpoints;\n" - "\n" - " /* If num_endpoints is zero, this specifies whether we are inside (-1)\n" - " * or outside (+1). Otherwise we're unsure (0). */\n" - " int side;\n" - " /* Offset to the arc-endpoints from the beginning of the glyph blob */\n" - " int offset;\n" - "\n" - " /* A single line is all we care about. It's right here. */\n" - " float line_angle;\n" - " float line_distance; /* From nominal glyph center */\n" - "};\n" - "\n" - "bool\n" - "glyphy_isinf (const float v)\n" - "{\n" - " return abs (v) >= GLYPHY_INFINITY * .5;\n" - "}\n" - "\n" - "bool\n" - "glyphy_iszero (const float v)\n" - "{\n" - " return abs (v) <= GLYPHY_EPSILON * 2.;\n" - "}\n" - "\n" - "vec2\n" - "glyphy_ortho (const vec2 v)\n" - "{\n" - " return vec2 (-v.y, v.x);\n" - "}\n" - "\n" - "int\n" - "glyphy_float_to_byte (const float v)\n" - "{\n" - " return int (v * (256. - GLYPHY_EPSILON));\n" - "}\n" - "\n" - "ivec4\n" - "glyphy_vec4_to_bytes (const vec4 v)\n" - "{\n" - " return ivec4 (v * (256. - GLYPHY_EPSILON));\n" - "}\n" - "\n" - "ivec2\n" - "glyphy_float_to_two_nimbles (const float v)\n" - "{\n" - " int f = glyphy_float_to_byte (v);\n" - " return ivec2 (f / 16, int(mod (float(f), 16.)));\n" - "}\n" - "\n" - "/* returns tan (2 * atan (d)) */\n" - "float\n" - "glyphy_tan2atan (const float d)\n" - "{\n" - " return 2. * d / (1. - d * d);\n" - "}\n" - "\n" - "glyphy_arc_endpoint_t\n" - "glyphy_arc_endpoint_decode (const vec4 v, const ivec2 nominal_size)\n" - "{\n" - " vec2 p = (vec2 (glyphy_float_to_two_nimbles (v.a)) + v.gb) / 16.;\n" - " float d = v.r;\n" - " if (d == 0.)\n" - " d = GLYPHY_INFINITY;\n" - " else\n" - "#define GLYPHY_MAX_D .5\n" - " d = float(glyphy_float_to_byte (d) - 128) * GLYPHY_MAX_D / 127.;\n" - "#undef GLYPHY_MAX_D\n" - " return glyphy_arc_endpoint_t (p * vec2(nominal_size), d);\n" - "}\n" - "\n" - "vec2\n" - "glyphy_arc_center (const glyphy_arc_t a)\n" - "{\n" - " return mix (a.p0, a.p1, .5) +\n" - " glyphy_ortho (a.p1 - a.p0) / (2. * glyphy_tan2atan (a.d));\n" - "}\n" - "\n" - "bool\n" - "glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p)\n" - "{\n" - " float d2 = glyphy_tan2atan (a.d);\n" - " return dot (p - a.p0, (a.p1 - a.p0) * mat2(1, d2, -d2, 1)) >= 0. &&\n" - " dot (p - a.p1, (a.p1 - a.p0) * mat2(1, -d2, d2, 1)) <= 0.;\n" - "}\n" - "\n" - "float\n" - "glyphy_arc_wedge_signed_dist_shallow (const glyphy_arc_t a, const vec2 p)\n" - "{\n" - " vec2 v = normalize (a.p1 - a.p0);\n" - " float line_d = dot (p - a.p0, glyphy_ortho (v));\n" - " if (a.d == 0.)\n" - " return line_d;\n" - "\n" - " float d0 = dot ((p - a.p0), v);\n" - " if (d0 < 0.)\n" - " return sign (line_d) * distance (p, a.p0);\n" - " float d1 = dot ((a.p1 - p), v);\n" - " if (d1 < 0.)\n" - " return sign (line_d) * distance (p, a.p1);\n" - " float r = 2. * a.d * (d0 * d1) / (d0 + d1);\n" - " if (r * line_d > 0.)\n" - " return sign (line_d) * min (abs (line_d + r), min (distance (p, a.p0), distance (p, a.p1)));\n" - " return line_d + r;\n" - "}\n" - "\n" - "float\n" - "glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p)\n" - "{\n" - " if (abs (a.d) <= .03)\n" - " return glyphy_arc_wedge_signed_dist_shallow (a, p);\n" - " vec2 c = glyphy_arc_center (a);\n" - " return sign (a.d) * (distance (a.p0, c) - distance (p, c));\n" - "}\n" - "\n" - "float\n" - "glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p)\n" - "{\n" - " /* Note: this doesn't handle points inside the wedge. */\n" - " vec2 m = mix (a.p0, a.p1, .5);\n" - " float d2 = glyphy_tan2atan (a.d);\n" - " if (dot (p - m, a.p1 - m) < 0.)\n" - " return dot (p - a.p0, normalize ((a.p1 - a.p0) * mat2(+d2, -1, +1, +d2)));\n" - " else\n" - " return dot (p - a.p1, normalize ((a.p1 - a.p0) * mat2(-d2, -1, +1, -d2)));\n" - "}\n" - "\n" - "int\n" - "glyphy_arc_list_offset (const vec2 p, const ivec2 nominal_size)\n" - "{\n" - " ivec2 cell = ivec2 (clamp (floor (p), vec2 (0.,0.), vec2(nominal_size - 1)));\n" - " return cell.y * nominal_size.x + cell.x;\n" - "}\n" - "\n" - "glyphy_arc_list_t\n" - "glyphy_arc_list_decode (const vec4 v, const ivec2 nominal_size)\n" - "{\n" - " glyphy_arc_list_t l;\n" - " ivec4 iv = glyphy_vec4_to_bytes (v);\n" - " l.side = 0; /* unsure */\n" - " if (iv.r == 0) { /* arc-list encoded */\n" - " l.offset = (iv.g * 256) + iv.b;\n" - " l.num_endpoints = iv.a;\n" - " if (l.num_endpoints == 255) {\n" - " l.num_endpoints = 0;\n" - " l.side = -1;\n" - " } else if (l.num_endpoints == 0)\n" - " l.side = +1;\n" - " } else { /* single line encoded */\n" - " l.num_endpoints = -1;\n" - /*" l.line_distance = float(((iv.r - 128) * 256 + iv.g) - 0x4000) / float (0x1FFF)\n" - " * max (float (nominal_size.x), float (nominal_size.y));\n" - " l.line_angle = float(-((iv.b * 256 + iv.a) - 0x8000)) / float (0x7FFF) * 3.14159265358979;\n"*/ - /*" l.line_distance = float(((iv.r - 128) * 256 + iv.g) - 16384) / 8191.0 \n" - " * max (float (nominal_size.x), float (nominal_size.y));\n" - " l.line_angle = float(-((iv.b * 256 + iv.a) - 32768)) / 32767. * 3.14159;\n"*/ - " l.line_distance = ( float(iv.r)/32. + 0.01*float(iv.g)/82.0 - 6.) \n" - " * max (float (nominal_size.x), float (nominal_size.y));\n" - " l.line_angle = ( -float(iv.b)/40.74 - float( iv.a )*0.0001 )-3.142;\n" - " }\n" - " return l;\n" - "}\n"; diff --git a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h b/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h deleted file mode 100644 index 37b1b13..0000000 --- a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h +++ /dev/null @@ -1,151 +0,0 @@ -static const char* glyphy_sdf_glsl = - "/*\n" - " * Copyright 2012 Google, Inc. All Rights Reserved.\n" - " *\n" - " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" - " * you may not use this file except in compliance with the License.\n" - " * You may obtain a copy of the License at\n" - " *\n" - " * http://www.apache.org/licenses/LICENSE-2.0\n" - " *\n" - " * Unless required by applicable law or agreed to in writing, software\n" - " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" - " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" - " * See the License for the specific language governing permissions and\n" - " * limitations under the License.\n" - " *\n" - " * Google Author(s): Behdad Esfahbod, Maysum Panju\n" - " */\n" - "\n" - "#ifndef GLYPHY_TEXTURE1D_FUNC\n" - "#define GLYPHY_TEXTURE1D_FUNC glyphy_texture1D_func\n" - "#endif\n" - "#ifndef GLYPHY_TEXTURE1D_EXTRA_DECLS\n" - "#define GLYPHY_TEXTURE1D_EXTRA_DECLS\n" - "#endif\n" - "#ifndef GLYPHY_TEXTURE1D_EXTRA_ARGS\n" - "#define GLYPHY_TEXTURE1D_EXTRA_ARGS\n" - "#endif\n" - "\n" - "#ifndef GLYPHY_SDF_TEXTURE1D_FUNC\n" - "#define GLYPHY_SDF_TEXTURE1D_FUNC GLYPHY_TEXTURE1D_FUNC\n" - "#endif\n" - "#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS\n" - "#define GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS GLYPHY_TEXTURE1D_EXTRA_DECLS\n" - "#endif\n" - "#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS\n" - "#define GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS GLYPHY_TEXTURE1D_EXTRA_ARGS\n" - "#endif\n" - "#ifndef GLYPHY_SDF_TEXTURE1D\n" - "#define GLYPHY_SDF_TEXTURE1D(offset) GLYPHY_RGBA(GLYPHY_SDF_TEXTURE1D_FUNC (offset GLYPHY_TEXTURE1D_EXTRA_ARGS))\n" - "#endif\n" - "\n" - "#ifndef GLYPHY_MAX_NUM_ENDPOINTS\n" - "#define GLYPHY_MAX_NUM_ENDPOINTS 32\n" - "#endif\n" - "\n" - "glyphy_arc_list_t\n" - "glyphy_arc_list (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n" - "{\n" - " int cell_offset = glyphy_arc_list_offset (p, nominal_size);\n" - " vec4 arc_list_data = GLYPHY_SDF_TEXTURE1D (cell_offset);\n" - " return glyphy_arc_list_decode (arc_list_data, nominal_size);\n" - "}\n" - "\n" - "float\n" - "glyphy_sdf (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n" - "{\n" - " glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS);\n" - "\n" - " /* Short-circuits */\n" - " if (arc_list.num_endpoints == 0) {\n" - " /* far-away cell */\n" - " return GLYPHY_INFINITY * float(arc_list.side);\n" - " } if (arc_list.num_endpoints == -1) {\n" - " /* single-line */\n" - " float angle = arc_list.line_angle;\n" - " vec2 n = vec2 (cos (angle), sin (angle));\n" - " return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance;\n" - " }\n" - "\n" - " float side = float(arc_list.side);\n" - " float min_dist = GLYPHY_INFINITY;\n" - " glyphy_arc_t closest_arc;\n" - "\n" - " glyphy_arc_endpoint_t endpoint_prev, endpoint;\n" - " endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size);\n" - " for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++)\n" - " {\n" - " if (i >= arc_list.num_endpoints) {\n" - " break;\n" - " }\n" - " endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size);\n" - " glyphy_arc_t a = glyphy_arc_t (endpoint_prev.p, endpoint.p, endpoint.d);\n" - " endpoint_prev = endpoint;\n" - " if (glyphy_isinf (a.d)) continue;\n" - "\n" - " if (glyphy_arc_wedge_contains (a, p))\n" - " {\n" - " float sdist = glyphy_arc_wedge_signed_dist (a, p);\n" - " float udist = abs (sdist) * (1. - GLYPHY_EPSILON);\n" - " if (udist <= min_dist) {\n" - " min_dist = udist;\n" - " side = sign (sdist);" - " }\n" - " } else {\n" - " float udist = min (distance (p, a.p0), distance (p, a.p1));\n" - " if (udist < min_dist) {\n" - " min_dist = udist;\n" - " side = 0.; /* unsure */\n" - " closest_arc = a;\n" - " } else if (side == 0. && udist == min_dist) {\n" - " /* If this new distance is the same as the current minimum,\n" - " * compare extended distances. Take the sign from the arc\n" - " * with larger extended distance. */\n" - " float old_ext_dist = glyphy_arc_extended_dist (closest_arc, p);\n" - " float new_ext_dist = glyphy_arc_extended_dist (a, p);\n" - "\n" - " float ext_dist = abs (new_ext_dist) <= abs (old_ext_dist) ?\n" - " old_ext_dist : new_ext_dist;\n" - "\n" - "#ifdef GLYPHY_SDF_PSEUDO_DISTANCE\n" - " /* For emboldening and stuff: */\n" - " min_dist = abs (ext_dist);\n" - "#endif\n" - " side = sign (ext_dist);\n" - " }\n" - " }\n" - " }\n" - "\n" - " if (side == 0.) {\n" - " // Technically speaking this should not happen, but it does. So try to fix it.\n" - " float ext_dist = glyphy_arc_extended_dist (closest_arc, p);\n" - " side = sign (ext_dist);\n" - " }\n" - "\n" - " return min_dist * side;\n" - "}\n" - "\n" - "float\n" - "glyphy_point_dist (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n" - "{\n" - " glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS);\n" - "\n" - " float side = float(arc_list.side);\n" - " float min_dist = GLYPHY_INFINITY;\n" - "\n" - " if (arc_list.num_endpoints == 0)\n" - " return min_dist;\n" - "\n" - " glyphy_arc_endpoint_t endpoint;\n" - " for (int i = 0; i < GLYPHY_MAX_NUM_ENDPOINTS; i++)\n" - " {\n" - " if (i >= arc_list.num_endpoints) {\n" - " break;\n" - " }\n" - " endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size);\n" - " if (glyphy_isinf (endpoint.d)) continue;\n" - " min_dist = min (min_dist, distance (p, endpoint.p));\n" - " }\n" - " return min_dist;\n" - "}\n"; diff --git a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.cpp b/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.cpp index 4be2524..6ff571a 100644 --- a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.cpp +++ b/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.cpp @@ -22,163 +22,10 @@ #include // INTERNAL INCLUDES -#include -#include +#include using namespace Dali; -namespace -{ -const char* const ENABLE_EXTENSION_PREFIX = - "#extension GL_OES_standard_derivatives : enable\n" - "precision highp float;\n" - "precision highp int;\n"; - -const char* const VERTEX_SHADER_MAIN = - "uniform mediump mat4 uProjection;\n" - "uniform mediump mat4 uModelView;\n" - "uniform mediump mat4 uMvpMatrix;\n" - "uniform bool uTextureMapped;\n" - "uniform mediump vec4 uCustomTextureCoords;\n" - "attribute highp vec2 aTexCoord;\n" - "varying mediump vec2 vTexCoord;\n" - "uniform mat3 uModelViewIT;\n" - "attribute mediump vec3 aNormal;\n" - "varying mediump vec3 vNormal;\n" - "attribute mediump vec2 aPosition;\n" - "varying mediump vec4 vVertex;\n" - "attribute mediump vec4 aColor;\n" - "varying mediump vec4 vColor;\n" - "varying vec4 v_glyph;\n" - "\n" - "vec4\n" - "glyph_vertex_transcode (vec2 v)\n" - "{\n" - " ivec2 g = ivec2 (v);\n" - " ivec2 corner = ivec2 (mod (v, 2.));\n" - " g /= 2;\n" - " ivec2 nominal_size = ivec2 (mod (vec2(g), 64.));\n" - " return vec4 (corner * nominal_size, g * 4);\n" - "}\n" - "\n" - "void\n" - "main()\n" - "{\n" - " gl_Position = uMvpMatrix * vec4 (aPosition, 0.0, 1.0);\n" - " v_glyph = glyph_vertex_transcode (aTexCoord);\n" - " vColor = aColor;\n" - "}\n"; - -const char* const FRAGMENT_SHADER_PREFIX = - "struct Material\n" - "{\n" - " mediump float mOpacity;\n" - " mediump float mShininess;\n" - " lowp vec4 mAmbient;\n" - " lowp vec4 mDiffuse;\n" - " lowp vec4 mSpecular;\n" - " lowp vec4 mEmissive;\n" - "};\n" - "uniform sampler2D sTexture;\n" - "uniform sampler2D sOpacityTexture;\n" - "uniform sampler2D sNormalMapTexture;\n" - "uniform sampler2D sEffect;\n" - "varying mediump vec2 vTexCoord;\n" - "uniform Material uMaterial;\n" - "uniform lowp vec4 uColor;\n" - "varying highp vec4 vVertex;\n" - "varying highp vec3 vNormal;\n" - "varying mediump vec4 vColor;\n" - "uniform vec4 u_atlas_info;\n" - "\n" - "#define GLYPHY_TEXTURE1D_EXTRA_DECLS , sampler2D _tex, ivec4 _atlas_info, ivec2 _atlas_pos\n" - "#define GLYPHY_TEXTURE1D_EXTRA_ARGS , _tex, _atlas_info, _atlas_pos\n" - "#define GLYPHY_DEMO_EXTRA_ARGS , sTexture, uu_atlas_info, gi.atlas_pos\n" - "\n" - "vec4\n" - "glyphy_texture1D_func (int offset GLYPHY_TEXTURE1D_EXTRA_DECLS)\n" - "{\n" - " ivec2 item_geom = _atlas_info.zw;\n" - " vec2 pos = (vec2 (_atlas_pos.xy * item_geom +\n" - " ivec2 (mod (float (offset), float (item_geom.x)), offset / item_geom.x)) +\n" - " + vec2 (.5, .5)) / vec2(_atlas_info.xy);\n" - " return texture2D (_tex, pos);\n" - "}\n"; - -static const char* FRAGMENT_SHADER_MAIN = - "uniform float u_contrast;\n" - "uniform float u_gamma_adjust;\n" - "uniform float u_outline_thickness;\n" - "uniform float u_outline;\n" - "uniform float u_boldness;\n" - "\n" - "varying vec4 v_glyph;\n" - "\n" - "\n" - "#define SQRT2_2 0.70711 /* 1 / sqrt(2.) */\n" - "#define SQRT2 1.41421\n" - "\n" - "struct glyph_info_t {\n" - " ivec2 nominal_size;\n" - " ivec2 atlas_pos;\n" - "};\n" - "\n" - "glyph_info_t\n" - "glyph_info_decode (vec4 v)\n" - "{\n" - " glyph_info_t gi;\n" - " gi.nominal_size = (ivec2 (mod (v.zw, 256.)) + 2) / 4;\n" - " gi.atlas_pos = ivec2 (v_glyph.zw) / 256;\n" - " return gi;\n" - "}\n" - "\n" - "\n" - "float\n" - "antialias (float d)\n" - "{\n" - " return smoothstep (-.75, +.75, d);\n" - "}\n" - "\n" - "vec4\n" - "source_over (const vec4 src, const vec4 dst)\n" - "{\n" - " // http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators_srcover\n" - " float alpha = src.a + (dst.a * (1. - src.a));\n" - " return vec4 (((src.rgb * src.a) + (dst.rgb * dst.a * (1. - src.a))) / alpha, alpha);\n" - "}\n" - "\n" - "void\n" - "main()\n" - "{\n" - " vec2 p = v_glyph.xy;\n" - " glyph_info_t gi = glyph_info_decode (v_glyph);\n" - "\n" - " /* isotropic antialiasing */\n" - " vec2 dpdx = dFdx (p);\n" - " vec2 dpdy = dFdy (p);\n" - " float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_2;\n" - "\n" - " vec4 color = vec4( vColor.rgb * uColor.rgb, vColor.a * uColor.a );\n" - "\n" - " ivec4 uu_atlas_info = ivec4( u_atlas_info );" - " float gsdist = glyphy_sdf (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS);\n" - " float sdist = gsdist / m * u_contrast;\n" - "\n" - " sdist -= u_boldness * 10.;\n" - " if ( glyphy_iszero( u_outline ) )\n" - " sdist = abs (sdist) - u_outline_thickness * .5;\n" - " if (sdist > 1.)\n" - " discard;\n" - " float alpha = antialias (-sdist);\n" - " if (u_gamma_adjust != 1.)\n" - " alpha = pow (alpha, 1./u_gamma_adjust);\n" - " color = vec4 (color.rgb,color.a * alpha);\n" - "\n" - " gl_FragColor = color;\n" - "}\n"; - -} // namespace - namespace Dali { namespace Toolkit @@ -203,14 +50,14 @@ GlyphyShader GlyphyShader::New(const Dali::Vector4& atlasInfo) std::ostringstream vertexShaderStringStream; std::ostringstream fragmentShaderStringStream; - vertexShaderStringStream << ENABLE_EXTENSION_PREFIX << VERTEX_SHADER_MAIN; + vertexShaderStringStream << SHADER_GLYPHY_SHADER_EXTENTION_PREFIX_DEF.data() << SHADER_GLYPHY_SHADER_MAIN_VERT.data(); - fragmentShaderStringStream << ENABLE_EXTENSION_PREFIX - << FRAGMENT_SHADER_PREFIX - << glyphy_common_glsl + fragmentShaderStringStream << SHADER_GLYPHY_SHADER_EXTENTION_PREFIX_DEF.data() + << SHADER_GLYPHY_SHADER_FRAGMENT_PREFIX_FRAG.data() + << SHADER_GLYPHY_COMMON_GLSL_SHADER_DEF.data() << "#define GLYPHY_SDF_PSEUDO_DISTANCE 1\n" - << glyphy_sdf_glsl - << FRAGMENT_SHADER_MAIN; + << SHADER_GLYPHY_SDF_GLSL_SHADER_DEF.data() + << SHADER_GLYPHY_SHADER_MAIN_FRAG.data(); Shader shaderEffectCustom = Shader::New(vertexShaderStringStream.str(), fragmentShaderStringStream.str(), diff --git a/dali-toolkit/internal/text/rendering/view-model.cpp b/dali-toolkit/internal/text/rendering/view-model.cpp index e7b40a5..f695cd2 100644 --- a/dali-toolkit/internal/text/rendering/view-model.cpp +++ b/dali-toolkit/internal/text/rendering/view-model.cpp @@ -225,6 +225,26 @@ bool ViewModel::IsBackgroundEnabled() const return mModel->IsBackgroundEnabled(); } +bool ViewModel::IsMarkupProcessorEnabled() const +{ + return mModel->IsMarkupProcessorEnabled(); +} + +const GlyphInfo* ViewModel::GetHyphens() const +{ + return mModel->GetHyphens(); +} + +const Length* ViewModel::GetHyphenIndices() const +{ + return mModel->GetHyphenIndices(); +} + +Length ViewModel::GetHyphensCount() const +{ + return mModel->GetHyphensCount(); +} + void ViewModel::ElideGlyphs() { mIsTextElided = false; diff --git a/dali-toolkit/internal/text/rendering/view-model.h b/dali-toolkit/internal/text/rendering/view-model.h index a84810a..9272956 100644 --- a/dali-toolkit/internal/text/rendering/view-model.h +++ b/dali-toolkit/internal/text/rendering/view-model.h @@ -211,6 +211,26 @@ public: bool IsBackgroundEnabled() const override; /** + * @copydoc ModelInterface::IsMarkupProcessorEnabled() + */ + bool IsMarkupProcessorEnabled() const override; + + /** + * @copydoc ModelInterface::GetHyphens() + */ + const GlyphInfo* GetHyphens() const override; + + /** + * @copydoc ModelInterface::GetHyphens() + */ + const Length* GetHyphenIndices() const override; + + /** + * @copydoc ModelInterface::GetHyphens() + */ + Length GetHyphensCount() const override; + + /** * @brief Does the text elide. * * It stores a copy of the visible glyphs and removes as many glyphs as needed diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index ec00903..417eaed 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,8 @@ #include #include +#include + using namespace Dali; namespace @@ -587,7 +590,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) Vector& srcCharacters = mModel->mLogicalModel->mText; Vector displayCharacters; bool useHiddenText = false; - if(mHiddenInput && mEventData != NULL && !mEventData->mIsShowingPlaceholderText) + if(mHiddenInput && mEventData != nullptr && !mEventData->mIsShowingPlaceholderText) { mHiddenInput->Substitute(srcCharacters, displayCharacters); useHiddenText = true; @@ -661,6 +664,39 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) requestedNumberOfCharacters, lineBreakInfo); + if(mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || + mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) + { + CharacterIndex end = startIndex + requestedNumberOfCharacters; + LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + + for(CharacterIndex index = startIndex; index < end; index++) + { + CharacterIndex wordEnd = index; + while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK)) + { + wordEnd++; + } + + if((wordEnd + 1) == end) // add last char + { + wordEnd++; + } + + Vector hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr); + + for(CharacterIndex i = 0; i < (wordEnd - index); i++) + { + if(hyphens[i]) + { + *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK; + } + } + + index = wordEnd; + } + } + // Create the paragraph info. mModel->mLogicalModel->CreateParagraphInfo(startIndex, requestedNumberOfCharacters); @@ -697,27 +733,30 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) TextAbstraction::FontDescription defaultFontDescription; TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale; - if(IsShowingPlaceholderText() && mEventData && (NULL != mEventData->mPlaceholderFont)) + //Get the number of points per one unit of point-size + uint32_t numberOfPointsPerOneUnitOfPointSize = mFontClient.GetNumberOfPointsPerOneUnitOfPointSize(); + + if(IsShowingPlaceholderText() && mEventData && (nullptr != mEventData->mPlaceholderFont)) { // If the placeholder font is set specifically, only placeholder font is changed. defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription; if(mEventData->mPlaceholderFont->sizeDefined) { - defaultPointSize = mEventData->mPlaceholderFont->mDefaultPointSize * mFontSizeScale * 64u; + defaultPointSize = mEventData->mPlaceholderFont->mDefaultPointSize * mFontSizeScale * numberOfPointsPerOneUnitOfPointSize; } } - else if(NULL != mFontDefaults) + else if(nullptr != mFontDefaults) { // Set the normal font and the placeholder font. defaultFontDescription = mFontDefaults->mFontDescription; if(mTextFitEnabled) { - defaultPointSize = mFontDefaults->mFitPointSize * 64u; + defaultPointSize = mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize; } else { - defaultPointSize = mFontDefaults->mDefaultPointSize * mFontSizeScale * 64u; + defaultPointSize = mFontDefaults->mDefaultPointSize * mFontSizeScale * numberOfPointsPerOneUnitOfPointSize; } } @@ -807,7 +846,8 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) // Create the 'number of glyphs' per character and the glyph to character conversion tables. mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); - updated = true; + + updated = true; } const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs; @@ -830,7 +870,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) updated = true; } - if((NULL != mEventData) && + if((nullptr != mEventData) && mEventData->mPreEditFlag && (0u != mModel->mVisualModel->mCharactersToGlyph.Count())) { @@ -858,6 +898,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::REVERSE: @@ -902,6 +948,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2: @@ -917,6 +969,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3: @@ -932,6 +990,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4: @@ -947,6 +1011,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::NONE: @@ -985,6 +1055,21 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) updated = true; } + if((NO_OPERATION != (SHAPE_TEXT & operations)) && + ! ((nullptr != mEventData) && + mEventData->mPreEditFlag && + (0u != mModel->mVisualModel->mCharactersToGlyph.Count()))) + { + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(true); + } + + updated = true; + } + + // The estimated number of lines. Used to avoid reallocations when layouting. mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count()); @@ -1064,7 +1149,7 @@ void Controller::Impl::RetrieveDefaultInputStyle(InputStyle& inputStyle) float Controller::Impl::GetDefaultFontLineHeight() { FontId defaultFontId = 0u; - if(NULL == mFontDefaults) + if(nullptr == mFontDefaults) { TextAbstraction::FontDescription fontDescription; defaultFontId = mFontClient.GetFontId(fontDescription, TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale); @@ -1384,7 +1469,7 @@ void Controller::Impl::SetPopupButtons() void Controller::Impl::ChangeState(EventData::State newState) { - if(NULL == mEventData) + if(nullptr == mEventData) { // Nothing to do if there is no text input. return; @@ -1700,7 +1785,7 @@ void Controller::Impl::GetCursorPosition(CharacterIndex logical, CharacterIndex Controller::Impl::CalculateNewCursorIndex(CharacterIndex index) const { - if(NULL == mEventData) + if(nullptr == mEventData) { // Nothing to do if there is no text input. return 0u; @@ -1750,7 +1835,7 @@ CharacterIndex Controller::Impl::CalculateNewCursorIndex(CharacterIndex index) c void Controller::Impl::UpdateCursorPosition(const CursorInfo& cursorInfo) { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this); - if(NULL == mEventData) + if(nullptr == mEventData) { // Nothing to do if there is no text input. DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition no event data\n"); @@ -1925,7 +2010,7 @@ void Controller::Impl::ScrollTextToMatchCursor() void Controller::Impl::RequestRelayout() { - if(NULL != mControlInterface) + if(nullptr != mControlInterface) { mControlInterface->RequestTextRelayout(); } @@ -2095,6 +2180,32 @@ Actor Controller::Impl::CreateBackgroundActor() return actor; } +void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns) +{ + //Underlined character runs for markup-processor + const Vector& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns; + const Vector& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph; + const Vector& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter; + + if(shouldClearPreUnderlineRuns) + { + mModel->mVisualModel->mUnderlineRuns.Clear(); + } + + for(Vector::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it) + { + CharacterIndex characterIndex = it->characterRun.characterIndex; + Length numberOfCharacters = it->characterRun.numberOfCharacters; + for(Length index=0u; indexmVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun); + } + } +} + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index ef4bb69..9f637d3 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -785,6 +785,13 @@ private: // Declared private and left undefined to avoid copies. Impl& operator=(const Impl&); + /** + * @brief Copy Underlined-Character-Runs from Logical-Model to Underlined-Glyph-Runs in Visual-Model + * + * @param shouldClearPreUnderlineRuns Whether should clear the existing Underlined-Glyph-Runs in Visual-Model + */ + void CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns); + public: ControlInterface* mControlInterface; ///< Reference to the text controller. EditableControlInterface* mEditableControlInterface; ///< Reference to the editable text controller. diff --git a/dali-toolkit/internal/text/text-controller-relayouter.cpp b/dali-toolkit/internal/text/text-controller-relayouter.cpp index 227d889..78e7331 100644 --- a/dali-toolkit/internal/text/text-controller-relayouter.cpp +++ b/dali-toolkit/internal/text/text-controller-relayouter.cpp @@ -48,81 +48,122 @@ namespace Toolkit { namespace Text { -Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n"); - Vector3 naturalSize; - // Make sure the model is up-to-date before layouting - controller.ProcessModifyEvents(); +Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask, bool restoreLinesAndGlyphPositions) +{ + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->CalculateLayoutSizeOnRequiredControllerSize\n"); + Size calculatedLayoutSize; Controller::Impl& impl = *controller.mImpl; ModelPtr& model = impl.mModel; VisualModelPtr& visualModel = model->mVisualModel; - if(impl.mRecalculateNaturalSize) + + // Store the pending operations mask so that it can be restored later on with no modifications made on it + // while getting the natural size were reflected on the original mask. + OperationsMask operationsPendingBackUp = static_cast(impl.mOperationsPending); + + // This is a hotfix for side effect on Scrolling, LineWrap and Invalid position of cursor in TextEditor after calling CalculateLayoutSizeOnRequiredControllerSize. + // The number of lines and glyph-positions inside visualModel have been changed by calling DoRelayout with requestedControllerSize. + // Store the mLines and mGlyphPositions from visualModel so that they can be restored later on with no modifications made on them. + //TODO: Refactor "DoRelayout" and extract common code of size calculation without modifying attributes of mVisualModel, and then blah, blah, etc. + Vector linesBackup = visualModel->mLines; + Vector glyphPositionsBackup = visualModel->mGlyphPositions; + + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast(CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + BIDI_INFO | + SHAPE_TEXT | + GET_GLYPH_METRICS); + + // Set the update info to relayout the whole text. + TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo; + textUpdateInfo.mParagraphCharacterIndex = 0u; + textUpdateInfo.mRequestedNumberOfCharacters = model->mLogicalModel->mText.Count(); + + // Make sure the model is up-to-date before layouting + impl.UpdateModel(onlyOnceOperations); + + // Get a reference to the pending operations member + OperationsMask& operationsPending = impl.mOperationsPending; + + // Layout the text for the new width. + operationsPending = static_cast(operationsPending | requestedOperationsMask); + + // Store the actual control's size to restore later. + const Size actualControlSize = visualModel->mControlSize; + + DoRelayout(controller, + requestedControllerSize, + static_cast(onlyOnceOperations | + requestedOperationsMask), + calculatedLayoutSize); + + + // Clear the update info. This info will be set the next time the text is updated. + textUpdateInfo.Clear(); + textUpdateInfo.mClearAll = true; + + // Restore the actual control's size. + visualModel->mControlSize = actualControlSize; + // Restore the previously backed-up pending operations' mask without the only once operations. + impl.mOperationsPending = static_cast(operationsPendingBackUp & ~onlyOnceOperations); + + // Restore the previously backed-up mLines and mGlyphPositions from visualModel. + if(restoreLinesAndGlyphPositions) { - // Store the pending operations mask so that it can be restored later on with no modifications made on it - // while getting the natural size were reflected on the original mask. - OperationsMask operationsPendingBackUp = static_cast(impl.mOperationsPending); - // Operations that can be done only once until the text changes. - const OperationsMask onlyOnceOperations = static_cast(CONVERT_TO_UTF32 | - GET_SCRIPTS | - VALIDATE_FONTS | - GET_LINE_BREAKS | - BIDI_INFO | - SHAPE_TEXT | - GET_GLYPH_METRICS); + visualModel->mLines = linesBackup; + visualModel->mGlyphPositions = glyphPositionsBackup; + } - // Set the update info to relayout the whole text. - TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo; - textUpdateInfo.mParagraphCharacterIndex = 0u; - textUpdateInfo.mRequestedNumberOfCharacters = model->mLogicalModel->mText.Count(); + return calculatedLayoutSize; +} - // Make sure the model is up-to-date before layouting - impl.UpdateModel(onlyOnceOperations); - // Get a reference to the pending operations member - OperationsMask& operationsPending = impl.mOperationsPending; +Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller) +{ + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n"); + Vector3 naturalSizeVec3; - // Layout the text for the new width. - operationsPending = static_cast(operationsPending | LAYOUT | REORDER); + // Make sure the model is up-to-date before layouting + controller.ProcessModifyEvents(); + + Controller::Impl& impl = *controller.mImpl; + ModelPtr& model = impl.mModel; + VisualModelPtr& visualModel = model->mVisualModel; + + if(impl.mRecalculateNaturalSize) + { + Size naturalSize; - // Store the actual control's size to restore later. - const Size actualControlSize = visualModel->mControlSize; + // Layout the text for the new width. + OperationsMask requestedOperationsMask = static_cast(LAYOUT | REORDER); + Size sizeMaxWidthAndMaxHeight = Size(MAX_FLOAT, MAX_FLOAT); - DoRelayout(controller, - Size(MAX_FLOAT, MAX_FLOAT), - static_cast(onlyOnceOperations | - LAYOUT | REORDER), - naturalSize.GetVectorXY()); + naturalSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeMaxWidthAndMaxHeight, requestedOperationsMask, true); // Stores the natural size to avoid recalculate it again // unless the text/style changes. - visualModel->SetNaturalSize(naturalSize.GetVectorXY()); + visualModel->SetNaturalSize(naturalSize); + naturalSizeVec3 = naturalSize; impl.mRecalculateNaturalSize = false; - // Clear the update info. This info will be set the next time the text is updated. - textUpdateInfo.Clear(); - textUpdateInfo.mClearAll = true; - - // Restore the actual control's size. - visualModel->mControlSize = actualControlSize; - // Restore the previously backed-up pending operations' mask without the only once operations. - impl.mOperationsPending = static_cast(operationsPendingBackUp & ~onlyOnceOperations); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSizeVec3.x, naturalSizeVec3.y, naturalSizeVec3.z); } else { - naturalSize = visualModel->GetNaturalSize(); + naturalSizeVec3 = visualModel->GetNaturalSize(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSizeVec3.x, naturalSizeVec3.y, naturalSizeVec3.z); } - naturalSize.x = ConvertToEven(naturalSize.x); - naturalSize.y = ConvertToEven(naturalSize.y); + naturalSizeVec3.x = ConvertToEven(naturalSizeVec3.x); + naturalSizeVec3.y = ConvertToEven(naturalSizeVec3.y); - return naturalSize; + return naturalSizeVec3; } bool Controller::Relayouter::CheckForTextFit(Controller& controller, float pointSize, const Size& layoutSize) @@ -226,6 +267,7 @@ void Controller::Relayouter::FitPointSizeforLayout(Controller& controller, const float Controller::Relayouter::GetHeightForWidth(Controller& controller, float width) { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", &controller, width); + // Make sure the model is up-to-date before layouting controller.ProcessModifyEvents(); @@ -235,52 +277,24 @@ float Controller::Relayouter::GetHeightForWidth(Controller& controller, float wi TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo; Size layoutSize; + if(fabsf(width - visualModel->mControlSize.width) > Math::MACHINE_EPSILON_1000 || textUpdateInfo.mFullRelayoutNeeded || textUpdateInfo.mClearAll) { - // Store the pending operations mask so that it can be restored later on with no modifications made on it - // while getting the natural size were reflected on the original mask. - OperationsMask operationsPendingBackUp = static_cast(impl.mOperationsPending); - // Operations that can be done only once until the text changes. - const OperationsMask onlyOnceOperations = static_cast(CONVERT_TO_UTF32 | - GET_SCRIPTS | - VALIDATE_FONTS | - GET_LINE_BREAKS | - BIDI_INFO | - SHAPE_TEXT | - GET_GLYPH_METRICS); - - // Set the update info to relayout the whole text. - textUpdateInfo.mParagraphCharacterIndex = 0u; - textUpdateInfo.mRequestedNumberOfCharacters = model->mLogicalModel->mText.Count(); - - // Make sure the model is up-to-date before layouting - impl.UpdateModel(onlyOnceOperations); - - // Get a reference to the pending operations member - OperationsMask& operationsPending = impl.mOperationsPending; // Layout the text for the new width. - operationsPending = static_cast(operationsPending | LAYOUT); + OperationsMask requestedOperationsMask = static_cast(LAYOUT); + Size sizeRequestedWidthAndMaxHeight = Size(width, MAX_FLOAT); - // Store the actual control's width. - const float actualControlWidth = visualModel->mControlSize.width; + // Skip restore, because if GetHeightForWidth called before rendering and layouting then visualModel->mControlSize will be zero which will make LineCount zero. + // The implementation of Get LineCount property depends on calling GetHeightForWidth then read mLines.Count() from visualModel direct. + // If the LineCount property is requested before rendering and layouting then the value will be zero, which is incorrect. + // So we will not restore the previously backed-up mLines and mGlyphPositions from visualModel in such case. + bool restoreLinesAndGlyphPositions = visualModel->mControlSize.width>0 && visualModel->mControlSize.height>0; - DoRelayout(controller, - Size(width, MAX_FLOAT), - static_cast(onlyOnceOperations | - LAYOUT), - layoutSize); - - // Clear the update info. This info will be set the next time the text is updated. - textUpdateInfo.Clear(); - textUpdateInfo.mClearAll = true; + layoutSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeRequestedWidthAndMaxHeight, requestedOperationsMask, restoreLinesAndGlyphPositions); - // Restore the actual control's width. - visualModel->mControlSize.width = actualControlWidth; - // Restore the previously backed-up pending operations' mask without the only once operations. - impl.mOperationsPending = static_cast(operationsPendingBackUp & ~onlyOnceOperations); DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height); } else diff --git a/dali-toolkit/internal/text/text-controller-relayouter.h b/dali-toolkit/internal/text/text-controller-relayouter.h index d2d8670..1b586b2 100644 --- a/dali-toolkit/internal/text/text-controller-relayouter.h +++ b/dali-toolkit/internal/text/text-controller-relayouter.h @@ -100,6 +100,21 @@ struct Controller::Relayouter * @param[in] controlSize The control size */ static void CalculateVerticalOffset(Controller& controller, const Size& controlSize); + + /** + * @brief Calculates the layout size of control according to @p requestedControllerSize and @p requestedOperationsMask + * + * GetNaturalSize() and GetHeightForWidth() calls this method. + * + * @param[in] controller The controller to calcualte size on it. + * @param[in] requestedControllerSize The requested size of controller to calcualte layout size on it. + * @param[in] requestedOperationsMask The requested operations-mask to calcualte layout size according to it. + * @param[in] restoreLinesAndGlyphPositions whether to restore lines and glyph-positions to status before requesting calculation on size. + * + * @return The calculated layout-size. + */ + static Size CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask, bool restoreLinesAndGlyphPositions); + }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller-text-updater.cpp b/dali-toolkit/internal/text/text-controller-text-updater.cpp index 69e05bf..36a2133 100644 --- a/dali-toolkit/internal/text/text-controller-text-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-text-updater.cpp @@ -82,7 +82,8 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string& MarkupProcessData markupProcessData(logicalModel->mColorRuns, logicalModel->mFontDescriptionRuns, logicalModel->mEmbeddedItems, - logicalModel->mAnchors); + logicalModel->mAnchors, + logicalModel->mUnderlinedCharacterRuns); Length textSize = 0u; const uint8_t* utf8 = NULL; @@ -254,7 +255,8 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri const Length numberOfCharactersInModel = logicalModel->mText.Count(); // Restrict new text to fit within Maximum characters setting. - Length maxSizeOfNewText = std::min((impl.mMaximumNumberOfCharacters - numberOfCharactersInModel), characterCount); + Length temp_length = (impl.mMaximumNumberOfCharacters > numberOfCharactersInModel ? impl.mMaximumNumberOfCharacters - numberOfCharactersInModel : 0); + Length maxSizeOfNewText = std::min(temp_length, characterCount); maxLengthReached = (characterCount > maxSizeOfNewText); // The cursor position. diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 15db50b..6866ff4 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -25,6 +25,7 @@ #include // INTERNAL INCLUDES +#include #include #include #include @@ -124,6 +125,8 @@ void Controller::SetMarkupProcessorEnabled(bool enable) GetText(text); SetText(text); } + + mImpl->mModel->mVisualModel->SetMarkupProcessorEnabled(enable); } bool Controller::IsMarkupProcessorEnabled() const @@ -403,15 +406,22 @@ void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode) { if(lineWrapMode != mImpl->mModel->mLineWrapMode) { - // Set the text wrap mode. - mImpl->mModel->mLineWrapMode = lineWrapMode; - // Update Text layout for applying wrap mode - mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | + mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | ALIGN | LAYOUT | UPDATE_LAYOUT_SIZE | REORDER); + + if((mImpl->mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || + (mImpl->mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) // hyphen is treated as line break + { + mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | GET_LINE_BREAKS); + } + + // Set the text wrap mode. + mImpl->mModel->mLineWrapMode = lineWrapMode; + mImpl->mTextUpdateInfo.mCharacterIndex = 0u; mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters; mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count(); diff --git a/dali-toolkit/internal/text/text-model-interface.h b/dali-toolkit/internal/text/text-model-interface.h index aafd430..c116f8f 100644 --- a/dali-toolkit/internal/text/text-model-interface.h +++ b/dali-toolkit/internal/text/text-model-interface.h @@ -265,6 +265,34 @@ public: * @return The background state. */ virtual bool IsBackgroundEnabled() const = 0; + + /** + * @brief Returns whether markup-processor is enabled or not. + * + * @return The markup-processor state. + */ + virtual bool IsMarkupProcessorEnabled() const = 0; + + /** + * @brief Returns the hyphens glyph info. + * + * @return hyphens glyph info. + */ + virtual const GlyphInfo* GetHyphens() const = 0; + + /** + * @brief Returns the indices of the hyphen in the text. + * + * @return the hyphen indices. + */ + virtual const Length* GetHyphenIndices() const = 0; + + /** + * @brief Returns number of hyphens to add in text. + * + * @return number of hyphens. + */ + virtual Length GetHyphensCount() const = 0; }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-model.cpp b/dali-toolkit/internal/text/text-model.cpp index 2d60854..948044e 100644 --- a/dali-toolkit/internal/text/text-model.cpp +++ b/dali-toolkit/internal/text/text-model.cpp @@ -184,6 +184,26 @@ bool Model::IsBackgroundEnabled() const return mVisualModel->IsBackgroundEnabled(); } +bool Model::IsMarkupProcessorEnabled() const +{ + return mVisualModel->IsMarkupProcessorEnabled(); +} + +const GlyphInfo* Model::GetHyphens() const +{ + return mVisualModel->mHyphen.glyph.Begin(); +} + +const Length* Model::GetHyphenIndices() const +{ + return mVisualModel->mHyphen.index.Begin(); +} + +Length Model::GetHyphensCount() const +{ + return mVisualModel->mHyphen.glyph.Size(); +} + Model::Model() : mLogicalModel(), mVisualModel(), diff --git a/dali-toolkit/internal/text/text-model.h b/dali-toolkit/internal/text/text-model.h index d52809c..4faa1bc 100644 --- a/dali-toolkit/internal/text/text-model.h +++ b/dali-toolkit/internal/text/text-model.h @@ -207,6 +207,26 @@ public: */ bool IsBackgroundEnabled() const override; + /** + * @copydoc ModelInterface::IsMarkupProcessorEnabled() + */ + bool IsMarkupProcessorEnabled() const override; + + /** + * @copydoc ModelInterface::GetHyphens() + */ + const GlyphInfo* GetHyphens() const override; + + /** + * @copydoc ModelInterface::GetHyphens() + */ + const Length* GetHyphenIndices() const override; + + /** + * @copydoc ModelInterface::GetHyphens() + */ + Length GetHyphensCount() const override; + private: // Private contructors & copy operator. /** * @brief Private constructor. diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h index 1a04135..63f7fd4 100644 --- a/dali-toolkit/internal/text/text-view-interface.h +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -159,6 +159,26 @@ public: virtual bool IsUnderlineEnabled() const = 0; /** + * @brief Returns the hyphens glyph info. + * + * @return hyphens glyph info. + */ + virtual const GlyphInfo* GetHyphens() const = 0; + + /** + * @brief Returns the indices of the hyphen in the text. + * + * @return the hyphen indices. + */ + virtual const Length* GetHyphenIndices() const = 0; + + /** + * @brief Returns number of hyphens to add in text. + * + * @return number of hyphens. + */ + virtual Length GetHyphensCount() const = 0; + /** * @brief Retrieves the underline height override * * @return Returns the override height for an underline, 0 indicates that adaptor will determine the height diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index 83ad28f..2f74699 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -388,6 +388,35 @@ bool View::IsUnderlineEnabled() const return false; } +const GlyphInfo* View::GetHyphens() const +{ + if(mImpl->mVisualModel) + { + return mImpl->mVisualModel->mHyphen.glyph.Begin(); + } + + return nullptr; +} + +const Length* View::GetHyphenIndices() const +{ + if(mImpl->mVisualModel) + { + return mImpl->mVisualModel->mHyphen.index.Begin(); + } + + return nullptr; +} + +Length View::GetHyphensCount() const +{ + if(mImpl->mVisualModel) + { + return mImpl->mVisualModel->mHyphen.glyph.Size(); + } + + return 0; +} float View::GetUnderlineHeight() const { if(mImpl->mVisualModel) diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index cc82820..3790fd0 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -121,6 +121,21 @@ public: bool IsUnderlineEnabled() const override; /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetHyphens() + */ + const GlyphInfo* GetHyphens() const override; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetHyphens() + */ + const Length* GetHyphenIndices() const override; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetHyphens() + */ + Length GetHyphensCount() const override; + + /** * @copydoc Dali::Toolkit::Text::ViewInterface::GetUnderlineHeight() */ float GetUnderlineHeight() const override; diff --git a/dali-toolkit/internal/text/underlined-character-run.h b/dali-toolkit/internal/text/underlined-character-run.h new file mode 100644 index 0000000..99d5967 --- /dev/null +++ b/dali-toolkit/internal/text/underlined-character-run.h @@ -0,0 +1,51 @@ +#ifndef DALI_TOOLKIT_TEXT_UNDERLINED_CHARACTER_RUN_H +#define DALI_TOOLKIT_TEXT_UNDERLINED_CHARACTER_RUN_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Text +{ +/** + * @brief Run of underlined characters with same properties. + */ +struct UnderlinedCharacterRun +{ + CharacterRun characterRun; ///< The initial character index and the number of characters of the run. + //TODO: add properties like color, height and style + //Vector4 color; ///< The color of underline. + //float height; ///< The height of underline. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_UNDERLINED_CHARACTER_RUN_H diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index eda5633..7edb428 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -384,6 +384,11 @@ void VisualModel::SetBackgroundEnabled(bool enabled) mBackgroundEnabled = enabled; } +void VisualModel::SetMarkupProcessorEnabled(bool enabled) +{ + mMarkupProcessorEnabled = enabled; +} + const Vector4& VisualModel::GetTextColor() const { return mTextColor; @@ -439,6 +444,11 @@ bool VisualModel::IsBackgroundEnabled() const return mBackgroundEnabled; } +bool VisualModel::IsMarkupProcessorEnabled() const +{ + return mMarkupProcessorEnabled; +} + Length VisualModel::GetNumberOfUnderlineRuns() const { return mUnderlineRuns.Count(); @@ -476,7 +486,8 @@ VisualModel::VisualModel() mCachedLineIndex(0u), mUnderlineEnabled(false), mUnderlineColorSet(false), - mBackgroundEnabled(false) + mBackgroundEnabled(false), + mMarkupProcessorEnabled(false) { } diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index 371b666..c355c3c 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -35,6 +35,13 @@ namespace Toolkit { namespace Text { +struct HyphenInfo +{ + Vector glyph; + Vector position; + Vector index; +}; + class VisualModel; typedef IntrusivePtr VisualModelPtr; @@ -353,6 +360,20 @@ public: */ bool IsBackgroundEnabled() const; + /** + * @brief Sets whether the text has a markup-processor or not. + * + * @param[in] enabled true if the text has a markup-processor. + */ + void SetMarkupProcessorEnabled(bool enabled); + + /** + * @brief Returns whether the text has a markup-processor or not. + * + * @return whether the text has a markup-processor or not. + */ + bool IsMarkupProcessorEnabled() const; + protected: /** * @brief A reference counted object may only be deleted by calling Unreference(). @@ -407,6 +428,8 @@ public: bool mUnderlineEnabled : 1; ///< Underline enabled flag bool mUnderlineColorSet : 1; ///< Has the underline color been explicitly set? bool mBackgroundEnabled : 1; ///< Background enabled flag + bool mMarkupProcessorEnabled : 1; ///< Markup-processor enabled flag + HyphenInfo mHyphen; ///< Contains hyphen glyph info & the character index to draw hyphen after. }; } // namespace Text diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp index 2286ea0..f23439d 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp @@ -120,7 +120,7 @@ void VectorAnimationManager::UnregisterEventCallback(CallbackBase* callback) } } -void VectorAnimationManager::Process() +void VectorAnimationManager::Process(bool postProcessor) { for(auto&& iter : mEventCallbacks) { diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h index c52b800..fe6b87a 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h @@ -92,7 +92,7 @@ protected: // Implementation of Processor /** * @copydoc Dali::Integration::Processor::Process() */ - void Process() override; + void Process(bool postProcessor) override; private: // Undefined diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index d9d6d5a..a1659bf 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp @@ -37,7 +37,7 @@ namespace Internal namespace { constexpr auto LOOP_FOREVER = -1; -constexpr auto NANOSECONDS_PER_SECOND(1e+9); +constexpr auto MICROSECONDS_PER_SECOND(1e+6); #if defined(DEBUG_ENABLED) Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION"); @@ -56,12 +56,13 @@ VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache) mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME), mLoopingMode(DevelImageVisual::LoopingMode::RESTART), mNextFrameStartTime(), - mFrameDurationNanoSeconds(0), + mFrameDurationMicroSeconds(MICROSECONDS_PER_SECOND / 60.0f), mFrameRate(60.0f), mCurrentFrame(0), mTotalFrame(0), mStartFrame(0), mEndFrame(0), + mDroppedFrames(0), mWidth(0), mHeight(0), mAnimationDataIndex(0), @@ -109,8 +110,8 @@ bool VectorAnimationTask::Load(const std::string& url) mEndFrame = mTotalFrame - 1; - mFrameRate = mVectorRenderer.GetFrameRate(); - mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate; + mFrameRate = mVectorRenderer.GetFrameRate(); + mFrameDurationMicroSeconds = MICROSECONDS_PER_SECOND / mFrameRate; uint32_t width, height; mVectorRenderer.GetDefaultSize(width, height); @@ -372,7 +373,7 @@ VectorAnimationTask::UploadCompletedSignalType& VectorAnimationTask::UploadCompl bool VectorAnimationTask::Rasterize() { bool stopped = false; - uint32_t currentFrame; + uint32_t currentFrame, droppedFrames = 0; { ConditionalWait::ScopedLock lock(mConditionalWait); @@ -381,13 +382,14 @@ bool VectorAnimationTask::Rasterize() // The task will be destroyed. We don't need rasterization. return false; } + droppedFrames = mDroppedFrames; } ApplyAnimationData(); if(mPlayState == PlayState::PLAYING && mUpdateFrameNumber) { - mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; + mCurrentFrame = mForward ? mCurrentFrame + droppedFrames + 1 : mCurrentFrame - droppedFrames - 1; Dali::ClampInPlace(mCurrentFrame, mStartFrame, mEndFrame); } @@ -521,22 +523,39 @@ uint32_t VectorAnimationTask::GetStoppedFrame(uint32_t startFrame, uint32_t endF return frame; } -std::chrono::time_point VectorAnimationTask::CalculateNextFrameTime(bool renderNow) +VectorAnimationTask::TimePoint VectorAnimationTask::CalculateNextFrameTime(bool renderNow) { + uint32_t droppedFrames = 0; + // std::chrono::time_point template has second parameter duration which defaults to the std::chrono::system_clock supported // duration. In some C++11 implementations it is a milliseconds duration, so it fails to compile unless mNextFrameStartTime // is casted to use the default duration. - mNextFrameStartTime = std::chrono::time_point_cast::duration>( - mNextFrameStartTime + std::chrono::nanoseconds(mFrameDurationNanoSeconds)); - auto current = std::chrono::system_clock::now(); - if(renderNow || mNextFrameStartTime < current) + mNextFrameStartTime = std::chrono::time_point_cast(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)); + auto current = std::chrono::system_clock::now(); + if(renderNow) + { + mNextFrameStartTime = current; + } + else if(mNextFrameStartTime < current) { + while(current > std::chrono::time_point_cast(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds))) + { + droppedFrames++; + mNextFrameStartTime = std::chrono::time_point_cast(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)); + } + + { + ConditionalWait::ScopedLock lock(mConditionalWait); + mDroppedFrames = droppedFrames; + } + mNextFrameStartTime = current; } + return mNextFrameStartTime; } -std::chrono::time_point VectorAnimationTask::GetNextFrameTime() +VectorAnimationTask::TimePoint VectorAnimationTask::GetNextFrameTime() { return mNextFrameStartTime; } diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h index 03b8a89..c14cc10 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h @@ -47,6 +47,8 @@ class VectorAnimationTask : public RefObject public: using UploadCompletedSignalType = Dali::VectorAnimationRenderer::UploadCompletedSignalType; + using TimePoint = std::chrono::time_point; + /** * Flags for re-sending data to the vector animation thread */ @@ -195,13 +197,13 @@ public: * @brief Calculates the time for the next frame rasterization. * @return The time for the next frame rasterization. */ - std::chrono::time_point CalculateNextFrameTime(bool renderNow); + TimePoint CalculateNextFrameTime(bool renderNow); /** * @brief Gets the time for the next frame rasterization. * @return The time for the next frame rasterization. */ - std::chrono::time_point GetNextFrameTime(); + TimePoint GetNextFrameTime(); private: /** @@ -284,32 +286,33 @@ private: PAUSED ///< The animation is paused }; - std::string mUrl; - VectorAnimationRenderer mVectorRenderer; - AnimationData mAnimationData[2]; - VectorAnimationThread& mVectorAnimationThread; - ConditionalWait mConditionalWait; - std::unique_ptr mAnimationFinishedTrigger; - PlayState mPlayState; - DevelImageVisual::StopBehavior::Type mStopBehavior; - DevelImageVisual::LoopingMode::Type mLoopingMode; - std::chrono::time_point mNextFrameStartTime; - int64_t mFrameDurationNanoSeconds; - float mFrameRate; - uint32_t mCurrentFrame; - uint32_t mTotalFrame; - uint32_t mStartFrame; - uint32_t mEndFrame; - uint32_t mWidth; - uint32_t mHeight; - uint32_t mAnimationDataIndex; - int32_t mLoopCount; - int32_t mCurrentLoop; - bool mForward; - bool mUpdateFrameNumber; - bool mNeedAnimationFinishedTrigger; - bool mAnimationDataUpdated; - bool mDestroyTask; + std::string mUrl; + VectorAnimationRenderer mVectorRenderer; + AnimationData mAnimationData[2]; + VectorAnimationThread& mVectorAnimationThread; + ConditionalWait mConditionalWait; + std::unique_ptr mAnimationFinishedTrigger; + PlayState mPlayState; + DevelImageVisual::StopBehavior::Type mStopBehavior; + DevelImageVisual::LoopingMode::Type mLoopingMode; + TimePoint mNextFrameStartTime; + int64_t mFrameDurationMicroSeconds; + float mFrameRate; + uint32_t mCurrentFrame; + uint32_t mTotalFrame; + uint32_t mStartFrame; + uint32_t mEndFrame; + uint32_t mDroppedFrames; + uint32_t mWidth; + uint32_t mHeight; + uint32_t mAnimationDataIndex; + int32_t mLoopCount; + int32_t mCurrentLoop; + bool mForward; + bool mUpdateFrameNumber; + bool mNeedAnimationFinishedTrigger; + bool mAnimationDataUpdated; + bool mDestroyTask; }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 03e0657..1c5f5e7 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -626,6 +626,10 @@ void ImageVisual::InitializeRenderer() if(mTextures) { mImpl->mRenderer.SetTextures(mTextures); + if(DevelTexture::IsNative(mTextures.GetTexture(0))) + { + UpdateShader(); + } mTextures.Reset(); // Visual should not keep a handle to the texture after this point. } diff --git a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp index 767bfb0..273f08b 100644 --- a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp @@ -278,7 +278,7 @@ void SvgRasterizeThread::ApplyRasterizedSVGToSampler() UnregisterProcessor(); } -void SvgRasterizeThread::Process() +void SvgRasterizeThread::Process(bool postProcessor) { ApplyRasterizedSVGToSampler(); } diff --git a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h index b915b13..0204bef 100644 --- a/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h +++ b/dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h @@ -166,7 +166,7 @@ public: /** * @copydoc Dali::Integration::Processor::Process() */ - void Process() override; + void Process(bool postProcessor) override; private: /** diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index 19e08b2..870ac09 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -528,12 +528,12 @@ void TextVisual::UpdateRenderer() shadowEnabled = true; } - const bool underlineEnabled = mController->GetTextModel()->IsUnderlineEnabled(); - const bool outlineEnabled = (mController->GetTextModel()->GetOutlineWidth() > Math::MACHINE_EPSILON_1); - const bool backgroundEnabled = mController->GetTextModel()->IsBackgroundEnabled(); - ; + const bool underlineEnabled = mController->GetTextModel()->IsUnderlineEnabled(); + const bool outlineEnabled = (mController->GetTextModel()->GetOutlineWidth() > Math::MACHINE_EPSILON_1); + const bool backgroundEnabled = mController->GetTextModel()->IsBackgroundEnabled(); + const bool markupProcessorEnabled = mController->IsMarkupProcessorEnabled(); - const bool styleEnabled = (shadowEnabled || underlineEnabled || outlineEnabled || backgroundEnabled); + const bool styleEnabled = (shadowEnabled || underlineEnabled || outlineEnabled || backgroundEnabled || markupProcessorEnabled); AddRenderer(control, relayoutSize, hasMultipleTextColors, containsColorGlyph, styleEnabled); diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.cpp b/dali-toolkit/internal/visuals/visual-factory-impl.cpp index 8c4b2f8..6bbc2df 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-impl.cpp @@ -166,6 +166,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyM break; } case VisualUrl::JSON: + case VisualUrl::RIVE: { visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap); break; @@ -330,6 +331,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const std::string& url, ImageD break; } case VisualUrl::JSON: + case VisualUrl::RIVE: { visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl); break; diff --git a/dali-toolkit/internal/visuals/visual-url.cpp b/dali-toolkit/internal/visuals/visual-url.cpp index e498313..97bc9b9 100644 --- a/dali-toolkit/internal/visuals/visual-url.cpp +++ b/dali-toolkit/internal/visuals/visual-url.cpp @@ -103,10 +103,12 @@ VisualUrl::Type ResolveType(const std::string& url) char GIF[4] = {'f', 'i', 'g', '.'}; char WEBP[5] = {'p', 'b', 'e', 'w', '.'}; char JSON[5] = {'n', 'o', 's', 'j', '.'}; + char RIVE[4] = {'v', 'i', 'r', '.'}; unsigned int svgScore = 0; unsigned int gifScore = 0; unsigned int webpScore = 0; unsigned int jsonScore = 0; + unsigned int riveScore = 0; int index = count; while(--index >= 0) { @@ -144,6 +146,14 @@ VisualUrl::Type ResolveType(const std::string& url) return VisualUrl::JSON; } } + if((offsetFromEnd < sizeof(RIVE)) && (currentChar == RIVE[offsetFromEnd])) + { + // early out if RIVE as can't be used in N patch for now + if(++riveScore == sizeof(RIVE)) + { + return VisualUrl::RIVE; + } + } switch(state) { case SUFFIX: diff --git a/dali-toolkit/internal/visuals/visual-url.h b/dali-toolkit/internal/visuals/visual-url.h index 8857184..827dfce 100644 --- a/dali-toolkit/internal/visuals/visual-url.h +++ b/dali-toolkit/internal/visuals/visual-url.h @@ -38,7 +38,8 @@ public: SVG, GIF, WEBP, - JSON + JSON, + RIVE }; enum ProtocolType diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index 2c90452..781b531 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -492,11 +492,8 @@ void Control::Initialize() if(type) { auto typeName = type.GetName(); - DevelControl::AppendAccessibilityAttribute(Self(), "t", typeName); + DevelControl::AppendAccessibilityAttribute(Self(), "class", typeName); } - - if(Accessibility::IsUp()) - mImpl->AccessibilityRegister(); } void Control::OnInitialize() @@ -593,20 +590,12 @@ void Control::OnSceneConnection(int depth) // The clipping renderer is only created if required. CreateClippingRenderer(*this); - // Request to be laid out when the control is connected to the Scene. - // Signal that a Relayout may be needed - if(Accessibility::IsUp()) - { - mImpl->AccessibilityRegister(); - } + mImpl->AccessibilityRegister(); } void Control::OnSceneDisconnection() { - if(Accessibility::IsUp()) - { - mImpl->AccessibilityDeregister(); - } + mImpl->AccessibilityDeregister(true); mImpl->OnSceneDisconnection(); } diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 6330360..c3e32cb 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -29,7 +29,7 @@ namespace Toolkit { const unsigned int TOOLKIT_MAJOR_VERSION = 2; const unsigned int TOOLKIT_MINOR_VERSION = 0; -const unsigned int TOOLKIT_MICRO_VERSION = 21; +const unsigned int TOOLKIT_MICRO_VERSION = 25; const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali-toolkit/shader-generator/shader-generator.cpp b/dali-toolkit/shader-generator/shader-generator.cpp new file mode 100644 index 0000000..d386fb3 --- /dev/null +++ b/dali-toolkit/shader-generator/shader-generator.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +namespace fs = filesystem; + +namespace +{ +/////////////////////////////////////////////////////////////////////////////////////////////////// +string PROGRAM_NAME; ///< We set the program name on this global early on for use in Usage. +string_view VERSION = "1.0.0"; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Supported extensions for the files in the input directory. +// clang-format off +constexpr string_view SHADER_EXTENSIONS[] = +{ + ".vert", + ".frag", + ".def" +}; +// clang-format on + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Function & variable to retrieve the size of the extension with the largest string size. +constexpr auto GetShaderExtensionMaxSize() +{ + auto maxSize = 0u; + for(const auto& extension : SHADER_EXTENSIONS) + { + if(extension.size() > maxSize) + { + maxSize = extension.size(); + } + } + return maxSize; +} +constexpr const int SHADER_MAX_EXTENSION_SIZE(GetShaderExtensionMaxSize()); + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Prints out the Usage to standard output. +void Usage() +{ + cout << "Usage: " << PROGRAM_NAME << " [OPTIONS] [IN_DIR] [OUT_DIR]" << endl; + cout << " IN_DIR: Input Directory which has all the shader files." << endl; + cout << " Supported extensions:"; + string extensions; + for(const auto& extension : SHADER_EXTENSIONS) + { + extensions = extensions + " \"" + string(extension) + "\","; + } + extensions.pop_back(); // Remove the last comma. + cout << extensions << "." << endl; + cout << " OUT_DIR: Directory where the generated shader source code will be outputted to." << endl; + cout << " This directory will be created if it does not exist." << endl; + cout << " Any existing files of the same name in the directory will be overwritten." << endl; + cout << " Options: " << endl; + cout << " -s|--skip Skips the generation of the built-in header and source files" << endl; + cout << " -v|--version Prints out the version" << endl; + cout << " -h|--help Help" << endl; + cout << " NOTE: The options can be placed after the IN_DIR & OUT_DIR as well" << endl; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Uses the filename to generate the shader variable name to use in source code. +/// @param[in] filename The filename of the shader (including the extension) +/// @return The shader variable name +string GetShaderVariableName(const string& filename) +{ + string shaderVariableName("SHADER_" + filename); + for_each( + shaderVariableName.begin(), + shaderVariableName.end(), + [](char& character) { + switch(character) + { + case '-': + case '.': + { + character = '_'; + break; + } + + default: + { + character = ::toupper(character); + break; + } + } + }); + return shaderVariableName; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Uses the ourDir & filename to generate the path of the output header file for the shader. +/// @param[in] outDir The directory where the readable shaders will be outputted to +/// @param[in] filename The filename of the shader (including the extension) +/// @return The path to the output file +fs::path GetShaderOutputFilePath(fs::path& outDir, const string& filename) +{ + string outFilename(filename); + replace(outFilename.end() - SHADER_MAX_EXTENSION_SIZE, outFilename.end(), '.', '-'); + outFilename = outDir.string() + "/" + outFilename + ".h"; + return outFilename; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Generates the header file from the input shader file. +/// @param[in] shaderFile The full path of the input shader file +/// @param[in] shaderVariableName The variable name to use for the string_view +/// @param[in] outFilePath The full path to the output file +void GenerateHeaderFile( + ifstream& shaderFile, + const string& shaderVariableName, + const fs::path& outFilePath) +{ + cout << " Generating \"" << shaderVariableName << "\" in " << outFilePath.filename(); + ofstream outFile(outFilePath); + if(outFile.is_open()) + { + outFile << "#pragma once" << endl + << endl; + outFile << "const std::string_view " << shaderVariableName << endl; + outFile << "{" << endl; + string line; + while(getline(shaderFile, line)) + { + outFile << "\"" << line << "\\n\"" << endl; + } + outFile << "};" << endl; + cout << " [OK]" << endl; + } + else + { + cout << " [FAIL]" << endl; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// If required, this accumulates data about all the shaders & generates the built-in cpp & header +class BuiltInFilesGenerator +{ +public: + /// Constructor + /// @param[in] outDir The path to the output directory + BuiltInFilesGenerator(const fs::path& outDir) + : mHeaderFilePath(outDir.string() + "/../" + string(HEADER_FILE_NAME)), + mSourceFilePath(outDir.string() + "/" + string(SOURCE_FILE_NAME)) + { + } + + /// Default destructor + ~BuiltInFilesGenerator() = default; + + /// Adds the variable and the header file name to the appropriate vectors. + /// @param[in] variableName The string_view variable name used + /// @param[in] headerFileName The name of the header used + void Add(string&& variableName, const std::string& headerFilename) + { + mVariableNames.emplace_back(variableName); + mHeaderFileNames.emplace_back(headerFilename); + } + + // Generates the built in files. + void Generate() + { + GenerateFile( + mVariableNames, + mHeaderFilePath, + "#pragma once\n\n#include \n\n", + "extern const std::string_view ", + ";"); + + GenerateFile( + mHeaderFileNames, + mSourceFilePath, + "#include \"../" + string(HEADER_FILE_NAME) + "\"\n\n", + "#include \"", + "\""); + } + +private: + /// Generates the required file. + /// @param[in] strings A reference to the vector to parse + /// @param[in] filePath Outputs the data to this file + /// @param[in] header Puts this before parsing any of the vector + /// @param[in] before For each string, puts this string before it on every line + /// @param[in] after For each string, puts this string after it on every line + void GenerateFile( + vector& strings, + const string& filePath, + const string_view header, + const string_view before, + const string_view after) + { + sort(strings.begin(), strings.end()); + cout << " Generating \"" << filePath << "\""; + ofstream outFile(filePath); + if(outFile) + { + outFile << header; + for(auto& current : strings) + { + outFile << before << current << after << endl; + } + cout << " [OK]" << endl; + } + else + { + cout << " [FAIL]" << endl; + } + } + + constexpr static string_view HEADER_FILE_NAME = "builtin-shader-extern-gen.h"; + constexpr static string_view SOURCE_FILE_NAME = "builtin-shader-gen.cpp"; + + const string mHeaderFilePath; ///< Path to the header file to generate + const string mSourceFilePath; ///< Path to the source file to generate + vector mVariableNames; ///< Holds all the variable names added through Add + vector mHeaderFileNames; ///< Holds all the header file names added through Add +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Generates the header files from the shaders in the input directory & built-in files if reqruied. +/// +/// @param[in] inDir The directory where all the input shader source is +/// @param[in] outDir The directory where the readable shaders will be outputted to +/// @param[in] generateBuiltInFiles If true, we generate the built-in files as well +/// @return 0 if successful, 1 if failure +int GenerateShaderSources(fs::path inDir, fs::path outDir, const bool generateBuiltInFiles) +{ + if(!fs::is_directory(inDir)) + { + cerr << "ERROR: " << inDir << " is not a valid directory" << endl; + Usage(); + return 1; + } + + try + { + fs::create_directories(outDir); + } + catch(...) + { + cerr << "ERROR: Unable to create directory " << outDir << endl; + return 1; + } + + cout << "====================================================================" << endl; + cout << "Shader Input Directory: " << inDir << endl; + cout << "Shader Output Directory: " << outDir << endl; + cout << "====================================================================" << endl; + + BuiltInFilesGenerator generator(outDir); + + for(auto& file : fs::directory_iterator(inDir)) + { + if(file.is_regular_file()) + { + for(const auto& extension : SHADER_EXTENSIONS) + { + if(file.path().extension() == extension) + { + const fs::path& path(file.path()); + const string filename(path.filename().string()); + string shaderVariableName(GetShaderVariableName(filename)); + ifstream shaderFile(path); + if(shaderFile.is_open()) + { + fs::path outFilePath(GetShaderOutputFilePath(outDir, filename)); + GenerateHeaderFile(shaderFile, shaderVariableName, outFilePath); + generator.Add(std::move(shaderVariableName), outFilePath.filename().string()); + } + break; + } + } + } + } + + if(generateBuiltInFiles) + { + generator.Generate(); + } + + cout << "====================================================================" << endl; + return 0; +} + +} // unnamed namespace + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// MAIN. +int main(int argc, char* argv[]) +{ + PROGRAM_NAME = argv[0]; + + bool generateBuiltInFiles = true; + + string inDir; + string outDir; + + for(auto i = 1; i < argc; ++i) + { + string option(argv[i]); + if(option == "--skip" || option == "-s") + { + generateBuiltInFiles = false; + } + else if(option == "--help" || option == "-h") + { + cout << "DALi Shader Generator v" << VERSION << endl + << endl; + Usage(); + return 0; + } + else if(option == "--version" || option == "-v") + { + cout << VERSION << endl; + return 0; + } + else if(*option.begin() == '-') + { + cerr << "ERROR: " << option << " is not a supported option" << endl; + Usage(); + return 1; + } + else if(inDir.empty()) + { + inDir = option; + } + else if(outDir.empty()) + { + outDir = option; + } + else if(inDir.size() && outDir.size()) + { + cerr << "ERROR: Too many options" << endl; + Usage(); + return 1; + } + } + + if(inDir.empty() || outDir.empty()) + { + cerr << "ERROR: Both IN_DIR & OUT_DIR not provided" << endl; + Usage(); + return 1; + } + + return GenerateShaderSources(inDir, outDir, generateBuiltInFiles); +} diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 6746d55..94d8e11 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali2-toolkit Summary: Dali 3D engine Toolkit -Version: 2.0.21 +Version: 2.0.25 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT @@ -379,6 +379,7 @@ esac %defattr(-,root,root,-) %{dev_include_path}/dali-toolkit/* %{_libdir}/pkgconfig/dali2-toolkit.pc +%{_bindir}/dali-shader-generator %files resources_360x360 %manifest dali-toolkit-resources.manifest