Merge "Added pixel format to fix bug with ktx loader" into devel/graphics
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 14 May 2021 16:42:33 +0000 (16:42 +0000)
committerGerrit Code Review <gerrit@review>
Fri, 14 May 2021 16:42:33 +0000 (16:42 +0000)
110 files changed:
automated-tests/.gitignore
automated-tests/resources/shape.riv [new file with mode: 0644]
automated-tests/src/dali-scene-loader/CMakeLists.txt
automated-tests/src/dali-scene-loader/utc-Dali-MeshDefinition.cpp [new file with mode: 0644]
automated-tests/src/dali-shader-generator/CMakeLists.txt [new file with mode: 0644]
automated-tests/src/dali-shader-generator/shader/fragment-shader.frag [new file with mode: 0644]
automated-tests/src/dali-shader-generator/shader/shader-define.def [new file with mode: 0644]
automated-tests/src/dali-shader-generator/shader/vertex-shader.vert [new file with mode: 0644]
automated-tests/src/dali-shader-generator/tct-dali-shader-generator-core.cpp [new file with mode: 0644]
automated-tests/src/dali-shader-generator/utc-Dali-ShaderGenerator.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Hyphen-Wrapping.cpp [new file with mode: 0755]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp [new file with mode: 0755]
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp
automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
automated-tests/src/dali-toolkit/utc-Dali-VideoView.cpp
automated-tests/src/dali-toolkit/utc-Dali-WebView.cpp
build/tizen/.gitignore
build/tizen/CMakeLists.txt
build/tizen/dali-scene-loader/CMakeLists.txt
build/tizen/shader-generator.sh [deleted file]
dali-scene-loader/public-api/mesh-definition.cpp
dali-toolkit/devel-api/controls/web-view/web-context.cpp [changed mode: 0644->0755]
dali-toolkit/devel-api/controls/web-view/web-context.h
dali-toolkit/devel-api/controls/web-view/web-cookie-manager.cpp [changed mode: 0644->0755]
dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h
dali-toolkit/devel-api/controls/web-view/web-view.cpp
dali-toolkit/devel-api/controls/web-view/web-view.h
dali-toolkit/devel-api/text/text-enumerations-devel.h
dali-toolkit/devel-api/text/text-utils-devel.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/video-view/video-view-impl.cpp
dali-toolkit/internal/controls/web-view/web-view-impl.cpp [changed mode: 0644->0755]
dali-toolkit/internal/controls/web-view/web-view-impl.h
dali-toolkit/internal/file.list
dali-toolkit/internal/graphics/shaders/glyphy-common-glsl-shader.def [new file with mode: 0644]
dali-toolkit/internal/graphics/shaders/glyphy-sdf-glsl-shader.def [new file with mode: 0644]
dali-toolkit/internal/graphics/shaders/glyphy-shader-extention-prefix.def [new file with mode: 0644]
dali-toolkit/internal/graphics/shaders/glyphy-shader-fragment-prefix.frag [new file with mode: 0644]
dali-toolkit/internal/graphics/shaders/glyphy-shader-main.frag [new file with mode: 0644]
dali-toolkit/internal/graphics/shaders/glyphy-shader-main.vert [new file with mode: 0644]
dali-toolkit/internal/text/hyphenator.cpp [new file with mode: 0644]
dali-toolkit/internal/text/hyphenator.h [new file with mode: 0644]
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/logical-model-impl.h
dali-toolkit/internal/text/markup-processor.cpp
dali-toolkit/internal/text/markup-processor.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/rendering/text-typesetter.h
dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h [deleted file]
dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h [deleted file]
dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.cpp
dali-toolkit/internal/text/rendering/view-model.cpp
dali-toolkit/internal/text/rendering/view-model.h
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller-relayouter.cpp
dali-toolkit/internal/text/text-controller-relayouter.h
dali-toolkit/internal/text/text-controller-text-updater.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-model-interface.h
dali-toolkit/internal/text/text-model.cpp
dali-toolkit/internal/text/text-model.h
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/text/underlined-character-run.h [new file with mode: 0644]
dali-toolkit/internal/text/visual-model-impl.cpp
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/svg/svg-rasterize-thread.cpp
dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-url.cpp
dali-toolkit/internal/visuals/visual-url.h
dali-toolkit/public-api/controls/control-impl.cpp
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/shader-generator/shader-generator.cpp [new file with mode: 0644]
packaging/dali-toolkit.spec

index b12e784..17d54d9 100644 (file)
@@ -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 (file)
index 0000000..2450a94
Binary files /dev/null and b/automated-tests/resources/shape.riv differ
index 108a3c4..7ac6035 100755 (executable)
@@ -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 (file)
index 0000000..37c170b
--- /dev/null
@@ -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 <vector>
+
+#include "dali-scene-loader/public-api/mesh-definition.h"
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+using namespace Dali::SceneLoader;
+
+int UtcDaliMeshDefinitionBlobApplyMinMaxBothMinMaxApplied(void)
+{
+  using Container = std::vector<float>;
+
+  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<float>;
+
+  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<float>;
+
+  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<float>;
+
+  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 (file)
index 0000000..4ef7ac6
--- /dev/null
@@ -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 (file)
index 0000000..d9b3d5a
--- /dev/null
@@ -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 (file)
index 0000000..c6e148b
--- /dev/null
@@ -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 (file)
index 0000000..e5cbaa7
--- /dev/null
@@ -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 (file)
index 0000000..539d80c
--- /dev/null
@@ -0,0 +1,7 @@
+#include <test-harness.h>
+#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 (file)
index 0000000..68fc2ab
--- /dev/null
@@ -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 <dali-toolkit-test-suite-utils.h>
+
+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;
+}
index e90e147..b914f96 100755 (executable)
@@ -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)
index d98f397..0a426b0 100755 (executable)
@@ -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 <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
 #include <dali-toolkit/internal/text/markup-processor.h>
+#include <dali-toolkit/internal/text/hyphenator.h>
 
 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<bool> 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,
index eb0dd40..6e30bbb 100644 (file)
@@ -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.
index c68e84f..fdd8f10 100644 (file)
@@ -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;
index bd8f3a4..f3d97a9 100644 (file)
@@ -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;
index e056f73..de772f3 100644 (file)
@@ -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;
index 7cbbe90..8515172 100755 (executable)
@@ -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;
index 2ab84e7..78d7cf8 100755 (executable)
@@ -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 (executable)
index 0000000..ccc8463
--- /dev/null
@@ -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 <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <dali-toolkit/internal/text/layouts/layout-engine.h>
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <toolkit-text-utils.h>
+
+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<FontDescriptionRun> 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<LineRun>& 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<FontDescriptionRun> 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<LineRun> 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<FontDescriptionRun> 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<LineRun> 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
index 05226d4..8bdecaa 100755 (executable)
@@ -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;
index 6e2d632..f46c401 100755 (executable)
@@ -185,7 +185,8 @@ namespace
     Vector<FontDescriptionRun> fontRuns;
     Vector<EmbeddedItem> items;
     Vector<Anchor> anchors;
-    MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors );
+    Vector<UnderlinedCharacterRun> underlinedCharacterRuns;
+    MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors, underlinedCharacterRuns );
     ProcessMarkupString( data.xHTMLEntityString, markupProcessData );
 
     for( Vector<EmbeddedItem>::Iterator it = items.Begin(),
index a7534f9..52c8808 100755 (executable)
@@ -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;
index 9445be6..b19d653 100755 (executable)
@@ -21,6 +21,7 @@
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 
+#include <dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h>
 #include <dali-toolkit/internal/controls/text-controls/text-editor-impl.h>
 #include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
@@ -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, "<u>ABC</u>EF<u>GH</u>" );
+  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<GlyphRun> 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
index 37d54e1..619e5f4 100755 (executable)
@@ -21,6 +21,7 @@
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 
+#include <dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h>
 #include <dali-toolkit/internal/controls/text-controls/text-field-impl.h>
 #include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
@@ -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, "<u>ABC</u>EF<u>GH</u>" );
+  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<GlyphRun> 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 (executable)
index 0000000..e85ea21
--- /dev/null
@@ -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 <iostream>
+#include <stdlib.h>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+#include <dali-toolkit/internal/controls/text-controls/text-label-impl.h>
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/text-controller-impl.h>
+
+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, "<u>ABC</u>EF<u>GH</u>" );
+  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<GlyphRun> 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
index df247e0..43157ff 100644 (file)
@@ -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;
index c3616b2..4970dc4 100644 (file)
@@ -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 );
 
index 1fe86c3..8f3095f 100644 (file)
@@ -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
index 18ce2ef..474706f 100755 (executable)
@@ -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 <toolkit-vector-animation-renderer.h>
 #include <toolkit-event-thread-callback.h>
 #include <memory>
+#include <thread>
+#include <chrono>
 
 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<int32_t>(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
 
index 2213465..a1ea51b 100755 (executable)
@@ -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
index 430615d..b30d3b6 100755 (executable)
@@ -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<std::string>& schemes) override
+  {
+  }
+
+  void RegisterJsPluginMimeTypes(const std::vector<std::string>& 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<std::string>& 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<Dali::WebEngineConsoleMessage> message(new MockWebEngineConsoleMessage());
     gInstance->mConsoleMessageSignal.Emit(std::move(message));
     std::shared_ptr<Dali::WebEnginePolicyDecision> policyDecision(new MockWebEnginePolicyDecision());
-    gInstance->mPolicyDecisionSignal.Emit(std::move(policyDecision));
+    gInstance->mResponsePolicyDecisionSignal.Emit(std::move(policyDecision));
 
     std::shared_ptr<Dali::WebEngineCertificate> 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()
index dfd0b72..83c6a09 100644 (file)
@@ -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<DummyControlImpl&>(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
index e9bd76e..fdf1697 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/public-api/image-loader/image.h>
 #include <dali-toolkit/dali-toolkit.h>
 #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<DummyControlImpl&>(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<std::string>();
+
+  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;
index 12d8805..626432e 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali-toolkit/dali-toolkit.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h>
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 
 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<int>( 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<int>( 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<int>( 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<int>( 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<int>( 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<int>( 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<int>( 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<int>( 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<uint32_t>(naturalSize.width), TEST_LOCATION );
+  DALI_TEST_GREATER( lessThanHeight, static_cast<uint32_t>(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<uint32_t>(naturalSize.width), TEST_LOCATION );
+    DALI_TEST_GREATER( lessThanHeight, static_cast<uint32_t>(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<int>( 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<int>( 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
index aa25cf2..c615774 100644 (file)
@@ -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<std::string>(), "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<uint32_t>(naturalSize.width), TEST_LOCATION );
+  DALI_TEST_GREATER( lessThanHeight, static_cast<uint32_t>(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<uint32_t>(naturalSize.width), TEST_LOCATION );
+    DALI_TEST_GREATER( lessThanHeight, static_cast<uint32_t>(naturalSize.height), TEST_LOCATION );
+
+  }
+
+  END_TEST;
+}
\ No newline at end of file
index ecefef7..ac7403b 100644 (file)
@@ -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<uint32_t>(naturalSize.width), TEST_LOCATION );
+  DALI_TEST_GREATER( lessThanHeight, static_cast<uint32_t>(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<int>( 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<int>( TextLabel::Property::LINE_COUNT );
+  /*
+    text will be :
+    Hi
+    Experi-
+    men
+  */
+  DALI_TEST_EQUALS( lineCount, 3, TEST_LOCATION );
+
+  END_TEST;
+}
index 9a77bba..de842bf 100644 (file)
@@ -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;
index 39ebd29..4fbe8c1 100755 (executable)
@@ -81,8 +81,8 @@ static int gRequestInterceptorCallbackCalled = 0;
 static std::shared_ptr<Dali::WebEngineRequestInterceptor> gRequestInterceptorInstance = nullptr;
 static int gConsoleMessageCallbackCalled = 0;
 static std::shared_ptr<Dali::WebEngineConsoleMessage> gConsoleMessageInstance = nullptr;
-static int gPolicyDecisionCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEnginePolicyDecision> gPolicyDecisionInstance = nullptr;
+static int gResponsePolicyDecidedCallbackCalled = 0;
+static std::shared_ptr<Dali::WebEnginePolicyDecision> gResponsePolicyDecisionInstance = nullptr;
 static int gCertificateConfirmCallbackCalled = 0;
 static std::shared_ptr<Dali::WebEngineCertificate> gCertificateConfirmInstance = nullptr;
 static int gSslCertificateChangedCallbackCalled = 0;
@@ -101,6 +101,7 @@ static std::shared_ptr<Dali::WebEngineContextMenu> gContextMenuInstance = nullpt
 static int gContextMenuItemSelectedCallbackCalled = 0;
 static std::shared_ptr<Dali::WebEngineContextMenuItem> 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<Dali::WebEnginePolicyDecision> decision)
+static void OnResponsePolicyDecided(WebView view, std::shared_ptr<Dali::WebEnginePolicyDecision> 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<std::string> 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)
index e59a17f..2d253c9 100644 (file)
@@ -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
index 8be2625..cd463b5 100644 (file)
@@ -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}"
index ae7fea2..8891e9d 100644 (file)
@@ -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 (executable)
index 7b6b2fc..0000000
+++ /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 <string_view>" >> $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
-
index 8317803..de37e30 100644 (file)
@@ -466,9 +466,9 @@ void MeshDefinition::Blob::ApplyMinMax(const std::vector<float>& 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<ClampFn>([](const float* min, const float* max, uint32_t i, float& value) {
                                                    value = std::min(std::max(min[i], value), max[i]);
-                                                 });
+                                                 }));
 
   if(!clampFn)
   {
old mode 100644 (file)
new mode 100755 (executable)
index 413f5ca..2a7090b
@@ -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<std::string>& schemes)
+{
+  mWebEngineContext.RegisterUrlSchemesAsCorsEnabled(schemes);
+}
+
+void WebContext::RegisterJsPluginMimeTypes(const std::vector<std::string>& 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<std::string>& 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
index cdf7f0e..531ec00 100755 (executable)
@@ -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<std::string>& 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<std::string>& 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<std::string>& 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;
 };
old mode 100644 (file)
new mode 100755 (executable)
index fba924a..61529a8
@@ -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
index adb133a..421db32 100755 (executable)
@@ -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;
 };
index d3c201a..5cac9f4 100755 (executable)
@@ -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()
index 4f9159d..b290bfd 100755 (executable)
@@ -234,9 +234,9 @@ public:
   using WebViewConsoleMessageSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineConsoleMessage>)>;
 
   /**
-   * @brief WebView signal type related with policy decision.
+   * @brief WebView signal type related with response policy decision.
    */
-  using WebViewPolicyDecisionSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEnginePolicyDecision>)>;
+  using WebViewResponsePolicyDecisionSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEnginePolicyDecision>)>;
 
   /**
    * @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.
index 0163cc6..a74af43 100644 (file)
@@ -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
 
index 1441dc4..a4dbce4 100644 (file)
@@ -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,
index 07c77d9..342784a 100644 (file)
@@ -120,7 +120,7 @@ void CanvasView::OnSizeSet(const Vector3& targetSize)
   mChanged = true;
 }
 
-void CanvasView::Process()
+void CanvasView::Process(bool postProcessor)
 {
   if(!mCanvasRenderer)
   {
index bc5c708..b2d5775 100644 (file)
@@ -82,7 +82,7 @@ protected: // Implementation of Processor
   /**
    * @copydoc Dali::Integration::Processor::Process()
    */
-  void Process() override;
+  void Process(bool postProcessor) override;
 
 private:
   /**
index 1c48bc1..9e69f95 100644 (file)
@@ -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;
   }
index 492461e..a3ab6c0 100644 (file)
@@ -544,7 +544,7 @@ public:
   Dali::Accessibility::Accessible*        GetAccessibilityObject();
 
   void AccessibilityRegister();
-  void AccessibilityDeregister();
+  void AccessibilityDeregister(bool remove);
 
   std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Actor)> accessibilityConstructor;
   std::unique_ptr<Dali::Accessibility::Accessible>                       accessibilityObject;
index 85b219e..509426e 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/rendering/texture-devel.h>
 #include <cstring>
 
 // 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);
old mode 100644 (file)
new mode 100755 (executable)
index 6a3af8d..3342374
@@ -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<Dali::WebEngineConsoleMessage> me
   }
 }
 
-void WebView::OnPolicyDecisionRequest(std::shared_ptr<Dali::WebEnginePolicyDecision> decision)
+void WebView::OnResponsePolicyDecided(std::shared_ptr<Dali::WebEnginePolicyDecision> 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))
index 4031ee6..a5cefa4 100755 (executable)
@@ -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<Dali::WebEngineConsoleMessage> 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<Dali::WebEnginePolicyDecision> decision);
+  void OnResponsePolicyDecided(std::shared_ptr<Dali::WebEnginePolicyDecision> 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<Dali::Toolkit::WebSettings>        mWebSettings;
   std::unique_ptr<Dali::Toolkit::WebBackForwardList> mWebBackForwardList;
 
-  Dali::Toolkit::ImageView mFaviconView;
-
   Dali::PropertyNotification mPositionUpdateNotification;
   Dali::PropertyNotification mSizeUpdateNotification;
   Dali::PropertyNotification mScaleUpdateNotification;
index ede26c1..395dfc8 100644 (file)
@@ -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 (file)
index 0000000..f044a16
--- /dev/null
@@ -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 (file)
index 0000000..2b5accd
--- /dev/null
@@ -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 (file)
index 0000000..3f7237d
--- /dev/null
@@ -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 (file)
index 0000000..4cb1423
--- /dev/null
@@ -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 (file)
index 0000000..4fc43da
--- /dev/null
@@ -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 (file)
index 0000000..9b0f342
--- /dev/null
@@ -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 (file)
index 0000000..66f99a3
--- /dev/null
@@ -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 <dali-toolkit/internal/text/hyphenator.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/hyphenation.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+
+#include <cstring> // for strcmp
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+const char* UTF8 = "UTF-8";
+
+Vector<bool> GetWordHyphens(const Character* word,
+                            Length           wordSize,
+                            const char*      lang)
+{
+  Vector<bool> 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 (file)
index 0000000..eef2246
--- /dev/null
@@ -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 <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/font-run.h>
+#include <dali-toolkit/internal/text/script-run.h>
+
+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<bool> GetWordHyphens(const Character* word,
+                            Length           wordSize,
+                            const char*      lang);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_HYPHENATOR_H
index fcf5f5e..25f83d1 100644 (file)
@@ -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<float>::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<float>::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<LineRun>& lines, const Vector<LineRun>::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<LineRun>& 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;
       }
index 12929fc..0de63d5 100644 (file)
@@ -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<UnderlinedCharacterRun> removedUnderlinedCharacterRuns;
+  UpdateCharacterRuns<UnderlinedCharacterRun>(index,
+                                numberOfCharacters,
+                                totalNumberOfCharacters,
+                                mUnderlinedCharacterRuns,
+                                removedUnderlinedCharacterRuns);
+
   // Process the background color runs.
   Vector<ColorRun> removedBackgroundColorRuns;
   UpdateCharacterRuns<ColorRun>(index,
index 921d911..80a1285 100644 (file)
@@ -33,6 +33,7 @@
 #include <dali-toolkit/internal/text/font-run.h>
 #include <dali-toolkit/internal/text/paragraph-run.h>
 #include <dali-toolkit/internal/text/script-run.h>
+#include <dali-toolkit/internal/text/underlined-character-run.h>
 
 namespace Dali
 {
@@ -219,6 +220,7 @@ public:
   Vector<BidirectionalLineInfoRun>      mBidirectionalLineInfo;
   Vector<EmbeddedItem>                  mEmbeddedItems;
   Vector<Anchor>                        mAnchors;
+  Vector<UnderlinedCharacterRun>        mUnderlinedCharacterRuns; ///< The underlined character run from markup-processor
 
   BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info.
 };
index a8a6ecc..ea7f869 100644 (file)
@@ -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
       } // <i></i>
       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.
-      } // <u></u>
+        ProcessTagForRun<UnderlinedCharacterRun>(
+          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {  });
+      }  // <u></u>
       else if(TokenComparison(XHTML_B_TAG, tag.buffer, tag.length))
       {
         ProcessTagForRun<FontDescriptionRun>(
@@ -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
index c75ca0c..ec45957 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/embedded-item.h>
 #include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/underlined-character-run.h>
 
 namespace Dali
 {
@@ -42,20 +43,23 @@ struct MarkupProcessData
   MarkupProcessData(Vector<ColorRun>&           colorRuns,
                     Vector<FontDescriptionRun>& fontRuns,
                     Vector<EmbeddedItem>&       items,
-                    Vector<Anchor>&             anchors)
+                    Vector<Anchor>&             anchors,
+                    Vector<UnderlinedCharacterRun>& underlinedCharacterRuns)
   : colorRuns(colorRuns),
     fontRuns(fontRuns),
     items(items),
     anchors(anchors),
+    underlinedCharacterRuns(underlinedCharacterRuns),
     markupProcessedText()
   {
   }
 
-  Vector<ColorRun>&           colorRuns;           ///< The color runs.
-  Vector<FontDescriptionRun>& fontRuns;            ///< The font description runs.
-  Vector<EmbeddedItem>&       items;               ///< The embedded items.
-  Vector<Anchor>&             anchors;             ///< The anchors.
-  std::string                 markupProcessedText; ///< The mark-up string.
+  Vector<ColorRun>&               colorRuns;               ///< The color runs.
+  Vector<FontDescriptionRun>&     fontRuns;                ///< The font description runs.
+  Vector<EmbeddedItem>&           items;                   ///< The embedded items.
+  Vector<Anchor>&                 anchors;                 ///< The anchors.
+  Vector<UnderlinedCharacterRun>& underlinedCharacterRuns; ///< The underlined character runs.
+  std::string                     markupProcessedText;     ///< The mark-up string.
 };
 
 /**
index 208460c..1023dc4 100644 (file)
@@ -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<MeshRecord>& meshContainer,
                     Vector<TextCacheEntry>&  newTextCache,
-                    Vector<Extent>&          extents)
+                    Vector<Extent>&          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<MeshRecord>& meshContainer,
@@ -416,16 +419,19 @@ struct AtlasRenderer::Impl
     Vector<Extent>          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 <u>World</u> Hello <u>World</u>", "<u>World</u> Hello <u>World</u>", "<u>   World</u> Hello <u>World</u>"
+        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<Extent>::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);
     }
   }
index abf7325..83d67d5 100644 (file)
@@ -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<GlyphRun> 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<GlyphRun>::ConstIterator itGlyphRun    = underlineRuns.Begin();
+    Vector<GlyphRun>::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))
 {
index 2f29a47..c9cd4cc 100644 (file)
@@ -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 "<color value='green'>Hello</color> <u>World</u> <i>Hello</i> <b>World</b>".
+   *    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 (file)
index 48a8335..0000000
+++ /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 (file)
index 37b1b13..0000000
+++ /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";
index 4be2524..6ff571a 100644 (file)
 #include <sstream>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h>
-#include <dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 
 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(),
index e7b40a5..f695cd2 100644 (file)
@@ -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;
index a84810a..9272956 100644 (file)
@@ -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
index ec00903..417eaed 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/color-segmentation.h>
 #include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/internal/text/hyphenator.h>
 #include <dali-toolkit/internal/text/multi-language-support.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
@@ -37,6 +38,8 @@
 #include <dali-toolkit/internal/text/text-run-container.h>
 #include <dali-toolkit/internal/text/text-selection-handle-controller.h>
 
+#include <dali-toolkit/internal/text/text-enumerations-impl.h>
+
 using namespace Dali;
 
 namespace
@@ -587,7 +590,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
   Vector<Character>& srcCharacters = mModel->mLogicalModel->mText;
   Vector<Character>  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<bool> 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<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
+    const Vector<GlyphIndex>&             charactersToGlyph       = mModel->mVisualModel->mCharactersToGlyph;
+    const Vector<Length>&                 glyphsPerCharacter      = mModel->mVisualModel->mGlyphsPerCharacter;
+
+    if(shouldClearPreUnderlineRuns)
+    {
+        mModel->mVisualModel->mUnderlineRuns.Clear();
+    }
+
+    for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
+    {
+        CharacterIndex characterIndex = it->characterRun.characterIndex;
+        Length numberOfCharacters = it->characterRun.numberOfCharacters;
+        for(Length index=0u; index<numberOfCharacters; index++)
+        {
+          GlyphRun underlineGlyphRun;
+          underlineGlyphRun.glyphIndex     = charactersToGlyph[characterIndex + index];
+          underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index];
+          mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
+        }
+    }
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index ef4bb69..9f637d3 100644 (file)
@@ -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.
index 227d889..78e7331 100644 (file)
@@ -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<OperationsMask>(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<LineRun> linesBackup = visualModel->mLines;
+  Vector<Vector2> glyphPositionsBackup = visualModel->mGlyphPositions;
+
+  // Operations that can be done only once until the text changes.
+  const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(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<OperationsMask>(operationsPending | requestedOperationsMask);
+
+  // Store the actual control's size to restore later.
+  const Size actualControlSize = visualModel->mControlSize;
+
+  DoRelayout(controller,
+              requestedControllerSize,
+              static_cast<OperationsMask>(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<OperationsMask>(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<OperationsMask>(impl.mOperationsPending);
-    // Operations that can be done only once until the text changes.
-    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(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<OperationsMask>(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<OperationsMask>(LAYOUT | REORDER);
+    Size sizeMaxWidthAndMaxHeight = Size(MAX_FLOAT, MAX_FLOAT);
 
-    DoRelayout(controller,
-               Size(MAX_FLOAT, MAX_FLOAT),
-               static_cast<OperationsMask>(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<OperationsMask>(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<OperationsMask>(impl.mOperationsPending);
-    // Operations that can be done only once until the text changes.
-    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(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<OperationsMask>(operationsPending | LAYOUT);
+    OperationsMask requestedOperationsMask = static_cast<OperationsMask>(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<OperationsMask>(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<OperationsMask>(operationsPendingBackUp & ~onlyOnceOperations);
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height);
   }
   else
index d2d8670..1b586b2 100644 (file)
@@ -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
index 69e05bf..36a2133 100644 (file)
@@ -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.
index 15db50b..6866ff4 100644 (file)
@@ -25,6 +25,7 @@
 #include <limits>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 #include <dali-toolkit/internal/text/text-controller-event-handler.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
 #include <dali-toolkit/internal/text/text-controller-input-font-handler.h>
@@ -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<OperationsMask>(mImpl->mOperationsPending |
+    mImpl->mOperationsPending = static_cast<OperationsMask>(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<OperationsMask>(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();
index aafd430..c116f8f 100644 (file)
@@ -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
index 2d60854..948044e 100644 (file)
@@ -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(),
index d52809c..4faa1bc 100644 (file)
@@ -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.
index 1a04135..63f7fd4 100644 (file)
@@ -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
index 83ad28f..2f74699 100644 (file)
@@ -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)
index cc82820..3790fd0 100644 (file)
@@ -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 (file)
index 0000000..99d5967
--- /dev/null
@@ -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 <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/glyph-run.h>
+
+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
index eda5633..7edb428 100644 (file)
@@ -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)
 {
 }
 
index 371b666..c355c3c 100644 (file)
@@ -35,6 +35,13 @@ namespace Toolkit
 {
 namespace Text
 {
+struct HyphenInfo
+{
+  Vector<GlyphInfo> glyph;
+  Vector<Vector2>   position;
+  Vector<Length>    index;
+};
+
 class VisualModel;
 typedef IntrusivePtr<VisualModel> 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
index 2286ea0..f23439d 100644 (file)
@@ -120,7 +120,7 @@ void VectorAnimationManager::UnregisterEventCallback(CallbackBase* callback)
   }
 }
 
-void VectorAnimationManager::Process()
+void VectorAnimationManager::Process(bool postProcessor)
 {
   for(auto&& iter : mEventCallbacks)
   {
index c52b800..fe6b87a 100644 (file)
@@ -92,7 +92,7 @@ protected: // Implementation of Processor
   /**
    * @copydoc Dali::Integration::Processor::Process()
    */
-  void Process() override;
+  void Process(bool postProcessor) override;
 
 private:
   // Undefined
index d9d6d5a..a1659bf 100644 (file)
@@ -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<std::chrono::system_clock> 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<std::chrono::time_point<std::chrono::system_clock>::duration>(
-    mNextFrameStartTime + std::chrono::nanoseconds(mFrameDurationNanoSeconds));
-  auto current = std::chrono::system_clock::now();
-  if(renderNow || mNextFrameStartTime < current)
+  mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(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<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)))
+    {
+      droppedFrames++;
+      mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds));
+    }
+
+    {
+      ConditionalWait::ScopedLock lock(mConditionalWait);
+      mDroppedFrames = droppedFrames;
+    }
+
     mNextFrameStartTime = current;
   }
+
   return mNextFrameStartTime;
 }
 
-std::chrono::time_point<std::chrono::system_clock> VectorAnimationTask::GetNextFrameTime()
+VectorAnimationTask::TimePoint VectorAnimationTask::GetNextFrameTime()
 {
   return mNextFrameStartTime;
 }
index 03b8a89..c14cc10 100644 (file)
@@ -47,6 +47,8 @@ class VectorAnimationTask : public RefObject
 public:
   using UploadCompletedSignalType = Dali::VectorAnimationRenderer::UploadCompletedSignalType;
 
+  using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
+
   /**
    * 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<std::chrono::system_clock> 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<std::chrono::system_clock> 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<EventThreadCallback>               mAnimationFinishedTrigger;
-  PlayState                                          mPlayState;
-  DevelImageVisual::StopBehavior::Type               mStopBehavior;
-  DevelImageVisual::LoopingMode::Type                mLoopingMode;
-  std::chrono::time_point<std::chrono::system_clock> 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<EventThreadCallback> 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
index 03e0657..1c5f5e7 100644 (file)
@@ -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.
   }
 
index 767bfb0..273f08b 100644 (file)
@@ -278,7 +278,7 @@ void SvgRasterizeThread::ApplyRasterizedSVGToSampler()
   UnregisterProcessor();
 }
 
-void SvgRasterizeThread::Process()
+void SvgRasterizeThread::Process(bool postProcessor)
 {
   ApplyRasterizedSVGToSampler();
 }
index b915b13..0204bef 100644 (file)
@@ -166,7 +166,7 @@ public:
   /**
    * @copydoc Dali::Integration::Processor::Process()
    */
-  void Process() override;
+  void Process(bool postProcessor) override;
 
 private:
   /**
index 19e08b2..870ac09 100644 (file)
@@ -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);
 
index 8c4b2f8..6bbc2df 100644 (file)
@@ -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;
index e498313..97bc9b9 100644 (file)
@@ -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:
index 8857184..827dfce 100644 (file)
@@ -38,7 +38,8 @@ public:
     SVG,
     GIF,
     WEBP,
-    JSON
+    JSON,
+    RIVE
   };
 
   enum ProtocolType
index 2c90452..781b531 100644 (file)
@@ -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();
 }
 
index 6330360..c3e32cb 100644 (file)
@@ -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 (file)
index 0000000..d386fb3
--- /dev/null
@@ -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 <algorithm>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <string_view>
+#include <vector>
+
+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 <string_view>\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<string>&   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<string> mVariableNames;   ///< Holds all the variable names added through Add
+  vector<string> 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);
+}
index 6746d55..94d8e11 100644 (file)
@@ -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