build
build.log
tct*core.h
-CMakeLists.txt
+/CMakeLists.txt
results_xml.*
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
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+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)
+
--- /dev/null
+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;
+}
--- /dev/null
+#version 300 es
+precision highp float;
--- /dev/null
+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*/
+}
--- /dev/null
+#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);
+}
--- /dev/null
+/*
+ * 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;
+}
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)
/*
- * 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.
#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
{
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;
MarkupProcessData markupProcessData( logicalModel->mColorRuns,
logicalModel->mFontDescriptionRuns,
logicalModel->mEmbeddedItems,
- logicalModel->mAnchors );
+ logicalModel->mAnchors,
+ logicalModel->mUnderlinedCharacterRuns);
Length textSize = 0u;
const uint8_t* utf8 = NULL;
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();
// Set the layout parameters.
textModel->mHorizontalAlignment = Text::HorizontalAlignment::BEGIN;
- textModel->mLineWrapMode = LineWrap::WORD;
textModel->mIgnoreSpacesAfterText = true;
textModel->mMatchSystemLanguageDirection = false;
Layout::Parameters layoutParameters( textArea,
#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.
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.
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;
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 );
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;
/*
- * 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.
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- data.markupProcessorEnabled );
+ data.markupProcessorEnabled,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
/*
- * 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.
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
/*
- * 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.
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
--- /dev/null
+/*
+ * 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
/*
- * 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.
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
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(),
/*
- * 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.
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
#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>
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
#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>
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
--- /dev/null
+/*
+ * 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
/*
- * 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.
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
layoutSize,
textModel,
metrics,
- false );
+ false,
+ LineWrap::WORD );
LogicalModelPtr logicalModel = textModel->mLogicalModel;
VisualModelPtr visualModel = textModel->mVisualModel;
#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.
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 );
/*
- * 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.
}
}
-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 )
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
/*
- * 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.
#include <toolkit-vector-animation-renderer.h>
#include <toolkit-event-thread-callback.h>
#include <memory>
+#include <thread>
+#include <chrono>
namespace Dali
{
namespace Adaptor
{
+namespace
+{
+Dali::Internal::Adaptor::VectorAnimationRenderer* gVectorAnimationRenderer = nullptr;
+}
+
class VectorAnimationRenderer: public Dali::BaseObject
{
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++;
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;
}
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();
uint32_t GetTotalFrameNumber() const
{
- return VECTOR_ANIMATION_TOTAL_FRAME_NUMBER;
+ return mTotalFrameNumber;
}
float GetFrameRate() const
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;
};
{
Internal::Adaptor::VectorAnimationRenderer* animationRenderer = new Internal::Adaptor::VectorAnimationRenderer();
+ Internal::Adaptor::gVectorAnimationRenderer = animationRenderer;
+
return VectorAnimationRenderer( animationRenderer );
}
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
#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.
#define VECTOR_ANIMATION_MARKER_END_FRAME_2 3
void RequestTrigger();
+void DelayRendering(uint32_t delay);
+uint32_t GetDroppedFrames();
} // VectorAnimationRenderer
} // Test
bool OnFormPasswordAcquired();
bool OnDownloadStarted();
bool OnMimeOverridden();
+bool OnChangesWatch();
static void ConnectToGlobalSignal( bool ( *func )() )
{
{
}
- bool DeleteWebStorageOrigin(Dali::WebEngineSecurityOrigin& origin)
+ bool DeleteWebStorage(Dali::WebEngineSecurityOrigin& origin)
{
return true;
}
{
}
- void DisableCache( bool cacheDisabled ) override
- {
- }
-
void ClearCache() override
{
}
}
}
+ 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;
{
}
+ void ChangesWatch( Dali::WebEngineCookieManager::WebEngineCookieManagerChangesWatchCallback callback ) override
+ {
+ if ( callback )
+ {
+ ConnectToGlobalSignal( &OnChangesWatch );
+ mChangesWatchCallback = callback;
+ }
+ }
+
+public:
+ Dali::WebEngineCookieManager::WebEngineCookieManagerChangesWatchCallback mChangesWatchCallback;
+
private:
Dali::WebEngineCookieManager::CookieAcceptPolicy mockCookieAcceptPolicy;
};
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:
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
return mConsoleMessageSignal;
}
- Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& PolicyDecisionSignal()
+ Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal()
{
- return mPolicyDecisionSignal;
+ return mResponsePolicyDecisionSignal;
}
Dali::WebEnginePlugin::WebEngineCertificateSignalType& CertificateConfirmSignal()
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;
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));
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 )
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()
/*
- * 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.
{
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 )
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
#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"
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;
#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;
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
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
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;
+}
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;
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;
static int gContextMenuItemSelectedCallbackCalled = 0;
static std::shared_ptr<Dali::WebEngineContextMenuItem> gContextMenuItemInstance = nullptr;
static int gHitTestCreatedCallbackCalled = 0;
+static int gCookieManagerChangsWatchCallbackCalled = 0;
struct CallbackFunctor
{
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 )
return true;
}
+static void OnChangesWatch()
+{
+ gCookieManagerChangsWatchCallbackCalled++;
+}
+
static bool OnHovered( Actor actor, const Dali::HoverEvent& hover )
{
gHovered = true;
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;
}
END_TEST;
}
-int UtcDaliWebViewPolicyDecisionRequest(void)
+int UtcDaliWebViewResponsePolicyDecisionRequest(void)
{
ToolkitTestApplication application;
// 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;
}
// 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();
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;
}
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);
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)
dali.info
*.dylib
dali2-*-config.cmake
-libdali2-scene-loader.so*
\ No newline at end of file
+libdali2-scene-loader.so*
+dali-shader-generator
# 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}"
add_definitions("-DDEBUG_ENABLED")
endif()
+ADD_DEFINITIONS( "-DBUILDING_DALI_SCENE_LOADER" )
+
foreach(flag ${PKGS_CFLAGS})
set(extra_flags "${extra_flags} ${flag}")
endforeach(flag)
${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}
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
+++ /dev/null
-#!/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
-
: (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)
{
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);
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()
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
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
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.
*/
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;
};
mWebEngineCookieManager.SetPersistentStorage(path, storage);
}
+void WebCookieManager::ChangesWatch(Dali::WebEngineCookieManager::WebEngineCookieManagerChangesWatchCallback callback)
+{
+ mWebEngineCookieManager.ChangesWatch(callback);
+}
+
} // namespace Toolkit
} // namespace Dali
*/
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;
};
return Dali::Toolkit::GetImpl(*this).GetBackForwardList();
}
-Dali::Toolkit::ImageView& WebView::GetFavicon()
+Dali::Toolkit::ImageView WebView::GetFavicon() const
{
return Dali::Toolkit::GetImpl(*this).GetFavicon();
}
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()
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.
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.
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.
#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.
};
} // 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
MarkupProcessData markupProcessData(colorRuns,
fontDescriptionRuns,
textModel->mLogicalModel->mEmbeddedItems,
- textModel->mLogicalModel->mAnchors);
+ textModel->mLogicalModel->mAnchors,
+ textModel->mLogicalModel->mUnderlinedCharacterRuns);
if(textParameters.markupEnabled)
{
// 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,
mChanged = true;
}
-void CanvasView::Process()
+void CanvasView::Process(bool postProcessor)
{
if(!mCanvasRenderer)
{
/**
* @copydoc Dali::Integration::Processor::Process()
*/
- void Process() override;
+ void Process(bool postProcessor) override;
private:
/**
StopObservingVisual(iter->visual);
}
- AccessibilityDeregister();
// All gesture detectors will be destroyed so no need to disconnect.
delete mStartingPinchScale;
{
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())
{
}
}
-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;
}
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;
#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
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;
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);
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 )
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);
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)
}
}
-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()));
return mConsoleMessageSignal;
}
-Dali::Toolkit::WebView::WebViewPolicyDecisionSignalType& WebView::PolicyDecisionSignal()
+Dali::Toolkit::WebView::WebViewResponsePolicyDecisionSignalType& WebView::ResponsePolicyDecisionSignal()
{
- return mPolicyDecisionSignal;
+ return mResponsePolicyDecisionSignal;
}
Dali::Toolkit::WebView::WebViewCertificateSignalType& WebView::CertificateConfirmSignal()
}
}
-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));
}
}
}
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))
/**
* @copydoc Dali::Toolkit::WebView::GetFavicon()
*/
- Dali::Toolkit::ImageView& GetFavicon();
+ Dali::Toolkit::ImageView GetFavicon() const;
/**
* @copydoc Dali::Toolkit::WebView::LoadUrl()
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()
* @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.
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.
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;
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;
${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
${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}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#extension GL_OES_standard_derivatives : enable
+precision highp float;
+precision highp int;
--- /dev/null
+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);
+}
--- /dev/null
+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;
+}
--- /dev/null
+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
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
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)
{
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;
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;)
(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");
(TextAbstraction::LINE_MUST_BREAK == lineBreakInfo))
{
LineLayout currentLineLayout = lineLayout;
-
+ oneHyphenLaidOut = false;
// Must break the line. Update the line layout and return.
MergeLineLayout(lineLayout, tmpLineLayout);
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.
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;
}
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)
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;
}
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,
#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
{
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.
};
}
/**
+ * @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.
}
/**
- * @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
* @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)
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();
} // <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>(
}
// Resize the model's vectors.
- ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex);
+ ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex);
}
} // namespace Text
#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
{
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.
};
/**
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
mRight(0.0f),
mUnderlinePosition(0.0f),
mUnderlineThickness(0.0f),
- mMeshRecordIndex(0u)
+ mMeshRecordIndex(0u),
+ mUnderlineChunkId(0u)
{
}
float mUnderlinePosition;
float mUnderlineThickness;
uint32_t mMeshRecordIndex;
+ uint32_t mUnderlineChunkId;
};
struct MaxBlockSize
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");
// 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;
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;
underlineGlyph,
currentUnderlinePosition,
currentUnderlineThickness,
- slot);
+ slot,
+ underlineChunkId);
}
void CreateActors(const std::vector<MeshRecord>& meshContainer,
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);
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)
}
lastUnderlinedFontId = glyph.fontId;
+
} // underline
AtlasGlyphManager::GlyphStyle style;
}
// 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
{
currentUnderlineThickness,
meshContainer,
newTextCache,
- extents);
+ extents,
+ underlineChunkId);
lastFontId = glyph.fontId; // Prevents searching for existing blocksizes when string of the same fontId.
}
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
bool underlineGlyph,
float underlinePosition,
float underlineThickness,
- AtlasManager::AtlasSlot& slot)
+ AtlasManager::AtlasSlot& slot,
+ uint32_t underlineChunkId)
{
if(slot.mImageId)
{
right,
baseLine,
underlinePosition,
- underlineThickness);
+ underlineThickness,
+ underlineChunkId);
}
return;
right,
baseLine,
underlinePosition,
- underlineThickness);
+ underlineThickness,
+ underlineChunkId);
}
}
}
float right,
float baseLine,
float underlinePosition,
- float underlineThickness)
+ float underlineThickness,
+ uint32_t underlineChunkId)
{
bool foundExtent = false;
for(Vector<Extent>::Iterator eIt = extents.Begin(),
eIt != eEndIt;
++eIt)
{
- if(Equals(baseLine, eIt->mBaseLine))
+ if(Equals(baseLine, eIt->mBaseLine) && underlineChunkId == eIt->mUnderlineChunkId)
{
foundExtent = true;
if(left < eIt->mLeft)
extent.mUnderlinePosition = underlinePosition;
extent.mUnderlineThickness = underlineThickness;
extent.mMeshRecordIndex = index;
+ extent.mUnderlineChunkId = underlineChunkId;
extents.PushBack(extent);
}
}
// 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
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);
}
// 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)
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);
}
// 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))
} // 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.
// Set the buffer of the glyph's bitmap into the final bitmap's buffer
TypesetGlyph(glyphData,
- position,
+ &position,
&color,
style,
pixelFormat);
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
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))
{
*/
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().
+++ /dev/null
-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";
+++ /dev/null
-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";
#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
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(),
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;
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
#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>
#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
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;
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);
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;
}
}
// 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;
updated = true;
}
- if((NULL != mEventData) &&
+ if((nullptr != mEventData) &&
mEventData->mPreEditFlag &&
(0u != mModel->mVisualModel->mCharactersToGlyph.Count()))
{
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:
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:
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:
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:
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:
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());
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);
void Controller::Impl::ChangeState(EventData::State newState)
{
- if(NULL == mEventData)
+ if(nullptr == mEventData)
{
// Nothing to do if there is no text input.
return;
CharacterIndex Controller::Impl::CalculateNewCursorIndex(CharacterIndex index) const
{
- if(NULL == mEventData)
+ if(nullptr == mEventData)
{
// Nothing to do if there is no text input.
return 0u;
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");
void Controller::Impl::RequestRelayout()
{
- if(NULL != mControlInterface)
+ if(nullptr != mControlInterface)
{
mControlInterface->RequestTextRelayout();
}
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
// 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.
{
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)
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();
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
* @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
MarkupProcessData markupProcessData(logicalModel->mColorRuns,
logicalModel->mFontDescriptionRuns,
logicalModel->mEmbeddedItems,
- logicalModel->mAnchors);
+ logicalModel->mAnchors,
+ logicalModel->mUnderlinedCharacterRuns);
Length textSize = 0u;
const uint8_t* utf8 = NULL;
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.
#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>
GetText(text);
SetText(text);
}
+
+ mImpl->mModel->mVisualModel->SetMarkupProcessorEnabled(enable);
}
bool Controller::IsMarkupProcessorEnabled() const
{
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();
* @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
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(),
*/
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.
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
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)
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;
--- /dev/null
+#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
mBackgroundEnabled = enabled;
}
+void VisualModel::SetMarkupProcessorEnabled(bool enabled)
+{
+ mMarkupProcessorEnabled = enabled;
+}
+
const Vector4& VisualModel::GetTextColor() const
{
return mTextColor;
return mBackgroundEnabled;
}
+bool VisualModel::IsMarkupProcessorEnabled() const
+{
+ return mMarkupProcessorEnabled;
+}
+
Length VisualModel::GetNumberOfUnderlineRuns() const
{
return mUnderlineRuns.Count();
mCachedLineIndex(0u),
mUnderlineEnabled(false),
mUnderlineColorSet(false),
- mBackgroundEnabled(false)
+ mBackgroundEnabled(false),
+ mMarkupProcessorEnabled(false)
{
}
{
namespace Text
{
+struct HyphenInfo
+{
+ Vector<GlyphInfo> glyph;
+ Vector<Vector2> position;
+ Vector<Length> index;
+};
+
class VisualModel;
typedef IntrusivePtr<VisualModel> VisualModelPtr;
*/
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().
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
}
}
-void VectorAnimationManager::Process()
+void VectorAnimationManager::Process(bool postProcessor)
{
for(auto&& iter : mEventCallbacks)
{
/**
* @copydoc Dali::Integration::Processor::Process()
*/
- void Process() override;
+ void Process(bool postProcessor) override;
private:
// Undefined
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");
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),
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);
bool VectorAnimationTask::Rasterize()
{
bool stopped = false;
- uint32_t currentFrame;
+ uint32_t currentFrame, droppedFrames = 0;
{
ConditionalWait::ScopedLock lock(mConditionalWait);
// 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);
}
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;
}
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
*/
* @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:
/**
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
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.
}
UnregisterProcessor();
}
-void SvgRasterizeThread::Process()
+void SvgRasterizeThread::Process(bool postProcessor)
{
ApplyRasterizedSVGToSampler();
}
/**
* @copydoc Dali::Integration::Processor::Process()
*/
- void Process() override;
+ void Process(bool postProcessor) override;
private:
/**
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);
break;
}
case VisualUrl::JSON:
+ case VisualUrl::RIVE:
{
visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
break;
break;
}
case VisualUrl::JSON:
+ case VisualUrl::RIVE:
{
visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
break;
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)
{
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:
SVG,
GIF,
WEBP,
- JSON
+ JSON,
+ RIVE
};
enum ProtocolType
if(type)
{
auto typeName = type.GetName();
- DevelControl::AppendAccessibilityAttribute(Self(), "t", typeName);
+ DevelControl::AppendAccessibilityAttribute(Self(), "class", typeName);
}
-
- if(Accessibility::IsUp())
- mImpl->AccessibilityRegister();
}
void Control::OnInitialize()
// 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();
}
{
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
--- /dev/null
+/*
+ * 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);
+}
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
%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